1# Copyright 2012-2017 The Meson development team 2 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6 7# http://www.apache.org/licenses/LICENSE-2.0 8 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15import abc 16import enum 17import os 18import typing as T 19 20from .. import mesonlib 21from ..mesonlib import EnvironmentException, MesonException 22from ..arglist import CompilerArgs 23 24if T.TYPE_CHECKING: 25 from ..coredata import KeyedOptionDictType 26 from ..environment import Environment 27 from ..mesonlib import MachineChoice 28 29 30@enum.unique 31class RSPFileSyntax(enum.Enum): 32 33 """Which RSP file syntax the compiler supports.""" 34 35 MSVC = enum.auto() 36 GCC = enum.auto() 37 38 39class StaticLinker: 40 41 id: str 42 43 def __init__(self, exelist: T.List[str]): 44 self.exelist = exelist 45 46 def compiler_args(self, args: T.Optional[T.Iterable[str]] = None) -> CompilerArgs: 47 return CompilerArgs(self, args) 48 49 def can_linker_accept_rsp(self) -> bool: 50 """ 51 Determines whether the linker can accept arguments using the @rsp syntax. 52 """ 53 return mesonlib.is_windows() 54 55 def get_base_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: 56 """Like compilers.get_base_link_args, but for the static linker.""" 57 return [] 58 59 def get_exelist(self) -> T.List[str]: 60 return self.exelist.copy() 61 62 def get_std_link_args(self, is_thin: bool) -> T.List[str]: 63 return [] 64 65 def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]: 66 return [] 67 68 def get_output_args(self, target: str) -> T.List[str]: 69 return[] 70 71 def get_coverage_link_args(self) -> T.List[str]: 72 return [] 73 74 def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, 75 rpath_paths: str, build_rpath: str, 76 install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]: 77 return ([], set()) 78 79 def thread_link_flags(self, env: 'Environment') -> T.List[str]: 80 return [] 81 82 def openmp_flags(self) -> T.List[str]: 83 return [] 84 85 def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: 86 return [] 87 88 @classmethod 89 def unix_args_to_native(cls, args: T.List[str]) -> T.List[str]: 90 return args[:] 91 92 @classmethod 93 def native_args_to_unix(cls, args: T.List[str]) -> T.List[str]: 94 return args[:] 95 96 def get_link_debugfile_name(self, targetfile: str) -> str: 97 return None 98 99 def get_link_debugfile_args(self, targetfile: str) -> T.List[str]: 100 # Static libraries do not have PDB files 101 return [] 102 103 def get_always_args(self) -> T.List[str]: 104 return [] 105 106 def get_linker_always_args(self) -> T.List[str]: 107 return [] 108 109 def rsp_file_syntax(self) -> RSPFileSyntax: 110 """The format of the RSP file that this compiler supports. 111 112 If `self.can_linker_accept_rsp()` returns True, then this needs to 113 be implemented 114 """ 115 assert not self.can_linker_accept_rsp(), f'{self.id} linker accepts RSP, but doesn\' provide a supported format, this is a bug' 116 raise EnvironmentException(f'{self.id} does not implement rsp format, this shouldn\'t be called') 117 118 119class VisualStudioLikeLinker: 120 always_args = ['/NOLOGO'] 121 122 def __init__(self, machine: str): 123 self.machine = machine 124 125 def get_always_args(self) -> T.List[str]: 126 return self.always_args.copy() 127 128 def get_linker_always_args(self) -> T.List[str]: 129 return self.always_args.copy() 130 131 def get_output_args(self, target: str) -> T.List[str]: 132 args = [] # type: T.List[str] 133 if self.machine: 134 args += ['/MACHINE:' + self.machine] 135 args += ['/OUT:' + target] 136 return args 137 138 @classmethod 139 def unix_args_to_native(cls, args: T.List[str]) -> T.List[str]: 140 from ..compilers import VisualStudioCCompiler 141 return VisualStudioCCompiler.unix_args_to_native(args) 142 143 @classmethod 144 def native_args_to_unix(cls, args: T.List[str]) -> T.List[str]: 145 from ..compilers import VisualStudioCCompiler 146 return VisualStudioCCompiler.native_args_to_unix(args) 147 148 def rsp_file_syntax(self) -> RSPFileSyntax: 149 return RSPFileSyntax.MSVC 150 151 152class VisualStudioLinker(VisualStudioLikeLinker, StaticLinker): 153 154 """Microsoft's lib static linker.""" 155 156 def __init__(self, exelist: T.List[str], machine: str): 157 StaticLinker.__init__(self, exelist) 158 VisualStudioLikeLinker.__init__(self, machine) 159 160 161class IntelVisualStudioLinker(VisualStudioLikeLinker, StaticLinker): 162 163 """Intel's xilib static linker.""" 164 165 def __init__(self, exelist: T.List[str], machine: str): 166 StaticLinker.__init__(self, exelist) 167 VisualStudioLikeLinker.__init__(self, machine) 168 169 170class ArLikeLinker(StaticLinker): 171 # POSIX requires supporting the dash, GNU permits omitting it 172 std_args = ['-csr'] 173 174 def can_linker_accept_rsp(self) -> bool: 175 # armar / AIX can't accept arguments using the @rsp syntax 176 # in fact, only the 'ar' id can 177 return False 178 179 def get_std_link_args(self, is_thin: bool) -> T.List[str]: 180 return self.std_args 181 182 def get_output_args(self, target: str) -> T.List[str]: 183 return [target] 184 185 def rsp_file_syntax(self) -> RSPFileSyntax: 186 return RSPFileSyntax.GCC 187 188 189class ArLinker(ArLikeLinker): 190 id = 'ar' 191 192 def __init__(self, exelist: T.List[str]): 193 super().__init__(exelist) 194 stdo = mesonlib.Popen_safe(self.exelist + ['-h'])[1] 195 # Enable deterministic builds if they are available. 196 stdargs = 'csr' 197 thinargs = '' 198 if '[D]' in stdo: 199 stdargs += 'D' 200 if '[T]' in stdo: 201 thinargs = 'T' 202 self.std_args = [stdargs] 203 self.std_thin_args = [stdargs + thinargs] 204 self.can_rsp = '@<' in stdo 205 206 def can_linker_accept_rsp(self) -> bool: 207 return self.can_rsp 208 209 def get_std_link_args(self, is_thin: bool) -> T.List[str]: 210 # FIXME: osx ld rejects this: "file built for unknown-unsupported file format" 211 if is_thin and not mesonlib.is_osx(): 212 return self.std_thin_args 213 else: 214 return self.std_args 215 216 217class ArmarLinker(ArLikeLinker): 218 id = 'armar' 219 220 221class DLinker(StaticLinker): 222 def __init__(self, exelist: T.List[str], arch: str, *, rsp_syntax: RSPFileSyntax = RSPFileSyntax.GCC): 223 super().__init__(exelist) 224 self.id = exelist[0] 225 self.arch = arch 226 self.__rsp_syntax = rsp_syntax 227 228 def get_std_link_args(self, is_thin: bool) -> T.List[str]: 229 return ['-lib'] 230 231 def get_output_args(self, target: str) -> T.List[str]: 232 return ['-of=' + target] 233 234 def get_linker_always_args(self) -> T.List[str]: 235 if mesonlib.is_windows(): 236 if self.arch == 'x86_64': 237 return ['-m64'] 238 elif self.arch == 'x86_mscoff' and self.id == 'dmd': 239 return ['-m32mscoff'] 240 return ['-m32'] 241 return [] 242 243 def rsp_file_syntax(self) -> RSPFileSyntax: 244 return self.__rsp_syntax 245 246 247class CcrxLinker(StaticLinker): 248 249 def __init__(self, exelist: T.List[str]): 250 super().__init__(exelist) 251 self.id = 'rlink' 252 253 def can_linker_accept_rsp(self) -> bool: 254 return False 255 256 def get_output_args(self, target: str) -> T.List[str]: 257 return [f'-output={target}'] 258 259 def get_linker_always_args(self) -> T.List[str]: 260 return ['-nologo', '-form=library'] 261 262 263class Xc16Linker(StaticLinker): 264 265 def __init__(self, exelist: T.List[str]): 266 super().__init__(exelist) 267 self.id = 'xc16-ar' 268 269 def can_linker_accept_rsp(self) -> bool: 270 return False 271 272 def get_output_args(self, target: str) -> T.List[str]: 273 return [f'{target}'] 274 275 def get_linker_always_args(self) -> T.List[str]: 276 return ['rcs'] 277 278class CompCertLinker(StaticLinker): 279 280 def __init__(self, exelist: T.List[str]): 281 super().__init__(exelist) 282 self.id = 'ccomp' 283 284 def can_linker_accept_rsp(self) -> bool: 285 return False 286 287 def get_output_args(self, target: str) -> T.List[str]: 288 return [f'-o{target}'] 289 290 291class C2000Linker(StaticLinker): 292 293 def __init__(self, exelist: T.List[str]): 294 super().__init__(exelist) 295 self.id = 'ar2000' 296 297 def can_linker_accept_rsp(self) -> bool: 298 return False 299 300 def get_output_args(self, target: str) -> T.List[str]: 301 return [f'{target}'] 302 303 def get_linker_always_args(self) -> T.List[str]: 304 return ['-r'] 305 306 307class AIXArLinker(ArLikeLinker): 308 id = 'aixar' 309 std_args = ['-csr', '-Xany'] 310 311 312def prepare_rpaths(raw_rpaths: str, build_dir: str, from_dir: str) -> T.List[str]: 313 # The rpaths we write must be relative if they point to the build dir, 314 # because otherwise they have different length depending on the build 315 # directory. This breaks reproducible builds. 316 internal_format_rpaths = [evaluate_rpath(p, build_dir, from_dir) for p in raw_rpaths] 317 ordered_rpaths = order_rpaths(internal_format_rpaths) 318 return ordered_rpaths 319 320 321def order_rpaths(rpath_list: T.List[str]) -> T.List[str]: 322 # We want rpaths that point inside our build dir to always override 323 # those pointing to other places in the file system. This is so built 324 # binaries prefer our libraries to the ones that may lie somewhere 325 # in the file system, such as /lib/x86_64-linux-gnu. 326 # 327 # The correct thing to do here would be C++'s std::stable_partition. 328 # Python standard library does not have it, so replicate it with 329 # sort, which is guaranteed to be stable. 330 return sorted(rpath_list, key=os.path.isabs) 331 332 333def evaluate_rpath(p: str, build_dir: str, from_dir: str) -> str: 334 if p == from_dir: 335 return '' # relpath errors out in this case 336 elif os.path.isabs(p): 337 return p # These can be outside of build dir. 338 else: 339 return os.path.relpath(os.path.join(build_dir, p), os.path.join(build_dir, from_dir)) 340 341class DynamicLinker(metaclass=abc.ABCMeta): 342 343 """Base class for dynamic linkers.""" 344 345 _BUILDTYPE_ARGS = { 346 'plain': [], 347 'debug': [], 348 'debugoptimized': [], 349 'release': [], 350 'minsize': [], 351 'custom': [], 352 } # type: T.Dict[str, T.List[str]] 353 354 @abc.abstractproperty 355 def id(self) -> str: 356 pass 357 358 def _apply_prefix(self, arg: T.Union[str, T.List[str]]) -> T.List[str]: 359 args = [arg] if isinstance(arg, str) else arg 360 if self.prefix_arg is None: 361 return args 362 elif isinstance(self.prefix_arg, str): 363 return [self.prefix_arg + arg for arg in args] 364 ret = [] 365 for arg in args: 366 ret += self.prefix_arg + [arg] 367 return ret 368 369 def __init__(self, exelist: T.List[str], 370 for_machine: mesonlib.MachineChoice, prefix_arg: T.Union[str, T.List[str]], 371 always_args: T.List[str], *, version: str = 'unknown version'): 372 self.exelist = exelist 373 self.for_machine = for_machine 374 self.version = version 375 self.prefix_arg = prefix_arg 376 self.always_args = always_args 377 self.machine = None # type: T.Optional[str] 378 379 def __repr__(self) -> str: 380 return '<{}: v{} `{}`>'.format(type(self).__name__, self.version, ' '.join(self.exelist)) 381 382 def get_id(self) -> str: 383 return self.id 384 385 def get_version_string(self) -> str: 386 return f'({self.id} {self.version})' 387 388 def get_exelist(self) -> T.List[str]: 389 return self.exelist.copy() 390 391 def get_accepts_rsp(self) -> bool: 392 # rsp files are only used when building on Windows because we want to 393 # avoid issues with quoting and max argument length 394 return mesonlib.is_windows() 395 396 def rsp_file_syntax(self) -> RSPFileSyntax: 397 """The format of the RSP file that this compiler supports. 398 399 If `self.can_linker_accept_rsp()` returns True, then this needs to 400 be implemented 401 """ 402 return RSPFileSyntax.GCC 403 404 def get_always_args(self) -> T.List[str]: 405 return self.always_args.copy() 406 407 def get_lib_prefix(self) -> str: 408 return '' 409 410 # XXX: is use_ldflags a compiler or a linker attribute? 411 412 def get_option_args(self, options: 'KeyedOptionDictType') -> T.List[str]: 413 return [] 414 415 def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]: 416 raise EnvironmentException(f'Language {self.id} does not support has_multi_link_arguments.') 417 418 def get_debugfile_name(self, targetfile: str) -> str: 419 '''Name of debug file written out (see below)''' 420 return None 421 422 def get_debugfile_args(self, targetfile: str) -> T.List[str]: 423 """Some compilers (MSVC) write debug into a separate file. 424 425 This method takes the target object path and returns a list of 426 commands to append to the linker invocation to control where that 427 file is written. 428 """ 429 return [] 430 431 def get_std_shared_lib_args(self) -> T.List[str]: 432 return [] 433 434 def get_std_shared_module_args(self, options: 'KeyedOptionDictType') -> T.List[str]: 435 return self.get_std_shared_lib_args() 436 437 def get_pie_args(self) -> T.List[str]: 438 # TODO: this really needs to take a boolean and return the args to 439 # disable pie, otherwise it only acts to enable pie if pie *isn't* the 440 # default. 441 raise EnvironmentException(f'Linker {self.id} does not support position-independent executable') 442 443 def get_lto_args(self) -> T.List[str]: 444 return [] 445 446 def sanitizer_args(self, value: str) -> T.List[str]: 447 return [] 448 449 def get_buildtype_args(self, buildtype: str) -> T.List[str]: 450 # We can override these in children by just overriding the 451 # _BUILDTYPE_ARGS value. 452 return self._BUILDTYPE_ARGS[buildtype] 453 454 def get_asneeded_args(self) -> T.List[str]: 455 return [] 456 457 def get_link_whole_for(self, args: T.List[str]) -> T.List[str]: 458 raise EnvironmentException( 459 f'Linker {self.id} does not support link_whole') 460 461 def get_allow_undefined_args(self) -> T.List[str]: 462 raise EnvironmentException( 463 f'Linker {self.id} does not support allow undefined') 464 465 @abc.abstractmethod 466 def get_output_args(self, outname: str) -> T.List[str]: 467 pass 468 469 def get_coverage_args(self) -> T.List[str]: 470 raise EnvironmentException(f"Linker {self.id} doesn't implement coverage data generation.") 471 472 @abc.abstractmethod 473 def get_search_args(self, dirname: str) -> T.List[str]: 474 pass 475 476 def export_dynamic_args(self, env: 'Environment') -> T.List[str]: 477 return [] 478 479 def import_library_args(self, implibname: str) -> T.List[str]: 480 """The name of the outputted import library. 481 482 This implementation is used only on Windows by compilers that use GNU ld 483 """ 484 return [] 485 486 def thread_flags(self, env: 'Environment') -> T.List[str]: 487 return [] 488 489 def no_undefined_args(self) -> T.List[str]: 490 """Arguments to error if there are any undefined symbols at link time. 491 492 This is the inverse of get_allow_undefined_args(). 493 494 TODO: A future cleanup might merge this and 495 get_allow_undefined_args() into a single method taking a 496 boolean 497 """ 498 return [] 499 500 def fatal_warnings(self) -> T.List[str]: 501 """Arguments to make all warnings errors.""" 502 return [] 503 504 def headerpad_args(self) -> T.List[str]: 505 # Only used by the Apple linker 506 return [] 507 508 def get_gui_app_args(self, value: bool) -> T.List[str]: 509 # Only used by VisualStudioLikeLinkers 510 return [] 511 512 def get_win_subsystem_args(self, value: str) -> T.List[str]: 513 # Only used if supported by the dynamic linker and 514 # only when targeting Windows 515 return [] 516 517 def bitcode_args(self) -> T.List[str]: 518 raise MesonException('This linker does not support bitcode bundles') 519 520 def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, 521 rpath_paths: str, build_rpath: str, 522 install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]: 523 return ([], set()) 524 525 def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, 526 suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]: 527 return [] 528 529 530class PosixDynamicLinkerMixin: 531 532 """Mixin class for POSIX-ish linkers. 533 534 This is obviously a pretty small subset of the linker interface, but 535 enough dynamic linkers that meson supports are POSIX-like but not 536 GNU-like that it makes sense to split this out. 537 """ 538 539 def get_output_args(self, outname: str) -> T.List[str]: 540 return ['-o', outname] 541 542 def get_std_shared_lib_args(self) -> T.List[str]: 543 return ['-shared'] 544 545 def get_search_args(self, dirname: str) -> T.List[str]: 546 return ['-L' + dirname] 547 548 549class GnuLikeDynamicLinkerMixin: 550 551 """Mixin class for dynamic linkers that provides gnu-like interface. 552 553 This acts as a base for the GNU linkers (bfd and gold), LLVM's lld, and 554 other linkers like GNU-ld. 555 """ 556 557 if T.TYPE_CHECKING: 558 for_machine = MachineChoice.HOST 559 def _apply_prefix(self, arg: T.Union[str, T.List[str]]) -> T.List[str]: ... 560 561 _BUILDTYPE_ARGS = { 562 'plain': [], 563 'debug': [], 564 'debugoptimized': [], 565 'release': ['-O1'], 566 'minsize': [], 567 'custom': [], 568 } # type: T.Dict[str, T.List[str]] 569 570 def get_buildtype_args(self, buildtype: str) -> T.List[str]: 571 # We can override these in children by just overriding the 572 # _BUILDTYPE_ARGS value. 573 return mesonlib.listify([self._apply_prefix(a) for a in self._BUILDTYPE_ARGS[buildtype]]) 574 575 def get_pie_args(self) -> T.List[str]: 576 return ['-pie'] 577 578 def get_asneeded_args(self) -> T.List[str]: 579 return self._apply_prefix('--as-needed') 580 581 def get_link_whole_for(self, args: T.List[str]) -> T.List[str]: 582 if not args: 583 return args 584 return self._apply_prefix('--whole-archive') + args + self._apply_prefix('--no-whole-archive') 585 586 def get_allow_undefined_args(self) -> T.List[str]: 587 return self._apply_prefix('--allow-shlib-undefined') 588 589 def get_lto_args(self) -> T.List[str]: 590 return ['-flto'] 591 592 def sanitizer_args(self, value: str) -> T.List[str]: 593 if value == 'none': 594 return [] 595 return ['-fsanitize=' + value] 596 597 def get_coverage_args(self) -> T.List[str]: 598 return ['--coverage'] 599 600 def export_dynamic_args(self, env: 'Environment') -> T.List[str]: 601 m = env.machines[self.for_machine] 602 if m.is_windows() or m.is_cygwin(): 603 return self._apply_prefix('--export-all-symbols') 604 return self._apply_prefix('-export-dynamic') 605 606 def import_library_args(self, implibname: str) -> T.List[str]: 607 return self._apply_prefix('--out-implib=' + implibname) 608 609 def thread_flags(self, env: 'Environment') -> T.List[str]: 610 if env.machines[self.for_machine].is_haiku(): 611 return [] 612 return ['-pthread'] 613 614 def no_undefined_args(self) -> T.List[str]: 615 return self._apply_prefix('--no-undefined') 616 617 def fatal_warnings(self) -> T.List[str]: 618 return self._apply_prefix('--fatal-warnings') 619 620 def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, 621 suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]: 622 m = env.machines[self.for_machine] 623 if m.is_windows() or m.is_cygwin(): 624 # For PE/COFF the soname argument has no effect 625 return [] 626 sostr = '' if soversion is None else '.' + soversion 627 return self._apply_prefix(f'-soname,{prefix}{shlib_name}.{suffix}{sostr}') 628 629 def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, 630 rpath_paths: str, build_rpath: str, 631 install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]: 632 m = env.machines[self.for_machine] 633 if m.is_windows() or m.is_cygwin(): 634 return ([], set()) 635 if not rpath_paths and not install_rpath and not build_rpath: 636 return ([], set()) 637 args = [] 638 origin_placeholder = '$ORIGIN' 639 processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir) 640 # Need to deduplicate rpaths, as macOS's install_name_tool 641 # is *very* allergic to duplicate -delete_rpath arguments 642 # when calling depfixer on installation. 643 all_paths = mesonlib.OrderedSet([os.path.join(origin_placeholder, p) for p in processed_rpaths]) 644 rpath_dirs_to_remove = set() 645 for p in all_paths: 646 rpath_dirs_to_remove.add(p.encode('utf8')) 647 # Build_rpath is used as-is (it is usually absolute). 648 if build_rpath != '': 649 all_paths.add(build_rpath) 650 for p in build_rpath.split(':'): 651 rpath_dirs_to_remove.add(p.encode('utf8')) 652 653 # TODO: should this actually be "for (dragonfly|open)bsd"? 654 if mesonlib.is_dragonflybsd() or mesonlib.is_openbsd(): 655 # This argument instructs the compiler to record the value of 656 # ORIGIN in the .dynamic section of the elf. On Linux this is done 657 # by default, but is not on dragonfly/openbsd for some reason. Without this 658 # $ORIGIN in the runtime path will be undefined and any binaries 659 # linked against local libraries will fail to resolve them. 660 args.extend(self._apply_prefix('-z,origin')) 661 662 # In order to avoid relinking for RPATH removal, the binary needs to contain just 663 # enough space in the ELF header to hold the final installation RPATH. 664 paths = ':'.join(all_paths) 665 if len(paths) < len(install_rpath): 666 padding = 'X' * (len(install_rpath) - len(paths)) 667 if not paths: 668 paths = padding 669 else: 670 paths = paths + ':' + padding 671 args.extend(self._apply_prefix('-rpath,' + paths)) 672 673 # TODO: should this actually be "for solaris/sunos"? 674 if mesonlib.is_sunos(): 675 return (args, rpath_dirs_to_remove) 676 677 # Rpaths to use while linking must be absolute. These are not 678 # written to the binary. Needed only with GNU ld: 679 # https://sourceware.org/bugzilla/show_bug.cgi?id=16936 680 # Not needed on Windows or other platforms that don't use RPATH 681 # https://github.com/mesonbuild/meson/issues/1897 682 # 683 # In addition, this linker option tends to be quite long and some 684 # compilers have trouble dealing with it. That's why we will include 685 # one option per folder, like this: 686 # 687 # -Wl,-rpath-link,/path/to/folder1 -Wl,-rpath,/path/to/folder2 ... 688 # 689 # ...instead of just one single looooong option, like this: 690 # 691 # -Wl,-rpath-link,/path/to/folder1:/path/to/folder2:... 692 for p in rpath_paths: 693 args.extend(self._apply_prefix('-rpath-link,' + os.path.join(build_dir, p))) 694 695 return (args, rpath_dirs_to_remove) 696 697 def get_win_subsystem_args(self, value: str) -> T.List[str]: 698 if 'windows' in value: 699 args = ['--subsystem,windows'] 700 elif 'console' in value: 701 args = ['--subsystem,console'] 702 else: 703 raise MesonException(f'Only "windows" and "console" are supported for win_subsystem with MinGW, not "{value}".') 704 if ',' in value: 705 args[-1] = args[-1] + ':' + value.split(',')[1] 706 707 return self._apply_prefix(args) 708 709 710class AppleDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker): 711 712 """Apple's ld implementation.""" 713 714 id = 'ld64' 715 716 def get_asneeded_args(self) -> T.List[str]: 717 return self._apply_prefix('-dead_strip_dylibs') 718 719 def get_allow_undefined_args(self) -> T.List[str]: 720 return self._apply_prefix('-undefined,dynamic_lookup') 721 722 def get_std_shared_module_args(self, options: 'KeyedOptionDictType') -> T.List[str]: 723 return ['-bundle'] + self._apply_prefix('-undefined,dynamic_lookup') 724 725 def get_pie_args(self) -> T.List[str]: 726 return [] 727 728 def get_link_whole_for(self, args: T.List[str]) -> T.List[str]: 729 result = [] # type: T.List[str] 730 for a in args: 731 result.extend(self._apply_prefix('-force_load')) 732 result.append(a) 733 return result 734 735 def get_coverage_args(self) -> T.List[str]: 736 return ['--coverage'] 737 738 def sanitizer_args(self, value: str) -> T.List[str]: 739 if value == 'none': 740 return [] 741 return ['-fsanitize=' + value] 742 743 def no_undefined_args(self) -> T.List[str]: 744 return self._apply_prefix('-undefined,error') 745 746 def headerpad_args(self) -> T.List[str]: 747 return self._apply_prefix('-headerpad_max_install_names') 748 749 def bitcode_args(self) -> T.List[str]: 750 return self._apply_prefix('-bitcode_bundle') 751 752 def fatal_warnings(self) -> T.List[str]: 753 return self._apply_prefix('-fatal_warnings') 754 755 def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, 756 suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]: 757 install_name = ['@rpath/', prefix, shlib_name] 758 if soversion is not None: 759 install_name.append('.' + soversion) 760 install_name.append('.dylib') 761 args = ['-install_name', ''.join(install_name)] 762 if darwin_versions: 763 args.extend(['-compatibility_version', darwin_versions[0], 764 '-current_version', darwin_versions[1]]) 765 return args 766 767 def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, 768 rpath_paths: str, build_rpath: str, 769 install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]: 770 if not rpath_paths and not install_rpath and not build_rpath: 771 return ([], set()) 772 args = [] 773 # @loader_path is the equivalent of $ORIGIN on macOS 774 # https://stackoverflow.com/q/26280738 775 origin_placeholder = '@loader_path' 776 processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir) 777 all_paths = mesonlib.OrderedSet([os.path.join(origin_placeholder, p) for p in processed_rpaths]) 778 if build_rpath != '': 779 all_paths.add(build_rpath) 780 for rp in all_paths: 781 args.extend(self._apply_prefix('-rpath,' + rp)) 782 783 return (args, set()) 784 785 786class GnuDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, DynamicLinker): 787 788 """Representation of GNU ld.bfd and ld.gold.""" 789 790 def get_accepts_rsp(self) -> bool: 791 return True 792 793 794class GnuGoldDynamicLinker(GnuDynamicLinker): 795 796 id = 'ld.gold' 797 798 799class GnuBFDDynamicLinker(GnuDynamicLinker): 800 801 id = 'ld.bfd' 802 803 804class LLVMDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, DynamicLinker): 805 806 """Representation of LLVM's ld.lld linker. 807 808 This is only the gnu-like linker, not the apple like or link.exe like 809 linkers. 810 """ 811 812 id = 'ld.lld' 813 814 def __init__(self, exelist: T.List[str], 815 for_machine: mesonlib.MachineChoice, prefix_arg: T.Union[str, T.List[str]], 816 always_args: T.List[str], *, version: str = 'unknown version'): 817 super().__init__(exelist, for_machine, prefix_arg, always_args, version=version) 818 819 # Some targets don't seem to support this argument (windows, wasm, ...) 820 _, _, e = mesonlib.Popen_safe(self.exelist + self._apply_prefix('--allow-shlib-undefined')) 821 self.has_allow_shlib_undefined = 'unknown argument: --allow-shlib-undefined' not in e 822 823 def get_allow_undefined_args(self) -> T.List[str]: 824 if self.has_allow_shlib_undefined: 825 return self._apply_prefix('--allow-shlib-undefined') 826 return [] 827 828 829class WASMDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, DynamicLinker): 830 831 """Emscripten's wasm-ld.""" 832 833 id = 'ld.wasm' 834 835 def get_allow_undefined_args(self) -> T.List[str]: 836 return ['-s', 'ERROR_ON_UNDEFINED_SYMBOLS=0'] 837 838 def no_undefined_args(self) -> T.List[str]: 839 return ['-s', 'ERROR_ON_UNDEFINED_SYMBOLS=1'] 840 841 def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, 842 suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]: 843 raise MesonException(f'{self.id} does not support shared libraries.') 844 845 def get_asneeded_args(self) -> T.List[str]: 846 return [] 847 848 def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, 849 rpath_paths: str, build_rpath: str, 850 install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]: 851 return ([], set()) 852 853 854class CcrxDynamicLinker(DynamicLinker): 855 856 """Linker for Renesis CCrx compiler.""" 857 858 id = 'rlink' 859 860 def __init__(self, for_machine: mesonlib.MachineChoice, 861 *, version: str = 'unknown version'): 862 super().__init__(['rlink.exe'], for_machine, '', [], 863 version=version) 864 865 def get_accepts_rsp(self) -> bool: 866 return False 867 868 def get_lib_prefix(self) -> str: 869 return '-lib=' 870 871 def get_std_shared_lib_args(self) -> T.List[str]: 872 return [] 873 874 def get_output_args(self, outputname: str) -> T.List[str]: 875 return [f'-output={outputname}'] 876 877 def get_search_args(self, dirname: str) -> 'T.NoReturn': 878 raise OSError('rlink.exe does not have a search dir argument') 879 880 def get_allow_undefined_args(self) -> T.List[str]: 881 return [] 882 883 def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, 884 suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]: 885 return [] 886 887 888class Xc16DynamicLinker(DynamicLinker): 889 890 """Linker for Microchip XC16 compiler.""" 891 892 id = 'xc16-gcc' 893 894 def __init__(self, for_machine: mesonlib.MachineChoice, 895 *, version: str = 'unknown version'): 896 super().__init__(['xc16-gcc.exe'], for_machine, '', [], 897 version=version) 898 899 def get_link_whole_for(self, args: T.List[str]) -> T.List[str]: 900 if not args: 901 return args 902 return self._apply_prefix('--start-group') + args + self._apply_prefix('--end-group') 903 904 def get_accepts_rsp(self) -> bool: 905 return False 906 907 def get_lib_prefix(self) -> str: 908 return '' 909 910 def get_std_shared_lib_args(self) -> T.List[str]: 911 return [] 912 913 def get_output_args(self, outputname: str) -> T.List[str]: 914 return [f'-o{outputname}'] 915 916 def get_search_args(self, dirname: str) -> 'T.NoReturn': 917 raise OSError('xc16-gcc.exe does not have a search dir argument') 918 919 def get_allow_undefined_args(self) -> T.List[str]: 920 return [] 921 922 def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, 923 suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]: 924 return [] 925 926 def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, 927 rpath_paths: str, build_rpath: str, 928 install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]: 929 return ([], set()) 930 931class CompCertDynamicLinker(DynamicLinker): 932 933 """Linker for CompCert C compiler.""" 934 935 id = 'ccomp' 936 937 def __init__(self, for_machine: mesonlib.MachineChoice, 938 *, version: str = 'unknown version'): 939 super().__init__(['ccomp'], for_machine, '', [], 940 version=version) 941 942 def get_link_whole_for(self, args: T.List[str]) -> T.List[str]: 943 if not args: 944 return args 945 return self._apply_prefix('-Wl,--whole-archive') + args + self._apply_prefix('-Wl,--no-whole-archive') 946 947 def get_accepts_rsp(self) -> bool: 948 return False 949 950 def get_lib_prefix(self) -> str: 951 return '' 952 953 def get_std_shared_lib_args(self) -> T.List[str]: 954 return [] 955 956 def get_output_args(self, outputname: str) -> T.List[str]: 957 return [f'-o{outputname}'] 958 959 def get_search_args(self, dirname: str) -> T.List[str]: 960 return [f'-L{dirname}'] 961 962 def get_allow_undefined_args(self) -> T.List[str]: 963 return [] 964 965 def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, 966 suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]: 967 raise MesonException(f'{self.id} does not support shared libraries.') 968 969 def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, 970 rpath_paths: str, build_rpath: str, 971 install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]: 972 return ([], set()) 973 974class C2000DynamicLinker(DynamicLinker): 975 976 """Linker for Texas Instruments C2000 compiler.""" 977 978 id = 'cl2000' 979 980 def __init__(self, exelist: T.List[str], for_machine: mesonlib.MachineChoice, 981 *, version: str = 'unknown version'): 982 super().__init__(exelist or ['cl2000.exe'], for_machine, '', [], 983 version=version) 984 985 def get_link_whole_for(self, args: T.List[str]) -> T.List[str]: 986 if not args: 987 return args 988 return self._apply_prefix('--start-group') + args + self._apply_prefix('--end-group') 989 990 def get_accepts_rsp(self) -> bool: 991 return False 992 993 def get_lib_prefix(self) -> str: 994 return '-l=' 995 996 def get_std_shared_lib_args(self) -> T.List[str]: 997 return [] 998 999 def get_output_args(self, outputname: str) -> T.List[str]: 1000 return ['-z', f'--output_file={outputname}'] 1001 1002 def get_search_args(self, dirname: str) -> 'T.NoReturn': 1003 raise OSError('cl2000.exe does not have a search dir argument') 1004 1005 def get_allow_undefined_args(self) -> T.List[str]: 1006 return [] 1007 1008 def get_always_args(self) -> T.List[str]: 1009 return [] 1010 1011 1012class ArmDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker): 1013 1014 """Linker for the ARM compiler.""" 1015 1016 id = 'armlink' 1017 1018 def __init__(self, for_machine: mesonlib.MachineChoice, 1019 *, version: str = 'unknown version'): 1020 super().__init__(['armlink'], for_machine, '', [], 1021 version=version) 1022 1023 def get_accepts_rsp(self) -> bool: 1024 return False 1025 1026 def get_std_shared_lib_args(self) -> 'T.NoReturn': 1027 raise MesonException('The Arm Linkers do not support shared libraries') 1028 1029 def get_allow_undefined_args(self) -> T.List[str]: 1030 return [] 1031 1032 1033class ArmClangDynamicLinker(ArmDynamicLinker): 1034 1035 """Linker used with ARM's clang fork. 1036 1037 The interface is similar enough to the old ARM ld that it inherits and 1038 extends a few things as needed. 1039 """ 1040 1041 def export_dynamic_args(self, env: 'Environment') -> T.List[str]: 1042 return ['--export_dynamic'] 1043 1044 def import_library_args(self, implibname: str) -> T.List[str]: 1045 return ['--symdefs=' + implibname] 1046 1047class QualcommLLVMDynamicLinker(LLVMDynamicLinker): 1048 1049 """ARM Linker from Snapdragon LLVM ARM Compiler.""" 1050 1051 id = 'ld.qcld' 1052 1053 1054class NAGDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker): 1055 1056 """NAG Fortran linker, ld via gcc indirection. 1057 1058 Using nagfor -Wl,foo passes option foo to a backend gcc invocation. 1059 (This linking gathers the correct objects needed from the nagfor runtime 1060 system.) 1061 To pass gcc -Wl,foo options (i.e., to ld) one must apply indirection 1062 again: nagfor -Wl,-Wl,,foo 1063 """ 1064 1065 id = 'nag' 1066 1067 def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, 1068 rpath_paths: str, build_rpath: str, 1069 install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]: 1070 if not rpath_paths and not install_rpath and not build_rpath: 1071 return ([], set()) 1072 args = [] 1073 origin_placeholder = '$ORIGIN' 1074 processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir) 1075 all_paths = mesonlib.OrderedSet([os.path.join(origin_placeholder, p) for p in processed_rpaths]) 1076 if build_rpath != '': 1077 all_paths.add(build_rpath) 1078 for rp in all_paths: 1079 args.extend(self._apply_prefix('-Wl,-Wl,,-rpath,,' + rp)) 1080 1081 return (args, set()) 1082 1083 def get_allow_undefined_args(self) -> T.List[str]: 1084 return [] 1085 1086 def get_std_shared_lib_args(self) -> T.List[str]: 1087 from ..compilers import NAGFortranCompiler 1088 return NAGFortranCompiler.get_nagfor_quiet(self.version) + ['-Wl,-shared'] 1089 1090 1091class PGIDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker): 1092 1093 """PGI linker.""" 1094 1095 id = 'pgi' 1096 1097 def get_allow_undefined_args(self) -> T.List[str]: 1098 return [] 1099 1100 def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, 1101 suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]: 1102 return [] 1103 1104 def get_std_shared_lib_args(self) -> T.List[str]: 1105 # PGI -shared is Linux only. 1106 if mesonlib.is_windows(): 1107 return ['-Bdynamic', '-Mmakedll'] 1108 elif mesonlib.is_linux(): 1109 return ['-shared'] 1110 return [] 1111 1112 def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, 1113 rpath_paths: str, build_rpath: str, 1114 install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]: 1115 if not env.machines[self.for_machine].is_windows(): 1116 return (['-R' + os.path.join(build_dir, p) for p in rpath_paths], set()) 1117 return ([], set()) 1118 1119NvidiaHPC_DynamicLinker = PGIDynamicLinker 1120 1121 1122class PGIStaticLinker(StaticLinker): 1123 def __init__(self, exelist: T.List[str]): 1124 super().__init__(exelist) 1125 self.id = 'ar' 1126 self.std_args = ['-r'] 1127 1128 def get_std_link_args(self, is_thin: bool) -> T.List[str]: 1129 return self.std_args 1130 1131 def get_output_args(self, target: str) -> T.List[str]: 1132 return [target] 1133 1134NvidiaHPC_StaticLinker = PGIStaticLinker 1135 1136 1137class VisualStudioLikeLinkerMixin: 1138 1139 """Mixin class for for dynamic linkers that act like Microsoft's link.exe.""" 1140 1141 if T.TYPE_CHECKING: 1142 for_machine = MachineChoice.HOST 1143 def _apply_prefix(self, arg: T.Union[str, T.List[str]]) -> T.List[str]: ... 1144 1145 _BUILDTYPE_ARGS = { 1146 'plain': [], 1147 'debug': [], 1148 'debugoptimized': [], 1149 # The otherwise implicit REF and ICF linker optimisations are disabled by 1150 # /DEBUG. REF implies ICF. 1151 'release': ['/OPT:REF'], 1152 'minsize': ['/INCREMENTAL:NO', '/OPT:REF'], 1153 'custom': [], 1154 } # type: T.Dict[str, T.List[str]] 1155 1156 def __init__(self, exelist: T.List[str], for_machine: mesonlib.MachineChoice, 1157 prefix_arg: T.Union[str, T.List[str]], always_args: T.List[str], *, 1158 version: str = 'unknown version', direct: bool = True, machine: str = 'x86'): 1159 # There's no way I can find to make mypy understand what's going on here 1160 super().__init__(exelist, for_machine, prefix_arg, always_args, version=version) # type: ignore 1161 self.machine = machine 1162 self.direct = direct 1163 1164 def get_buildtype_args(self, buildtype: str) -> T.List[str]: 1165 return mesonlib.listify([self._apply_prefix(a) for a in self._BUILDTYPE_ARGS[buildtype]]) 1166 1167 def invoked_by_compiler(self) -> bool: 1168 return not self.direct 1169 1170 def get_output_args(self, outputname: str) -> T.List[str]: 1171 return self._apply_prefix(['/MACHINE:' + self.machine, '/OUT:' + outputname]) 1172 1173 def get_always_args(self) -> T.List[str]: 1174 parent = super().get_always_args() # type: ignore 1175 return self._apply_prefix('/nologo') + T.cast(T.List[str], parent) 1176 1177 def get_search_args(self, dirname: str) -> T.List[str]: 1178 return self._apply_prefix('/LIBPATH:' + dirname) 1179 1180 def get_std_shared_lib_args(self) -> T.List[str]: 1181 return self._apply_prefix('/DLL') 1182 1183 def get_debugfile_name(self, targetfile: str) -> str: 1184 basename = targetfile.rsplit('.', maxsplit=1)[0] 1185 return basename + '.pdb' 1186 1187 def get_debugfile_args(self, targetfile: str) -> T.List[str]: 1188 return self._apply_prefix(['/DEBUG', '/PDB:' + self.get_debugfile_name(targetfile)]) 1189 1190 def get_link_whole_for(self, args: T.List[str]) -> T.List[str]: 1191 # Only since VS2015 1192 args = mesonlib.listify(args) 1193 l = [] # T.List[str] 1194 for a in args: 1195 l.extend(self._apply_prefix('/WHOLEARCHIVE:' + a)) 1196 return l 1197 1198 def get_allow_undefined_args(self) -> T.List[str]: 1199 return [] 1200 1201 def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, 1202 suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]: 1203 return [] 1204 1205 def import_library_args(self, implibname: str) -> T.List[str]: 1206 """The command to generate the import library.""" 1207 return self._apply_prefix(['/IMPLIB:' + implibname]) 1208 1209 def rsp_file_syntax(self) -> RSPFileSyntax: 1210 return RSPFileSyntax.MSVC 1211 1212 1213class MSVCDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker): 1214 1215 """Microsoft's Link.exe.""" 1216 1217 id = 'link' 1218 1219 def __init__(self, for_machine: mesonlib.MachineChoice, always_args: T.List[str], *, 1220 exelist: T.Optional[T.List[str]] = None, 1221 prefix: T.Union[str, T.List[str]] = '', 1222 machine: str = 'x86', version: str = 'unknown version', 1223 direct: bool = True): 1224 super().__init__(exelist or ['link.exe'], for_machine, 1225 prefix, always_args, machine=machine, version=version, direct=direct) 1226 1227 def get_always_args(self) -> T.List[str]: 1228 return self._apply_prefix(['/nologo', '/release']) + super().get_always_args() 1229 1230 def get_gui_app_args(self, value: bool) -> T.List[str]: 1231 return self.get_win_subsystem_args("windows" if value else "console") 1232 1233 def get_win_subsystem_args(self, value: str) -> T.List[str]: 1234 return self._apply_prefix([f'/SUBSYSTEM:{value.upper()}']) 1235 1236 1237class ClangClDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker): 1238 1239 """Clang's lld-link.exe.""" 1240 1241 id = 'lld-link' 1242 1243 def __init__(self, for_machine: mesonlib.MachineChoice, always_args: T.List[str], *, 1244 exelist: T.Optional[T.List[str]] = None, 1245 prefix: T.Union[str, T.List[str]] = '', 1246 machine: str = 'x86', version: str = 'unknown version', 1247 direct: bool = True): 1248 super().__init__(exelist or ['lld-link.exe'], for_machine, 1249 prefix, always_args, machine=machine, version=version, direct=direct) 1250 1251 def get_output_args(self, outputname: str) -> T.List[str]: 1252 # If we're being driven indirectly by clang just skip /MACHINE 1253 # as clang's target triple will handle the machine selection 1254 if self.machine is None: 1255 return self._apply_prefix([f"/OUT:{outputname}"]) 1256 1257 return super().get_output_args(outputname) 1258 1259 def get_gui_app_args(self, value: bool) -> T.List[str]: 1260 return self.get_win_subsystem_args("windows" if value else "console") 1261 1262 def get_win_subsystem_args(self, value: str) -> T.List[str]: 1263 return self._apply_prefix([f'/SUBSYSTEM:{value.upper()}']) 1264 1265 1266class XilinkDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker): 1267 1268 """Intel's Xilink.exe.""" 1269 1270 id = 'xilink' 1271 1272 def __init__(self, for_machine: mesonlib.MachineChoice, always_args: T.List[str], *, 1273 exelist: T.Optional[T.List[str]] = None, 1274 prefix: T.Union[str, T.List[str]] = '', 1275 machine: str = 'x86', version: str = 'unknown version', 1276 direct: bool = True): 1277 super().__init__(['xilink.exe'], for_machine, '', always_args, version=version) 1278 1279 def get_gui_app_args(self, value: bool) -> T.List[str]: 1280 return self.get_win_subsystem_args("windows" if value else "console") 1281 1282 def get_win_subsystem_args(self, value: str) -> T.List[str]: 1283 return self._apply_prefix([f'/SUBSYSTEM:{value.upper()}']) 1284 1285 1286class SolarisDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker): 1287 1288 """Sys-V derived linker used on Solaris and OpenSolaris.""" 1289 1290 id = 'ld.solaris' 1291 1292 def get_link_whole_for(self, args: T.List[str]) -> T.List[str]: 1293 if not args: 1294 return args 1295 return self._apply_prefix('--whole-archive') + args + self._apply_prefix('--no-whole-archive') 1296 1297 def get_pie_args(self) -> T.List[str]: 1298 # Available in Solaris 11.2 and later 1299 pc, stdo, stde = mesonlib.Popen_safe(self.exelist + self._apply_prefix('-zhelp')) 1300 for line in (stdo + stde).split('\n'): 1301 if '-z type' in line: 1302 if 'pie' in line: 1303 return ['-z', 'type=pie'] 1304 break 1305 return [] 1306 1307 def get_asneeded_args(self) -> T.List[str]: 1308 return self._apply_prefix(['-z', 'ignore']) 1309 1310 def no_undefined_args(self) -> T.List[str]: 1311 return ['-z', 'defs'] 1312 1313 def get_allow_undefined_args(self) -> T.List[str]: 1314 return ['-z', 'nodefs'] 1315 1316 def fatal_warnings(self) -> T.List[str]: 1317 return ['-z', 'fatal-warnings'] 1318 1319 def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, 1320 rpath_paths: str, build_rpath: str, 1321 install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]: 1322 if not rpath_paths and not install_rpath and not build_rpath: 1323 return ([], set()) 1324 processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir) 1325 all_paths = mesonlib.OrderedSet([os.path.join('$ORIGIN', p) for p in processed_rpaths]) 1326 rpath_dirs_to_remove = set() 1327 for p in all_paths: 1328 rpath_dirs_to_remove.add(p.encode('utf8')) 1329 if build_rpath != '': 1330 all_paths.add(build_rpath) 1331 for p in build_rpath.split(':'): 1332 rpath_dirs_to_remove.add(p.encode('utf8')) 1333 1334 # In order to avoid relinking for RPATH removal, the binary needs to contain just 1335 # enough space in the ELF header to hold the final installation RPATH. 1336 paths = ':'.join(all_paths) 1337 if len(paths) < len(install_rpath): 1338 padding = 'X' * (len(install_rpath) - len(paths)) 1339 if not paths: 1340 paths = padding 1341 else: 1342 paths = paths + ':' + padding 1343 return (self._apply_prefix(f'-rpath,{paths}'), rpath_dirs_to_remove) 1344 1345 def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, 1346 suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]: 1347 sostr = '' if soversion is None else '.' + soversion 1348 return self._apply_prefix(f'-soname,{prefix}{shlib_name}.{suffix}{sostr}') 1349 1350 1351class AIXDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker): 1352 1353 """Sys-V derived linker used on AIX""" 1354 1355 id = 'ld.aix' 1356 1357 def get_always_args(self) -> T.List[str]: 1358 return self._apply_prefix(['-bnoipath', '-bbigtoc']) + super().get_always_args() 1359 1360 def no_undefined_args(self) -> T.List[str]: 1361 return self._apply_prefix(['-bernotok']) 1362 1363 def get_allow_undefined_args(self) -> T.List[str]: 1364 return self._apply_prefix(['-berok']) 1365 1366 def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, 1367 rpath_paths: str, build_rpath: str, 1368 install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]: 1369 all_paths = mesonlib.OrderedSet() # type: mesonlib.OrderedSet[str] 1370 # install_rpath first, followed by other paths, and the system path last 1371 if install_rpath != '': 1372 all_paths.add(install_rpath) 1373 if build_rpath != '': 1374 all_paths.add(build_rpath) 1375 for p in rpath_paths: 1376 all_paths.add(os.path.join(build_dir, p)) 1377 # We should consider allowing the $LIBPATH environment variable 1378 # to override sys_path. 1379 sys_path = env.get_compiler_system_dirs(self.for_machine) 1380 if len(sys_path) == 0: 1381 # get_compiler_system_dirs doesn't support our compiler. 1382 # Use the default system library path 1383 all_paths.update(['/usr/lib', '/lib']) 1384 else: 1385 # Include the compiler's default library paths, but filter out paths that don't exist 1386 for p in sys_path: 1387 if os.path.isdir(p): 1388 all_paths.add(p) 1389 return (self._apply_prefix('-blibpath:' + ':'.join(all_paths)), set()) 1390 1391 def thread_flags(self, env: 'Environment') -> T.List[str]: 1392 return ['-pthread'] 1393 1394 1395class OptlinkDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker): 1396 1397 """Digital Mars dynamic linker for windows.""" 1398 1399 id = 'optlink' 1400 1401 def __init__(self, exelist: T.List[str], for_machine: mesonlib.MachineChoice, 1402 *, version: str = 'unknown version'): 1403 # Use optlink instead of link so we don't interfer with other link.exe 1404 # implementations. 1405 super().__init__(exelist, for_machine, '', [], version=version) 1406 1407 def get_allow_undefined_args(self) -> T.List[str]: 1408 return [] 1409 1410 def get_debugfile_args(self, targetfile: str) -> T.List[str]: 1411 # Optlink does not generate pdb files. 1412 return [] 1413 1414 def get_always_args(self) -> T.List[str]: 1415 return [] 1416 1417 1418class CudaLinker(PosixDynamicLinkerMixin, DynamicLinker): 1419 """Cuda linker (nvlink)""" 1420 1421 id = 'nvlink' 1422 1423 @staticmethod 1424 def parse_version() -> str: 1425 version_cmd = ['nvlink', '--version'] 1426 try: 1427 _, out, _ = mesonlib.Popen_safe(version_cmd) 1428 except OSError: 1429 return 'unknown version' 1430 # Output example: 1431 # nvlink: NVIDIA (R) Cuda linker 1432 # Copyright (c) 2005-2018 NVIDIA Corporation 1433 # Built on Sun_Sep_30_21:09:22_CDT_2018 1434 # Cuda compilation tools, release 10.0, V10.0.166 1435 # we need the most verbose version output. Luckily starting with V 1436 return out.strip().split('V')[-1] 1437 1438 def get_accepts_rsp(self) -> bool: 1439 # nvcc does not support response files 1440 return False 1441 1442 def get_lib_prefix(self) -> str: 1443 # nvcc doesn't recognize Meson's default .a extension for static libraries on 1444 # Windows and passes it to cl as an object file, resulting in 'warning D9024 : 1445 # unrecognized source file type 'xxx.a', object file assumed'. 1446 # 1447 # nvcc's --library= option doesn't help: it takes the library name without the 1448 # extension and assumes that the extension on Windows is .lib; prefixing the 1449 # library with -Xlinker= seems to work. 1450 # 1451 # On Linux, we have to use rely on -Xlinker= too, since nvcc/nvlink chokes on 1452 # versioned shared libraries: 1453 # 1454 # nvcc fatal : Don't know what to do with 'subprojects/foo/libbar.so.0.1.2' 1455 # 1456 from ..compilers import CudaCompiler 1457 return CudaCompiler.LINKER_PREFIX 1458 1459 def fatal_warnings(self) -> T.List[str]: 1460 return ['--warning-as-error'] 1461 1462 def get_allow_undefined_args(self) -> T.List[str]: 1463 return [] 1464 1465 def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, 1466 suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]: 1467 return [] 1468