Skip to content
This repository was archived by the owner on Mar 21, 2024. It is now read-only.

Commit 0e9e5b1

Browse files
committed
Add find_package and add_subdirectory CMake support.
To validate installation + packages, run the new tests: ``` mkdir build cd build cmake -Dlibcudacxx_ENABLE_CMAKE_TESTS=ON .. ctest --output-on-failure ```
1 parent 4e9f28e commit 0e9e5b1

11 files changed

+285
-0
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,4 @@ compare_git_to_perforce.bash
3737
.clangd/
3838
.cache
3939
compile_commands.json
40+
*~

CMakeLists.txt

+27
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,33 @@
11
cmake_minimum_required(VERSION 3.8)
22
project(libcudacxx CXX)
33

4+
# Determine whether libcudacxx is the top-level project or included into
5+
# another project via add_subdirectory().
6+
if ("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_LIST_DIR}")
7+
set(libcudacxx_TOPLEVEL_PROJECT ON)
8+
else()
9+
set(libcudacxx_TOPLEVEL_PROJECT OFF)
10+
endif()
11+
12+
include(cmake/libcudacxxInstallRules.cmake)
13+
14+
if (NOT libcudacxx_TOPLEVEL_PROJECT)
15+
include(cmake/libcudacxxAddSubdir.cmake)
16+
return()
17+
endif()
18+
19+
# Note that this currently returns and skips the rest of the build
20+
# system.
21+
option(libcudacxx_ENABLE_CMAKE_TESTS "Enable ctest-based testing." OFF)
22+
if (libcudacxx_ENABLE_CMAKE_TESTS)
23+
# Might be able to lower this, but would need to do some testing:
24+
cmake_minimum_required(VERSION 3.20.1)
25+
include(CTest)
26+
enable_testing() # Must be called in root CMakeLists.txt
27+
add_subdirectory(cmake/test/)
28+
return()
29+
endif()
30+
431
set(PACKAGE_NAME libcudacxx)
532
set(PACKAGE_VERSION 11.0)
633
set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")

cmake/libcudacxxAddSubdir.cmake

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
find_package(libcudacxx REQUIRED CONFIG
2+
NO_DEFAULT_PATH # Only check the explicit path in HINTS:
3+
HINTS "${CMAKE_CURRENT_LIST_DIR}/.."
4+
)

cmake/libcudacxxInstallRules.cmake

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
option(libcudacxx_ENABLE_INSTALL_RULES
2+
"Enable installation of libcudacxx" ${libcudacxx_TOPLEVEL_PROJECT}
3+
)
4+
5+
if (NOT libcudacxx_ENABLE_INSTALL_RULES)
6+
return()
7+
endif()
8+
9+
# Bring in CMAKE_INSTALL_LIBDIR
10+
include(GNUInstallDirs)
11+
12+
# libcudacxx is a header library; no need to build anything before installing:
13+
set(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY TRUE)
14+
15+
# Libcudacxx headers
16+
install(DIRECTORY "${libcudacxx_SOURCE_DIR}/include/cuda"
17+
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
18+
)
19+
install(DIRECTORY "${libcudacxx_SOURCE_DIR}/include/nv"
20+
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
21+
)
22+
23+
# Libcudacxx cmake package
24+
install(DIRECTORY "${libcudacxx_SOURCE_DIR}/lib/cmake/libcudacxx"
25+
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake"
26+
PATTERN libcudacxx-header-search EXCLUDE
27+
)
28+
29+
# Need to configure a file to store CMAKE_INSTALL_INCLUDEDIR
30+
# since it can be defined by the user. This is common to work around collisions
31+
# with the CTK installed headers.
32+
configure_file("${libcudacxx_SOURCE_DIR}/lib/cmake/libcudacxx/libcudacxx-header-search.cmake.in"
33+
"${libcudacxx_BINARY_DIR}/lib/cmake/libcudacxx/libcudacxx-header-search.cmake"
34+
@ONLY
35+
)
36+
install(FILES "${libcudacxx_BINARY_DIR}/lib/cmake/libcudacxx/libcudacxx-header-search.cmake"
37+
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/libcudacxx"
38+
)

