diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py index 090c1ab94..38a938f24 100644 --- a/mesonbuild/compilers/cuda.py +++ b/mesonbuild/compilers/cuda.py @@ -45,7 +45,7 @@ cuda_debug_args: T.Dict[bool, T.List[str]] = { } -class _Phase(enum.Enum): +class Phase(enum.Enum): COMPILER = 'compiler' LINKER = 'linker' @@ -309,14 +309,14 @@ class CudaCompiler(Compiler): raise ValueError("-Xcompiler flag merging failed, unknown argument form!") return xflags - def _to_host_flags(self, flags: T.List[str], phase: _Phase = _Phase.COMPILER) -> T.List[str]: + @classmethod + def to_host_flags_base(cls, flags: T.List[str], phase: Phase = Phase.COMPILER, default_include_dirs: T.Optional[T.List[str]] = None) -> T.List[str]: """ Translate generic "GCC-speak" plus particular "NVCC-speak" flags to NVCC flags. NVCC's "short" flags have broad similarities to the GCC standard, but have gratuitous, irritating differences. """ - xflags = [] flagit = iter(flags) @@ -371,7 +371,7 @@ class CudaCompiler(Compiler): # an exception for -D (where this would be value-changing) and -U (because # it isn't possible to define a macro with a comma in the name). - if flag in self._FLAG_PASSTHRU_NOARGS: + if flag in cls._FLAG_PASSTHRU_NOARGS: xflags.append(flag) continue @@ -404,16 +404,16 @@ class CudaCompiler(Compiler): else: # -Isomething val = flag[2:] flag = flag[:2] # -I - elif flag in self._FLAG_LONG2SHORT_WITHARGS or \ - flag in self._FLAG_SHORT2LONG_WITHARGS: + elif flag in cls._FLAG_LONG2SHORT_WITHARGS or \ + flag in cls._FLAG_SHORT2LONG_WITHARGS: # This is either -o or a multi-letter flag, and it is receiving its # value isolated. try: val = next(flagit) # -o something except StopIteration: pass - elif flag.split('=', 1)[0] in self._FLAG_LONG2SHORT_WITHARGS or \ - flag.split('=', 1)[0] in self._FLAG_SHORT2LONG_WITHARGS: + elif flag.split('=', 1)[0] in cls._FLAG_LONG2SHORT_WITHARGS or \ + flag.split('=', 1)[0] in cls._FLAG_SHORT2LONG_WITHARGS: # This is either -o or a multi-letter flag, and it is receiving its # value after an = sign. flag, val = flag.split('=', 1) # -o=something @@ -442,14 +442,14 @@ class CudaCompiler(Compiler): xflags.append('-prec-div=true') xflags.append('-Xcompiler='+flag) else: - xflags.append('-Xcompiler='+self._shield_nvcc_list_arg(flag)) + xflags.append('-Xcompiler='+cls._shield_nvcc_list_arg(flag)) # The above should securely handle GCC's -Wl, -Wa, -Wp, arguments. continue assert val is not None # Should only trip if there is a missing argument. # Take care of the various NVCC-supported flags that need special handling. - flag = self._FLAG_LONG2SHORT_WITHARGS.get(flag, flag) + flag = cls._FLAG_LONG2SHORT_WITHARGS.get(flag, flag) if flag in {'-include', '-isystem', '-I', '-L', '-l'}: # These flags are known to GCC, but list-valued in NVCC. They potentially @@ -461,14 +461,14 @@ class CudaCompiler(Compiler): # -U with comma arguments is impossible in GCC-speak (and thus unambiguous #in NVCC-speak, albeit unportable). if len(flag) == 2: - xflags.append(flag+self._shield_nvcc_list_arg(val)) - elif flag == '-isystem' and val in self.host_compiler.get_default_include_dirs(): + xflags.append(flag+cls._shield_nvcc_list_arg(val)) + elif flag == '-isystem' and default_include_dirs is not None and val in default_include_dirs: # like GnuLikeCompiler, we have to filter out include directories specified # with -isystem that overlap with the host compiler's search path pass else: xflags.append(flag) - xflags.append(self._shield_nvcc_list_arg(val)) + xflags.append(cls._shield_nvcc_list_arg(val)) elif flag == '-O': # Handle optimization levels GCC knows about that NVCC does not. if val == 'fast': @@ -489,13 +489,16 @@ class CudaCompiler(Compiler): xflags.append(flag) xflags.append(val) - return self._merge_flags(xflags) + return cls._merge_flags(xflags) + + def _to_host_flags(self, flags: T.List[str], phase: Phase = Phase.COMPILER) -> T.List[str]: + return self.to_host_flags_base(flags, phase, self.host_compiler.get_default_include_dirs()) def needs_static_linker(self) -> bool: return False def thread_link_flags(self, environment: 'Environment') -> T.List[str]: - return self._to_host_flags(self.host_compiler.thread_link_flags(environment), _Phase.LINKER) + return self._to_host_flags(self.host_compiler.thread_link_flags(environment), Phase.LINKER) def sanity_check(self, work_dir: str, env: 'Environment') -> None: mlog.debug('Sanity testing ' + self.get_display_language() + ' compiler:', ' '.join(self.exelist)) @@ -684,13 +687,13 @@ class CudaCompiler(Compiler): def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: args = self.get_ccbin_args(options) - return args + self._to_host_flags(self.host_compiler.get_option_link_args(self._to_host_compiler_options(options)), _Phase.LINKER) + return args + self._to_host_flags(self.host_compiler.get_option_link_args(self._to_host_compiler_options(options)), Phase.LINKER) def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]: return self._to_host_flags(self.host_compiler.get_soname_args( - env, prefix, shlib_name, suffix, soversion, darwin_versions), _Phase.LINKER) + env, prefix, shlib_name, suffix, soversion, darwin_versions), Phase.LINKER) def get_compile_only_args(self) -> T.List[str]: return ['-c'] @@ -729,20 +732,20 @@ class CudaCompiler(Compiler): return self._to_host_flags(self.host_compiler.get_compile_debugfile_args(rel_obj, pch)) def get_link_debugfile_args(self, targetfile: str) -> T.List[str]: - return self._to_host_flags(self.host_compiler.get_link_debugfile_args(targetfile), _Phase.LINKER) + return self._to_host_flags(self.host_compiler.get_link_debugfile_args(targetfile), Phase.LINKER) def get_depfile_suffix(self) -> str: return 'd' def get_optimization_link_args(self, optimization_level: str) -> T.List[str]: - return self._to_host_flags(self.host_compiler.get_optimization_link_args(optimization_level), _Phase.LINKER) + return self._to_host_flags(self.host_compiler.get_optimization_link_args(optimization_level), Phase.LINKER) def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, rpath_paths: T.Tuple[str, ...], build_rpath: str, install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]: (rpath_args, rpath_dirs_to_remove) = self.host_compiler.build_rpath_args( env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath) - return (self._to_host_flags(rpath_args, _Phase.LINKER), rpath_dirs_to_remove) + return (self._to_host_flags(rpath_args, Phase.LINKER), rpath_dirs_to_remove) def linker_to_compiler_args(self, args: T.List[str]) -> T.List[str]: return args @@ -767,7 +770,7 @@ class CudaCompiler(Compiler): return [] def get_std_exe_link_args(self) -> T.List[str]: - return self._to_host_flags(self.host_compiler.get_std_exe_link_args(), _Phase.LINKER) + return self._to_host_flags(self.host_compiler.get_std_exe_link_args(), Phase.LINKER) def find_library(self, libname: str, env: 'Environment', extra_dirs: T.List[str], libtype: LibType = LibType.PREFER_SHARED, lib_prefix_warning: bool = True) -> T.Optional[T.List[str]]: @@ -783,16 +786,16 @@ class CudaCompiler(Compiler): host_crt_compile_args = self.host_compiler.get_crt_compile_args(crt_val, buildtype) if any(arg in {'/MDd', '/MD', '/MTd'} for arg in host_crt_compile_args): host_link_arg_overrides += ['/NODEFAULTLIB:LIBCMT.lib'] - return self._to_host_flags(host_link_arg_overrides + self.host_compiler.get_crt_link_args(crt_val, buildtype), _Phase.LINKER) + return self._to_host_flags(host_link_arg_overrides + self.host_compiler.get_crt_link_args(crt_val, buildtype), Phase.LINKER) def get_target_link_args(self, target: 'BuildTarget') -> T.List[str]: - return self._to_host_flags(super().get_target_link_args(target), _Phase.LINKER) + return self._to_host_flags(super().get_target_link_args(target), Phase.LINKER) def get_dependency_compile_args(self, dep: 'Dependency') -> T.List[str]: return self._to_host_flags(super().get_dependency_compile_args(dep)) def get_dependency_link_args(self, dep: 'Dependency') -> T.List[str]: - return self._to_host_flags(super().get_dependency_link_args(dep), _Phase.LINKER) + return self._to_host_flags(super().get_dependency_link_args(dep), Phase.LINKER) def get_ccbin_args(self, ccoptions: 'KeyedOptionDictType') -> T.List[str]: key = self.form_compileropt_key('ccbindir') diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py index 0a95f90dd..22c5cb5aa 100644 --- a/mesonbuild/compilers/detect.py +++ b/mesonbuild/compilers/detect.py @@ -616,7 +616,8 @@ def detect_cpp_compiler(env: 'Environment', for_machine: MachineChoice) -> Compi return _detect_c_or_cpp_compiler(env, 'cpp', for_machine) def detect_cuda_compiler(env: 'Environment', for_machine: MachineChoice) -> Compiler: - from .cuda import CudaCompiler + from .cuda import CudaCompiler, Phase + from ..options import OptionKey from ..linkers.linkers import CudaLinker popen_exceptions = {} is_cross = env.is_cross_build(for_machine) @@ -648,6 +649,12 @@ def detect_cuda_compiler(env: 'Environment', for_machine: MachineChoice) -> Comp cpp_compiler = detect_cpp_compiler(env, for_machine) cls = CudaCompiler env.coredata.add_lang_args(cls.language, cls, for_machine, env) + key = OptionKey('cuda_link_args', machine=for_machine) + if key in env.options: + # To fix LDFLAGS issue + val = env.options[key] + assert isinstance(val, list) + env.coredata.set_options({key: cls.to_host_flags_base(val, Phase.LINKER)}) linker = CudaLinker(compiler, for_machine, CudaCompiler.LINKER_PREFIX, [], version=CudaLinker.parse_version()) return cls(ccache, compiler, version, for_machine, is_cross, host_compiler=cpp_compiler, info=info, linker=linker) raise EnvironmentException(f'Could not find suitable CUDA compiler: "{"; ".join([" ".join(c) for c in compilers])}"')