Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ARCHES
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ mips-linux-muslsf
mipsel-linux-muslsf
mips64-linux-muslsf
s390x-linux-musl
riscv64-linux-musl
loongarch64-unknown-linux-musl
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ ARCHES := $(shell cat ARCHES)
# Create the individual build/clean/dist-clean rules for each arch...
define rules_for_each_arch

$(strip $(1)).build: $(TOOLS)/musl-cross/.unpacked $(ROOT)/mettle/configure
$(strip $(1)).build: $(TOOLS)/musl-cross/.unpacked $(if $(findstring riscv64,$(strip $(1))),$(TOOLS)/musl-cross/.riscv64-unpacked) $(if $(findstring loongarch64,$(strip $(1))),$(TOOLS)/musl-cross/.loongarch64-unpacked) $(ROOT)/mettle/configure
make TARGET=$(strip $(1))

$(strip $(1)).install:
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ The available platform triples for Linux targets are:
* `mipsel-linux-muslsf`
* `mips64-linux-muslsf`
* `s390x-linux-musl`
* `riscv64-linux-musl`
* `loongarch64-unknown-linux-musl`

For Mingw32-64 Windows targets, the following triples are added. On up-to-date
Debian / Ubuntu systems, the `mingw-w64` package will install both toolchains.
Expand Down
14 changes: 13 additions & 1 deletion make/Makefile.common
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ ifeq (,$(findstring mingw,$(TARGET)))
endif

CPPFLAGS:=$(CPPFLAGS) -I$(BUILD)/include -DCURL_STATICLIB
CONFIG_FIXUP=cp $(ROOT)/mettle/config.guess $(ROOT)/mettle/config.sub . ;
CONFIG_FIXUP=cp $(ROOT)/mettle/config.guess $(ROOT)/mettle/config.sub . ; [ ! -d config ] || cp $(ROOT)/mettle/config.guess $(ROOT)/mettle/config.sub config/ ;
CONFIGURE=configure --prefix=$(BUILD) --disable-shared ac_cv_path_PKGCONFIG=$(CWD)/pkg-config
CONFIGURE_STATIC=configure --prefix=$(BUILD) --static
ifneq "$(TARGET)" "native"
Expand All @@ -41,6 +41,18 @@ ifeq "$(D)" "1"
CFLAGS:=$(CFLAGS) -g
endif

# loongarch64's toolchain is much newer (GCC 14) than the others here and
# flags -Werror=calloc-transposed-args (added in GCC 14) against several
# third-party deps (json-c, etc) that pass calloc()'s count/size arguments
# in the other order. Harmless either way since both arguments are
# multiplied together, so silence it for this target rather than patching
# every affected dep. Must land before ENV is captured below, since libs
# built with -Werror do so via their own build systems (eg. json-c's
# configure.ac appends -Wall -Werror itself), not by inheriting it from us.
ifneq (,$(findstring loongarch64,$(TARGET)))
CFLAGS:=$(CFLAGS) -Wno-error=calloc-transposed-args
endif

# Libraries cannot be compiled with -Werror due to the multiple compilation warnings.
# This would be probably a good idea to update them to their latest versions and see if these issues are fixed.
ENV:=$(ENV) ARFLAGS="cr" AR_FLAGS="cr" LDFLAGS="-L$(BUILD)/lib $(LDFLAGS)" CC="$(CC)" CPP="$(CPP)" AR="$(AR)" RANLIB="$(RANLIB)" CFLAGS="$(CFLAGS)" CPPFLAGS="$(CPPFLAGS)" OBJCFLAGS="$(OBJCFLAGS)"
Expand Down
17 changes: 15 additions & 2 deletions make/Makefile.libpcap
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,23 @@ $(BUILD)/libpcap/Makefile: $(TOOLS) $(BUILD)/libpcap/configure $(LIBPCAP_DEPS)
$(CONFIG_FIXUP) \
$(ENV) ./$(CONFIGURE) $(LIBPCAP_CONFIG_FLAGS) $(LOGBUILD)

