C++23中的import使用CMake实践

一、使用CMake进行模块编程

在前面开发中对使用import模块开发进行了简单的入门应用说明。但在实际的开发中,可能有更多的开发者使用CMake来开发C++程序,那么如何在cmake中使用模块进行开发呢?本文将对此通过一个基础的例程来进行分析说明。

此处的环境仍然是使用上文一样的环境,Ubuntu25.10,其它均为默认环境(gcc15.2 cmake3.31.6)

二、入门的程序

还是使用一个简单的例程:

c 复制代码
import std;
int main()
{
    std::cout << "Hello World!" << std::endl;
    return 0;
}

下面可以使用两种方法:

  1. 使用g++和cmake
    其CMakelists.txt文件为:
    下面再把直接使用前文命令预编译好后的CMakeLists.txt文件描述一下:

    cmake_minimum_required(VERSION 3.16)

    project(importCMake LANGUAGES CXX)

    set(CMAKE_CXX_STANDARD 23)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    set(CMAKE_CXX_EXTENSIONS OFF)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fmodules-ts")
    add_executable(importCMake main.cpp)

    include(GNUInstallDirs)
    install(TARGETS importCMake
    LIBRARY DESTINATION {CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION {CMAKE_INSTALL_BINDIR}
    )

但是需要提前在当前目录编译:

复制代码
g++ -std=c++23 -fmodules-ts -fsearch-include-path -c bits/std.cc

从而生成相关的std库依赖包。其它的编译处理方式与原来的编译没有区别。

直接使用类似下面Clang的直接编译的方式,将依赖库和应用一起编译完成,没有测试成功,总是报工具链不支持。

  1. 使用clang和cmake

其CMakeLists.txt的文件内容为:

复制代码
cmake_minimum_required(VERSION 3.31.6 FATAL_ERROR)
# 实验库CMake匹配GUID支持到 https://github.com/Kitware/CMake/blob/master/Help/dev/experimental.rst查看,必须严格匹配
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "0e5b6991-d74f-4b3d-a41c-cf096e0b2508")
# 设置Clang编译器
set(CMAKE_CXX_COMPILER "clang++")
set(CMAKE_C_COMPILER "clang")
# 使用Clang的libc++
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++")
set(CMAKE_CXX_EXTENSIONS OFF) # 避免编译命令设置 -std=gnu23
# C++23
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_MODULE_STD 1) # 自动编译 std 模块
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # 生成 compile_commands.json 文件
project(importCMake2 LANGUAGES CXX)
add_executable(importCMake2)
target_sources(importCMake2
  main.cpp
)

在上面的CMake文件中,编译器使用提Clang。尝试了一上午使用g++没有搞定。查询各种资料和相关配置说明,都无法直接使用cmakelists.txt文件一步生成相关的文件。如果象前文一样预编译好gcm文件,倒是也可以使用CMake,但这样失去了便捷性。

三、编译和处理

这里重点分析一下Clang+CMake的编译。在上面的相关文件编写完成后,可以用下面的方法进行编译:

复制代码
#进入工程目录
mkdir build
cd build
cmake -G Ninja ..
ninja

此时会报下面的错误:

复制代码
CMake Error at /usr/share/cmake-3.31/Modules/CMakeTestCXXCompiler.cmake:73 (message):
  The C++ compiler

    "/usr/bin/clang++"

  is not able to compile a simple test program.

  It fails with the following output:

    Change Dir: '/home/fpc/importCMake2/build/CMakeFiles/CMakeScratch/TryCompile-I54ppq'

    Run Build Command(s): /usr/bin/ninja -v cmTC_cd1cc
    [1/2] /usr/bin/clang++   -stdlib=libc++  -std=c++23 -MD -MT CMakeFiles/cmTC_cd1cc.dir/testCXXCompiler.cxx.o -MF CMakeFiles/cmTC_cd1cc.dir/testCXXCompiler.cxx.o.d -o CMakeFiles/cmTC_cd1cc.dir/testCXXCompiler.cxx.o -c /home/fpc/importCMake2/build/CMakeFiles/CMakeScratch/TryCompile-I54ppq/testCXXCompiler.cxx
    [2/2] : && /usr/bin/clang++ -stdlib=libc++ -stdlib=libc++ CMakeFiles/cmTC_cd1cc.dir/testCXXCompiler.cxx.o -o cmTC_cd1cc   && :
    FAILED: cmTC_cd1cc
    : && /usr/bin/clang++ -stdlib=libc++ -stdlib=libc++ CMakeFiles/cmTC_cd1cc.dir/testCXXCompiler.cxx.o -o cmTC_cd1cc   && :
    /usr/bin/ld: 找不到 -lc++: 没有那个文件或目录
    clang++: error: linker command failed with exit code 1 (use -v to see invocation)
    ninja: build stopped: subcommand failed.

  CMake will not be able to correctly generate this project.
Call Stack (most recent call first):
  CMakeLists.txt:24 (project)

从错误提示可看到需要安装相关的Clang自己的libc++的库,使用下面的命令:

复制代码
sudo apt install libc++-dev

重新编译即可成功。在build/CMakeFiles/__cmake_cxx23.dir目录下,可以看到std.pcm,这和前文中的std.o的功能一致。

四、总结

目前看来,g++和cmake一起相关的匹配细节还是有一些问题。至少是不太方便使用。大家可以使用Clang来写成同样的工作。当然,如果习惯使用g++,也可以使用前文的方式先用命令搞定std库的编译,再使用cmake,也没有问题。

不过大家不用担心,随着最终的版本落地,这种不方便适配的情况会很快改善。

相关推荐
王老师青少年编程1 天前
csp信奥赛C++高频考点专项训练之贪心算法 --【哈夫曼贪心】:合并果子
c++·算法·贪心·csp·信奥赛·哈夫曼贪心·合并果子
叼烟扛炮1 天前
C++第二讲:类和对象(上)
数据结构·c++·算法·类和对象·struct·实例化
样例过了就是过了1 天前
LeetCode热题100 最长公共子序列
c++·算法·leetcode·动态规划
谭欣辰1 天前
C++ 排列组合完整指南
开发语言·c++·算法
橙子也要努力变强1 天前
信号捕捉底层机制-机理篇2
linux·服务器·c++
盐焗鹌鹑蛋1 天前
【C++】stack和queue类
c++
郝学胜-神的一滴1 天前
罗德里格斯旋转公式(Rodrigues‘ Rotation Formula)完整推导
c++·unity·godot·图形渲染·three.js·unreal
lzh200409191 天前
深入理解进程:从PCB内核结构到写时拷贝的底层实战
linux·c++
aseity1 天前
跨平台项目中QString 与 非Qt 跨平台动态库在字符集上的一个实用的互操作约定.
c++·经验分享
CN-Dust1 天前
【C++】while语句例题专题
数据结构·c++·算法