cmake/test/CMakeLists.txt

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
if ("MSVC" STREQUAL "${CMAKE_CXX_COMPILER_ID}")
2+
# There's a bug that prevents build-and-test from working on MSVC.
3+
# See NVIDIA/nvbench#43.
4+
return()
5+
endif()
6+
7+
set(cmake_opts
8+
-D "CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
9+
-D "CMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}"
10+
-D "CMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
11+
)
12+
13+
# Temporary installation prefix for tests against installed project:
14+
set(tmp_install_prefix "${CMAKE_CURRENT_BINARY_DIR}/test_install")
15+
16+
# Add a build-and-test CTest.
17+
# - full_test_name_var will be set to the full name of the test.
18+
# - subdir is the relative path to the test project directory.
19+
# - test_id is used to generate a unique name for this test, allowing the
20+
# subdir to be reused.
21+
# - Any additional args will be passed to the project configure step.
22+
function(libcudacxx_add_compile_test full_test_name_var subdir test_id)
23+
set(test_name libcudacxx.test.cmake.${subdir}.${test_id})
24+
set(src_dir "${CMAKE_CURRENT_SOURCE_DIR}/${subdir}")
25+
set(build_dir "${CMAKE_CURRENT_BINARY_DIR}/${subdir}/${test_id}")
26+
add_test(NAME ${test_name}
27+
COMMAND "${CMAKE_CTEST_COMMAND}"
28+
--build-and-test "${src_dir}" "${build_dir}"
29+
--build-generator "${CMAKE_GENERATOR}"
30+
--build-options
31+
${cmake_opts}
32+
${ARGN}
33+
--test-command "${CMAKE_CTEST_COMMAND}" --output-on-failure
34+
)
35+
set(${full_test_name_var} ${test_name} PARENT_SCOPE)
36+
endfunction()
37+
38+
################################################################################
39+
# Test against source dir
40+
41+
libcudacxx_add_compile_test(test_name
42+
test_export
43+
source_tree
44+
-D "libcudacxx_DIR=${libcudacxx_SOURCE_DIR}/lib/cmake/libcudacxx/"
45+
-D TEST_TYPE=SOURCE_TREE
46+
)
47+
48+
################################################################################
49+
# Test against install tree
50+
51+
libcudacxx_add_compile_test(test_name
52+
test_export
53+
install_tree
54+
-D "libcudacxx_DIR=${tmp_install_prefix}/lib/cmake/libcudacxx/"
55+
-D TEST_TYPE=INSTALL_TREE
56+
)
57+
set_tests_properties(${test_name} PROPERTIES FIXTURES_REQUIRED install_tree)
58+
59+
################################################################################
60+
# Install tree fixtures
61+
add_test(NAME libcudacxx.test.cmake.install_tree.install
62+
COMMAND "${CMAKE_COMMAND}"
63+
--install "${libcudacxx_BINARY_DIR}"
64+
--prefix "${tmp_install_prefix}"
65+
)
66+
set_tests_properties(libcudacxx.test.cmake.install_tree.install PROPERTIES
67+
FIXTURES_SETUP install_tree
68+
)
69+
70+
add_test(NAME libcudacxx.test.cmake.install_tree.cleanup
71+
COMMAND "${CMAKE_COMMAND}" -E rm -rf "${tmp_install_prefix}"
72+
)
73+
set_tests_properties(libcudacxx.test.cmake.install_tree.cleanup PROPERTIES
74+
FIXTURES_CLEANUP install_tree
75+
)

