This issue is related to #259 but is specific to tcc on windows/msys2.
Presently muon converts msys2 pkg-config -l libs into .dll.a paths which error out on tcc. tcc can only handle .dll files and .def files. Changing the .dll.a file extension to .dll alone is not sufficient. The patch below introduces a new linker handler lib_adjust for use by ld-tcc to convert .dll.a paths to (versioned) msys2 .dll paths:
$ dlltool -I c:/msys64/ucrt64/lib/libglib-2.0.dll.a
libglib-2.0-0.dll
$ ls -1 c:/msys64/ucrt64/bin/libglib-2.0-0.dll
c:/msys64/ucrt64/bin/libglib-2.0-0.dll
Note the -0 DLL version in the file name, and the file exists in the bin directory, not the lib directory. The $MINGW_PREFIX of the original .dll.a file (/ucrt64 in this example) is retained.
It is possible that a lib_adjust handler could similarly be added to the msvc 'link' script for the /LIBPATH:xxx issue.
--- a/include/toolchains.h
+++ b/include/toolchains.h
@@ -196,4 +196,5 @@ typedef bool ((*compiler_get_arg_func_1srb)(TOOLCHAIN_SIG_1srb));
_(input_output, linker, TOOLCHAIN_PARAMS_2s) \
_(lib, linker, TOOLCHAIN_PARAMS_1s) \
+ _(lib_adjust, linker, TOOLCHAIN_PARAMS_1s) \
_(no_undefined, linker, TOOLCHAIN_PARAMS_0) \
_(pgo, linker, TOOLCHAIN_PARAMS_1i) \
--- a/src/functions/compiler.c
+++ b/src/functions/compiler.c
@@ -1956,5 +1956,5 @@ FUNC_IMPL(compiler, get_argument_syntax, tc_string, func_impl_flag_impure)
static obj
-find_library_check_dirs(struct workspace *wk, const char *libname, obj libdirs, const char **exts, uint32_t exts_len)
+find_library_check_dirs(struct workspace *wk, obj compiler, const char *libname, obj libdirs, const char **exts, uint32_t exts_len)
{
static const char *pref[] = { "", "lib" };
@@ -1974,4 +1974,13 @@ find_library_check_dirs(struct workspace *wk, const char *libname, obj libdirs,
if (fs_file_exists(path.buf)) {
+ if (compiler) {
+ const char *adjusted = toolchain_compiler_flatten_one_optional(wk,
+ toolchain_linker_lib_adjust(wk, compiler, path.buf));
+
+ if (adjusted) {
+ return make_str(wk, adjusted);
+ }
+ }
+
return tstr_into_str(wk, &path);
}
@@ -2008,5 +2017,5 @@ find_library(struct workspace *wk, obj compiler, const char *libname, obj extra_
// First check in dirs if the kw is set.
if (extra_dirs) {
- if ((found = find_library_check_dirs(wk, libname, extra_dirs, ext_order, ext_order_len))) {
+ if ((found = find_library_check_dirs(wk, compiler, libname, extra_dirs, ext_order, ext_order_len))) {
return (struct find_library_result){ found, find_library_found_location_extra_dirs };
}
@@ -2022,5 +2031,5 @@ find_library(struct workspace *wk, obj compiler, const char *libname, obj extra_
// Next, check system libdirs
if (!found) {
- if ((found = find_library_check_dirs(wk, libname, comp->libdirs, ext_order, ext_order_len))) {
+ if ((found = find_library_check_dirs(wk, compiler, libname, comp->libdirs, ext_order, ext_order_len))) {
return (struct find_library_result){ found, find_library_found_location_system_dirs };
}
--- a/src/script/runtime/toolchains.meson
+++ b/src/script/runtime/toolchains.meson
@@ -270,4 +270,6 @@ toolchain.register_linker(
)
+tcc_dll_cache = {}
+
toolchain.register_linker(
'ld-tcc',
@@ -293,4 +295,25 @@ toolchain.register_linker(
return ['-l', lib]
endfunc,
+ 'lib_adjust': func(_c compiler, lib str) -> list[str]
+ # tcc cannot handle msys2 .dll.a files, so convert
+ # the .dll.a path to a .dll path with dlltool.
+ # Cache path pairs to reduce expensive dlltool calls.
+ if tcc_dll_cache.has_key(lib)
+ return [tcc_dll_cache[lib]]
+ endif
+ if lib.endswith('.dll.a') and lib.contains('/msys64/') and lib.contains('/lib/')
+ dlltool = find_program('dlltool', required: false)
+ if dlltool.found()
+ arr := lib.split('/')
+ dllname := run_command(dlltool, '-I', lib, check: true).stdout().strip()
+ if dllname.endswith('.dll') and arr[-2] == 'lib'
+ dllpath := '/'.join(arr.slice(0, -2) + ['bin', dllname])
+ tcc_dll_cache[lib] = dllpath
+ return [dllpath]
+ endif
+ endif
+ endif
+ return [lib]
+ endfunc,
'rpath': func(c compiler, s1 str) -> list[str]
return c.machine().system() == 'windows' ? [] : ['-rpath,' + s1]
--- a/src/toolchains.c
+++ b/src/toolchains.c
@@ -1228,4 +1228,5 @@ toolchain_handler_info_init(struct workspace *wk)
doc(input_output, linker, .desc = "Passed in `input` and `output` and orders them properly, optionally adding additional flags.");
doc(lib, linker, .desc = "`-l`");
+ doc(lib_adjust, linker, .desc = "Adjust library file path and name.");
doc(no_undefined, linker, .desc = "`--no-undefined`");
doc(pgo, linker, .desc = "", .enum_arg = "enum compiler_pgo_stage");
Here are the corresponding changes to meson-tests to have the test frameworks/7 gnome work on windows with gcc, clang and tcc:
--- a/common/44 pkgconfig-gen/meson.build
+++ b/common/44 pkgconfig-gen/meson.build
@@ -202,5 +202,6 @@ if host_machine.system() == 'windows'
read1,
read1
- + '.replace(\'-lz.dll\',\'-lz\')',
+ + '.replace(\'-lz.dll\',\'-lz\')'
+ + '.replace(\'-lzlib1\',\'-lz\')',
)
endif
--- a/frameworks/7 gnome/meson.build
+++ b/frameworks/7 gnome/meson.build
@@ -23,4 +23,9 @@ endif
cc = meson.get_compiler('c')
+if cc.get_id() == 'tcc'
+ # Have tcc pretend to be gcc to get glib and gio defines working.
+ add_global_arguments('-D__GNUC__=4', language: 'c')
+endif
+
add_global_arguments('-DMESON_TEST_1', language: 'c')
if cc.get_id() == 'intel'
@@ -45,5 +50,9 @@ endif
gnome = import('gnome')
gio = dependency('gio-2.0')
-giounix = dependency('gio-unix-2.0')
+if host_machine.system() == 'windows'
+ giounix = dependency('gio-windows-2.0')
+else
+ giounix = dependency('gio-unix-2.0')
+endif
glib = dependency('glib-2.0')
gobj = dependency('gobject-2.0')
--- a/frameworks/7 gnome/resources-data/meson.build
+++ b/frameworks/7 gnome/resources-data/meson.build
@@ -6,4 +6,5 @@ fake_generator_script = '''
import os, sys
assert os.path.exists(sys.argv[1]), "File %s not found" % sys.argv[1]
+sys.stdout.reconfigure(newline='\n') # avoid \r\n on windows
print("This is a generated resource.")
'''
Currently muon CI doesn't add the msys2 packages necessary for frameworks/7 gnome to run, so this test is skipped. If the following msys2 packages are added then the test ought to work with all supported msys2 compilers:
libglib-2.0 libintl libgio-2.0 libgobject-2.0 libgmodule-2.0 gio-windows-2.0
Note that doing so would probably add a minute to each msys2 run.
This issue is related to #259 but is specific to tcc on windows/msys2.
Presently muon converts msys2
pkg-config-llibs into.dll.apaths which error out on tcc. tcc can only handle.dllfiles and.deffiles. Changing the.dll.afile extension to.dllalone is not sufficient. The patch below introduces a new linker handlerlib_adjustfor use byld-tccto convert.dll.apaths to (versioned) msys2.dllpaths:Note the
-0DLL version in the file name, and the file exists in thebindirectory, not thelibdirectory. The$MINGW_PREFIXof the original.dll.afile (/ucrt64in this example) is retained.It is possible that a
lib_adjusthandler could similarly be added to the msvc'link'script for the/LIBPATH:xxxissue.Here are the corresponding changes to
meson-teststo have the testframeworks/7 gnomework on windows with gcc, clang and tcc:Currently muon CI doesn't add the msys2 packages necessary for
frameworks/7 gnometo run, so this test is skipped. If the following msys2 packages are added then the test ought to work with all supported msys2 compilers:Note that doing so would probably add a minute to each msys2 run.