I have problems cross-compiling for non-linux targets (i.e. mingw)
muon doesn't officially supports cross-compilation.. but as long as CC/CXX/LDFLAGS/CFLAGS/CXXFLAGS are exported with proper values.. cross-compilation succeeds
the meson docs mention env variables to override default compiler and linker (CC CXX CC_LD CXX_LD) https://mesonbuild.com/Reference-tables.html#compiler-and-linker-selection-variables
But there's no way to override the AR command, so I have to use a --cross-file
[18/19] rm -f libpkgconf.a && i686-w64-mingw32-ar csrD libpkgconf.a ...
[19/19] i686-w64-mingw32-gcc -o pkgconf.exe ...
So AR is definitely not hard-coded, it can be changed... in a meson --cross-file
muon: https://github.com/annacrombie/muon/blob/master/src/backend/ninja/rules.c#L303
[18/19] rm -f libpkgconf.a && ar csrD libpkgconf.a ...
[19/19] i686-w64-mingw32-gcc -o pkgconf ....
../i686-w64-mingw32/bin/ld: libpkgconf.a: error adding symbols: archive has no index; run ranlib to add one
When dealing with pure Makefiles, the AR
env variable is usually supported
Perhaps muon should recognize the AR env variable and assign it to the (new) internal ar command or something.. Or maybe recognize something muon-specific: MUON_AR
, as a muon extension
ar
is just one of several possible binutils apps that are used when building stuff
deleted comment
This works for me, simple apps that support mingw natively compile fine. But muon can't install .exe files, because the extension is missing, but this patch that adds support for
AR
env variable works for meThis actually fixes potential issues with linux cross-builds as well, the system AR may be too old/unsuitable for the cross-compiler toolchain, so there's a strong need to override it, like this:
export AR=i686-w64-mingw32-ar
,export AR=i686-linux-musl-ar
diff --git a/include/compilers.h b/include/compilers.h index c91e9d4c..6d076a34 100644 --- a/include/compilers.h +++ b/include/compilers.h @@ -159,5 +159,5 @@ enum compiler_language coalesce_link_languages(enum compiler_language cur, enum bool compiler_detect(struct workspace *wk, obj *comp, enum compiler_language lang); void compilers_init(void); -const char *ar_arguments(void); +const char *ar_arguments(struct workspace *wk); #endif diff --git a/src/backend/ninja/build_target.c b/src/backend/ninja/build_target.c index d7f7a344..f4eca755 100644 --- a/src/backend/ninja/build_target.c +++ b/src/backend/ninja/build_target.c @@ -116,6 +116,8 @@ write_tgt_sources_iter(struct workspace *wk, void *_ctx, obj val) bool ninja_write_build_tgt(struct workspace *wk, obj tgt_id, struct write_tgt_ctx *wctx) { + obj ar; + const char *ar_str = NULL; struct obj_build_target *tgt = get_obj_build_target(wk, tgt_id); L("writing rules for target '%s'", get_cstr(wk, tgt->build_name)); @@ -227,7 +229,9 @@ ninja_write_build_tgt(struct workspace *wk, obj tgt_id, struct write_tgt_ctx *wc break; case tgt_static_library: linker_type = "static"; - link_args = ar_arguments(); + get_option_value(wk, NULL, "env.AR", &ar); + ar_str = get_cstr(wk,ar); + link_args = ar_arguments(wk); break; default: assert(false); @@ -248,6 +252,10 @@ ninja_write_build_tgt(struct workspace *wk, obj tgt_id, struct write_tgt_ctx *wc fputs(" || ", wctx->out); fputs(get_cstr(wk, ctx.order_deps), wctx->out); } + + if (ar_str) { + fprintf(wctx->out, "\n AR = %s", ar_str); + } fprintf(wctx->out, "\n LINK_ARGS = %s\n", link_args); if (tgt->flags & build_tgt_flag_build_by_default) { diff --git a/src/backend/ninja/rules.c b/src/backend/ninja/rules.c index 53f27109..41972d9f 100644 --- a/src/backend/ninja/rules.c +++ b/src/backend/ninja/rules.c @@ -300,7 +300,7 @@ ninja_write_rules(FILE *out, struct workspace *wk, struct project *main_proj, fprintf(out, "rule static_linker\n" - " command = rm -f $out && ar $LINK_ARGS $out $in\n" + " command = rm -f $out && $AR $LINK_ARGS $out $in\n" " description = linking static $out\n" "\n" "rule CUSTOM_COMMAND\n" diff --git a/src/compilers.c b/src/compilers.c index a391ce90..618d9b1e 100644 --- a/src/compilers.c +++ b/src/compilers.c @@ -1059,10 +1059,13 @@ enum ar_type { }; static enum ar_type -compiler_detect_ar_type(void) +compiler_detect_ar_type(struct workspace *wk) { + obj ar; + get_option_value(wk, NULL, "env.AR", &ar); + struct run_cmd_ctx cmd_ctx = { 0 }; - if (!run_cmd_argv(&cmd_ctx, (char *[]){ "ar", "--version", NULL }, NULL, 0)) { + if (!run_cmd_argv(&cmd_ctx, (char *[]){ get_cstr(wk, ar), "--version", NULL }, NULL, 0)) { run_cmd_ctx_destroy(&cmd_ctx); return ar_posix; } @@ -1078,13 +1081,13 @@ compiler_detect_ar_type(void) } const char * -ar_arguments(void) +ar_arguments(struct workspace *wk) { static enum ar_type ar_type; static bool ar_type_initialized = false; if (!ar_type_initialized) { - ar_type = compiler_detect_ar_type(); + ar_type = compiler_detect_ar_type(wk); ar_type_initialized = true; } diff --git a/src/options.c b/src/options.c index 527c46b2..32eea47f 100644 --- a/src/options.c +++ b/src/options.c @@ -814,12 +814,14 @@ init_global_options(struct workspace *wk) "option('env.CC', type: 'array', value: ['cc'])\n" "option('env.NINJA', type: 'array', value: ['ninja'])\n" + "option('env.AR', type: 'string', value: 'ar')\n" )) { return false; } set_binary_from_env(wk, "CC", "env.CC"); set_binary_from_env(wk, "NINJA", "env.NINJA"); + set_str_opt_from_env(wk, "AR", "env.AR"); set_compile_opt_from_env(wk, "c_args", "CFLAGS", "CPPFLAGS"); set_compile_opt_from_env(wk, "c_link_args", "CFLAGS", "LDFLAGS"); diff --git a/src/script/global_options.meson b/src/script/global_options.meson index 58ab2567..eaab0e9e 100644 --- a/src/script/global_options.meson +++ b/src/script/global_options.meson @@ -148,6 +148,7 @@ option('cpp_winlibs', type: 'array', value: []) # TODO option('env.CC', type: 'array', value: ['cc']) option('env.CXX', type: 'array', value: ['c++']) +option('env.AR', type: 'string', value: 'ar') option('env.OBJC', type: 'array', value: ['cc']) option('env.NINJA', type: 'array', value: ['ninja']) option('env.NASM', type: 'array', value: ['nasm'])
As far as I can tell, $AR is supported by meson too, see https://github.com/mesonbuild/meson/blob/82d0d1755d5c88e0415a3deb4102d4cdcf0d7435/mesonbuild/envconfig.py#L118
So it makes sense to support it in muon for the same reason.
I export all those variables for binutils apps, usually to deal with projects that only support plain Makefiles, I patch Makefiles so that stuff works the way it should
meson doesn't like it when LD and/or CC_LD is not set to some predefined value (gold, lld, bfd?, etc), so I don't export those variables when I use meson, only with muon. but muon doesn't support changing the linker, so it's not problem anyway
So basically LD is the linker binary and CC_LD may be a param for the compiler?, I shouldn't export CC_LD to test this with meson, but I'm pretty sure it works, now it should be documented somewhere that (almost) all binutils binaries can be overridden through environment variables
The fact that AR is hard-coded is indeed a major issue when using something else than the default system compiler. The patch above doesn't seem cause side effects, looks ok to me, but I'm not really sure what I'm doing. The only change I think of is this, to silence a warning .... I also notice that
run_cmd_arr()
can be used but does not apply to string typediff --git a/src/compilers.c b/src/compilers.c index a391ce90..4815ab0e 100644 --- a/src/compilers.c +++ b/src/compilers.c @@ -1059,10 +1059,14 @@ enum ar_type { }; static enum ar_type -compiler_detect_ar_type(void) +compiler_detect_ar_type(struct workspace *wk) { + obj ar; + get_option_value(wk, NULL, "env.AR", &ar); + char *ar_cmd[] = { (char*)get_cstr(wk, ar), "--version", NULL }; + struct run_cmd_ctx cmd_ctx = { 0 }; - if (!run_cmd_argv(&cmd_ctx, (char *[]){ "ar", "--version", NULL }, NULL, 0)) { + if (!run_cmd_argv(&cmd_ctx, ar_cmd, NULL, 0)) { run_cmd_ctx_destroy(&cmd_ctx); return ar_posix; }
Yes meson recognizes the AR env variable and overrides the default ar string if your export it. So this just increases meson compatibility
Well meson does require the --cross-file if cross compiling for a different CPU architecture (or a different libc without generating static binaries), apparently it always creates a test binary that needs to run. That's not an issue with muon unless the meson project specifies something like
compiler: native
, and then tries to run the binary, that's when muon will die (i.e. muon can't cross compile muon)
I've finally implemented this, let me know if there are issues with it