ixx 声明文件
icc 实现文件
async_simple框架用的后缀是cppm
可以在模块中用模板,我是直接export的命名空间!!!
学习可以看看这篇博客学习
cmake 官网文档链接:
https://cmake.org/cmake/help/latest/prop_tgt/CXX_MODULE_SETS.html
CXX_MODULE_SETS¶
New in version 3.25.
Note Experimental. Gated by CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API
Read-only list of the target's PRIVATE and PUBLIC C++ module sets (i.e. all file sets with the type CXX_MODULES). Files listed in these file sets are treated as source files for the purpose of IDE integration.
C++ module sets may be defined using the target_sources() command FILE_SET option with type CXX_MODULES.
See also CXX_MODULE_SET_, CXX_MODULE_SET and INTERFACE_CXX_MODULE_SETS.
1、必须是3.25以上的版本
2、模块文件使用target_sources()导入
3、需要设置CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API参数
4、linux 平台:必须使用ninja 1.11以上编译,github上有二进制包,单个文件的,clang大于15版本,cmake project name 必须等到CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API 设置完后才可以设置
6、windows平台mvsc可以直接使用,忽略以上3、4条,因为他可以自动扫描依赖没这么麻烦,但是必须保持最新版本
CMakeLists.txt:
cmake_minimum_required(VERSION 3.25.2)
if (UNIX)
set(CMAKE_GENERATOR "/usr/bin/ninja")
set(CMAKE_C_COMPILER "clang-16")
set(CMAKE_CXX_COMPILER "clang++-16")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "2182bf5c-ef0d-489a-91da-49dbc3090d2a")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FORMAT "clang")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FLAG "@" )
# 必须设置,否则他会去找gcc的头文件
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem /usr/lib/llvm-16/lib/clang/16/include -Wall -Wextra -Wunused-parameter")
include(cxx_modules_rules_clang.cmake)
endif()
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
if (WIN32)
add_definitions("/utf-8")
add_definitions("/wd4828 /wd4267")
#set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zf /O3 /openmp /MP /std:c++20 /bigobj /await:strict")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Zf /O0 /openmp /MP /std:c++20 /bigobj /await:strict")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Zf /O3 /openmp /MP /std:c20 /bigobj /await:strict")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Zf /O0 /openmp /MP /std:c20 /bigobj /await:strict")
#[如果确认不需要PDB, 即不需要调试开源库, 完全可以在设置里将/Zi或/ZI去掉]
# 文件utf-8
add_compile_options("$<$:/utf-8>" )
add_compile_options("$<$:/utf-8>" )
else()
# Wreturn-type 协程是空实现
#-fmodules-ts 模块
#-fcoroutines-ts 协程
#-fconcepts-ts 概念
#-fsanitize=address 检查内存溢出
#-freport-bug 打印完整的编译 bug
# -Wunused-result 忽略返回结果
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20 -fmodules-ts -fsanitize=address -fcoroutines-ts -fconcepts-ts -fpermissive -Wreturn-type -freport-bug -Wunused-result")
set(CXX_FLAGS "${CXX_FLAGS} -std=c++20 -fmodules-ts -fsanitize=address -fcoroutines-ts -fconcepts-ts -fpermissive -Wreturn-typ -freport-buge -Wunused-result")
#add_compile_options(-fmodules)
#add_compile_options(-fbuiltin-module-map)
#add_compile_options(-fimplicit-module-maps)
#add_compile_options(-fprebuilt-module-path=${PREBUILT_MODULE_PATH})
endif ()
# 源文件
file(GLOB_RECURSE SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/*.c
${CMAKE_CURRENT_SOURCE_DIR}/src/*.ui
${CMAKE_CURRENT_SOURCE_DIR}/src/*.qrc
)
# 头文件
file(GLOB_RECURSE CURRENT_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/src/*.h
${CMAKE_CURRENT_SOURCE_DIR}/src/*.hpp
${CMAKE_CURRENT_SOURCE_DIR}/src/*.h
${CMAKE_CURRENT_SOURCE_DIR}/src/*.hpp)
#!!! 重点递归查找模板文件 FAST_MODULES保存所有的模块文件
file(GLOB_RECURSE FAST_MODULES
${CMAKE_CURRENT_SOURCE_DIR}/src/*.ixx
${CMAKE_CURRENT_SOURCE_DIR}/src/*.cxx
${CMAKE_CURRENT_SOURCE_DIR}/src/*.cppm)
# 构建可执行程序
add_executable(
${APP_NAME}#[[项目名称]]
${SOURCE_FILES} #[[源文件]]
${CURRENT_HEADERS} #[[头文件]]
${CMAKE_CURRENT_SOURCE_DIR}/run/main.cpp #[[主函数入口]])
#!!!追加模板
target_sources(
${APP_NAME}
PUBLIC
${FAST_MODULES}
)
${CMAKE_CXX_COMPILER_CLANG_SCAN_DEPS}
?clang-scan-deps-${llvm版本号}
apt install clang-tools-16
https://apt.llvm.org/ 这个网址进去找到对应的扩展源
cmake实验性的version号,github-cmake上可以找到这个东西
下面的string(…) 就是调用这个clang-scan-deps扫描工具
cxx_modules_rules_clang.cmake:
set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
string(CONCAT CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE
"${CMAKE_CXX_COMPILER_CLANG_SCAN_DEPS}"
" -format=p1689"
" --"
" "
" -x c++
" -MT "
" -MD -MF "
" > " )
set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FORMAT "clang")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FLAG "@" )
# Default to C++ extensions being off. Clang's modules support have trouble
# with extensions right now.
set(CMAKE_CXX_EXTENSIONS OFF)
//声明是一个模板
module;
#include
#include
#include
#include
// 导出.hpp文件后,从这个模块开始,后面用这个文件智能import
export import
// 导出整个命名空间
export module tuple_utils;
namespace tuple_utils{
/***********递归+特化方式遍历打印tuple***************/
template<typename Tuple, std::size_t N>
struct tuple_printer {
static void print(const Tuple &t) {
tuple_printer<Tuple, N - 1>::print(t);
std::cout << ", " << std::get<N - 1>(t);
}
};
template<typename Tuple>
struct tuple_printer<Tuple, 1> {
static void print(const Tuple &t) {
std::cout << std::get<0>(t);
}
};
template<typename... Args>
void print_tuple(const std::tuple<Args...> &t) {
tuple_printer<decltype(t), sizeof...(Args)>::print(t);
std::cout << std::endl;
}
/***********使用流的方式,这里用到了C++14的index_sequence****************/
template<typename Char, typename Traits, typename Tuple, std::size_t... Index>
void print_tuple_impl(std::basic_ostream<Char, Traits> &os, const Tuple &t, std::index_sequence<Index...>) {
using swallow = int[]; // guaranties left to right order
(void) swallow{0, (void(os << (Index == 0 ? "" : ", ") << std::get<Index>(t)), 0)...};
}
template<typename Char, typename Traits, typename... Args>
decltype(auto) operator<<(std::basic_ostream<Char, Traits> &os, const std::tuple<Args...> &t) {
os << "(";
print_tuple_impl(os, t, std::index_sequence_for<Args...>{});
return os << ")";
}
/***********将std::array转换成std::tuple,这里用到了C++14的index_sequence****************/
template<typename Array, std::size_t... Index>
decltype(auto) array2tuple_impl(const Array &a, std::index_sequence<Index...>) {
return std::make_tuple(a[Index]...);
}
template<typename T, std::size_t N>
decltype(auto) array2tuple(const std::array<T, N> &a) {
return array2tuple_impl(a, std::make_index_sequence<N>{});
}
/***********通过元素类型获取元素的值****************/
template<typename T, std::size_t N, typename... Args>
struct index_of;
template<typename T, std::size_t N, typename... Args>
struct index_of<T, N, T, Args...> : std::integral_constant<int, N> {
};
template<typename T, std::size_t N, typename U, typename... Args>
struct index_of<T, N, U, Args...> : std::integral_constant<int, index_of<T, N + 1, Args...>::value> {
};
template<typename T, std::size_t N>
struct index_of<T, N> : std::integral_constant<int, -1> {
};
template<typename T, typename... Args>
T get_element_by_type(const std::tuple<Args...> &t) {
return std::get<index_of<T, 0, Args...>::value>(t);
};
/***********通过std::tuple作为参数调用函数****************/
template<typename Function, typename Tuple, std::size_t... Index>
decltype(auto) invoke_impl(Function &&func, Tuple &&t, std::index_sequence<Index...>) {
return func(std::get<Index>(std::forward<Tuple>(t))...);
};
template<typename Function, typename Tuple>
decltype(auto) invoke(Function &&func, Tuple &&t) {
constexpr auto size = std::tuple_size<typename std::decay<Tuple>::type>::value;
return invoke_impl(std::forward<Function>(func), std::forward<Tuple>(t), std::make_index_sequence<size>{});
};
/***********make_from_tuple****************/
template<typename T, typename Tuple, std::size_t... Index>
decltype(auto) make_from_tuple_impl(Tuple &&t, std::index_sequence<Index...>) {
return T{std::get<Index>(std::forward<Tuple>(t))...};
};
template<typename T, typename Tuple>
decltype(auto) make_from_tuple(Tuple &&t) {
constexpr auto size = std::tuple_size<typename std::decay<Tuple>::type>::value;
return make_from_tuple_impl<T>(std::forward<Tuple>(t), std::make_index_sequence<size>{});
};
}