# libpcap's AC_LBL_C_INIT macro has a pre-existing bug (unrelated to
# riscv64) where its "if test $GCC = yes" check doesn't see the
# already-detected GNU compiler at that point in the generated configure
# script, falling into the non-GCC branch that appends -I/usr/local/include
# to INCLS. That's always been silently harmless before, since the old
# musl-cross toolchains don't care about host-path leakage; the riscv64
# Buildroot toolchain's wrapper actively rejects it as unsafe cross-compile
# input. INCLS is a plain (non-recursive) Makefile variable, so it can be
# overridden straight on the make command line.
ifneq (,$(findstring riscv64,$(TARGET)))
LIBPCAP_BUILD_FLAGS = INCLS=-I.
endif

$(BUILD)/lib/libpcap.a: $(BUILD)/libpcap/Makefile
@echo "Building libpcap for $(TARGET)"
@cd $(BUILD)/libpcap; \
$(ENV) $(MAKE) $(LOGBUILD) ; \
$(MAKE_INSTALL) $(LOGBUILD)
$(ENV) $(MAKE) $(LIBPCAP_BUILD_FLAGS) $(LOGBUILD) ; \
$(MAKE_INSTALL) $(LIBPCAP_BUILD_FLAGS) $(LOGBUILD)

libpcap: $(BUILD)/lib/libpcap.a
3 changes: 2 additions & 1 deletion make/Makefile.libsigar
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ $(BUILD)/libsigar/configure:
@cd $(BUILD); \
rm -fr libsigar; \
$(TAR) zxf $(ROOT)/deps/libsigar-1.6.7.tar.gz; \
mv libsigar-1.6.7 libsigar
mv libsigar-1.6.7 libsigar; \
sed -i 's/case 192: return "num";/case 192: return "num"; case 243: return "riscv64"; case 258: return "loongarch64";/' libsigar/src/sigar_elf.c

$(BUILD)/libsigar/Makefile: $(TOOLS) $(BUILD)/libsigar/configure
@echo "Configuring libsigar for $(TARGET)"
Expand Down
102 changes: 102 additions & 0 deletions make/Makefile.tools
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,18 @@ ifneq (,$(findstring musl,$(TARGET)))
TOOLS_DEPS:=$(TOOLS_DEPS) $(TOOLS)/musl-cross/.unpacked elf2bin
endif

# riscv64's toolchain is fetched and wired up separately; see the
# .riscv64-unpacked rule below for why.
ifneq (,$(findstring riscv64,$(TARGET)))
TOOLS_DEPS:=$(TOOLS_DEPS) $(TOOLS)/musl-cross/.riscv64-unpacked
endif

# loongarch64's toolchain is fetched and wired up separately; see the
# .loongarch64-unpacked rule below for why.
ifneq (,$(findstring loongarch64,$(TARGET)))
TOOLS_DEPS:=$(TOOLS_DEPS) $(TOOLS)/musl-cross/.loongarch64-unpacked
endif

ifeq "$(shell uname -s)" "Darwin"
BUILD_HOST=osx
TOOLS_DEPS:=$(TOOLS_DEPS) coreutils
Expand Down Expand Up @@ -244,4 +256,94 @@ $(TOOLS)/musl-cross/.unpacked: musl-cross-$(BUILD_HOST)-$(TOOLCHAIN_VERSION).tar
@cd $(TOOLS) && tar xfm $(ROOT)/musl-cross-$(BUILD_HOST)-$(TOOLCHAIN_VERSION).tar.xz
@touch $(TOOLS)/musl-cross/.unpacked

# riscv64 isn't in the shared musl-cross bundle (it predates musl's riscv64
# port). The musl.cc riscv64-linux-musl-cross toolchain (gcc 11.2.1) is
# available, but its binutils has a genuine bug linking -static-pie for
# riscv64: it leaves R_RISCV_JUMP_SLOT relocations against PLT stubs that
# never get resolved (no dynamic linker in a static binary), segfaulting
# at the first such call. Confirmed arch-specific, not a general
# "newer toolchain" issue: the exact same gcc/binutils vintage links a
# clean, correct static-pie binary for aarch64. A newer toolchain (gcc
# 13.2.0 / binutils 2.42, from Bootlin) fixes it for riscv64 too, so that's
# what's used here instead.
#
# Its tool prefix (riscv64-buildroot-linux-musl-*) differs from the
# riscv64-linux-musl-* convention every other rule in this file assumes
# (CC=$(TOOLS)/musl-cross/bin/$(TARGET)-*), so thin exec wrapper scripts
# are generated under that expected name. Plain symlinks don't work here:
# Buildroot's gcc/g++ are themselves wrapper scripts that derive the real
# (*.br_real) binary's name from their own invoked name, which breaks
# under a symlink with a different basename; exec'ing from a real script
# gives the real binary its own correct argv0.
RISCV64_TOOLCHAIN=riscv64-lp64d--musl--bleeding-edge-2024.02-1
RISCV64_TOOLCHAIN_PREFIX=riscv64-buildroot-linux-musl

