With this CMakeLists.txt,
I can build and check the simple example of a module interface.
But clang-tidy
does not find the BMI
file?
cmake_minimum_required(VERSION 3.26)
set(CMAKE_EXPORT_COMPILE_COMMANDS YES)
project(clang-tidy-issue LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_EXTENSIONS NO)
set(CMAKE_CXX_STANDARD_REQUIRED YES)
set(CMAKE_CXX_SCAN_FOR_MODULES YES)
# First find clang-tidy, this also allows users to provide hints
find_program(CLANG_TIDY NAMES clang-tidy REQUIRED)
# https://clang.llvm.org/docs/StandardCPlusPlusModules.html#how-to-build-projects-using-modules
# clang++ -std=c++20 -x c++-module foo.cxx --precompile -o build/foo.pcm
# clang++ -std=c++20 main.cxx -fprebuilt-module-path=build build/foo.pcm -o build/Hello
#
# see https://gitlab.kitware.com/cmake/cmake/-/blob/v3.26.3/Help/dev/experimental.rst?ref_type=tags#c-20-module-apis
# and https://gitlab.kitware.com/cmake/cmake/-/blob/v3.26.3/.gitlab/ci/cxx_modules_rules_gcc.cmake?ref_type=tags
# https://gitlab.kitware.com/cmake/cmake/-/blob/v3.26.3/.gitlab/ci/cxx_modules_rules_clang.cmake?ref_type=tags
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API 2182bf5c-ef0d-489a-91da-49dbc3090d2a)
set(CMake_TEST_CXXModules_UUID "a246741c-d067-4019-a8fb-3d16b0c9d1d3")
# 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")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
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++")
set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY};-checks=*,-llvmlibc-*,-fuchsia-*,-cppcoreguidelines-init-variables")
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FORMAT "clang")
set(BMI ${CMAKE_CURRENT_BINARY_DIR}/foo.pcm)
# FIXME: This does not work, clang-tidy is a pre, not a post compile step! CK
#XXX string(CONCAT CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY}"
#XXX "-extra-arg=-fprebuilt-module-path=${CMAKE_CURRENT_BINARY_DIR}"
#XXX )
endif()
file(WRITE foo.cppm
[=[
// Global module fragment where #includes can happen
module;
#include <iostream>
// first thing after the Global module fragment must be a module command
// XXX import std.core;
export module foo;
export class foo {
public:
foo() = default;
~foo() = default;
void helloworld();
};
void foo::helloworld() { std::cout << "hello world\n"; }
]=]
)
file(WRITE main.cxx
[=[
import foo;
auto main() -> int
{
foo myFoo;
myFoo.helloworld();
return 0;
}
]=]
)
add_library(foo)
target_sources(
foo
PUBLIC FILE_SET
cxx_modules
TYPE
CXX_MODULES
FILES
foo.cppm
)
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
# TODO(CK): How to control the location of the c++20 Binary Module Interface (BMI) output directory?
#XXX target_compile_options(foo
#XXX PRIVATE -fmodule-output=${BMI} -x c++-module
#XXX PUBLIC -fmodule-file=foo=${BMI}
#XXX )
endif()
add_executable(hello main.cxx)
target_link_libraries(hello foo)
enable_testing()
add_test(NAME hello COMMAND hello)
install(TARGETS foo ARCHIVE PUBLIC_HEADER
FILE_SET cxx_modules DESTINATION include
CXX_MODULES_BMI DESTINATION share/cxx-modules
)
include(cpack)