I am writing a CXX+CUDA project, and I'm compiling using nvcc, with CXX compiler of icpc.
I want to add different compilation flags for icpc for different files. In CXX standalone this is possible using set_source_files_properties()
method, but I tried it in my case and it didn't work.
Minimal example for my structure -
cat main.cu
#include "file1.cuh"
#include "file2.cuh"
int main() {
int3 size = make_int3(1, 1, 1);
std::cout << size.x << std::endl;
print_x<<<1,1>>>(size);
print_y<<<1,1>>>(size);
return 0;
}
cat file1.cuh
#include <cuda_runtime.h>
__global__ void print_x(int3 arr);
cat file1.cu
#include "file1.cuh"
#include <iostream>
__global__ void print_x(int3 arr) { printf("%d", arr.x); }
cat file2.cuh
#include <cuda_runtime.h>
#include <iostream>
__global__ void print_y(int3 arr);
cat file2.cu
#include "file2.cuh"
__global__ void print_y(int3 arr) { printf("%d", arr.y); }
cat CMakeLists.txt
set(CMAKE_C_COMPILER "icc")
set(CMAKE_CXX_COMPILER "icpc")
set(CMAKE_CUDA_COMPILER "nvcc")
project(proj LANGUAGES CXX CUDA)
set(COMMON_CC_COMPILER_FLAGS -std=c++17 -Wextra -pedantic -Werror -Wall -lstdc++fs)
set(COMMON_FLAGS ${COMMON_CC_COMPILER_FLAGS})
string(JOIN ", " COMMON_FLAGS_FOR_CUDA_CC_COMPILER "${COMMON_CC_COMPILER_FLAGS}")
string(REPLACE ";" "," COMMON_FLAGS_FOR_CUDA_CC_COMPILER "${COMMON_FLAGS_FOR_CUDA_CC_COMPILER}")
set(CMAKE_CUDA_STANDARD 17)
set(COMMON_FLAGS_CUDA -ccbin=icpc --compiler-options "${COMMON_FLAGS_FOR_CUDA_CC_COMPILER}")
string(REPLACE ";" " " FLAGS "${COMMON_FLAGS}")
list(APPEND COMMON_FLAGS -DFLAGS="${FLAGS}")
include_directories(${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES})
add_executable(proj main.cu file1.cu file2.cu)
target_compile_options(proj PRIVATE $<$<COMPILE_LANGUAGE:CXX>:${COMMON_FLAGS}> $<$<COMPILE_LANGUAGE:CUDA>:${COMMON_FLAGS_CUDA}>)
When compiling this project, the flags under --compiler-options
indeed pass correctly to icpc, but I want different flags for each source. For example, I would like file1.cu
to also be compiled with -pedantic -Werror
.
I'm trying to do this by adding:
set_source_files_properties(
file1.cu
PROPERTIES
COMPILE_FLAGS "--compiler-options -Wall")
to the CMakeLists.txt
file, but I see no change in the compilation command applied for this file (I checked using VERBOSE=1 make
). I tried several other variations after PROPERTIES
, but none of them work.
How can I get different additional compilation flags to apply to different files?
Note: that I want the compilation to be done automatically using CMake since I have a large project with many components, so usage of CUDA_COMPILE
method is not relevant in my state. I'm looking for some parallel method to set_source_files_properties()
which is applicable in my scope.
I am using icpc 2021.4, nvcc 12.2, and cmake 3.21.4.
I just built a project similar to yours (more of an MWE...) with CMake 3.28.3, and did not experience this problem.
CMakeLists.txt
:
cmake_minimum_required(VERSION 3.25 FATAL_ERROR)
set(CMAKE_CUDA_COMPILER "nvcc")
set(CMAKE_CUDA_HOST_COMPILER "icpc")
project(my_proj LANGUAGES CXX CUDA)
add_library(my_proj foo.cu bar.cu)
set_source_files_properties(foo.cu
PROPERTIES COMPILE_FLAGS "--compiler-options -Wunused-parameter")
foo.cu
:
int foo(int x) { return (100 > 1) == 3; }
bar.cu
:
int bar(int x) { return (100 > 1) == 3; }
and this is what the build looks like:
$ cmake --build build
[2/3] Building CUDA object CMakeFiles/my_proj.dir/foo.cu.o
/tmp/delme/foo.cu: In function ‘int foo(int)’:
/tmp/delme/foo.cu:1:13: warning: unused parameter ‘x’ [-Wunused-parameter]
int foo(int x) { return (100 > 1) == 3; }
~~~~^
[3/3] Linking CUDA static library libmy_proj.a
so, one compilation and one linking had no issues, and one compilation complained about the unused parameter - just as expected.
Let's suppose that you have four files:
main.cu
can be compiled with no special flags for the host-side codefile1.cu
needs to be compiled with flag -O1
for the host-side codefile2.cu
and file3.cu
need to be compiled with flag -Ofast
for the host-side code.Now, use an "object library target" for each combination of compilation flags:
add_library(compiled_with_o1 OBJECT file1.cu)
add_library(compiled_with_ofast OBJECT file2.cu file3.cu)
add_executable(my_program main.cu) # no special wrapping for main.cu
target_link_libraries(my_program compiled_with_o1 compiled_with_ofast)
You can now use CMake's per-target compilation options setting command, like so:
target_compile_options(compiled_with_o1 PRIVATE "--compiler-options -O1")
target_compile_options(compiled_with_ofast PRIVATE "--compiler-options -Ofast")
Notes: The second approach is the same basic idea as @paleonix' answer, but with OBJECT
libraries.