$(RISCV64_TOOLCHAIN).tar.bz2:
@echo "Downloading riscv64 toolchain"
curl -f -O https://toolchains.bootlin.com/downloads/releases/toolchains/riscv64-lp64d/tarballs/$(RISCV64_TOOLCHAIN).tar.bz2

$(TOOLS)/musl-cross/.riscv64-unpacked: $(TOOLS)/musl-cross/.unpacked $(RISCV64_TOOLCHAIN).tar.bz2
@echo "Unpacking riscv64 toolchain"
@if [ "$(shell uname -s)" != "Linux" ] || [ "$(shell uname -m)" != "x86_64" ]; then \
echo "$(RISCV64_TOOLCHAIN).tar.bz2 only ships Linux x86_64 host binaries; can't build riscv64 targets on $(shell uname -s) $(shell uname -m)" >&2; \
exit 1; \
fi
@rm -fr $(TOOLS)/riscv64-buildroot
@mkdir -p $(TOOLS)/riscv64-buildroot
@cd $(TOOLS)/riscv64-buildroot && tar xfj $(ROOT)/$(RISCV64_TOOLCHAIN).tar.bz2 --strip-components=1
@$(TOOLS)/riscv64-buildroot/relocate-sdk.sh
@mkdir -p $(TOOLS)/musl-cross/bin
@for t in $(TOOLS)/riscv64-buildroot/bin/$(RISCV64_TOOLCHAIN_PREFIX)-*; do \
base=$$(basename $$t); \
case $$base in *.br_real) continue ;; esac; \
name=$${base#$(RISCV64_TOOLCHAIN_PREFIX)-}; \
case $$name in cc|c++) continue ;; esac; \
wrapper=$(TOOLS)/musl-cross/bin/riscv64-linux-musl-$$name; \
printf '#!/bin/sh\nexec "%s" "$$@"\n' "$$t" > $$wrapper; \
chmod +x $$wrapper; \
done
@touch $(TOOLS)/musl-cross/.riscv64-unpacked

# loongarch64 predates musl's port too (musl added support in 1.2.4/1.2.5),
# and doesn't appear in the shared musl-cross bundle or in Bootlin's
# toolchain catalog. The loong64/cross-tools project publishes a musl-libc
# loongarch64-unknown-linux-musl toolchain (crosstool-NG, gcc 14.3.0) built
# for an x86_64 Linux host; pinned to a specific dated release here for
# reproducibility, since "latest"/"stable" tags in that repo move.
#
# Its tool prefix (loongarch64-unknown-linux-musl-*) already matches the
# ARCHES/TARGET convention this file assumes (CC=$(TOOLS)/musl-cross/bin/
# $(TARGET)-*), so no renaming wrapper is needed here. And unlike
# Buildroot's gcc/g++ (see the riscv64 rule above), these are plain,
# non-argv0-dependent ELF binaries with no baked-in RPATH, so plain
# symlinks into musl-cross/bin work fine -- verified gcc resolves its own
# real install path through the symlink and finds its libexec/lib/sysroot.
#
# Default -static --static -pie silently produces a plain static EXEC (no
# PIE) on this toolchain rather than failing, so mettle/configure.ac special
# -cases loongarch64 to just -static-pie, which links a correct static-pie
# binary here on its own (verified via readelf: DYN type, no PT_INTERP, no
# NEEDED entries, only R_LARCH_RELATIVE relocs).
LOONGARCH64_TOOLCHAIN_RELEASE=20260612
LOONGARCH64_TOOLCHAIN=x86_64-cross-tools-loongarch64-unknown-linux-musl-stable

$(LOONGARCH64_TOOLCHAIN).tar.xz:
@echo "Downloading loongarch64 toolchain"
curl -fL -o $(LOONGARCH64_TOOLCHAIN).tar.xz https://github.com/loong64/cross-tools/releases/download/$(LOONGARCH64_TOOLCHAIN_RELEASE)/$(LOONGARCH64_TOOLCHAIN).tar.xz

