用Meson可构建简单项目,CMake构建双可执行文件遇main重定义问题
哦,这个坑我见太多了!你遇到的问题根本不是CMake的限制,而是你大概率写错了CMakeLists.txt的逻辑——把两个包含main()的源文件塞进了同一个可执行目标里,或者重复引用了某个带main的文件到多个目标中。Meson你能成功,肯定是因为你分开声明了两个独立的可执行目标,而CMake这边没做对。
先给你拆解下报错原因:链接器在生成可执行文件时,要求整个目标里只能有一个main()入口。如果你的CMake脚本把source1.cpp和test.cpp都加到同一个add_executable里,链接器就会看到两个main定义,直接抛出“Multiple definition”的错误,这完全符合预期。
正确的CMake写法
你需要为每个带main()的源文件单独创建一个可执行目标,目标名称必须唯一,具体步骤如下:
1. 基础版本(无共用代码)
如果source1.cpp和test.cpp是完全独立的(没有共用的其他源文件),直接写两个add_executable即可:
# 生成发布版可执行文件,对应source1.cpp里的main() add_executable(MyApp source1.cpp) # 生成测试版可执行文件,对应test.cpp里的main() add_executable(MyAppTest test.cpp)
这样CMake会生成两个独立的可执行文件:MyApp(发布版)和MyAppTest(测试版),各自对应自己的main入口,完全不会冲突。
2. 进阶版本(有共用代码)
如果你的项目里有共用的工具类/函数(比如utils.cpp),不要把这些文件重复加到两个可执行目标里,而是把它们编译成一个库,再链接到两个目标:
# 把共用代码编译成静态库(STATIC也可以换成SHARED生成动态库,看需求) add_library(MyAppCommon STATIC utils.cpp) # 发布版:仅包含source1.cpp,链接共用库 add_executable(MyApp source1.cpp) target_link_libraries(MyApp PRIVATE MyAppCommon) # 测试版:仅包含test.cpp,链接共用库 add_executable(MyAppTest test.cpp) target_link_libraries(MyAppTest PRIVATE MyAppCommon)
这种方式不仅避免了代码重复编译,还能让项目结构更清晰。
你可能踩的错误写法
对比一下,你之前的CMake脚本大概率是类似这样的错误写法:
# ❌ 错误!把两个带main的文件加到同一个目标里 add_executable(MyApp source1.cpp test.cpp)
这种写法会让CMake尝试把两个main()都打包进同一个可执行文件,链接器自然会报错。
额外优化:给不同版本设置专属编译选项
你还可以给发布版和测试版设置不同的编译参数,比如发布版开启优化,测试版开启调试信息:
# 发布版:开启O2优化 target_compile_options(MyApp PRIVATE -O2) # 测试版:开启调试信息和警告 target_compile_options(MyAppTest PRIVATE -g -Wall -Wextra)
核心思路就是:每个可执行目标对应唯一的main入口源文件,目标名称不能重复,共用代码通过库来管理。按照这个逻辑写,CMake生成两个可执行文件和Meson一样轻松!
内容的提问来源于stack exchange,提问作者Pietro

