Skip to content

Commit

Permalink
Cleanup and build module my way
Browse files Browse the repository at this point in the history
Add example to test import std with cmake

Test only Release builds on CI
  • Loading branch information
ClausKlein committed Dec 31, 2024
1 parent 511114a commit be999c2
Show file tree
Hide file tree
Showing 13 changed files with 170 additions and 53 deletions.
6 changes: 3 additions & 3 deletions .CMakeUserPresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"dev-mode"
],
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
},
Expand Down Expand Up @@ -64,7 +64,7 @@
{
"name": "dev",
"configurePreset": "dev",
"configuration": "Debug",
"configuration": "Release",
"jobs": 12,
"targets": [
"install"
Expand All @@ -83,7 +83,7 @@
{
"name": "dev",
"configurePreset": "dev",
"configuration": "Debug",
"configuration": "Release",
"output": {
"outputOnFailure": true
},
Expand Down
66 changes: 40 additions & 26 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ include(cmake/prelude.cmake)

# Set experimental flag to enable `import std` support from CMake.
# This must be enabled before C++ language support.
# FIXME: set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD 0e5b6991-d74f-4b3d-a41c-cf096e0b2508)
# TODO: set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD 0e5b6991-d74f-4b3d-a41c-cf096e0b2508)

project(fmt
VERSION 11.1.1.1
Expand All @@ -16,6 +16,10 @@ project(fmt

include(cmake/variables.cmake)

if(CMAKE_BUILD_TYPE STREQUAL Release)
include(cmake/example.cmake)
endif()

set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_EXTENSIONS ON)
set(CMAKE_CXX_STANDARD_REQUIRED YES)
Expand All @@ -27,42 +31,51 @@ set(CPPdefinitions FMT_USE_FCNTL=0)
set(ADD_STDLIB_MODULES)

option(FMT_SEPARATE_COMPILATION "build fmt lib too" ${PROJECT_IS_TOP_LEVEL})
option(FMT_USE_MODULES "Export a CXX_MODULE fmt if possible" ${PROJECT_IS_TOP_LEVEL})
option(FMT_IMPORT_STD "Import the module std" ${PROJECT_IS_TOP_LEVEL})
if(UNIX)
option(FMT_USE_MODULES "Export a CXX_MODULE fmt if possible" ${PROJECT_IS_TOP_LEVEL})
endif()
# TODO: option(FMT_IMPORT_STD "Import the module std" ${PROJECT_IS_TOP_LEVEL})

if(FMT_USE_MODULES)
list(APPEND CPPdefinitions FMT_MODULE)
# XXX NO! list(APPEND CPPdefinitions FMT_ATTACH_TO_GLOBAL_MODULE)

if(FMT_IMPORT_STD)
if(UNIX)
# possible for clang++-18 or newer only!
if(DEFINED ENV{LLVM_ROOT})
message(STATUS "LLVM_ROOT=$ENV{LLVM_ROOT}")
set(LLVM_LIBC_SOURCE $ENV{LLVM_ROOT}/share/libc++/v1)
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 18.0)
#XXX set(ADD_STDLIB_MODULES stdlib)
endif()
endif()

# Tell CMake that we explicitly want `import std`.
# This will initialize the property on all targets declared after this to 1
if(CMAKE_CXX_COMPILER_IMPORT_STD)
set(CMAKE_CXX_MODULE_STD ON)
endif()
if(CMAKE_CXX_MODULE_STD OR ADD_STDLIB_MODULES)
list(APPEND CPPdefinitions HAS_STDLIB_MODULES)
# FIXME: NO! list(APPEND CPPdefinitions FMT_ATTACH_TO_GLOBAL_MODULE)

if(APPLE)
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.0)
execute_process(OUTPUT_VARIABLE LLVM_PREFIX COMMAND brew --prefix llvm@19 COMMAND_ECHO STDOUT)
string(STRIP ${LLVM_PREFIX} LLVM_PREFIX)
message(STATUS "LLVM_PREFIX=${LLVM_PREFIX}")

# /usr/local/opt/llvm/share/libc++/v1/std.cppm
set(LLVM_LIBC_SOURCE ${LLVM_PREFIX}/share/libc++/v1)
file(REAL_PATH ${LLVM_PREFIX} LLVM_ROOT)
message(STATUS "LLVM_ROOT=${LLVM_ROOT}")

if(EXISTS ${LLVM_LIBC_SOURCE}/std.cppm)
message(STATUS "LLVM_LIBC_SOURCE=${LLVM_LIBC_SOURCE}")
set(ADD_STDLIB_MODULES stdlib)
endif()

add_compile_options(-fexperimental-library)
add_link_options(-lc++experimental)
add_link_options(-L${LLVM_ROOT}/lib/c++ -lc++experimental)
add_compile_options(-stdlib=libc++)
add_link_options(-stdlib=libc++)
endif()

message(STATUS "CMAKE_CXX_COMPILER_IMPORT_STD=${CMAKE_CXX_COMPILER_IMPORT_STD}")
# Tell CMake that we explicitly want `import std`.
# This will initialize the property on all targets declared after this to 1
if(CMAKE_CXX_COMPILER_IMPORT_STD)
set(CMAKE_CXX_MODULE_STD ON)
endif()

if(CMAKE_CXX_MODULE_STD AND ADD_STDLIB_MODULES)
# FIXME: NO! list(APPEND CPPdefinitions FMT_IMPORT_STD)
list(APPEND CPPdefinitions HAS_STDLIB_MODULES)
endif()
endif()

message(STATUS "CMAKE_CXX_COMPILER_IMPORT_STD=${CMAKE_CXX_COMPILER_IMPORT_STD}")

message(STATUS "CPPdefinitions=${CPPdefinitions}")
else()
set(CMAKE_VERIFY_INTERFACE_HEADER_SETS ${PROJECT_IS_TOP_LEVEL})
Expand Down Expand Up @@ -115,7 +128,6 @@ if(FMT_SEPARATE_COMPILATION)
# file(GLOB_RECURSE _fmt_all_sources "${fmt_SOURCE_DIR}/src/*.cc")

add_library(fmt STATIC)
add_library(fmt::fmt ALIAS fmt)
target_sources(
fmt PUBLIC FILE_SET public_headers TYPE HEADERS BASE_DIRS ${fmt_SOURCE_DIR}/include FILES ${_fmt_public_header}
)
Expand All @@ -127,6 +139,7 @@ if(FMT_SEPARATE_COMPILATION)
target_compile_options(fmt PUBLIC $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CXX_COMPILER_ID:MSVC>>:/utf-8>)

if(FMT_USE_MODULES)
add_library(fmt::fmt-module ALIAS fmt)
target_compile_definitions(fmt PUBLIC ${CPPdefinitions})
# cmake-format: off
target_sources(fmt PUBLIC
Expand All @@ -139,6 +152,7 @@ if(FMT_SEPARATE_COMPILATION)
)
# cmake-format: on
else()
add_library(fmt::fmt ALIAS fmt)
set(CMAKE_CXX_SCAN_FOR_MODULES OFF)
target_compile_definitions(fmt PUBLIC ${CPPdefinitions})
target_sources(fmt PUBLIC ${_fmt_all_sources})
Expand Down
5 changes: 2 additions & 3 deletions CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"warnings": {
"dev": true,
"deprecated": true,
"uninitialized": true,
"uninitialized": false,
"unusedCli": true,
"systemVars": false
},
Expand Down Expand Up @@ -40,7 +40,7 @@
"name": "clang-tidy",
"hidden": true,
"cacheVariables": {
"CMAKE_CXX_CLANG_TIDY": "clang-tidy-18;--header-filter=^${sourceDir}/"
"CMAKE_CXX_CLANG_TIDY": "clang-tidy;--header-filter=^${sourceDir}/"
}
},
{
Expand Down Expand Up @@ -159,7 +159,6 @@
"binaryDir": "${sourceDir}/build/sanitize",
"inherits": [
"gen-Linux",
"clang-tidy",
"dev-mode"
],
"cacheVariables": {
Expand Down
9 changes: 7 additions & 2 deletions GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ ifeq (${hostSystemName},Darwin)
export LLVM_PREFIX:=$(shell brew --prefix llvm@19)
export LLVM_ROOT:=$(shell realpath ${LLVM_PREFIX})

export LDFLAGS?=-L${LLVM_ROOT}/lib/c++
#XXX export LDFLAGS?=-L${LLVM_ROOT}/lib/c++
export PATH:=${LLVM_ROOT}/bin:${PATH}
export CXX:=clang++
else ifeq (${UNAME},Linux)
export LLVM_ROOT:=/usr/lib/llvm-19
endif

.PHONY: all check test format clean distclean
.PHONY: all check test example format clean distclean
all: .init
cmake --workflow --preset dev --fresh

Expand All @@ -39,6 +39,11 @@ test:
cmake --build build/tests
ctest --test-dir build/tests

example:
cmake -B build/example -S example -G Ninja
cmake --build build/example -- -v
ctest --test-dir build/example --verbose

.init: requirements.txt .CMakeUserPresets.json
perl -p -e 's/<hostSystemName>/${hostSystemName}/;' .CMakeUserPresets.json > CMakeUserPresets.json
-pip3 install --user --upgrade -r requirements.txt
Expand Down
3 changes: 1 addition & 2 deletions cmake/CPM.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ endif()
# Expand relative path. This is important if the provided path contains a tilde (~)
get_filename_component(CPM_DOWNLOAD_LOCATION ${CPM_DOWNLOAD_LOCATION} ABSOLUTE)

file(DOWNLOAD
https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake
file(DOWNLOAD https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake
${CPM_DOWNLOAD_LOCATION} EXPECTED_HASH SHA256=${CPM_HASH_SUM}
)

Expand Down
22 changes: 22 additions & 0 deletions cmake/example.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
include(ExternalProject)

ExternalProject_Add(
example
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/example
#--Download step--------------
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/example
#--Update/Patch step----------
#--Configure step-------------
USES_TERMINAL_CONFIGURE TRUE
CONFIGURE_COMMAND cmake -G "${CMAKE_GENERATOR}" -S ${CMAKE_CURRENT_SOURCE_DIR}/example -B . #
-D CMAKE_BUILD_TYPE=$<CONFIG> -D CMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
#--Build step-----------------
USES_TERMINAL_BUILD TRUE
# BUILD_IN_SOURCE 1
BUILD_COMMAND cmake --build <BINARY_DIR> -j 8
#--Install step---------------
USES_TERMINAL_INSTALL TRUE
INSTALL_COMMAND ctest --verbose
#--Logging -------------------
LOG_BUILD OFF
)
18 changes: 18 additions & 0 deletions cmake/install-config.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,25 @@ function(add_fmt_module NAME)
${FMT_ROOT}/lib/cmake/fmt/module/fmt.cppm
)
# cmake-format: on
endfunction()

# Build the stdlib module
function(add_stdlib_module NAME)
add_library(${NAME})
# cmake-format: off
target_sources(${NAME} PUBLIC
FILE_SET CXX_MODULES
BASE_DIRS ${LLVM_LIBC_SOURCE}
FILES
${LLVM_LIBC_SOURCE}/std.cppm
${LLVM_LIBC_SOURCE}/std.compat.cppm
)
# cmake-format: on
target_compile_features(
${NAME} PUBLIC "$<$<COMPILE_FEATURES:cxx_std_23>:cxx_std_23>" "$<$<NOT:$<COMPILE_FEATURES:cxx_std_23>>:cxx_std_20>"
)
target_compile_definitions(${NAME} PUBLIC _LIBCPP_HAS_NO_LOCALIZATION)
target_compile_options(${NAME} PRIVATE -Wno-reserved-module-identifier)
endfunction()

include("${CMAKE_CURRENT_LIST_DIR}/fmtTargets.cmake")
35 changes: 35 additions & 0 deletions example/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# CMake 3.30 is required for C++23 `import std` support; we use 3.29.20240416
# here so that in-development versions satisfy it.
cmake_minimum_required(VERSION 3.30 FATAL_ERROR)

# Set experimental flag to enable `import std` support from CMake.
# This must be enabled before C++ language support.
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD # This specific value changes as experimental support evolves. See
# `Help/dev/experimental.rst` in the CMake source corresponding to
# your CMake build for the exact value to use.
"0e5b6991-d74f-4b3d-a41c-cf096e0b2508"
)

# C++ needs to be enabled.
project(import_std LANGUAGES CXX)

# Tell CMake that we explicitly want `import std`. This will initialize the
# property on all targets declared after this to 1
set(CMAKE_CXX_MODULE_STD 1)

# Make a library.
add_library(uses_std STATIC)
# Add sources.
target_sources(uses_std PRIVATE uses_std.cxx)
# Tell CMake we're using C++23 but only C++20 is needed to consume it.
target_compile_features(uses_std PRIVATE cxx_std_23 INTERFACE cxx_std_20)

# Make an executable.
add_executable(main)
# Note that this source is *not* allowed to `import std` as it ends up
# with only C++20 support due to the `uses_std` INTERFACE requirements.
target_sources(main PRIVATE main.cxx)
target_link_libraries(main PRIVATE uses_std)

enable_testing()
add_test(NAME main COMMAND main)
13 changes: 13 additions & 0 deletions example/main.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include <string>

void hello_world(std::string const& name);

int main(int argc, char* argv[])
{
const char* name = "Voldemort?";
hello_world(name);
while (--argc > 0) {
hello_world(argv[argc]);
}
return 0;
}
6 changes: 6 additions & 0 deletions example/uses_std.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import std;

void hello_world(std::string const& name)
{
std::print("Hello World! My name is {}\n", name);
}
12 changes: 8 additions & 4 deletions module/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ if(PROJECT_IS_TOP_LEVEL)
# see https://releases.llvm.org/15.0.0/projects/libcxx/docs/ReleaseNotes.html
# Always use libc++
add_compile_options(-fexperimental-library)
add_link_options(-lc++experimental)
add_link_options(-L${LLVM_ROOT}/lib/c++ -lc++experimental)
add_compile_options(-stdlib=libc++)
add_link_options(-stdlib=libc++)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 14.0)
Expand All @@ -32,8 +32,12 @@ if(PROJECT_IS_TOP_LEVEL)
message(STATUS "CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES=${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}")
endif()
if(USE_MODULES)
if(NOT CMAKE_CXX_COMPILER_IMPORT_STD AND ADD_STDLIB_MODULES)
message(WARNING "ADD_STDLIB_MODULES=${ADD_STDLIB_MODULES}")
add_stdlib_module(${ADD_STDLIB_MODULES})
endif()
# Build the fmt module
add_fmt_module(fmt_module)
add_fmt_module(fmt-module)
endif()
endif()

Expand All @@ -45,8 +49,8 @@ foreach(_file ${ALL_TESTS})
add_executable(module_${_file})
target_sources(module_${_file} PRIVATE ../../tests/${_file}.cc)
if(USE_MODULES)
target_link_libraries(module_${_file} fmt_module)
#XXX target_compile_definitions(module_${_file} PUBLIC USE_MODULES)
target_link_libraries(module_${_file} fmt-module ${ADD_STDLIB_MODULES})
# XXX: NOT USED! target_compile_definitions(module_${_file} PUBLIC USE_MODULES)
else()
target_link_libraries(module_${_file} fmt::fmt-header-only)
endif()
Expand Down
Loading

0 comments on commit be999c2

Please sign in to comment.