diff options
author | Robert Maynard <rmaynard@nvidia.com> | 2024-07-16 13:40:46 (GMT) |
---|---|---|
committer | Robert Maynard <rmaynard@nvidia.com> | 2024-08-02 17:35:53 (GMT) |
commit | b90ae10dda15c424bd3beb2955baf45b1a788ae4 (patch) | |
tree | d0199c987c1bdb7c90871d5301438e4f68881108 | |
parent | c99ff40b213d6b3d207dae66c9692ed1b8a0a2f0 (diff) | |
download | CMake-b90ae10dda15c424bd3beb2955baf45b1a788ae4.zip CMake-b90ae10dda15c424bd3beb2955baf45b1a788ae4.tar.gz CMake-b90ae10dda15c424bd3beb2955baf45b1a788ae4.tar.bz2 |
Add support for unity builds with CUDA sources
Fixes #22750
-rw-r--r-- | Help/prop_tgt/UNITY_BUILD.rst | 3 | ||||
-rw-r--r-- | Help/release/dev/unity-build-supports-cuda.rst | 5 | ||||
-rw-r--r-- | Source/cmLocalGenerator.cxx | 4 | ||||
-rw-r--r-- | Source/cmVisualStudio10TargetGenerator.cxx | 6 | ||||
-rw-r--r-- | Tests/CudaOnly/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Tests/CudaOnly/Unity/CMakeLists.txt | 14 | ||||
-rw-r--r-- | Tests/CudaOnly/Unity/a.cu | 12 | ||||
-rw-r--r-- | Tests/CudaOnly/Unity/b.cu | 5 | ||||
-rw-r--r-- | Tests/CudaOnly/Unity/main.cu | 8 | ||||
-rw-r--r-- | Tests/RunCMake/CMakeLists.txt | 5 | ||||
-rw-r--r-- | Tests/RunCMake/UnityBuild/RunCMakeTest.cmake | 5 | ||||
-rw-r--r-- | Tests/RunCMake/UnityBuild/f.cu | 5 | ||||
-rw-r--r-- | Tests/RunCMake/UnityBuild/unitybuild_cuda-check.cmake | 5 | ||||
-rw-r--r-- | Tests/RunCMake/UnityBuild/unitybuild_cuda.cmake | 14 | ||||
-rw-r--r-- | Tests/RunCMake/UnityBuild/unitybuild_cuda_group-check.cmake | 27 | ||||
-rw-r--r-- | Tests/RunCMake/UnityBuild/unitybuild_cuda_group.cmake | 28 | ||||
-rw-r--r-- | Tests/RunCMake/UnityBuild/unitybuild_cxx_and_cuda-check.cmake | 42 | ||||
-rw-r--r-- | Tests/RunCMake/UnityBuild/unitybuild_cxx_and_cuda.cmake | 40 |
18 files changed, 227 insertions, 2 deletions
diff --git a/Help/prop_tgt/UNITY_BUILD.rst b/Help/prop_tgt/UNITY_BUILD.rst index 577b0c9..ee00171 100644 --- a/Help/prop_tgt/UNITY_BUILD.rst +++ b/Help/prop_tgt/UNITY_BUILD.rst @@ -38,6 +38,9 @@ Unity builds are supported for the following languages: ``CXX`` .. versionadded:: 3.16 +``CUDA`` + .. versionadded:: 3.31 + ``OBJC`` .. versionadded:: 3.29 diff --git a/Help/release/dev/unity-build-supports-cuda.rst b/Help/release/dev/unity-build-supports-cuda.rst new file mode 100644 index 0000000..b6c09d1 --- /dev/null +++ b/Help/release/dev/unity-build-supports-cuda.rst @@ -0,0 +1,5 @@ +unity-build-supports-cuda +------------------------- + +* The :prop_tgt:`UNITY_BUILD` target property now supports the + CUDA (``CUDA``) language. diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 7b0bf4e..eb16c7a 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -3162,6 +3162,8 @@ std::string unity_file_extension(std::string const& lang) extension = "_c.c"; } else if (lang == "CXX") { extension = "_cxx.cxx"; + } else if (lang == "CUDA") { + extension = "_cu.cu"; } else if (lang == "OBJC") { extension = "_m.m"; } else if (lang == "OBJCXX") { @@ -3291,7 +3293,7 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target) cmValue afterInclude = target->GetProperty("UNITY_BUILD_CODE_AFTER_INCLUDE"); cmValue unityMode = target->GetProperty("UNITY_BUILD_MODE"); - for (std::string lang : { "C", "CXX", "OBJC", "OBJCXX" }) { + for (std::string lang : { "C", "CXX", "OBJC", "OBJCXX", "CUDA" }) { std::vector<UnityBatchedSource> filtered_sources; std::copy_if(unitySources.begin(), unitySources.end(), std::back_inserter(filtered_sources), diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index f5fd8d2..c9b323e 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -2686,6 +2686,12 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0) } } } + if (haveUnityBuild && strcmp(tool, "CudaCompile") == 0 && + si.Source->GetProperty("UNITY_SOURCE_FILE")) { + if (!si.Source->GetPropertyAsBool("SKIP_UNITY_BUILD_INCLUSION")) { + exclude_configs = all_configs; + } + } if (si.Kind == cmGeneratorTarget::SourceKindObjectSource || si.Kind == cmGeneratorTarget::SourceKindUnityBatched) { diff --git a/Tests/CudaOnly/CMakeLists.txt b/Tests/CudaOnly/CMakeLists.txt index 128d371..77061a9 100644 --- a/Tests/CudaOnly/CMakeLists.txt +++ b/Tests/CudaOnly/CMakeLists.txt @@ -19,6 +19,7 @@ add_cuda_test_macro(CudaOnly.Toolkit CudaOnlyToolkit) add_cuda_test_macro(CudaOnly.ToolkitBeforeLang CudaOnlyToolkitBeforeLang) add_cuda_test_macro(CudaOnly.ToolkitMultipleDirs CudaOnlyToolkitMultipleDirs) add_cuda_test_macro(CudaOnly.TryCompileTargetStatic CudaOnlyTryCompileTargetStatic) +add_cuda_test_macro(CudaOnly.Unity CudaOnlyUnity) add_cuda_test_macro(CudaOnly.WithDefs CudaOnlyWithDefs) add_cuda_test_macro(CudaOnly.CircularLinkLine CudaOnlyCircularLinkLine) add_cuda_test_macro(CudaOnly.ResolveDeviceSymbols CudaOnlyResolveDeviceSymbols) diff --git a/Tests/CudaOnly/Unity/CMakeLists.txt b/Tests/CudaOnly/Unity/CMakeLists.txt new file mode 100644 index 0000000..0bdc1f6 --- /dev/null +++ b/Tests/CudaOnly/Unity/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.30) +project(Unity CUDA) + +set(CMAKE_UNITY_BUILD 1) + +add_library(UnityObjects STATIC a.cu b.cu) + +add_executable(CudaOnlyUnity main.cu) +target_link_libraries(CudaOnlyUnity PRIVATE UnityObjects) + +if(APPLE) + # Help the static cuda runtime find the driver (libcuda.dyllib) at runtime. + set_property(TARGET CudaOnlyUnity PROPERTY BUILD_RPATH ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES}) +endif() diff --git a/Tests/CudaOnly/Unity/a.cu b/Tests/CudaOnly/Unity/a.cu new file mode 100644 index 0000000..7f3752c --- /dev/null +++ b/Tests/CudaOnly/Unity/a.cu @@ -0,0 +1,12 @@ + +__device__ int function(int a, int b); + +__global__ void kernel() +{ + function(2, 3); +} + +void test_unity_functions() +{ + kernel<<<1, 1, 1>>>(); +} diff --git a/Tests/CudaOnly/Unity/b.cu b/Tests/CudaOnly/Unity/b.cu new file mode 100644 index 0000000..69d799a --- /dev/null +++ b/Tests/CudaOnly/Unity/b.cu @@ -0,0 +1,5 @@ + +__device__ int function(int a, int b) +{ + return b * b * a + 1; +} diff --git a/Tests/CudaOnly/Unity/main.cu b/Tests/CudaOnly/Unity/main.cu new file mode 100644 index 0000000..1cbbbe6 --- /dev/null +++ b/Tests/CudaOnly/Unity/main.cu @@ -0,0 +1,8 @@ + +void test_unity_functions(); + +int main(int argc, char** argv) +{ + test_unity_functions(); + return 0; +} diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index db5ef96..ce57bcf 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -1201,7 +1201,10 @@ add_RunCMake_test(PrecompileHeaders -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID} -DCMAKE_C_SIMULATE_ID=${CMAKE_C_SIMULATE_ID} -DCMAKE_C_COMPILER_VERSION=${CMAKE_C_COMPILER_VERSION}) -add_RunCMake_test(UnityBuild -DCMake_TEST_OBJC=${CMake_TEST_OBJC}) +add_RunCMake_test(UnityBuild -DCMake_TEST_OBJC=${CMake_TEST_OBJC} -DCMake_TEST_CUDA=${CMake_TEST_CUDA}) +set_property(TEST RunCMake.UnityBuild APPEND + PROPERTY LABELS "CUDA") + add_RunCMake_test(CMakePresets -DPython_EXECUTABLE=${Python_EXECUTABLE} -DCMake_TEST_JSON_SCHEMA=${CMake_TEST_JSON_SCHEMA} diff --git a/Tests/RunCMake/UnityBuild/RunCMakeTest.cmake b/Tests/RunCMake/UnityBuild/RunCMakeTest.cmake index 0ec8c42..78996e4 100644 --- a/Tests/RunCMake/UnityBuild/RunCMakeTest.cmake +++ b/Tests/RunCMake/UnityBuild/RunCMakeTest.cmake @@ -21,6 +21,11 @@ if(CMake_TEST_OBJC) run_cmake(unitybuild_objcxx_group) run_cmake(unitybuild_c_and_cxx_and_objc_and_objcxx) endif() +if(CMake_TEST_CUDA) + run_cmake(unitybuild_cuda) + run_cmake(unitybuild_cuda_group) + run_cmake(unitybuild_cxx_and_cuda) +endif() run_cmake(unitybuild_batchsize) run_cmake(unitybuild_default_batchsize) run_cmake(unitybuild_skip) diff --git a/Tests/RunCMake/UnityBuild/f.cu b/Tests/RunCMake/UnityBuild/f.cu new file mode 100644 index 0000000..d5813c6 --- /dev/null +++ b/Tests/RunCMake/UnityBuild/f.cu @@ -0,0 +1,5 @@ +int f(int x) +{ + (void)x; + return 0; +} diff --git a/Tests/RunCMake/UnityBuild/unitybuild_cuda-check.cmake b/Tests/RunCMake/UnityBuild/unitybuild_cuda-check.cmake new file mode 100644 index 0000000..9a078cd --- /dev/null +++ b/Tests/RunCMake/UnityBuild/unitybuild_cuda-check.cmake @@ -0,0 +1,5 @@ +set(unitybuild_cu "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_0_cu.cu") +if(NOT EXISTS "${unitybuild_cu}") + set(RunCMake_TEST_FAILED "Generated unity source files ${unitybuild_cu} does not exist.") + return() +endif() diff --git a/Tests/RunCMake/UnityBuild/unitybuild_cuda.cmake b/Tests/RunCMake/UnityBuild/unitybuild_cuda.cmake new file mode 100644 index 0000000..399a9b1 --- /dev/null +++ b/Tests/RunCMake/UnityBuild/unitybuild_cuda.cmake @@ -0,0 +1,14 @@ + +set(CMAKE_CUDA_ARCHITECTURES all-major) +project(unitybuild_cuda CUDA) + +set(srcs "") +foreach(s RANGE 1 8) + set(src "${CMAKE_CURRENT_BINARY_DIR}/s${s}.cu") + file(WRITE "${src}" "int s${s}(void) { return 0; }\n") + list(APPEND srcs "${src}") +endforeach() + +add_library(tgt SHARED ${srcs}) + +set_target_properties(tgt PROPERTIES UNITY_BUILD ON) diff --git a/Tests/RunCMake/UnityBuild/unitybuild_cuda_group-check.cmake b/Tests/RunCMake/UnityBuild/unitybuild_cuda_group-check.cmake new file mode 100644 index 0000000..7d2a2dc --- /dev/null +++ b/Tests/RunCMake/UnityBuild/unitybuild_cuda_group-check.cmake @@ -0,0 +1,27 @@ +set(unitybuild_a_cu "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_a_cu.cu") +if(NOT EXISTS "${unitybuild_a_cu}") + set(RunCMake_TEST_FAILED "Generated unity source files ${unitybuild_a_cu} does not exist.") + return() +else() + #verify that odr2 is not part of this source set + file(STRINGS ${unitybuild_a_cu} unitybuild_a_cu_strings) + string(REGEX MATCH ".*#include.*odr2.cu" matched_code ${unitybuild_a_cu_strings}) + if(matched_code) + set(RunCMake_TEST_FAILED "Generated unity file includes un-expected ord2.cu source file") + return() + endif() +endif() + +set(unitybuild_b_cu "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_b_cu.cu") +if(NOT EXISTS "${unitybuild_b_cu}") + set(RunCMake_TEST_FAILED "Generated unity source files ${unitybuild_b_cu} does not exist.") + return() +else() + #verify that odr1 is not part of this source set + file(STRINGS ${unitybuild_b_cu} unitybuild_b_cu_strings) + string(REGEX MATCH ".*#include.*odr1.cu" matched_code ${unitybuild_b_cu_strings}) + if(matched_code) + set(RunCMake_TEST_FAILED "Generated unity file includes un-expected ord1.cu source file") + return() + endif() +endif() diff --git a/Tests/RunCMake/UnityBuild/unitybuild_cuda_group.cmake b/Tests/RunCMake/UnityBuild/unitybuild_cuda_group.cmake new file mode 100644 index 0000000..d4a0522 --- /dev/null +++ b/Tests/RunCMake/UnityBuild/unitybuild_cuda_group.cmake @@ -0,0 +1,28 @@ +set(CMAKE_CUDA_ARCHITECTURES all-major) +project(unitybuild_cu CUDA) + +set(srcs "") +foreach(s RANGE 1 4) + set(src "${CMAKE_CURRENT_BINARY_DIR}/s${s}.cu") + file(WRITE "${src}" "int s${s}(void) { return 0; }\n") + list(APPEND srcs "${src}") +endforeach() + +foreach(s RANGE 1 2) + set(src "${CMAKE_CURRENT_BINARY_DIR}/odr${s}.cu") + file(WRITE "${src}" "namespace odr { int s${s}(void) { return 0; } }\n") + list(APPEND srcs "${src}") +endforeach() + +add_library(tgt SHARED ${srcs}) + +set_target_properties(tgt PROPERTIES UNITY_BUILD ON + UNITY_BUILD_MODE GROUP + ) + +set_source_files_properties(s1.cu s2.cu odr1.cu + PROPERTIES UNITY_GROUP "a" + ) +set_source_files_properties(s3.cu s4.cu odr2.cu + PROPERTIES UNITY_GROUP "b" + ) diff --git a/Tests/RunCMake/UnityBuild/unitybuild_cxx_and_cuda-check.cmake b/Tests/RunCMake/UnityBuild/unitybuild_cxx_and_cuda-check.cmake new file mode 100644 index 0000000..d53242a --- /dev/null +++ b/Tests/RunCMake/UnityBuild/unitybuild_cxx_and_cuda-check.cmake @@ -0,0 +1,42 @@ +set(unitybuild_a_cu "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_a_cu.cu") +if(NOT EXISTS "${unitybuild_a_cu}") + set(RunCMake_TEST_FAILED "Generated unity source files ${unitybuild_a_cu} does not exist.") + return() +else() + #verify that the 4 c file is part of this grouping and therefore UNITY_BUILD_BATCH_SIZE + #was ignored + file(STRINGS ${unitybuild_a_cu} unitybuild_a_c_strings) + string(REGEX MATCH ".*#include.*s1.cu.*#include.*s2.cu.*#include.*s3.cu.*#include.*s4.cu.*" matched_code ${unitybuild_a_c_strings}) + if(NOT matched_code) + set(RunCMake_TEST_FAILED "Generated unity file doesn't include expected source files") + return() + endif() +endif() + +set(unitybuild_b_cu "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_b_cu.cu") +if(NOT EXISTS "${unitybuild_b_cu}") + set(RunCMake_TEST_FAILED "Generated unity source files ${unitybuild_b_cu} does not exist.") + return() +endif() + + +set(unitybuild_a_cxx "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_a_cxx.cxx") +if(NOT EXISTS "${unitybuild_a_cxx}") + set(RunCMake_TEST_FAILED "Generated unity source files ${unitybuild_a_cxx} does not exist.") + return() +else() + #verify that the 4 cxx file are part of this grouping and therefore UNITY_BUILD_BATCH_SIZE + #was ignored + file(STRINGS ${unitybuild_a_cxx} unitybuild_a_cxx_strings) + string(REGEX MATCH ".*#include.*s1.cxx.*#include.*s2.cxx.*#include.*s3.cxx.*#include.*s4.cxx.*" matched_code ${unitybuild_a_cxx_strings}) + if(NOT matched_code) + set(RunCMake_TEST_FAILED "Generated unity file doesn't include expected source files") + return() + endif() +endif() + +set(unitybuild_b_cxx "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_b_cxx.cxx") +if(NOT EXISTS "${unitybuild_b_cxx}") + set(RunCMake_TEST_FAILED "Generated unity source files ${unitybuild_b_cxx} does not exist.") + return() +endif() diff --git a/Tests/RunCMake/UnityBuild/unitybuild_cxx_and_cuda.cmake b/Tests/RunCMake/UnityBuild/unitybuild_cxx_and_cuda.cmake new file mode 100644 index 0000000..c633ed1 --- /dev/null +++ b/Tests/RunCMake/UnityBuild/unitybuild_cxx_and_cuda.cmake @@ -0,0 +1,40 @@ +set(CMAKE_CUDA_ARCHITECTURES all-major) +project(unitybuild_c_and_cxx CUDA CXX) + +set(srcs f.cu) +foreach(s RANGE 1 8) + set(src_cu "${CMAKE_CURRENT_BINARY_DIR}/s${s}.cu") + file(WRITE "${src_cu}" " +int f(int);\n +int s${s}(void) { return f(${s}); }\n" + ) + + set(src_cxx "${CMAKE_CURRENT_BINARY_DIR}/s${s}.cxx") + file(WRITE "${src_cxx}" " +extern \"C\" { \n + int f(int); \n +}\n + int s${s}(void) { return f(${s}); }\n" + ) + + list(APPEND srcs "${src_cu}") + list(APPEND srcs "${src_cxx}") +endforeach() + + + +add_library(tgt SHARED ${srcs}) + +set_target_properties(tgt PROPERTIES UNITY_BUILD ON + UNITY_BUILD_MODE GROUP + #UNITY_BUILD_BATCH_SIZE will be ignored + UNITY_BUILD_BATCH_SIZE 2) + +set_source_files_properties(s1.cu s2.cu s3.cu s4.cu + s1.cxx s2.cxx s3.cxx s4.cxx + PROPERTIES UNITY_GROUP "a" + ) +set_source_files_properties(s5.cu s6.cu s7.cu s8.cu + s5.cxx s6.cxx s7.cxx s8.cxx + PROPERTIES UNITY_GROUP "b" + ) |