diff --git a/CMakeLists.txt b/CMakeLists.txt index 05741a9..72dc436 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,95 +1,117 @@ # TODO: Lower the min version required cmake_minimum_required(VERSION 3.18) -# Project's name project(OpenRAND VERSION 1.0) -# Set the C++ standard +# Set the C++ standard and ensure it's strictly required set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) -#- Wdouble-promotion : implicit float->double promotion is a really bad idea for GPU -set(CMAKE_CXX_FLAGS - "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wdouble-promotion -Wconversion -O3 -fopenmp") -include_directories(${PROJECT_SOURCE_DIR}/include) +# Define the main library as an interface +add_library(${PROJECT_NAME} INTERFACE) -include(FetchContent) +# Create an alias target for users to include OpenRAND with a namespace +# This isn't explicitly necessary as OpenRAND is header-only but it takes including OpenRAND +# via find_package + target_link_libraries straightforward. +add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) + +# Specify the C++ flags using target_compile_options and generator expressions for better control and compatibility +target_compile_options(${PROJECT_NAME} INTERFACE + $<$: + -Wall -Wextra -Wdouble-promotion -Wconversion -O3> + $<$: + -Wall -Wextra -Wconversion -O3> + $<$: + /W4 /O2> +) -# Build TestU01 statistical test suite -set(TESTU01_PATH "" CACHE PATH "Path to TestU01 library") +# Include directories for the interface target +target_include_directories(${PROJECT_NAME} INTERFACE + $ + $ +) -# Only build tests, examples and benchmarks if this isn't compiled -# as a dependecy of another project. -# Thanks to: https://www.foonathan.net/2022/06/cmake-fetchcontent/ -if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) - enable_testing() - add_subdirectory(tests) - - add_subdirectory(examples) - add_subdirectory(benchmarks) +# Options to control the build process +option(OpenRAND_ENABLE_TESTS "Enable building of tests" OFF) +option(OpenRAND_ENABLE_EXAMPLES "Enable building of examples" OFF) +option(OpenRAND_ENABLE_BENCHMARKS "Enable building of benchmarks" OFF) + +message(STATUS "OpenRAND_ENABLE_TESTS: ${OpenRAND_ENABLE_TESTS}") +message(STATUS "OpenRAND_ENABLE_EXAMPLES: ${OpenRAND_ENABLE_EXAMPLES}") +message(STATUS "OpenRAND_ENABLE_BENCHMARKS: ${OpenRAND_ENABLE_BENCHMARKS}") + +if(OpenRAND_ENABLE_TESTS) + # Fetch GoogleTest for managing tests + include(FetchContent) FetchContent_Declare( googletest URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip DOWNLOAD_EXTRACT_TIMESTAMP TRUE ) - # For Windows: Prevent overriding the parent project's compiler/linker settings set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + set(INSTALL_GTEST OFF CACHE BOOL "" FORCE) # Prevent GTest from being installed FetchContent_MakeAvailable(googletest) + + enable_testing() + add_subdirectory(tests) +endif() + +if(OpenRAND_ENABLE_EXAMPLES) + add_subdirectory(examples) +endif() - # TODO: it's still being built as DEBUG +if(OpenRAND_ENABLE_BENCHMARKS) + # Fetch GoogleBenchmarks for managing benchmarks + include(FetchContent) FetchContent_Declare( - google_benchmark - GIT_REPOSITORY https://github.com/google/benchmark.git - GIT_TAG main - CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release + google_benchmark + GIT_REPOSITORY https://github.com/google/benchmark.git + GIT_TAG main + CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release # TODO: it's still being built as DEBUG ) set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "" FORCE) + set(BENCHMARK_ENABLE_INSTALL OFF CACHE BOOL "" FORCE) # Prevent GoogleBenchmarks from being installed FetchContent_MakeAvailable(google_benchmark) + + add_subdirectory(benchmarks) endif() +# Installation rules for the library include(GNUInstallDirs) -add_library(${PROJECT_NAME} INTERFACE) -target_include_directories(${PROJECT_NAME} - INTERFACE - $ - $ -) - -# Rules to install the library in system -# It follows the guide in: https://dominikberner.ch/cmake-interface-lib/ - -# Export the targets +# Installation rules for the library install(TARGETS ${PROJECT_NAME} - EXPORT ${PROJECT_NAME}Targets - INCLUDES DESTINATION include) - + EXPORT ${PROJECT_NAME}Targets + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} +) +# Exporting and installing the package configuration include(CMakePackageConfigHelpers) write_basic_package_version_file( - ${PROJECT_NAME}ConfigVersion.cmake + "${PROJECT_NAME}ConfigVersion.cmake" VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion ) configure_package_config_file( - "${PROJECT_SOURCE_DIR}/cmake/${PROJECT_NAME}Config.cmake.in" - "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" - INSTALL_DESTINATION - ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/cmake) - + "${PROJECT_SOURCE_DIR}/cmake/${PROJECT_NAME}Config.cmake.in" + "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} +) -# Create and install the export file install(EXPORT ${PROJECT_NAME}Targets -FILE ${PROJECT_NAME}Targets.cmake -DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/cmake) - + FILE ${PROJECT_NAME}Targets.cmake + NAMESPACE ${PROJECT_NAME}:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} +) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" - "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" - DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/cmake) - + "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} +) -# Copy entire openrand directory -install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/openrand DESTINATION include) \ No newline at end of file +# Install the include directory +install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/openrand + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} +) diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt index 5962132..4c0127b 100644 --- a/benchmarks/CMakeLists.txt +++ b/benchmarks/CMakeLists.txt @@ -1,15 +1,13 @@ add_executable(raw_speed_cpu raw_speed_cpu.cpp) -target_include_directories(raw_speed_cpu PRIVATE ${CMAKE_SOURCE_DIR}/include) -target_link_libraries(raw_speed_cpu benchmark::benchmark) - +target_link_libraries(raw_speed_cpu PRIVATE benchmark::benchmark ${PROJECT_NAME}) include(CheckLanguage) check_language(CUDA) if (CMAKE_CUDA_COMPILER) - message(STATUS "CUDA FOUND: building CUDA benchmarks") - enable_language(CUDA) - add_executable(raw_speed_cuda raw_speed_cuda.cu) - target_include_directories(raw_speed_cuda PRIVATE ${CMAKE_SOURCE_DIR}/include) + message(STATUS "CUDA FOUND: Building CUDA benchmarks") + enable_language(CUDA) + add_executable(raw_speed_cuda raw_speed_cuda.cu) + target_link_libraries(raw_speed_cuda PRIVATE ${PROJECT_NAME}) else() - message(STATUS "skipping: CUDA benchmarks, CUDA not found") + message(STATUS "CUDA not found: Skipping CUDA benchmarks") endif() \ No newline at end of file diff --git a/benchmarks/raw_speed_cuda.cu b/benchmarks/raw_speed_cuda.cu index d6ee60c..5cb9a95 100644 --- a/benchmarks/raw_speed_cuda.cu +++ b/benchmarks/raw_speed_cuda.cu @@ -32,7 +32,6 @@ #include #include - #include #include #include diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index db62e28..93fccb9 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,18 +1,31 @@ -# Add the executable -add_executable(basic_usage basic_usage.cpp) -add_executable(pi_openmp pi_openmp.cpp) -add_executable(serial_parallel_equivalence state_forwarding.cpp) +# OpenMP-dependent examples +find_package(OpenMP) +if(OpenMP_CXX_FOUND) + message(STATUS "OpenMP FOUND: Building OpenMP examples") + add_executable(serial_parallel_equivalence state_forwarding.cpp) + target_link_libraries(serial_parallel_equivalence PRIVATE OpenMP::OpenMP_CXX ${PROJECT_NAME}) + + add_executable(basic_usage basic_usage.cpp) + target_link_libraries(basic_usage PRIVATE OpenMP::OpenMP_CXX ${PROJECT_NAME}) + + add_executable(pi_openmp pi_openmp.cpp) + target_link_libraries(pi_openmp PRIVATE OpenMP::OpenMP_CXX ${PROJECT_NAME}) +else() + message(STATUS "OpenMP not found: Skipping OpenMP examples") +endif() + +# MPI examples include(CheckLanguage) check_language(CUDA) if (CMAKE_CUDA_COMPILER) - message(STATUS "CUDA FOUND: building CUDA examples") - enable_language(CUDA) - add_executable(pi_cuda pi_cuda.cu) - target_include_directories(pi_cuda PRIVATE ${CMAKE_SOURCE_DIR}/include) - set_property(TARGET pi_cuda PROPERTY CUDA_STANDARD 17) + message(STATUS "CUDA FOUND: Building CUDA examples") + enable_language(CUDA) + add_executable(pi_cuda pi_cuda.cu) + target_link_libraries(pi_cuda PRIVATE ${PROJECT_NAME}) + set_property(TARGET pi_cuda PROPERTY CUDA_STANDARD 17) else() - message(STATUS "skipping: CUDA examples, CUDA not found") + message(STATUS "CUDA not found: Skipping CUDA examples") endif() diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 541fff5..ac784e2 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,6 +1,5 @@ find_package(Python COMPONENTS Interpreter REQUIRED) - enable_testing() add_executable( @@ -8,8 +7,7 @@ add_executable( test_uniform.cpp ) target_link_libraries( - uniform - GTest::gtest_main + uniform PRIVATE GTest::gtest_main ${PROJECT_NAME} ) add_executable( @@ -17,8 +15,7 @@ add_executable( test_normal.cpp ) target_link_libraries( - normal - GTest::gtest_main + normal PRIVATE GTest::gtest_main ${PROJECT_NAME} ) add_executable( @@ -26,8 +23,7 @@ add_executable( test_base.cpp ) target_link_libraries( - base - GTest::gtest_main + base PRIVATE GTest::gtest_main ${PROJECT_NAME} ) include(GoogleTest) @@ -39,16 +35,20 @@ gtest_discover_tests(base) # Statistical tests, not run through gtest framework add_executable(pract_rand pract_rand.cpp) add_executable(pract_rand_multi pract_rand_multistream.cpp) +target_link_libraries(pract_rand ${PROJECT_NAME}) +target_link_libraries(pract_rand_multi ${PROJECT_NAME}) -if(NOT TESTU01_PATH STREQUAL "") +OPTION(TESTU01_PATH "Path to the TestU01 library" "") +MESSAGE(STATUS "TESTU01_PATH: ${TESTU01_PATH}") +if(TESTU01_PATH) message(STATUS "Building TESTU01 statistical test suite") link_directories(${TESTU01_PATH}/lib) add_executable(testu01_serial testu01.cpp) - target_link_libraries(testu01_serial testu01 probdist mylib) + target_link_libraries(testu01_serial testu01 probdist mylib ${PROJECT_NAME}) target_include_directories(testu01_serial PUBLIC ${TESTU01_PATH}/include) add_executable(testu01_multi testu01-multistream.cpp) - target_link_libraries(testu01_multi testu01 probdist mylib) + target_link_libraries(testu01_multi testu01 probdist mylib ${PROJECT_NAME}) target_include_directories(testu01_multi PUBLIC ${TESTU01_PATH}/include) else() message(STATUS "TESTU01_PATH not set, not building statistical test suite")