@@ -1962,23 +1962,22 @@ def generate_rust_target(self, target: build.BuildTarget) -> None:
19621962 except KeyError :
19631963 pass
19641964
1965- # Since 1.61.0 Rust has a special modifier for whole-archive linking,
1966- # before that it would treat linking two static libraries as
1967- # whole-archive linking. However, to make this work we have to disable
1968- # bundling, which can't be done until 1.63.0… So for 1.61–1.62 we just
1969- # have to hope that the default cases of +whole-archive are sufficient.
1970- # See: https://github.com/rust-lang/rust/issues/99429
1971- if mesonlib .version_compare (rustc .version , '>= 1.63.0' ):
1972- whole_archive = '+whole-archive,-bundle'
1973- else :
1974- whole_archive = ''
1975-
1976- # FIXME: Seems broken on MacOS: https://github.com/rust-lang/rust/issues/116674
1977- if mesonlib .version_compare (rustc .version , '>= 1.67.0' ) and not mesonlib .is_osx ():
1965+ if mesonlib .version_compare (rustc .version , '>= 1.67.0' ):
19781966 verbatim = '+verbatim'
19791967 else :
19801968 verbatim = ''
19811969
1970+ def _link_library (libname : str , static : bool , bundle : bool = False ):
1971+ type_ = 'static' if static else 'dylib'
1972+ modifiers = []
1973+ if not bundle and static :
1974+ modifiers .append ('-bundle' )
1975+ if verbatim :
1976+ modifiers .append (verbatim )
1977+ if modifiers :
1978+ type_ += ':' + ',' .join (modifiers )
1979+ args .extend (['-l' , f'{ type_ } ={ libname } ' ])
1980+
19821981 linkdirs = mesonlib .OrderedSet ()
19831982 external_deps = target .external_deps .copy ()
19841983 target_deps = target .get_dependencies ()
@@ -2001,64 +2000,53 @@ def generate_rust_target(self, target: build.BuildTarget) -> None:
20012000 if isinstance (d , build .StaticLibrary ):
20022001 external_deps .extend (d .external_deps )
20032002
2004- lib = None
2005- modifiers = []
2003+ # Pass native libraries directly to the linker with "-C link-arg"
2004+ # because rustc's "-l:+verbatim=" is not portable and we cannot rely
2005+ # on linker to find the right library without using verbatim filename.
2006+ # For example "-lfoo" won't find "foo.so" in the case name_prefix set
2007+ # to "", or would always pick the shared library when both "libfoo.so"
2008+ # and "libfoo.a" are available.
2009+ # See https://doc.rust-lang.org/rustc/command-line-arguments.html#linking-modifiers-verbatim.
2010+ #
2011+ # However, rustc static linker (rlib and staticlib) requires using
2012+ # "-l" argument and does not rely on platform specific dynamic linker.
2013+ lib = self .get_target_filename_for_linking (d )
20062014 link_whole = d in target .link_whole_targets
2007- if link_whole and whole_archive :
2008- modifiers .append (whole_archive )
2009- if verbatim :
2010- modifiers .append (verbatim )
2011- lib = self .get_target_filename_for_linking (d )
2012- elif rustc .linker .id in {'link' , 'lld-link' } and isinstance (d , build .StaticLibrary ):
2013- # Rustc doesn't follow Meson's convention that static libraries
2014- # are called .a, and import libraries are .lib, so we have to
2015- # manually handle that.
2016- if link_whole :
2017- if isinstance (target , build .StaticLibrary ):
2018- # If we don't, for static libraries the only option is
2019- # to make a copy, since we can't pass objects in, or
2020- # directly affect the archiver. but we're not going to
2021- # do that given how quickly rustc versions go out of
2022- # support unless there's a compelling reason to do so.
2023- # This only affects 1.61–1.66
2024- mlog .warning ('Due to limitations in Rustc versions 1.61–1.66 and meson library naming,' ,
2025- 'whole-archive linking with MSVC may or may not work. Upgrade rustc to' ,
2026- '>= 1.67. A best effort is being made, but likely won\' t work' )
2027- lib = d .name
2028- else :
2029- # When doing dynamic linking (binaries and [c]dylibs),
2030- # we can instead just proxy the correct arguments to the linker
2031- for link_whole_arg in rustc .linker .get_link_whole_for ([self .get_target_filename_for_linking (d )]):
2032- args += ['-C' , f'link-arg={ link_whole_arg } ' ]
2033- else :
2034- args += ['-C' , f'link-arg={ self .get_target_filename_for_linking (d )} ' ]
2015+ if isinstance (target , build .StaticLibrary ):
2016+ static = isinstance (d , build .StaticLibrary )
2017+ libname = os .path .basename (lib ) if verbatim else d .name
2018+ # rlib does not support bundling. That probably could cause
2019+ # unusable installed rlib if they link to uninstalled static
2020+ # libraries. Installing rlib is not something we generally
2021+ # support anyway.
2022+ # https://github.com/rust-lang/rust/issues/108081
2023+ bundle = cratetype == 'staticlib' and link_whole
2024+ _link_library (libname , static , bundle )
2025+ elif link_whole :
2026+ link_whole_args = rustc .linker .get_link_whole_for ([lib ])
2027+ args += [f'-Clink-arg={ a } ' for a in link_whole_args ]
20352028 else :
2036- lib = d .name
2037-
2038- if lib :
2039- _type = 'static' if isinstance (d , build .StaticLibrary ) else 'dylib'
2040- if modifiers :
2041- _type += ':' + ',' .join (modifiers )
2042- args += ['-l' , f'{ _type } ={ lib } ' ]
2029+ args .append (f'-Clink-arg={ lib } ' )
20432030
20442031 for e in external_deps :
20452032 for a in e .get_link_args ():
20462033 if a in rustc .native_static_libs :
20472034 # Exclude link args that rustc already add by default
2048- continue
2049- if a .endswith (('.dll' , '.so' , '.dylib' , '.a' , '.lib' )):
2050- dir_ , lib = os .path .split (a )
2051- linkdirs .add (dir_ )
2052- lib , ext = os .path .splitext (lib )
2053- if lib .startswith ('lib' ):
2054- lib = lib [3 :]
2055- _type = 'static' if a .endswith (('.a' , '.lib' )) else 'dylib'
2056- args .extend (['-l' , f'{ _type } ={ lib } ' ])
2035+ pass
20572036 elif a .startswith ('-L' ):
20582037 args .append (a )
2059- elif a .startswith ('-l' ):
2060- _type = 'static' if e .static else 'dylib'
2061- args .extend (['-l' , f'{ _type } ={ a [2 :]} ' ])
2038+ elif a .endswith (('.dll' , '.so' , '.dylib' , '.a' , '.lib' )) and isinstance (target , build .StaticLibrary ):
2039+ dir_ , lib = os .path .split (a )
2040+ linkdirs .add (dir_ )
2041+ if not verbatim :
2042+ lib , ext = os .path .splitext (lib )
2043+ if lib .startswith ('lib' ):
2044+ lib = lib [3 :]
2045+ static = a .endswith (('.a' , '.lib' ))
2046+ _link_library (lib , static )
2047+ else :
2048+ args .append (f'-Clink-arg={ a } ' )
2049+
20622050 for d in linkdirs :
20632051 if d == '' :
20642052 d = '.'
0 commit comments