Support AR env variable?

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

Assigned to
10 months ago
a month ago
No labels applied.

~wdlkmpx 10 months ago* · edit

deleted comment

~wdlkmpx 10 months ago* · edit

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 me

This 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);
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)
 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
 	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);
@@ -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,
 		"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"
 		"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(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)) {
 		return ar_posix;
@@ -1078,13 +1081,13 @@ compiler_detect_ar_type(void)
 const char *
+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'])

~eschwartz 10 months ago

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.

~wdlkmpx 10 months ago · edit

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

~wdlkmpx 10 months ago · edit

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 type

diff --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(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)) {
 		return ar_posix;

~wdlkmpx 10 months ago · edit

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)

~lattis REPORTED IMPLEMENTED a month ago

I've finally implemented this, let me know if there are issues with it

Register here or Log in to comment, or comment via email.