Skip to content

Add cmake support #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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
# "<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -E -x c++ <SOURCE>"
# " -MT <DYNDEP_FILE> -MD -MF <DEP_FILE>"
# " -fmodules-ts -fdep-file=<DYNDEP_FILE> -fdep-output=<OBJECT> -fdep-format=trtbd"
# " -o <PREPROCESSED_SOURCE>"
# )
# set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FORMAT "gcc")
# set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FLAG "-fmodules-ts -fmodule-mapper=<MODULE_MAP_FILE> -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} @<OBJECT>.modmap")

elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)

endif()

add_subdirectory(testsimple)
add_subdirectory(testall)

33 changes: 33 additions & 0 deletions cmake/CPM.cmake
Original file line number Diff line number Diff line change
@@ -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})
87 changes: 87 additions & 0 deletions cmake/options.cmake
Original file line number Diff line number Diff line change
@@ -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/[email protected]")
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 $<BUILD_INTERFACE:project_warnings project_options>)
endif()
add_test(NAME ${program} COMMAND ${program})
endforeach()
endmacro()
27 changes: 27 additions & 0 deletions testall/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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 $<BUILD_INTERFACE:project_warnings project_options>)
endif()
add_executable(modall_test modall_test.cpp)
target_link_libraries(modall_test testall)
add_test(NAME modall_test COMMAND modall_test)
24 changes: 24 additions & 0 deletions testsimple/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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 $<BUILD_INTERFACE:project_warnings project_options>)
endif()
add_executable(modsimple_test modsimple_test.cpp)
target_link_libraries(modsimple_test testsimple)
add_test(NAME modsimple_test COMMAND modsimple_test)
4 changes: 2 additions & 2 deletions testsimple/modsimple_if.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
};
Expand Down