cmake/test/test_export/CMakeLists.txt

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
cmake_minimum_required(VERSION 3.20.1)
2+
project(libcudacxxTestExport CXX)
3+
4+
message(STATUS "libcudacxx_DIR=${libcudacxx_DIR}")
5+
find_package(libcudacxx)
6+
7+
add_executable(version_check version_check.cxx)
8+
target_link_libraries(version_check PRIVATE libcudacxx::libcudacxx)
9+
enable_testing()
10+
add_test(NAME version_check COMMAND "$<TARGET_FILE:version_check>")
11+
set_property(TEST version_check PROPERTY
12+
PASS_REGULAR_EXPRESSION
13+
"${libcudacxx_VERSION_MAJOR}\.${libcudacxx_VERSION_MINOR}\.${libcudacxx_VERSION_PATCH}"
14+
)
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#include <cuda/std/atomic>
2+
3+
#include <cstdio>
4+
5+
int main()
6+
{
7+
cuda::std::atomic<int> x{0};
8+
9+
printf("Built with libcudacxx version %d.%d.%d.\n",
10+
_LIBCUDACXX_CUDA_API_VERSION_MAJOR,
11+
_LIBCUDACXX_CUDA_API_VERSION_MINOR,
12+
_LIBCUDACXX_CUDA_API_VERSION_PATCH);
13+
14+
return x;
15+
}
16+
17+
18+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Parse version information from version header:
2+
include("${CMAKE_CURRENT_LIST_DIR}/libcudacxx-header-search.cmake")
3+
4+
file(READ "${_libcudacxx_VERSION_INCLUDE_DIR}/cuda/std/detail/__config"
5+
libcudacxx_VERSION_HEADER
6+
)
7+
8+
string(REGEX MATCH
9+
"#define[ \t]+_LIBCUDACXX_CUDA_API_VERSION[ \t]+([0-9]+)" unused_var
10+
"${libcudacxx_VERSION_HEADER}"
11+
)
12+
13+
set(libcudacxx_VERSION_FLAT ${CMAKE_MATCH_1})
14+
math(EXPR libcudacxx_VERSION_MAJOR "${libcudacxx_VERSION_FLAT} / 1000000")
15+
math(EXPR libcudacxx_VERSION_MINOR "(${libcudacxx_VERSION_FLAT} / 1000) % 1000")
16+
math(EXPR libcudacxx_VERSION_PATCH "${libcudacxx_VERSION_FLAT} % 1000")
17+
set(libcudacxx_VERSION_TWEAK 0)
18+
19+
set(libcudacxx_VERSION
20+
"${libcudacxx_VERSION_MAJOR}.${libcudacxx_VERSION_MINOR}.${libcudacxx_VERSION_PATCH}.${libcudacxx_VERSION_TWEAK}"
21+
)
22+
23+
set(PACKAGE_VERSION ${libcudacxx_VERSION})
24+
set(PACKAGE_VERSION_COMPATIBLE FALSE)
25+
set(PACKAGE_VERSION_EXACT FALSE)
26+
set(PACKAGE_VERSION_UNSUITABLE FALSE)
27+
28+
if(PACKAGE_VERSION VERSION_GREATER_EQUAL PACKAGE_FIND_VERSION)
29+
if(PACKAGE_FIND_VERSION_MAJOR VERSION_EQUAL libcudacxx_VERSION_MAJOR)
30+
set(PACKAGE_VERSION_COMPATIBLE TRUE)
31+
endif()
32+
33+
if(PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION)
34+
set(PACKAGE_VERSION_EXACT TRUE)
35+
endif()
36+
endif()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#
2+
# find_package(libcudacxx) config file.
3+
#
4+
# Defines a libcudacxx::libcudacxx target that may be linked from user projects to include
5+
# libcudacxx.
6+
7+
if (TARGET libcudacxx::libcudacxx)
8+
return()
9+
endif()
10+
11+
function(_libcudacxx_declare_interface_alias alias_name ugly_name)
12+
# 1) Only IMPORTED and ALIAS targets can be placed in a namespace.
13+
# 2) When an IMPORTED library is linked to another target, its include
14+
# directories are treated as SYSTEM includes.
15+
# 3) nvcc will automatically check the CUDA Toolkit include path *before* the
16+
# system includes. This means that the Toolkit libcudacxx will *always* be used
17+
# during compilation, and the include paths of an IMPORTED libcudacxx::libcudacxx
18+
# target will never have any effect.
19+
# 4) This behavior can be fixed by setting the property NO_SYSTEM_FROM_IMPORTED
20+
# on EVERY target that links to libcudacxx::libcudacxx. This would be a burden and a
21+
# footgun for our users. Forgetting this would silently pull in the wrong libcudacxx!
22+
# 5) A workaround is to make a non-IMPORTED library outside of the namespace,
23+
# configure it, and then ALIAS it into the namespace (or ALIAS and then
24+
# configure, that seems to work too).
25+
add_library(${ugly_name} INTERFACE)
26+
add_library(${alias_name} ALIAS ${ugly_name})
27+
endfunction()
28+
29+
#
30+
# Setup targets
31+
#
32+
33+
_libcudacxx_declare_interface_alias(libcudacxx::libcudacxx _libcudacxx_libcudacxx)
34+
# Pull in the include dir detected by libcudacxx-config-version.cmake
35+
set(_libcudacxx_INCLUDE_DIR "${_libcudacxx_VERSION_INCLUDE_DIR}"
36+
CACHE INTERNAL "Location of libcudacxx headers."
37+
)
38+
unset(_libcudacxx_VERSION_INCLUDE_DIR CACHE) # Clear tmp variable from cache
39+
target_include_directories(_libcudacxx_libcudacxx INTERFACE "${_libcudacxx_INCLUDE_DIR}")
40+
41+
#
42+
# Standardize version info
43+
#
44+
45+
set(LIBCUDACXX_VERSION ${${CMAKE_FIND_PACKAGE_NAME}_VERSION} CACHE INTERNAL "")
46+
set(LIBCUDACXX_VERSION_MAJOR ${${CMAKE_FIND_PACKAGE_NAME}_VERSION_MAJOR} CACHE INTERNAL "")
47+
set(LIBCUDACXX_VERSION_MINOR ${${CMAKE_FIND_PACKAGE_NAME}_VERSION_MINOR} CACHE INTERNAL "")
48+
set(LIBCUDACXX_VERSION_PATCH ${${CMAKE_FIND_PACKAGE_NAME}_VERSION_PATCH} CACHE INTERNAL "")
49+
set(LIBCUDACXX_VERSION_TWEAK ${${CMAKE_FIND_PACKAGE_NAME}_VERSION_TWEAK} CACHE INTERNAL "")
50+
set(LIBCUDACXX_VERSION_COUNT ${${CMAKE_FIND_PACKAGE_NAME}_VERSION_COUNT} CACHE INTERNAL "")
51+
52+
include(FindPackageHandleStandardArgs)
53+
if (NOT libcudacxx_CONFIG)
54+
set(libcudacxx_CONFIG "${CMAKE_CURRENT_LIST_FILE}")
55+
endif()
56+
find_package_handle_standard_args(libcudacxx CONFIG_MODE)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Parse version information from version header:
2+
unset(_libcudacxx_VERSION_INCLUDE_DIR CACHE) # Clear old result to force search
3+
find_path(_libcudacxx_VERSION_INCLUDE_DIR cuda/std/detail/__config
4+
NO_DEFAULT_PATH # Only search explicit paths below:
5+
PATHS
6+
"${CMAKE_CURRENT_LIST_DIR}/../../../include" # Source tree
7+
)
8+
set_property(CACHE _libcudacxx_VERSION_INCLUDE_DIR PROPERTY TYPE INTERNAL)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Parse version information from version header:
2+
unset(_libcudacxx_VERSION_INCLUDE_DIR CACHE) # Clear old result to force search
3+
find_path(_libcudacxx_VERSION_INCLUDE_DIR cuda/std/detail/__config
4+
NO_DEFAULT_PATH # Only search explicit paths below:
5+
PATHS
6+
"${CMAKE_CURRENT_LIST_DIR}/../../../@CMAKE_INSTALL_INCLUDEDIR@" # Install tree
7+
)
8+
set_property(CACHE _libcudacxx_VERSION_INCLUDE_DIR PROPERTY TYPE INTERNAL)

0 commit comments

Comments
 (0)