Skip to content

Commit 555847f

Browse files
NNemecjpakkane
authored andcommitted
Fix MSVC /link argument ordering (mesonbuild#5598)
* correct handling of LDFLAGS in find_library and sanity_check on MSVC (fixes mesonbuild#3629) The MSVC compiler requires all linker flags to be placed after the compiler flags, separated by a "/link" argument. This was already handled for regular linking commands, but not yet for the aforementioned special code paths. * on MSVC, add /link separator between compiler and linker flags when it is missing * avoid unnecessary /link argument
1 parent 19cda6b commit 555847f

File tree

1 file changed

+32
-19
lines changed

1 file changed

+32
-19
lines changed

mesonbuild/compilers/clike.py

+32-19
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,8 @@ def sanity_check_impl(self, work_dir, environment, sname, code):
255255
# a ton of compiler flags to differentiate between
256256
# arm and x86_64. So just compile.
257257
mode = 'compile'
258-
extra_flags = self._get_basic_compiler_args(environment, mode)
258+
cargs, largs = self._get_basic_compiler_args(environment, mode)
259+
extra_flags = cargs + self.linker_to_compiler_args(largs)
259260

260261
# Is a valid executable output for all toolchains and platforms
261262
binname += '.exe'
@@ -264,7 +265,9 @@ def sanity_check_impl(self, work_dir, environment, sname, code):
264265
with open(source_name, 'w') as ofile:
265266
ofile.write(code)
266267
# Compile sanity check
267-
cmdlist = self.exelist + extra_flags + [source_name] + self.get_output_args(binary_name)
268+
# NOTE: extra_flags must be added at the end. On MSVC, it might contain a '/link' argument
269+
# after which all further arguments will be passed directly to the linker
270+
cmdlist = self.exelist + [source_name] + self.get_output_args(binary_name) + extra_flags
268271
pc, stdo, stde = mesonlib.Popen_safe(cmdlist, cwd=work_dir)
269272
mlog.debug('Sanity check compiler command line:', ' '.join(cmdlist))
270273
mlog.debug('Sanity check compile stdout:')
@@ -329,10 +332,10 @@ def has_header_symbol(self, hname, symbol, prefix, env, *, extra_args=None, depe
329332
dependencies=dependencies)
330333

331334
def _get_basic_compiler_args(self, env, mode):
332-
args = []
335+
cargs, largs = [], []
333336
# Select a CRT if needed since we're linking
334337
if mode == 'link':
335-
args += self.get_linker_debug_crt_args()
338+
cargs += self.get_linker_debug_crt_args()
336339

337340
# Add CFLAGS/CXXFLAGS/OBJCFLAGS/OBJCXXFLAGS and CPPFLAGS from the env
338341
sys_args = env.coredata.get_external_args(self.for_machine, self.language)
@@ -341,17 +344,17 @@ def _get_basic_compiler_args(self, env, mode):
341344
# also used during linking. These flags can break
342345
# argument checks. Thanks, Autotools.
343346
cleaned_sys_args = self.remove_linkerlike_args(sys_args)
344-
args += cleaned_sys_args
347+
cargs += cleaned_sys_args
345348

346349
if mode == 'link':
347350
# Add LDFLAGS from the env
348351
sys_ld_args = env.coredata.get_external_link_args(self.for_machine, self.language)
349352
# CFLAGS and CXXFLAGS go to both linking and compiling, but we want them
350353
# to only appear on the command line once. Remove dupes.
351-
args += [x for x in sys_ld_args if x not in sys_args]
354+
largs += [x for x in sys_ld_args if x not in sys_args]
352355

353-
args += self.get_compiler_args_for_mode(mode)
354-
return args
356+
cargs += self.get_compiler_args_for_mode(mode)
357+
return cargs, largs
355358

356359
def _get_compiler_check_args(self, env, extra_args, dependencies, mode='compile'):
357360
if extra_args is None:
@@ -365,19 +368,27 @@ def _get_compiler_check_args(self, env, extra_args, dependencies, mode='compile'
365368
elif not isinstance(dependencies, list):
366369
dependencies = [dependencies]
367370
# Collect compiler arguments
368-
args = compilers.CompilerArgs(self)
371+
cargs = compilers.CompilerArgs(self)
372+
largs = []
369373
for d in dependencies:
370374
# Add compile flags needed by dependencies
371-
args += d.get_compile_args()
375+
cargs += d.get_compile_args()
372376
if mode == 'link':
373377
# Add link flags needed to find dependencies
374-
args += d.get_link_args()
378+
largs += d.get_link_args()
379+
380+
ca, la = self._get_basic_compiler_args(env, mode)
381+
cargs += ca
382+
largs += la
375383

376-
args += self._get_basic_compiler_args(env, mode)
384+
cargs += self.get_compiler_check_args()
377385

378-
args += self.get_compiler_check_args()
379-
# extra_args must override all other arguments, so we add them last
380-
args += extra_args
386+
# on MSVC compiler and linker flags must be separated by the "/link" argument
387+
# at this point, the '/link' argument may already be part of extra_args, otherwise, it is added here
388+
if self.linker_to_compiler_args([]) == ['/link'] and largs != [] and not ('/link' in extra_args):
389+
extra_args += ['/link']
390+
391+
args = cargs + extra_args + largs
381392
return args
382393

383394
def compiles(self, code, env, *, extra_args=None, dependencies=None, mode='compile', disable_cache=False):
@@ -964,10 +975,12 @@ def find_library_real(self, libname, env, extra_dirs, code, libtype: LibType):
964975
# search for .a. This is only allowed if libtype is LibType.PREFER_SHARED
965976
if ((not extra_dirs and libtype is LibType.PREFER_SHARED) or
966977
libname in self.internal_libs):
967-
args = ['-l' + libname]
968-
largs = self.linker_to_compiler_args(self.get_allow_undefined_link_args())
969-
if self.links(code, env, extra_args=(args + largs), disable_cache=True)[0]:
970-
return args
978+
cargs = ['-l' + libname]
979+
largs = self.get_allow_undefined_link_args()
980+
extra_args = cargs + self.linker_to_compiler_args(largs)
981+
982+
if self.links(code, env, extra_args=extra_args, disable_cache=True)[0]:
983+
return cargs
971984
# Don't do a manual search for internal libs
972985
if libname in self.internal_libs:
973986
return None

0 commit comments

Comments
 (0)