Search code examples
cmakecudaclangclang++ninja

How to compile Cuda within Clang when included by main c++ file?


I am currently working on a project, where I want to execute some code in Cuda, which should be called from the main c++ file. When I am compiling with Clang only the .cpp files are compiled and the compiler tells me "expected exprission" on the <<<>>> Kernel call notation. Any Idea how I can fix this?

I have a .cuh files with the definition which I am including and a .cu source file. I am using CMake to configure the project and building it with Ninja.

I am using ccached clang++ and supplying "--cuda-path=/usr/local/cuda-10.1 --cuda-gpu-arch=sm_61 -L/usr/local/cuda-10.1/lib64 -lcudart_static -ldl -lrt -pthread -std=c++17" to clang args.

When I add the -x cuda flag, the error does not appear, but instead it tells me that a library that I am linking against is not allowed to overwrite some host function, but I think this is because it wants to compile everything as cuda, which is not intended.

I am passing all files inside my source folder to add_executable in CMake via a GLOB ${APP_PATH}/src/*, which should add all files.

main.cpp

#include "ParticleEngine.cuh"

...

int main(){
 simulation_timestep(&this->particles[0], this->gravity, 1, delta_frame,
                      this->particles.size());
}

ParticleEngine.cuh

#pragma once
#include "cuda_runtime.h"
#include "device_launch_parameters.h"

void simulation_timestep(Particle *particles, ci::vec3 gravity, double mass,
                         double time_delta, unsigned long long n_particles);

ParticleEngine.cu

#include "ParticleEngine.cuh"

__global__ void particle_kernel(Particle *particles, ci::vec3 *gravity,
                                double *mass, double *time_delta) {
...
}


void simulation_timestep(Particle *particles, ci::vec3 gravity, double mass,
                         double time_delta, unsigned long long n_particles) {

  ... //memcpy stuff

  particle_kernel<<<dimgrid, dimblock>>>(cuda_particles, cuda_gravity,
                                         cuda_mass, cuda_time_delta);

  ...
}

edit: Full error message:

[build] In file included from ../src/main.cpp:1:
[build] ../src/ParticleEngine.cu:43:20: error: expected expression
[build]   particle_kernel<<<dimgrid, dimblock>>>(cuda_particles, cuda_gravity,
[build]                    ^

edit: Error message when executing clang with -x cuda:

[build] /home/mebenstein/Cinder/include/glm/gtx/io.inl:97:32: error: __host__ __device__ function 'get_facet' cannot overload __host__ function 'get_facet'
[build]         GLM_FUNC_QUALIFIER FTy const& get_facet(std::basic_ios<CTy, CTr>& ios)
[build]                                       ^
[build] /home/mebenstein/Cinder/include/glm/gtx/io.hpp:145:14: note: previous declaration is here
[build]                 FTy const& get_facet(std::basic_ios<CTy,CTr>&);
[build]                            ^

I am including the c++ library cinder in main.cpp and this error appears.


Solution

  • #include in C++ works by literally replacing that statement with the contents of the included file. As a consequence, the included file is also parsed as C++ code.

    To compile a file as CUDA code, the file needs to be a separate compilation unit, i.e. given as an argument to the clang invocation. It also either needs to have a name ending in .cu, or the -x cuda flag needs to be given to clang.

    Update after error messages have been included in the question:

    It appears that Cinder does not support compilation of the CUDA part with clang++ because of a difference in how __host__/__device__ attributes are treated.

    At this point your options are the following:

    1. You can modify Cinder to also support clang++, it's open source.

    2. You can ask the Cinder authors or third parties whether they are willing to make the necessary changes. A cash incentive may or may not increase willingness.

    3. You can use nvcc to compile the code.