Skip to content

Commit

Permalink
Consolidate packages and install rules (#2456)
Browse files Browse the repository at this point in the history
* Migrate CMake packages to central location.

* Remove obsolete infra tests.

These tests check that consumers can

add_subdirectory(cccl/cub)
add_subdirectory(cccl/thrust)

to add Thrust or CUB to their build.
This hasn't been sensible or supported since we migrated to the monorepo.

Now that we're moving shared CMake infra to the CCCL, these tests are finally actually failing.

* Migrate install rules to top-level, use `cccl_generate_install_rules` helper to reduce redundancy.

* Remove libcudacxx export tests.

These tests are redundant with CCCL-level tests, and
no longer function now that install rules are centralized
at the top level.

* Make std arg for test_thrust.ps1 optional.

* Ensure that cudax::Thrust target is only created once.
  • Loading branch information
alliepiper authored Sep 25, 2024
1 parent 17e0c83 commit 2cbf40b
Show file tree
Hide file tree
Showing 59 changed files with 250 additions and 644 deletions.
7 changes: 2 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,10 @@ endif()
# Enable CXX so CMake can configure install paths
project(CCCL LANGUAGES CXX)

# Optionally include installation rules for non-top-level builds:
option(CCCL_ENABLE_INSTALL_RULES "Enable installation of CCCL." ${CCCL_TOPLEVEL_PROJECT})
if (CCCL_ENABLE_INSTALL_RULES)
include(cmake/CCCLInstallRules.cmake)
endif()
include(cmake/CCCLInstallRules.cmake)

# Support adding CCCL to a parent project via add_subdirectory.
include(cmake/CCCLAddSubdirHelper.cmake) # Always include, this is used by subprojects as well.
if (NOT CCCL_TOPLEVEL_PROJECT)
include(cmake/CCCLAddSubdir.cmake)
endif()
Expand Down
41 changes: 0 additions & 41 deletions CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@
"cacheVariables": {
"CCCL_ENABLE_LIBCUDACXX": true,
"LIBCUDACXX_ENABLE_LIBCUDACXX_TESTS": false,
"libcudacxx_ENABLE_CMAKE_TESTS": false,
"libcudacxx_ENABLE_CODEGEN": true,
"LIBCUDACXX_ENABLE_CUDA": false
}
Expand Down Expand Up @@ -471,18 +470,6 @@
"configurePreset": "all-dev-debug",
"inherits": "all-dev"
},
{
"name": "libcudacxx-ctest-base",
"hidden": true,
"inherits": [
"base"
],
"filter": {
"exclude": {
"name": "^libcudacxx\\.test\\.(lit|atomics\\.codegen\\.diff)$"
}
}
},
{
"name": "libcudacxx-codegen",
"configurePreset": "libcudacxx-codegen",
Expand All @@ -492,34 +479,6 @@
}
}
},
{
"name": "libcudacxx-ctest-cpp11",
"configurePreset": "libcudacxx-cpp11",
"inherits": [
"libcudacxx-ctest-base"
]
},
{
"name": "libcudacxx-ctest-cpp14",
"configurePreset": "libcudacxx-cpp14",
"inherits": [
"libcudacxx-ctest-base"
]
},
{
"name": "libcudacxx-ctest-cpp17",
"configurePreset": "libcudacxx-cpp17",
"inherits": [
"libcudacxx-ctest-base"
]
},
{
"name": "libcudacxx-ctest-cpp20",
"configurePreset": "libcudacxx-cpp20",
"inherits": [
"libcudacxx-ctest-base"
]
},
{
"name": "libcudacxx-lit-base",
"hidden": true,
Expand Down
6 changes: 0 additions & 6 deletions ci/test_libcudacxx.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,8 @@ CMAKE_OPTIONS=""

configure_preset libcudacxx "$PRESET" "$CMAKE_OPTIONS"

# The libcudacxx tests are split into two presets, one for
# regular ctest tests and another that invokes the lit tests
# harness with extra options for verbosity, etc:
CTEST_PRESET="libcudacxx-ctest-cpp${CXX_STANDARD}"
LIT_PRESET="libcudacxx-lit-cpp${CXX_STANDARD}"

test_preset "libcudacxx (CTest)" ${CTEST_PRESET}

source "./sccache_stats.sh" "start"
test_preset "libcudacxx (lit)" ${LIT_PRESET}
source "./sccache_stats.sh" "end"
Expand Down
2 changes: 1 addition & 1 deletion ci/windows/test_thrust.ps1
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Param(
[Parameter(Mandatory = $true)]
[Parameter(Mandatory = $false)]
[Alias("std")]
[ValidateNotNullOrEmpty()]
[ValidateSet(11, 14, 17, 20)]
Expand Down
9 changes: 4 additions & 5 deletions cmake/CCCLAddSubdir.cmake
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
find_package(CCCL REQUIRED CONFIG
NO_DEFAULT_PATH # Only check the explicit path in HINTS:
HINTS "${CCCL_SOURCE_DIR}"
COMPONENTS ${CCCL_REQUIRED_COMPONENTS}
OPTIONAL_COMPONENTS ${CCCL_OPTIONAL_COMPONENTS}
cccl_add_subdir_helper(CCCL
# These component lists may be set by users to explicitly request subprojects:
REQUIRED_COMPONENTS "${CCCL_REQUIRED_COMPONENTS}"
OPTIONAL_COMPONENTS "${CCCL_OPTIONAL_COMPONENTS}"
)
43 changes: 43 additions & 0 deletions cmake/CCCLAddSubdirHelper.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# project_name: The name of the project when calling `find_package`. Case sensitive.
# `PACKAGE_FILEBASE` the name of the project in the config files, ie. ${PACKAGE_FILEBASE}-config.cmake.
# `PACKAGE_PATH` the path to the project's CMake package config files.
function(cccl_add_subdir_helper project_name)
set(options)
set(oneValueArgs PACKAGE_PATH PACKAGE_FILEBASE REQUIRED_COMPONENTS OPTIONAL_COMPONENTS)
set(multiValueArgs)
cmake_parse_arguments(CCCL_SUBDIR "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})

if (DEFINED CCCL_SUBDIR_PACKAGE_FILEBASE)
set(package_filebase "${CCCL_SUBDIR_PACKAGE_FILEBASE}")
else()
string(TOLOWER "${project_name}" package_filebase)
endif()

if (DEFINED CCCL_SUBDIR_PACKAGE_PATH)
set(package_prefix "${CCCL_SUBDIR_PACKAGE_PATH}/${package_filebase}")
else()
set(package_prefix "${CCCL_SOURCE_DIR}/lib/cmake/${package_filebase}/${package_filebase}")
endif()

set(CMAKE_FIND_PACKAGE_NAME ${project_name})
set(${CMAKE_FIND_PACKAGE_NAME}_FIND_COMPONENTS)
if (DEFINED CCCL_SUBDIR_REQUIRED_COMPONENTS)
list(APPEND ${CMAKE_FIND_PACKAGE_NAME}_FIND_COMPONENTS ${CCCL_SUBDIR_REQUIRED_COMPONENTS})
foreach(component IN LISTS CCCL_SUBDIR_REQUIRED_COMPONENTS)
set(${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED_${component} TRUE)
endforeach()
endif()

if (DEFINED CCCL_SUBDIR_OPTIONAL_COMPONENTS)
list(APPEND ${CMAKE_FIND_PACKAGE_NAME}_FIND_COMPONENTS ${CCCL_SUBDIR_OPTIONAL_COMPONENTS})
endif()

# This effectively does a `find_package` actually going through the find_package
# machinery. Using `find_package` works for the first configure, but creates
# inconsistencies during subsequent configurations when using CPM..
#
# More details are in the discussion at
# https://github.com/NVIDIA/libcudacxx/pull/242#discussion_r794003857
include("${package_prefix}-config-version.cmake")
include("${package_prefix}-config.cmake")
endfunction()
120 changes: 116 additions & 4 deletions cmake/CCCLInstallRules.cmake
Original file line number Diff line number Diff line change
@@ -1,9 +1,121 @@
# Bring in CMAKE_INSTALL_LIBDIR
# Bring in CMAKE_INSTALL_* vars
include(GNUInstallDirs)

# CCCL has no installable binaries, no need to build before installing:
set(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY TRUE)

install(DIRECTORY "${CCCL_SOURCE_DIR}/lib/cmake/cccl"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/"
)
# Usage:
# cccl_generate_install_rules(PROJECT_NAME DEFAULT_ENABLE
# [NO_HEADERS]
# [HEADER_SUBDIR <subdir1> [subdir2 ...]]
# [HEADERS_INCLUDE <pattern1> [pattern2 ...]]
# [HEADERS_EXCLUDE <pattern1> [pattern2 ...]]
# [PACKAGE]
# )
#
# Options:
# PROJECT_NAME: The case-sensitive name of the project. Used to generate the option flag.
# DEFAULT_ENABLE: Whether the install rules should be enabled by default.
# NO_HEADERS: If set, no install rules will be generated for headers.
# HEADERS_SUBDIRS: If set, a separate install rule will be generated for each subdirectory relative to the project dir.
# If not set, <CCCL_SOURCE_DIR>/<PROJECT_NAME_LOWER>/<PROJECT_NAME_LOWER> will be used.
# HEADERS_INCLUDE: A list of globbing patterns that match installable header files.
# HEADERS_EXCLUDE: A list of globbing patterns that match header files to exclude from installation.
# PACKAGE: If set, install the project's CMake package.
#
# Notes:
# - The generated cache option will be named <PROJECT_NAME>_ENABLE_INSTALL_RULES.
# - The header globs are applied relative to <CCCL_SOURCE_DIR>/<PROJECT_NAME_LOWER>/<SUBDIR>.
# - The cmake package is assumed to be located at <CCCL_SOURCE_DIR>/lib/cmake/<PROJECT_NAME_LOWER>.
# - If a <PROJECT_NAME_LOWER>-header-search.cmake.in file exists in the CMake package directory,
# it will be configured and installed.
#
function(cccl_generate_install_rules project_name enable_rules_by_default)
set(options PACKAGE NO_HEADERS)
set(oneValueArgs)
set(multiValueArgs HEADERS_SUBDIRS HEADERS_INCLUDE HEADERS_EXCLUDE)
cmake_parse_arguments(CGIR "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})

string(TOLOWER ${project_name} project_name_lower)
set(project_source_dir "${CCCL_SOURCE_DIR}/${project_name_lower}")
set(header_dest_dir "${CMAKE_INSTALL_INCLUDEDIR}")
set(package_source_dir "${CCCL_SOURCE_DIR}/lib/cmake/${project_name_lower}")
set(package_dest_dir "${CMAKE_INSTALL_LIBDIR}/cmake/")
set(header_search_template "${package_source_dir}/${project_name_lower}-header-search.cmake.in")
set(header_search_temporary "${CCCL_BINARY_DIR}/${project_name_lower}-header-search.cmake")

if (NOT DEFINED CGIR_HEADERS_SUBDIRS)
set(CGIR_HEADERS_SUBDIRS "${project_name_lower}")
endif()

set(flag_name ${project_name}_ENABLE_INSTALL_RULES)
option(${flag_name} "Enable installation of ${project_name} files." ${enable_rules_by_default})
if (${flag_name})
# Headers:
if (NOT CGIR_NO_HEADERS)
foreach(subdir IN LISTS CGIR_HEADERS_SUBDIRS)
set(header_globs)
if(DEFINED CGIR_HEADERS_INCLUDE OR DEFINED CGIR_HEADERS_EXCLUDE)
set(header_globs "FILES_MATCHING")

foreach (header_glob IN LISTS CGIR_HEADERS_INCLUDE)
list(APPEND header_globs "PATTERN" "${header_glob}")
endforeach()

foreach (header_glob IN LISTS CGIR_HEADERS_EXCLUDE)
list(APPEND header_globs "PATTERN" "${header_glob}" "EXCLUDE")
endforeach()
endif()

install(
DIRECTORY "${project_source_dir}/${subdir}"
DESTINATION "${header_dest_dir}"
${header_globs}
)
endforeach()
endif()

# CMake package:
install(
DIRECTORY "${package_source_dir}"
DESTINATION "${package_dest_dir}"
REGEX .*header-search.cmake.* EXCLUDE
)

# Header search infra:
if (EXISTS "${header_search_template}")
# Need to configure a file to store the infix specified in
# CMAKE_INSTALL_INCLUDEDIR since it can be defined by the user
set(_CCCL_RELATIVE_LIBDIR "${CMAKE_INSTALL_LIBDIR}")
if(_CCCL_RELATIVE_LIBDIR MATCHES "^${CMAKE_INSTALL_PREFIX}")
# libdir is an abs string that starts with prefix
string(LENGTH "${CMAKE_INSTALL_PREFIX}" to_remove)
string(SUBSTRING "${_CCCL_RELATIVE_LIBDIR}" ${to_remove} -1 relative)
# remove any leading "/""
string(REGEX REPLACE "^/(.)" "\\1" _CCCL_RELATIVE_LIBDIR "${relative}")
elseif(_CCCL_RELATIVE_LIBDIR MATCHES "^/")
message(FATAL_ERROR "CMAKE_INSTALL_LIBDIR ('${CMAKE_INSTALL_LIBDIR}') must be a relative path or an absolute path under CMAKE_INSTALL_PREFIX ('${CMAKE_INSTALL_PREFIX}')")
endif()
set(install_location "${_CCCL_RELATIVE_LIBDIR}/cmake/${project_name_lower}")

# Transform to a list of directories, replace each directory with "../"
# and convert back to a string
string(REGEX REPLACE "/" ";" from_install_prefix "${install_location}")
list(TRANSFORM from_install_prefix REPLACE ".+" "../")
list(JOIN from_install_prefix "" from_install_prefix)

configure_file("${header_search_template}" "${header_search_temporary}" @ONLY)
install(
FILES "${header_search_temporary}"
DESTINATION "${install_location}"
)
endif()

endif()
endfunction()

include("${CMAKE_CURRENT_LIST_DIR}/install/cccl.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/install/cub.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/install/cudax.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/install/libcudacxx.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/install/thrust.cmake")
4 changes: 4 additions & 0 deletions cmake/install/cccl.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
cccl_generate_install_rules(CCCL ${CCCL_TOPLEVEL_PROJECT}
NO_HEADERS
PACKAGE
)
4 changes: 4 additions & 0 deletions cmake/install/cub.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
cccl_generate_install_rules(CUB ${CCCL_TOPLEVEL_PROJECT}
HEADERS_INCLUDE "*.cuh" "*.hpp"
PACKAGE
)
5 changes: 5 additions & 0 deletions cmake/install/cudax.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
cccl_generate_install_rules(cudax ${CCCL_TOPLEVEL_PROJECT}
HEADERS_SUBDIRS "include/cuda"
HEADERS_INCLUDE "*.cuh"
PACKAGE
)
6 changes: 6 additions & 0 deletions cmake/install/libcudacxx.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
cccl_generate_install_rules(libcudacxx ${CCCL_TOPLEVEL_PROJECT}
HEADERS_SUBDIRS "include/cuda" "include/nv"
HEADERS_INCLUDE "*"
HEADERS_EXCLUDE "CMakeLists.txt"
PACKAGE
)
4 changes: 4 additions & 0 deletions cmake/install/thrust.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
cccl_generate_install_rules(Thrust ${CCCL_TOPLEVEL_PROJECT}
HEADERS_INCLUDE "*.h" "*.inl"
PACKAGE
)
5 changes: 0 additions & 5 deletions cub/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@ endif()
# GNUInstallDirs CMake module.
enable_language(CXX)

option(CUB_ENABLE_INSTALL_RULES "Enable installation of CUB" ${CUB_TOPLEVEL_PROJECT})
if (CUB_ENABLE_INSTALL_RULES)
include(cmake/CubInstallRules.cmake)
endif()

# Support adding CUB to a parent project via add_subdirectory.
# See examples/cmake/add_subdir/CMakeLists.txt for details.
if (NOT CUB_TOPLEVEL_PROJECT)
Expand Down
5 changes: 1 addition & 4 deletions cub/cmake/CubAddSubdir.cmake
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
find_package(CUB REQUIRED CONFIG
NO_DEFAULT_PATH # Only check the explicit path in HINTS:
HINTS "${CMAKE_CURRENT_LIST_DIR}/.."
)
cccl_add_subdir_helper(CUB)
5 changes: 3 additions & 2 deletions cub/cmake/CubBuildTargetList.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,15 @@ function(cub_build_target_list)
# Set up the CUB target while testing out our find_package scripts.
find_package(CUB REQUIRED CONFIG
NO_DEFAULT_PATH # Only check the explicit path in HINTS:
HINTS "${CUB_SOURCE_DIR}"
HINTS "${CCCL_SOURCE_DIR}/lib/cmake/cub/"
)

# TODO
# Some of the iterators and unittests depend on thrust. We should break the
# cyclical dependency by migrating CUB's Thrust bits into Thrust.
find_package(Thrust ${CUB_VERSION} EXACT CONFIG
HINTS "../thrust" # Monorepo path
NO_DEFAULT_PATH # Only check the explicit path in HINTS:
HINTS "${CCCL_SOURCE_DIR}/lib/cmake/thrust/"
)

if (Thrust_FOUND)
Expand Down
42 changes: 0 additions & 42 deletions cub/cmake/CubInstallRules.cmake

This file was deleted.

1 change: 0 additions & 1 deletion cub/examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,5 @@ function(cub_add_example target_name_var example_name example_src cub_target)
)
endfunction()

add_subdirectory(cmake)
add_subdirectory(block)
add_subdirectory(device)
Loading

0 comments on commit 2cbf40b

Please sign in to comment.