diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..07857ef --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,74 @@ +cmake_minimum_required(VERSION 3.26) + +#--------------------------------------------------------------------------------------- +# Compiler config +#--------------------------------------------------------------------------------------- +if(NOT DEFINED CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 20) +endif() +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +#============================= +project(samples LANGUAGES CXX) +#============================= + +include(cmake/options.cmake) + +# ---- Setup default project_options ---- + +# cmake-format: off +project_options( + # PREFIX ${PROJECT_NAME} + ENABLE_CACHE + #NO! ENABLE_CLANG_TIDY + ${ENABLE_COVERAGE} + ${OPTION_ENABLED_SANITIZER} + #XXX ENABLE_SANITIZER_ADDRESS + #XXX ENABLE_SANITIZER_UNDEFINED_BEHAVIOR + #XXX ENABLE_SANITIZER_THREAD + #XXX ENABLE_SANITIZER_MEMORY + WARNINGS_AS_ERRORS +) +# cmake-format: on + +target_compile_features(project_options INTERFACE cxx_std_${CMAKE_CXX_STANDARD}) + +enable_testing() + +# ---- Setup experimental cmake C++20 module support ---- + +# see https://releases.llvm.org/15.0.0/projects/libcxx/docs/ReleaseNotes.html +#XXX add_compile_options(-fexperimental-library) +#XXX add_link_options(-lc++experimental) + +set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API 2182bf5c-ef0d-489a-91da-49dbc3090d2a) +set(CMake_TEST_CXXModules_UUID "a246741c-d067-4019-a8fb-3d16b0c9d1d3") + +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") + # string(CONCAT CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE + # " -E -x c++ " + # " -MT -MD -MF " + # " -fmodules-ts -fdep-file= -fdep-output= -fdep-format=trtbd" + # " -o " + # ) + # set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FORMAT "gcc") + # set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FLAG "-fmodules-ts -fmodule-mapper= -fdep-format=trtbd -x c++") + +elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1) + set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FORMAT "clang") + set(CMAKE_EXE_LINKER_FLAGS -lstdc++) + # Workaround for C++Modules: Missing module map flags in exported compile commands + # see https://gitlab.kitware.com/cmake/cmake/-/issues/24618 + set(CMAKE_CXX_COMPILE_OBJECT "${CMAKE_CXX_COMPILE_OBJECT} @.modmap") + +elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1) + +endif() + +add_subdirectory(testsimple) +add_subdirectory(testall) + diff --git a/cmake/CPM.cmake b/cmake/CPM.cmake new file mode 100644 index 0000000..a3086b7 --- /dev/null +++ b/cmake/CPM.cmake @@ -0,0 +1,33 @@ +set(CPM_DOWNLOAD_VERSION 0.38.1) + +if(CPM_SOURCE_CACHE) + set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") +elseif(DEFINED ENV{CPM_SOURCE_CACHE}) + set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") +else() + set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake") +endif() + +# Expand relative path. This is important if the provided path contains a tilde (~) +get_filename_component(CPM_DOWNLOAD_LOCATION ${CPM_DOWNLOAD_LOCATION} ABSOLUTE) + +function(download_cpm) + message(STATUS "Downloading CPM.cmake to ${CPM_DOWNLOAD_LOCATION}") + file(DOWNLOAD + https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake + ${CPM_DOWNLOAD_LOCATION} + ) +endfunction() + +if(NOT (EXISTS ${CPM_DOWNLOAD_LOCATION})) + download_cpm() +else() + # resume download if it previously failed + file(READ ${CPM_DOWNLOAD_LOCATION} check) + if("${check}" STREQUAL "") + download_cpm() + endif() + unset(check) +endif() + +include(${CPM_DOWNLOAD_LOCATION}) diff --git a/cmake/options.cmake b/cmake/options.cmake new file mode 100644 index 0000000..c30a54b --- /dev/null +++ b/cmake/options.cmake @@ -0,0 +1,87 @@ +include_guard() + +if(PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR) + message( + FATAL_ERROR + "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there." + ) +endif() + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) +set(CMAKE_DEBUG_POSTFIX D) +set(CMAKE_SKIP_INSTALL_RULES ON) + +option(OPTION_ENABLE_UNITY "Enable Unity builds of project" OFF) +option(OPTION_ENABLE_CLANG_TIDY "Enable clang-tdiy as prebuild step" OFF) +option(BUILD_SHARED_LIBS "Global flag to cause add_library() to create shared libraries if on." OFF) + +if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + if(APPLE) + set(OPTION_ENABLED_SANITIZER + "ENABLE_SANITIZER_ADDRESS; ENABLE_SANITIZER_UNDEFINED_BEHAVIOR" + CACHE STRING "Enabled sanitizer for debug build" + ) + else() + set(OPTION_ENABLED_SANITIZER + "ENABLE_SANITIZER_MEMORY" + CACHE STRING "Enabled sanitizer for debug build" + ) + endif() +endif() + +option(OPTION_ENABLE_COVERAGE "Enable test coverage of projects" OFF) +if(OPTION_ENABLE_COVERAGE) + set(ENABLE_COVERAGE "ENABLE_COVERAGE") +endif() + +if(OPTION_ENABLE_UNITY) + set(ENABLE_UNITY "ENABLE_UNITY") +endif() + +if(CMAKE_EXPORT_COMPILE_COMMANDS) + set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}) +endif() + +include(${CMAKE_CURRENT_LIST_DIR}/CPM.cmake) + +cpmaddpackage("gh:aminya/project_options@0.29.0") +list(APPEND CMAKE_MODULE_PATH ${project_options_SOURCE_DIR}/src) + +# Disable clang-tidy for target +macro(target_disable_clang_tidy TARGET) + find_program(CLANGTIDY clang-tidy) + if(CLANGTIDY) + set_target_properties(${TARGET} PROPERTIES C_CLANG_TIDY "") + set_target_properties(${TARGET} PROPERTIES CXX_CLANG_TIDY "") + endif() +endmacro() + +macro(check_system_property DIRECTORY) + get_property( + _value + DIRECTORY ${DIRECTORY} + PROPERTY SYSTEM + SET + ) + if(NOT _value) + message(SEND_ERROR "SYSTEM property is NOT defined for ${DIRECTORY}") + endif() +endmacro() + +macro(set_system_property DIRECTORY) + message(TRACE "${DIRECTORY}") + set_property(DIRECTORY ${DIRECTORY} PROPERTY SYSTEM ON) + check_system_property(${DIRECTORY}) +endmacro() + +macro(add_tests FILES) + foreach(source IN LISTS ${FILES}) + string(REGEX REPLACE "\.cpp$" "" program ${source}) + add_executable(${program} ${program}.cpp) + set_target_properties(${program} PROPERTIES CXX_STANDARD ${CMAKE_CXX_STANDARD}) + if(CMAKE_SKIP_INSTALL_RULES OR CMAKE_BUILD_TYPE STREQUAL "Debug") + target_link_libraries(${program} PRIVATE $) + endif() + add_test(NAME ${program} COMMAND ${program}) + endforeach() +endmacro() diff --git a/testall/CMakeLists.txt b/testall/CMakeLists.txt new file mode 100644 index 0000000..f56044e --- /dev/null +++ b/testall/CMakeLists.txt @@ -0,0 +1,27 @@ +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") + add_compile_options(-Wno-unused-command-line-argument) +endif() + +# +# module with partitions +# +add_library(testall) +target_sources( + testall + PRIVATE modall_impl.cpp + PUBLIC FILE_SET + cxx_modules + TYPE + CXX_MODULES + FILES + modall_if.cppm + modall_ifpart.cppm # interface partition + modall_part.cppm # internal partition +) +set_target_properties(testall PROPERTIES CXX_STANDARD ${CMAKE_CXX_STANDARD}) +if(CMAKE_SKIP_INSTALL_RULES AND CMAKE_BUILD_TYPE STREQUAL "Debug") + target_link_libraries(testall PUBLIC $) +endif() +add_executable(modall_test modall_test.cpp) +target_link_libraries(modall_test testall) +add_test(NAME modall_test COMMAND modall_test) diff --git a/testsimple/CMakeLists.txt b/testsimple/CMakeLists.txt new file mode 100644 index 0000000..f2108af --- /dev/null +++ b/testsimple/CMakeLists.txt @@ -0,0 +1,24 @@ +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") + add_compile_options(-Wno-unused-command-line-argument) +endif() + +# +# module with partitions +# +add_library(testsimple) +target_sources( + testsimple + PUBLIC FILE_SET + cxx_modules + TYPE + CXX_MODULES + FILES + modsimple_if.cppm +) +set_target_properties(testsimple PROPERTIES CXX_STANDARD ${CMAKE_CXX_STANDARD}) +if(CMAKE_SKIP_INSTALL_RULES AND CMAKE_BUILD_TYPE STREQUAL "Debug") + target_link_libraries(testsimple PUBLIC $) +endif() +add_executable(modsimple_test modsimple_test.cpp) +target_link_libraries(modsimple_test testsimple) +add_test(NAME modsimple_test COMMAND modsimple_test) diff --git a/testsimple/modsimple_if.cppm b/testsimple/modsimple_if.cppm index 5ae557c..ddbd7bf 100644 --- a/testsimple/modsimple_if.cppm +++ b/testsimple/modsimple_if.cppm @@ -19,10 +19,10 @@ export class Square { private: int value; public: - Square(int i) + Square(int i) : value{square(i)} { } - int getValue() const { + [[nodiscard]] int getValue() const { return value; } };