Skip to content

Commit

Permalink
Use CTest dynamic resource spec generation
Browse files Browse the repository at this point in the history
CMake has supported dynamic resource spec generation since 3.28.
Since we now require 3.30, use this feature instead of implementing
it ourselves.
  • Loading branch information
KyleFromNVIDIA committed Feb 27, 2025
1 parent b01af45 commit 06b7834
Show file tree
Hide file tree
Showing 21 changed files with 199 additions and 130 deletions.
10 changes: 7 additions & 3 deletions rapids-cmake/test/detail/generate_installed_CTestTestfile.cmake
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#=============================================================================
# Copyright (c) 2023-2024, NVIDIA CORPORATION.
# Copyright (c) 2023-2025, NVIDIA CORPORATION.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -267,8 +267,12 @@ set(test_file_content
"
set(CTEST_SCRIPT_DIRECTORY \".\")
set(CMAKE_INSTALL_PREFIX \"./${_RAPIDS_INSTALL_PREFIX}\")
set(CTEST_RESOURCE_SPEC_FILE \"./${rapids_test_json_file_name}\")
execute_process(COMMAND ./${rapids_test_generate_exe_name} OUTPUT_FILE \"\${CTEST_RESOURCE_SPEC_FILE}\" COMMAND_ERROR_IS_FATAL ANY)
add_test(generate_resource_spec ./${rapids_test_generate_exe_name} \"./${rapids_test_json_file_name}\")
execute_process(COMMAND ./${rapids_test_generate_exe_name} --cwd COMMAND_ERROR_IS_FATAL ANY OUTPUT_VARIABLE _cwd)
set_tests_properties(generate_resource_spec PROPERTIES
FIXTURES_SETUP resource_spec
GENERATED_RESOURCE_SPEC_FILE \"\${_cwd}/${rapids_test_json_file_name}\"
)
\n\n
")

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022-2024, NVIDIA CORPORATION.
* Copyright (c) 2022-2025, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -18,6 +18,8 @@
#include <cuda_runtime_api.h>
#endif

#include <filesystem>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
Expand Down Expand Up @@ -47,7 +49,7 @@ void to_json(std::ostream& buffer, gpu const& g)
buffer << "\t\t{\"id\": \"" << g.id << "\", \"slots\": " << g.slots << "}";
}

int main()
int main(int argc, char** argv)
{
std::vector<gpu> gpus;
int nDevices = 0;
Expand All @@ -67,19 +69,36 @@ int main()
gpus.push_back(gpu(0));
#endif

if (argc != 2) {
std::cout << "Usage: " << argv[0] << " <filename>\n";
return 1;
}

// GENERATED_RESOURCE_SPEC_FILE requires an absolute path, and CMake does
// not have a "give me the current working directory" command, so we have to
// get it from here.
std::string arg = argv[1];
if (arg == "--cwd") {
std::cout << std::filesystem::current_path().string();
std::cout.flush();
return 0;
}

std::ofstream fout(argv[1]);

version v;
std::cout << "{\n";
to_json(std::cout, v);
std::cout << ",\n";
std::cout << "\"local\": [{\n";
std::cout << "\t\"gpus\": [\n";
fout << "{\n";
to_json(fout, v);
fout << ",\n";
fout << "\"local\": [{\n";
fout << "\t\"gpus\": [\n";
for (int i = 0; i < gpus.size(); ++i) {
to_json(std::cout, gpus[i]);
if (i != (gpus.size() - 1)) { std::cout << ","; }
std::cout << "\n";
to_json(fout, gpus[i]);
if (i != (gpus.size() - 1)) { fout << ","; }
fout << "\n";
}
std::cout << "\t]\n";
std::cout << "}]\n";
std::cout << "}" << std::endl;
fout << "\t]\n";
fout << "}]\n";
fout << "}" << std::endl;
return 0;
}
32 changes: 0 additions & 32 deletions rapids-cmake/test/detail/generate_resource_spec/CMakeLists.txt

This file was deleted.

5 changes: 3 additions & 2 deletions rapids-cmake/test/detail/run_gpu_test.cmake
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#=============================================================================
# Copyright (c) 2022-2024, NVIDIA CORPORATION.
# Copyright (c) 2022-2025, NVIDIA CORPORATION.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -16,8 +16,9 @@
cmake_minimum_required(VERSION 3.26.4)

if(DEFINED ENV{CTEST_RESOURCE_GROUP_COUNT})
math(EXPR max_index "$ENV{CTEST_RESOURCE_GROUP_COUNT}-1")
# cmake-lint: disable=E1120
foreach(index RANGE 0 ${CTEST_RESOURCE_GROUP_COUNT})
foreach(index RANGE 0 "${max_index}")
set(allocation $ENV{CTEST_RESOURCE_GROUP_${index}_GPUS})
if(DEFINED allocation)
# strings look like "id:value,slots:value" so let's make a super lazy parser by deleting `id:`
Expand Down
35 changes: 19 additions & 16 deletions rapids-cmake/test/generate_resource_spec.cmake
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#=============================================================================
# Copyright (c) 2022-2024, NVIDIA CORPORATION.
# Copyright (c) 2022-2025, NVIDIA CORPORATION.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -66,23 +66,26 @@ function(rapids_test_generate_resource_spec DESTINATION filepath)
include(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/detail/default_names.cmake)
set(eval_exe ${PROJECT_BINARY_DIR}/rapids-cmake/${rapids_test_generate_exe_name})

if(NOT EXISTS "${eval_exe}")
if(NOT TARGET generate_ctest_json)
find_package(CUDAToolkit QUIET)
file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/rapids-cmake/")

try_compile(result "${PROJECT_BINARY_DIR}/rapids-cmake/generate_ctest_json-build"
"${CMAKE_CURRENT_FUNCTION_LIST_DIR}/detail/generate_resource_spec"
generate_resource_spec
CMAKE_FLAGS "-DCUDAToolkit_ROOT=${CUDAToolkit_ROOT}" "-Doutput_file=${eval_exe}"
"-Dlang=${rapids_lang}" "-Dcuda_toolkit=${CUDAToolkit_FOUND}"
OUTPUT_VARIABLE compile_output)

if(NOT result)
string(REPLACE "\n" "\n " compile_output "${compile_output}")
message(FATAL_ERROR "rapids_test_generate_resource_spec failed to build detection executable.\nfailure details are:\n ${compile_output}"
)

add_executable(generate_ctest_json
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/detail/generate_resource_spec.cpp)
if(CUDAToolkit_FOUND)
target_link_libraries(generate_ctest_json PRIVATE CUDA::cudart_static)
target_compile_definitions(generate_ctest_json PRIVATE HAVE_CUDA)
endif()
set_property(SOURCE ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/detail/generate_resource_spec.cpp
PROPERTY LANGUAGE ${rapids_lang})
set_target_properties(generate_ctest_json
PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/rapids-cmake/"
OUTPUT_NAME ${rapids_test_generate_exe_name})
target_compile_features(generate_ctest_json PRIVATE cxx_std_17)

add_test(NAME generate_resource_spec COMMAND generate_ctest_json "${filepath}")
set_tests_properties(generate_resource_spec
PROPERTIES FIXTURES_SETUP resource_spec GENERATED_RESOURCE_SPEC_FILE
"${filepath}")
endif()
execute_process(COMMAND ${eval_exe} OUTPUT_FILE "${filepath}" COMMAND_ERROR_IS_FATAL ANY)

endfunction()
3 changes: 2 additions & 1 deletion rapids-cmake/test/gpu_requirements.cmake
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#=============================================================================
# Copyright (c) 2022-2024, NVIDIA CORPORATION.
# Copyright (c) 2022-2025, NVIDIA CORPORATION.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -87,6 +87,7 @@ function(rapids_test_gpu_requirements test_name)

if(gpus AND percent)
set_property(TEST ${test_name} PROPERTY RESOURCE_GROUPS "${gpus},gpus:${percent}")
set_property(TEST ${test_name} PROPERTY FIXTURES_REQUIRED resource_spec)
endif()

endfunction()
6 changes: 2 additions & 4 deletions rapids-cmake/test/init.cmake
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#=============================================================================
# Copyright (c) 2022-2023, NVIDIA CORPORATION.
# Copyright (c) 2022-2025, NVIDIA CORPORATION.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -58,10 +58,8 @@ function(rapids_test_init)
include(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/generate_resource_spec.cmake)
set(rapids_test_spec_file "${PROJECT_BINARY_DIR}/${rapids_test_json_file_name}")

rapids_test_generate_resource_spec(DESTINATION "${rapids_test_spec_file}")

if(NOT CTEST_RESOURCE_SPEC_FILE)
set(CTEST_RESOURCE_SPEC_FILE "${rapids_test_spec_file}" PARENT_SCOPE)
rapids_test_generate_resource_spec(DESTINATION "${rapids_test_spec_file}")
endif()

endfunction()
9 changes: 4 additions & 5 deletions rapids-cmake/test/install_relocatable.cmake
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#=============================================================================
# Copyright (c) 2022-2023, NVIDIA CORPORATION.
# Copyright (c) 2022-2025, NVIDIA CORPORATION.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -104,10 +104,9 @@ function(rapids_test_install_relocatable)
# We need to install the rapids-test gpu detector, and the json script we also need to write out /
# install the new CTestTestfile.cmake
include(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/detail/default_names.cmake)
if(EXISTS "${PROJECT_BINARY_DIR}/rapids-cmake/${rapids_test_generate_exe_name}")
install(PROGRAMS "${PROJECT_BINARY_DIR}/rapids-cmake/${rapids_test_generate_exe_name}"
COMPONENT ${_RAPIDS_TEST_INSTALL_COMPONENT_SET} DESTINATION ${_RAPIDS_TEST_DESTINATION}
${to_exclude})
if(TARGET generate_ctest_json)
install(TARGETS generate_ctest_json COMPONENT ${_RAPIDS_TEST_INSTALL_COMPONENT_SET}
DESTINATION ${_RAPIDS_TEST_DESTINATION} ${to_exclude})
endif()
if(EXISTS "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/detail/run_gpu_test.cmake")
install(FILES "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/detail/run_gpu_test.cmake"
Expand Down
4 changes: 2 additions & 2 deletions testing/test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#=============================================================================
# Copyright (c) 2022-2024, NVIDIA CORPORATION.
# Copyright (c) 2022-2025, NVIDIA CORPORATION.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -15,7 +15,7 @@
#=============================================================================
add_cmake_config_test( rapids-test.cmake )

add_cmake_config_test(generate_resource_spec-no-gpus.cmake)
add_cmake_build_test(generate_resource_spec-no-gpus)
add_cmake_config_test(generate_resource_spec-simple.cmake)

set(percent_error_message "rapids_test_gpu_requirements requires a numeric PERCENT value [1-100].")
Expand Down
42 changes: 42 additions & 0 deletions testing/test/generate_resource_spec-no-gpus/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#=============================================================================
# Copyright (c) 2022-2025, NVIDIA CORPORATION.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#=============================================================================
cmake_minimum_required(VERSION 3.30.4)
project(rapids-test-project LANGUAGES CUDA)

include(${rapids-cmake-dir}/test/generate_resource_spec.cmake)

enable_testing()

rapids_test_generate_resource_spec(DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/spec.json )

add_test(NAME read_spec_file COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/read_spec_file.cmake)
set_tests_properties(read_spec_file PROPERTIES
FIXTURES_REQUIRED resource_spec
)
# Set the visible device list to invalid device ids so we have zero visible
set_tests_properties(generate_resource_spec PROPERTIES
ENVIRONMENT CUDA_VISIBLE_DEVICES=-1
)

set(_config_arg)
get_property(_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(_multi_config)
set(_config_arg -C $<CONFIG>)
endif()
add_custom_target(run_tests ALL
COMMAND ${CMAKE_CTEST_COMMAND} --test-dir ${CMAKE_CURRENT_BINARY_DIR} --no-tests=error -V ${_config_arg}
)
add_dependencies(run_tests generate_ctest_json)
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#=============================================================================
# Copyright (c) 2022-2023, NVIDIA CORPORATION.
# Copyright (c) 2025, NVIDIA CORPORATION.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -13,22 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#=============================================================================
include(${rapids-cmake-dir}/test/generate_resource_spec.cmake)

enable_language(CUDA)

# Set the visible device list to invalid device ids so we have zero visible
set(ENV{CUDA_VISIBLE_DEVICES} -1)

set(CTEST_RESOURCE_SPEC_FILE "sentinel file")
rapids_test_generate_resource_spec(DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/spec.json )

if(NOT CTEST_RESOURCE_SPEC_FILE STREQUAL "sentinel file")
message(FATAL_ERROR "CTEST_RESOURCE_SPEC_FILE shouldn't be modified by calling rapids_test_generate_resource_spec")
endif()

if(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/spec.json")
message(FATAL_ERROR "rapids_test_ll generate_resource_spec failed to write out the requested spec file")
message(FATAL_ERROR "rapids_test_generate_resource_spec failed to write out the requested spec file")
endif()

file(READ "${CMAKE_CURRENT_BINARY_DIR}/spec.json" content)
Expand Down
6 changes: 3 additions & 3 deletions testing/test/generate_resource_spec-simple.cmake
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#=============================================================================
# Copyright (c) 2022-2023, NVIDIA CORPORATION.
# Copyright (c) 2022-2025, NVIDIA CORPORATION.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -24,6 +24,6 @@ if(NOT CTEST_RESOURCE_SPEC_FILE STREQUAL "sentinel file")
message(FATAL_ERROR "CTEST_RESOURCE_SPEC_FILE shouldn't be modified by calling rapids_test_generate_resource_spec")
endif()

if(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/spec.json")
message(FATAL_ERROR "rapids_test_generate_resource_spec failed to write out the requested spec file")
if(NOT TEST generate_resource_spec)
message(FATAL_ERROR "rapids_test_generate_resource_spec failed to create the generate_resource_spec test")
endif()
16 changes: 11 additions & 5 deletions testing/test/init-simple.cmake
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#=============================================================================
# Copyright (c) 2022-2023, NVIDIA CORPORATION.
# Copyright (c) 2022-2025, NVIDIA CORPORATION.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -19,10 +19,16 @@ enable_language(CUDA)

rapids_test_init()

if(NOT DEFINED CTEST_RESOURCE_SPEC_FILE)
message(FATAL_ERROR "CTEST_RESOURCE_SPEC_FILE should be set after calling rapids_test_init")
if(NOT TEST generate_resource_spec)
message(FATAL_ERROR "generate_resource_spec test should exist after calling rapids_test_init")
endif()

if(NOT EXISTS "${CTEST_RESOURCE_SPEC_FILE}")
message(FATAL_ERROR "CTEST_RESOURCE_SPEC_FILE should exist on disk after calling rapids_test_init")
get_test_property(generate_resource_spec FIXTURES_SETUP fixtures_setup)
if(NOT fixtures_setup STREQUAL "resource_spec")
message(FATAL_ERROR "generate_resource_spec FIXTURES_SETUP property should be set to \"resource_spec\"")
endif()

get_test_property(generate_resource_spec GENERATED_RESOURCE_SPEC_FILE grsf)
if(NOT grsf STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/resource_spec.json")
message(FATAL_ERROR "generate_resource_spec FIXTURES_SETUP property should be set to \"${CMAKE_CURRENT_BINARY_DIR}/resource_spec.json\"")
endif()
Loading

0 comments on commit 06b7834

Please sign in to comment.