Bug 5591814: Update CMakeLists.txt and add cmake/InstallSamples.cmake to support make install

This commit is contained in:
Shawn Zeng 2025-10-31 16:57:26 +08:00
parent 9df0ef6411
commit 547f65851f
2 changed files with 174 additions and 0 deletions

View File

@ -22,4 +22,10 @@ endif()
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} --extended-lambda")
# Include installation configuration
include(cmake/InstallSamples.cmake)
add_subdirectory(Samples)
# Setup installation for all samples
setup_samples_install()

168
cmake/InstallSamples.cmake Normal file
View File

@ -0,0 +1,168 @@
# InstallSamples.cmake
# Configuration for installing CUDA samples to organized directory structure
#
# This module sets up installation paths organized by:
# - Target Architecture (x86_64, aarch64, etc.)
# - Target OS (linux, windows, darwin)
# - Build Type (release, debug)
#
# Default installation path: build/bin/${TARGET_ARCH}/${TARGET_OS}/${BUILD_TYPE}
#
# Installation structure:
# - Executables: installed to flat root directory only (easy access)
# - Data files (.ll, .ptx, .fatbin, etc.): installed to subdirectories (preserves relative paths)
# - run_tests.py handles path resolution automatically for both nested and flat structures
#
# Users can override by setting CMAKE_INSTALL_PREFIX or CUDA_SAMPLES_INSTALL_DIR
# Detect target architecture - use lowercase of CMAKE_SYSTEM_PROCESSOR
string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" TARGET_ARCH)
# Detect target OS
if(WIN32)
set(TARGET_OS "windows")
elseif(APPLE)
set(TARGET_OS "darwin")
elseif(UNIX)
if(CMAKE_SYSTEM_NAME MATCHES QNX)
set(TARGET_OS "qnx")
else()
set(TARGET_OS "linux")
endif()
else()
set(TARGET_OS "unknown")
endif()
# Get build type (default to release if not specified)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "release")
endif()
string(TOLOWER "${CMAKE_BUILD_TYPE}" BUILD_TYPE_LOWER)
# Set default install prefix to build/bin if not explicitly set by user
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/bin" CACHE PATH "Installation directory" FORCE)
endif()
# Create the installation path: bin/$(TARGET_ARCH)/$(TARGET_OS)/$(BUILD_TYPE)
set(CUDA_SAMPLES_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${TARGET_ARCH}/${TARGET_OS}/${BUILD_TYPE_LOWER}" CACHE PATH "Installation directory for CUDA samples")
# Print installation configuration
message(STATUS "CUDA Samples installation configured:")
message(STATUS " Architecture: ${TARGET_ARCH}")
message(STATUS " OS: ${TARGET_OS}")
message(STATUS " Build Type: ${BUILD_TYPE_LOWER}")
message(STATUS " Install Directory: ${CUDA_SAMPLES_INSTALL_DIR}")
# Function to setup installation for the project
# This should be called after all targets are defined
function(setup_samples_install)
# Create an install script that will copy executables and specific file types
# - Executables: copied to flat root directory (easy access)
# - Data files: copied to subdirectories (preserves relative paths)
# - run_tests.py automatically tries flattened paths as fallback
# This script runs at install time, after the build is complete
install(CODE "
file(GLOB_RECURSE SAMPLE_FILES
LIST_DIRECTORIES false
\"${CMAKE_BINARY_DIR}/Samples/*/*\"
\"${CMAKE_BINARY_DIR}/Samples/*/*/*\")
# Filter to include executable files and specific file types
foreach(SAMPLE_FILE IN LISTS SAMPLE_FILES)
# Skip non-files
if(NOT IS_DIRECTORY \"\${SAMPLE_FILE}\")
get_filename_component(SAMPLE_EXT \"\${SAMPLE_FILE}\" EXT)
get_filename_component(SAMPLE_NAME \"\${SAMPLE_FILE}\" NAME)
set(SHOULD_INSTALL FALSE)
# Skip build artifacts and CMake files
if(NOT SAMPLE_EXT MATCHES \"\\\\.(o|a|so|cmake)$\" AND
NOT SAMPLE_NAME MATCHES \"^(Makefile|cmake_install\\\\.cmake)$\" AND
NOT \"\${SAMPLE_FILE}\" MATCHES \"/CMakeFiles/\")
# Determine file type and whether to install
set(IS_EXECUTABLE FALSE)
set(IS_INTERMEDIATE_FILE FALSE)
# Check if file has required extension (fatbin, ptx, bc, raw, ppm)
if(SAMPLE_EXT MATCHES \"\\\\.(fatbin|ptx|bc|raw|ppm)$\")
set(SHOULD_INSTALL TRUE)
set(IS_INTERMEDIATE_FILE TRUE)
else()
# Check if file is executable
if(IS_SYMLINK \"\${SAMPLE_FILE}\" OR
(EXISTS \"\${SAMPLE_FILE}\" AND NOT IS_DIRECTORY \"\${SAMPLE_FILE}\"))
execute_process(
COMMAND test -x \"\${SAMPLE_FILE}\"
RESULT_VARIABLE HAS_EXEC_BIT
OUTPUT_QUIET ERROR_QUIET
)
if(HAS_EXEC_BIT EQUAL 0)
set(SHOULD_INSTALL TRUE)
set(IS_EXECUTABLE TRUE)
endif()
endif()
endif()
endif()
if(SHOULD_INSTALL)
get_filename_component(FILE_NAME \"\${SAMPLE_FILE}\" NAME)
if(IS_EXECUTABLE)
# Executables: install to flat directory for easy access
# run_tests.py will handle finding data files via flattened paths
message(STATUS \"Installing: ${CUDA_SAMPLES_INSTALL_DIR}/\${FILE_NAME}\")
file(COPY \"\${SAMPLE_FILE}\"
DESTINATION \"${CUDA_SAMPLES_INSTALL_DIR}\"
FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
GROUP_READ GROUP_EXECUTE
WORLD_READ WORLD_EXECUTE)
else()
# Data/intermediate files: preserve subdirectory structure (no execute bit)
# This maintains original relative paths for compatibility
# file(RELATIVE_PATH REL_PATH \"${CMAKE_BINARY_DIR}/Samples\" \"\${SAMPLE_FILE}\")
# get_filename_component(REL_DIR \"\${REL_PATH}\" DIRECTORY)
# set(DEST_DIR \"${CUDA_SAMPLES_INSTALL_DIR}/\${REL_DIR}\")
message(STATUS \"Installing: ${CUDA_SAMPLES_INSTALL_DIR}/\${FILE_NAME}\")
file(COPY \"\${SAMPLE_FILE}\"
DESTINATION \"${CUDA_SAMPLES_INSTALL_DIR}\"
FILE_PERMISSIONS OWNER_READ OWNER_WRITE
GROUP_READ
WORLD_READ)
endif()
endif()
endif()
endforeach()
# Copy everything from bin/bin (created by libNVVM samples install)
# The libNVVM samples install their .ll and data files to bin/bin
# Skip files that already exist (e.g., executable files already copied above)
set(BIN_BIN_DIR \"${CMAKE_BINARY_DIR}/bin/bin\")
if(EXISTS \"\${BIN_BIN_DIR}\" AND IS_DIRECTORY \"\${BIN_BIN_DIR}\")
file(GLOB_RECURSE BIN_BIN_FILES
RELATIVE \"\${BIN_BIN_DIR}\"
\"\${BIN_BIN_DIR}/*\")
foreach(REL_FILE IN LISTS BIN_BIN_FILES)
set(SRC_FILE \"\${BIN_BIN_DIR}/\${REL_FILE}\")
set(DEST_FILE \"${CUDA_SAMPLES_INSTALL_DIR}/\${REL_FILE}\")
# Only copy if destination doesn't exist (avoid duplicate executables)
if(NOT EXISTS \"\${DEST_FILE}\")
get_filename_component(DEST_DIR \"\${DEST_FILE}\" DIRECTORY)
message(STATUS \"Installing from bin/bin: \${DEST_FILE}\")
file(COPY \"\${SRC_FILE}\"
DESTINATION \"\${DEST_DIR}\"
USE_SOURCE_PERMISSIONS)
endif()
endforeach()
# Remove bin/bin after copying
message(STATUS \"Removing bin/bin directory\")
file(REMOVE_RECURSE \"\${BIN_BIN_DIR}\")
endif()
")
endfunction()