Repository: mesonbuild/meson

Issue:
Meson cross compiling CUDA
Short version: What is the best way to cross compile a CUDA program using meson.

Here is my code:

``` c++
#include <iostream>
#include <cuda_runtime.h>

__global__
void hello(int *b)
{
    *b = 42;
}

int main(){
    int *pd;
    cudaMalloc(&pd, sizeof(int));
    hello<<<1, 1>>>(pd);
    cudaDeviceSynchronize();

    int res = 0;
    cudaMemcpy(&res, pd, sizeof(int), cudaMemcpyDeviceToHost );
    cudaFree(pd);

    std::cout << "hello world: " << res << std::endl;
    return 0;
}
```

I installed my gcc cross compiler in /opt/cross and the needed CUDA libs in /opt/cross/lib/cuda

This command works.
```
nvcc -ccbin /opt/cross/bin/aarch64-linux-g++ -std=c++14 -I/usr/local/cuda/include -L/opt/cross/lib/cuda --gpu-architecture=compute_72 --gpu-code=sm_72 src/hello.cu
```

But with meson it fails.

`meson build src --cross-file arm_build.txt`
```
The Meson build system
Version: 0.51.1
Source dir: /home/shalom/cuda-workspace/meson-cuda-hello-world/src
Build dir: /home/shalom/cuda-workspace/meson-cuda-hello-world/build
Build type: cross build
Project name: hello-cuda
Project version: undefined
C++ compiler for the build machine: c++ (gcc 8.3.0 "c++ (Ubuntu 8.3.0-6ubuntu1) 8.3.0")
Cuda compiler for the build machine: nvcc (nvcc 10.1.168)
C++ compiler for the host machine: /opt/cross/bin/aarch64-linux-g++ (gcc 8.3.0 "aarch64-linux-g++ (GCC) 8.3.0")                                                                       

meson.build:1:0: ERROR:

A full log can be found at /home/shalom/cuda-workspace/meson-cuda-hello-world/build/meson-logs/meson-log.txt
```

Here is my meson.build file:
```
project('hello-cuda', 'cpp', 'cuda')

cuda_comp = meson.get_compiler('cuda')
cuda = import('unstable-cuda')
nvcc_flags = cuda.nvcc_arch_flags(cuda_comp, 'Common')
executable('hello-cuda', 'hello.cu', cuda_args : nvcc_flags)
```

Here is my arm_build.txt cross file:
```
[binaries]
c = '/opt/cross/bin/aarch64-linux-gcc'
cpp = '/opt/cross/bin/aarch64-linux-g++'
ar = '/opt/cross/bin/aarch64-linux-ar'
as = '/opt/cross/bin/aarch64-linux-as'
strip = '/opt/cross/bin/aarch64-linux-strip'
ranlib = '/opt/cross/bin/aarch64-linux-ranlib'
ld = '/opt/cross/bin/aarch64-linux-ld'
objdump = '/opt/cross/bin/aarch64-linux-objdump'
objcopy = '/opt/cross/bin/aarch64-linux-objcopy'
size = '/opt/cross/bin/aarch64-linux-size'
pkgconfig = 'aarch64-linux-gnu-pkg-config'
cuda = '/usr/local/cuda/bin/nvcc -ccbin /opt/cross/bin/aarch64-linux-g++ -std=c++14'

[properties]
needs_exe_wrapper = true
#c_link_args = ['--target=arm-linux-gnueabihf']

[host_machine]
system = 'linux'
cpu_family = 'arm'
cpu = 'aarch64'
endian = 'little'
```

What am I doing wrong? What do I need to change to get the cross compile to work?



Discussion:
Please fix your markdown

> A full log can be found at /home/shalom/cuda-workspace/meson-cuda-hello-world/build/meson-logs/meson-log.txt`

I think that has more information than what you pasted?
I fixed the markdown. Sorry about that...

Looking at the project I removed the cpp declearation of the project. So this:
`project('hello-cuda', 'cpp', 'cuda')`
changed to this:
`project('hello-cuda', 'cuda')`

I also added the include paths into my cross file. So this:
`cuda = '/usr/local/cuda/bin/nvcc -ccbin /opt/cross/bin/aarch64-linux-g++ -std=c++14'`
changed to this:
`cuda = '/usr/local/cuda/bin/nvcc -ccbin /opt/cross/bin/aarch64-linux-g++ -std=c++14 -I/usr/local/cuda/include -L/opt/cross/lib/cuda'`

I still get the same failure. Here is my messon-log.txt:
```
Build started at 2019-08-13T09:50:16.425212
Main binary: /usr/bin/python3
Python system: Linux
The Meson build system
Version: 0.51.1
Source dir: /home/shalom/cuda-workspace/meson-cuda-hello-world/src
Build dir: /home/shalom/cuda-workspace/meson-cuda-hello-world/build
Build type: cross build
Project name: hello-cuda
Project version: undefined
No CUFLAGS in the environment, not changing global flags.
No LDFLAGS in the environment, not changing global flags.
Sanity testing Cuda compiler: nvcc
Is cross compiler: None.
Sanity check compiler command line:  nvcc -w -cudart static /home/shalom/cuda-workspace/meson-cuda-hello-world/build/meson-private/sanitycheckcuda.cu -o /home/shalom/cuda-workspace/meson-cuda-hello-world/build/meson-private/sanitycheckcuda.exe
Sanity check compile stdout:

Sanity check compile stderr:

Sanity check run command line:  nvcc --run "/home/shalom/cuda-workspace/meson-cuda-hello-world/build/meson-private/sanitycheckcuda.exe"                                               
Sanity check run stdout:

Sanity check run stderr:
100

cudaGetDeviceCount() returned 100

Cuda compiler for the build machine: nvcc (nvcc 10.1.168)

meson.build:1:0: ERROR:

```


Resolving patch:
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -1383,8 +1383,6 @@ def detect_cuda_compiler(self, for_machine):
         for compiler in compilers:
             if isinstance(compiler, str):
                 compiler = [compiler]
-            else:
-                raise EnvironmentException()
             arg = '--version'
             try:
                 p, out, err = Popen_safe(compiler + [arg])


Test patch:
diff --git a/test cases/cuda/13 cuda compiler setting/meson.build b/test cases/cuda/13 cuda compiler setting/meson.build
new file mode 100644
--- /dev/null
+++ b/test cases/cuda/13 cuda compiler setting/meson.build	
@@ -0,0 +1,5 @@
+project('simple', 'cuda', version : '1.0.0')
+
+exe = executable('prog', 'prog.cu')
+test('cudatest', exe)
+
diff --git a/test cases/cuda/13 cuda compiler setting/nativefile.ini b/test cases/cuda/13 cuda compiler setting/nativefile.ini
new file mode 100644
--- /dev/null
+++ b/test cases/cuda/13 cuda compiler setting/nativefile.ini	
@@ -0,0 +1,5 @@
+[binaries]
+
+cuda = 'nvcc'
+
+
diff --git a/test cases/cuda/13 cuda compiler setting/prog.cu b/test cases/cuda/13 cuda compiler setting/prog.cu
new file mode 100644
--- /dev/null
+++ b/test cases/cuda/13 cuda compiler setting/prog.cu	
@@ -0,0 +1,30 @@
+#include <iostream>
+
+int main(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;
+}
+