# 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()