aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/compilers/cuda.py
diff options
context:
space:
mode:
Diffstat (limited to 'mesonbuild/compilers/cuda.py')
-rw-r--r--mesonbuild/compilers/cuda.py119
1 files changed, 101 insertions, 18 deletions
diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py
index 57935d8..f6f78f1 100644
--- a/mesonbuild/compilers/cuda.py
+++ b/mesonbuild/compilers/cuda.py
@@ -14,9 +14,11 @@
import os.path
import typing
+from functools import partial
+from .. import coredata
from .. import mlog
-from ..mesonlib import EnvironmentException, MachineChoice, Popen_safe
+from ..mesonlib import EnvironmentException, MachineChoice, Popen_safe, OptionOverrideProxy, is_windows
from .compilers import (Compiler, cuda_buildtype_args, cuda_optimization_args,
cuda_debug_args)
@@ -28,19 +30,29 @@ class CudaCompiler(Compiler):
LINKER_PREFIX = '-Xlinker='
- def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwargs):
+ _universal_flags = {'compiler': ['-I', '-D', '-U', '-E'], 'linker': ['-l', '-L']}
+
+ def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrapper, host_compiler, **kwargs):
if not hasattr(self, 'language'):
self.language = 'cuda'
super().__init__(exelist, version, for_machine, **kwargs)
self.is_cross = is_cross
self.exe_wrapper = exe_wrapper
+ self.host_compiler = host_compiler
+ self.base_options = host_compiler.base_options
self.id = 'nvcc'
- default_warn_args = []
- self.warn_args = {'0': [],
- '1': default_warn_args,
- '2': default_warn_args + ['-Xcompiler=-Wextra'],
- '3': default_warn_args + ['-Xcompiler=-Wextra',
- '-Xcompiler=-Wpedantic']}
+ self.warn_args = {level: self._to_host_flags(flags) for level, flags in host_compiler.warn_args.items()}
+
+ @classmethod
+ def _to_host_flags(cls, flags, phase='compiler'):
+ return list(map(partial(cls._to_host_flag, phase=phase), flags))
+
+ @classmethod
+ def _to_host_flag(cls, flag, phase):
+ if not flag[0] in ['-', '/'] or flag[:2] in cls._universal_flags[phase]:
+ return flag
+
+ return '-X{}={}'.format(phase, flag)
def needs_static_linker(self):
return False
@@ -55,7 +67,7 @@ class CudaCompiler(Compiler):
return []
def thread_link_flags(self, environment):
- return self._cook_link_args(super().thread_link_flags())
+ return self._to_host_flags(self.host_compiler.thread_link_flags(environment))
def sanity_check(self, work_dir, environment):
mlog.debug('Sanity testing ' + self.get_display_language() + ' compiler:', ' '.join(self.exelist))
@@ -163,16 +175,48 @@ class CudaCompiler(Compiler):
int main () {{ return 0; }}'''
return self.compiles(t.format(**fargs), env, extra_args, dependencies)
- @staticmethod
- def _cook_link_args(args: typing.List[str]) -> typing.List[str]:
- """Fixup arguments."""
- return [a.replace(' ', '\\') for a in args]
+ def get_options(self):
+ opts = super().get_options()
+ opts.update({'cuda_std': coredata.UserComboOption('C++ language standard to use',
+ ['none', 'c++03', 'c++11', 'c++14'],
+ 'none')})
+ return opts
+
+ def _to_host_compiler_options(self, options):
+ overrides = {name: opt.value for name, opt in options.copy().items()}
+ return OptionOverrideProxy(overrides, self.host_compiler.get_options())
+
+ def get_option_compile_args(self, options):
+ args = []
+ # On Windows, the version of the C++ standard used by nvcc is dictated by
+ # the combination of CUDA version and MSVC verion; the --std= is thus ignored
+ # and attempting to use it will result in a warning: https://stackoverflow.com/a/51272091/741027
+ if not is_windows():
+ std = options['cuda_std']
+ if std.value != 'none':
+ args.append('--std=' + std.value)
+
+ return args + self._to_host_flags(self.host_compiler.get_option_compile_args(self._to_host_compiler_options(options)))
+
+ @classmethod
+ def _cook_link_args(cls, args: typing.List[str]) -> typing.List[str]:
+ # Prepare link args for nvcc
+ cooked = [] # type: typing.List[str]
+ for arg in args:
+ if arg.startswith('-Wl,'): # strip GNU-style -Wl prefix
+ arg = arg.replace('-Wl,', '', 1)
+ arg = arg.replace(' ', '\\') # espace whitespace
+ cooked.append(arg)
+ return cls._to_host_flags(cooked, 'linker')
+
+ def get_option_link_args(self, options):
+ return self._cook_link_args(self.host_compiler.get_option_link_args(self._to_host_compiler_options(options)))
def name_string(self):
return ' '.join(self.exelist)
def get_soname_args(self, *args):
- return self._cook_link_args(super().get_soname_args(*args))
+ return self._cook_link_args(self.host_compiler.get_soname_args(*args))
def get_dependency_gen_args(self, outtarget, outfile):
return []
@@ -184,6 +228,9 @@ class CudaCompiler(Compiler):
return ['-O0']
def get_optimization_args(self, optimization_level):
+ # alternatively, consider simply redirecting this to the host compiler, which would
+ # give us more control over options like "optimize for space" (which nvcc doesn't support):
+ # return self._to_host_flags(self.host_compiler.get_optimization_args(optimization_level))
return cuda_optimization_args[optimization_level]
def get_debug_args(self, is_debug):
@@ -196,30 +243,45 @@ class CudaCompiler(Compiler):
return self.warn_args[level]
def get_buildtype_args(self, buildtype):
- return cuda_buildtype_args[buildtype]
+ # nvcc doesn't support msvc's "Edit and Continue" PDB format; "downgrade" to
+ # a regular PDB to avoid cl's warning to that effect (D9025 : overriding '/ZI' with '/Zi')
+ host_args = ['/Zi' if arg == '/ZI' else arg for arg in self.host_compiler.get_buildtype_args(buildtype)]
+ return cuda_buildtype_args[buildtype] + self._to_host_flags(host_args)
def get_include_args(self, path, is_system):
if path == '':
path = '.'
return ['-I' + path]
+ def get_compile_debugfile_args(self, rel_obj, **kwargs):
+ return self._to_host_flags(self.host_compiler.get_compile_debugfile_args(rel_obj, **kwargs))
+
+ def get_link_debugfile_args(self, targetfile):
+ return self._cook_link_args(self.host_compiler.get_link_debugfile_args(targetfile))
+
def depfile_for_object(self, objfile):
return objfile + '.' + self.get_depfile_suffix()
def get_depfile_suffix(self):
return 'd'
+ def get_linker_debug_crt_args(self) -> typing.List[str]:
+ return self._cook_link_args(self.host_compiler.get_linker_debug_crt_args())
+
+ def get_buildtype_linker_args(self, buildtype):
+ return self._cook_link_args(self.host_compiler.get_buildtype_linker_args(buildtype))
+
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str,
install_rpath: str) -> typing.List[str]:
- return self._cook_link_args(super().build_rpath_args(
+ return self._cook_link_args(self.host_compiler.build_rpath_args(
env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath))
def linker_to_compiler_args(self, args):
return args
def get_pic_args(self):
- return ['-Xcompiler=-fPIC']
+ return self._to_host_flags(self.host_compiler.get_pic_args())
def compute_parameters_with_absolute_paths(self, parameter_list, build_dir):
return []
@@ -228,4 +290,25 @@ class CudaCompiler(Compiler):
return ['-o', target]
def get_std_exe_link_args(self) -> typing.List[str]:
- return []
+ return self._cook_link_args(self.host_compiler.get_std_exe_link_args())
+
+ def get_crt_compile_args(self, crt_val, buildtype):
+ return self._to_host_flags(self.host_compiler.get_crt_compile_args(crt_val, buildtype))
+
+ def get_crt_link_args(self, crt_val, buildtype):
+ # nvcc defaults to static, release version of msvc runtime and provides no
+ # native option to override it; override it with /NODEFAULTLIB
+ host_link_arg_overrides = []
+ 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._cook_link_args(host_link_arg_overrides + self.host_compiler.get_crt_link_args(crt_val, buildtype))
+
+ def get_target_link_args(self, target):
+ return self._cook_link_args(super().get_target_link_args(target))
+
+ def get_dependency_compile_args(self, dep):
+ return self._to_host_flags(super().get_dependency_compile_args(dep))
+
+ def get_dependency_link_args(self, dep):
+ return self._cook_link_args(super().get_dependency_link_args(dep))