Repository: mesonbuild/meson

Issue:
Undefined references to UBSan when linking CUDA project with `b_sanitize=undefined`
**Describe the bug**
Hi, as a follow-up to https://github.com/mesonbuild/meson/issues/8337, I've noticed that when I enable UBSan for my project (`-Db_sanitize=undefined`), nvcc is fails to link the executables, producing lots of error about undefined references from libubsan. My current workaround is to add the followin snippet to meson.build:

```
  if get_option('b_sanitize') == 'undefined'
    add_project_link_arguments('-lubsan', language: 'cuda')
  endif
```

This isn't sth that is a blocker for me or very problematic because the workaround is very simple, just giving you a heads up; @obilaniu would you care to take a look? 

**To Reproduce**
Use the same project that was included with https://github.com/mesonbuild/meson/issues/8337, just add `-Db_sanitize=undefined` to `meson setup` invocation.

**Expected behavior**
Project linking without errors.

**system parameters**
* Native build
* Ubuntu 18.04, gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0, Ubuntu packages: cuda-10-0, libboost-all-dev
* Python 3.6.9
* meson 0.56.1
* ninja 1.8.2


Discussion:

Resolving patch:
diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py
--- a/mesonbuild/compilers/cuda.py
+++ b/mesonbuild/compilers/cuda.py
@@ -625,6 +625,12 @@ def get_optimization_args(self, optimization_level: str) -> T.List[str]:
         # return self._to_host_flags(self.host_compiler.get_optimization_args(optimization_level))
         return cuda_optimization_args[optimization_level]
 
+    def sanitizer_compile_args(self, value: str) -> T.List[str]:
+        return self._to_host_flags(self.host_compiler.sanitizer_compile_args(value))
+
+    def sanitizer_link_args(self, value: str) -> T.List[str]:
+        return self._to_host_flags(self.host_compiler.sanitizer_link_args(value))
+
     def get_debug_args(self, is_debug: bool) -> T.List[str]:
         return cuda_debug_args[is_debug]
 


Test patch:
diff --git a/test cases/cuda/15 sanitizer/meson.build b/test cases/cuda/15 sanitizer/meson.build
new file mode 100644
--- /dev/null
+++ b/test cases/cuda/15 sanitizer/meson.build	
@@ -0,0 +1,4 @@
+project('simple', 'cuda', version : '1.0.0',
+        default_options: ['b_sanitize=address,undefined'])
+
+libtests = shared_library('tests', 'prog.cu')
diff --git a/test cases/cuda/15 sanitizer/prog.cu b/test cases/cuda/15 sanitizer/prog.cu
new file mode 100644
--- /dev/null
+++ b/test cases/cuda/15 sanitizer/prog.cu	
@@ -0,0 +1,30 @@
+#include <iostream>
+
+int run_tests(void) {
+    int cuda_devices = 0;
+    std::cout << "CUDA version: " << CUDART_VERSION << "\n";
+    cudaGetDeviceCount(&cuda_devices);
+    if(cuda_devices == 0) {
+        std::cout << "No Cuda hardware found. Exiting.\n";
+        return 0;
+    }
+    std::cout << "This computer has " << cuda_devices << " Cuda device(s).\n";
+    cudaDeviceProp props;
+    cudaGetDeviceProperties(&props, 0);
+    std::cout << "Properties of device 0.\n\n";
+
+    std::cout << "  Name:            " << props.name << "\n";
+    std::cout << "  Global memory:   " << props.totalGlobalMem << "\n";
+    std::cout << "  Shared memory:   " << props.sharedMemPerBlock << "\n";
+    std::cout << "  Constant memory: " << props.totalConstMem << "\n";
+    std::cout << "  Block registers: " << props.regsPerBlock << "\n";
+
+    std::cout << "  Warp size:         " << props.warpSize << "\n";
+    std::cout << "  Threads per block: " << props.maxThreadsPerBlock << "\n";
+    std::cout << "  Max block dimensions: [ " << props.maxThreadsDim[0] << ", " << props.maxThreadsDim[1]  << ", " << props.maxThreadsDim[2] << " ]" << "\n";
+    std::cout << "  Max grid dimensions:  [ " << props.maxGridSize[0] << ", " << props.maxGridSize[1]  << ", " << props.maxGridSize[2] << " ]" << "\n";
+    std::cout << "\n";
+
+    return 0;
+}
+