$(TOOLS)/musl-cross/.loongarch64-unpacked: $(TOOLS)/musl-cross/.unpacked $(LOONGARCH64_TOOLCHAIN).tar.xz
@echo "Unpacking loongarch64 toolchain"
@if [ "$(shell uname -s)" != "Linux" ] || [ "$(shell uname -m)" != "x86_64" ]; then \
echo "$(LOONGARCH64_TOOLCHAIN).tar.xz only ships Linux x86_64 host binaries; can't build loongarch64 targets on $(shell uname -s) $(shell uname -m)" >&2; \
exit 1; \
fi
@rm -fr $(TOOLS)/loongarch64-cross
@mkdir -p $(TOOLS)/loongarch64-cross
@cd $(TOOLS)/loongarch64-cross && tar xf $(ROOT)/$(LOONGARCH64_TOOLCHAIN).tar.xz --strip-components=1
@mkdir -p $(TOOLS)/musl-cross/bin
@for t in $(TOOLS)/loongarch64-cross/bin/loongarch64-unknown-linux-musl-*; do \
ln -sf $$t $(TOOLS)/musl-cross/bin/$$(basename $$t); \
done
@touch $(TOOLS)/musl-cross/.loongarch64-unpacked

$(TOOLS): $(TOOLS_DEPS)
23 changes: 22 additions & 1 deletion mettle/configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,28 @@ AC_CONFIG_FILES([
AC_ARG_ENABLE([staticpie],
AS_HELP_STRING([--enable-staticpie], [Building Static PIE]))
AS_IF([test "x$enable_staticpie" = "xyes"], [
AC_SUBST([PLATFORM_LDADD], ['-static --static -pie'])
AS_CASE([$host_cpu],
dnl -static --static -pie relies on crt1.o rather than the
dnl relocatable rcrt1.o, needed for a real static-pie link.
dnl -static-pie alone isn't enough on this toolchain: its gcc
dnl driver only conditions -dynamic-linker on literal "-static"
dnl (not "-static-pie"), so without an explicit override the
dnl linker still emits a dynamically-linked PIE with a real
dnl PT_INTERP. Passing -static and -pie straight to the linker,
dnl plus suppressing the interpreter explicitly, produces a
dnl correct static-pie binary (verified via readelf: DYN type,
dnl no PT_INTERP, no NEEDED entries, zero JUMP_SLOT relocs).
[riscv64], [AC_SUBST([PLATFORM_LDADD], ['-static-pie -Wl,-static -Wl,-pie -Wl,--no-dynamic-linker'])],
dnl -static --static -pie silently links a plain static EXEC
dnl (no PIE at all) on this toolchain instead of erroring, so
dnl the omission wouldn't be caught by a build failure. Plain
dnl -static-pie alone already produces a correct static-pie
dnl binary here (verified via readelf: DYN type, no PT_INTERP,
dnl no NEEDED entries, only R_LARCH_RELATIVE relocs), so no
dnl further linker overrides are needed like riscv64 required.
[loongarch64], [AC_SUBST([PLATFORM_LDADD], ['-static-pie'])],
[AC_SUBST([PLATFORM_LDADD], ['-static --static -pie'])]
)
AM_CONDITIONAL([MAKEBIN], [true])
], [
AM_CONDITIONAL([MAKEBIN], [false])
Expand Down
2 changes: 1 addition & 1 deletion mettle/m4/check-libc.m4
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ AM_CONDITIONAL([HAVE_TIMEGM], [test "x$ac_cv_func_timegm" = xyes])

AC_DEFUN([CHECK_PROGNAME], [
AC_CACHE_CHECK([if libc defines __progname], ac_cv_libc_defines___progname, [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <stdio.h>]],
[[ extern char *__progname; printf("%s", __progname); ]])],
[ ac_cv_libc_defines___progname="yes" ],
[ ac_cv_libc_defines___progname="no"
Expand Down
2 changes: 2 additions & 0 deletions util/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,8 @@ typedef struct {
#define EM_MICROBLAZE 189
#define EM_TILEGX 191
#define EM_NUM 192
#define EM_RISCV 243
#define EM_LOONGARCH 258
#define EM_ALPHA 0x9026

// The following conflicts with a libev define, don't think we're actually
Expand Down
Loading