CMake中add_executable生成MySQL测试程序时额外生成库文件的原因
在Windows环境下使用CMake编译PostgreSQL和MySQL的测试程序时,PostgreSQL测试程序仅生成预期的test-postgres.exe和test-postgres.pdb,但MySQL测试程序除了test-mysql.exe和test-mysql.pdb外,还额外生成了test-mysql.lib和test-mysql.exp文件。
你的CMake配置
cmake_minimum_required(VERSION 3.10) project(olivine) find_package(PostgreSQL REQUIRED) add_executable(test-postgres test-postgres.cpp) target_include_directories(test-postgres PRIVATE ${PostgreSQL_INCLUDE_DIRS}) target_link_libraries(test-postgres PRIVATE ${PostgreSQL_LIBRARIES}) if(WIN32) find_path(MYSQL_INCLUDE_DIR NAMES "mysql.h" PATHS "$ENV{PROGRAMFILES}/MySQL/*/include" "$ENV{SYSTEMDRIVE}/MySQL/*/include") find_library(MYSQL_LIBRARY NAMES "mysqlclient" PATHS "$ENV{PROGRAMFILES}/MySQL/*/lib" "$ENV{SYSTEMDRIVE}/MySQL/*/lib") endif() add_executable(test-mysql test-mysql.cpp) target_include_directories(test-mysql PRIVATE ${MYSQL_INCLUDE_DIR}) target_link_libraries(test-mysql PRIVATE ${MYSQL_LIBRARY})
编译输出文件列表
Directory of C:\olivine\build\Debug 06/12/2023 07:14 PM <DIR> . 06/12/2023 07:13 PM <DIR> .. 06/07/2023 04:20 AM 4,561,920 libcrypto-3-x64.dll 06/07/2023 04:20 AM 775,168 libssl-3-x64.dll 06/12/2023 07:14 PM 8,736,768 test-mysql.exe 06/12/2023 07:14 PM 707 test-mysql.exp 06/12/2023 07:14 PM 1,774 test-mysql.lib 06/12/2023 07:14 PM 11,554,816 test-mysql.pdb 06/12/2023 06:31 PM 75,264 test-postgres.exe 06/12/2023 06:31 PM 1,445,888 test-postgres.pdb
原因分析
这是因为你的MySQL测试代码中存在被导出的符号(比如通过__declspec(dllexport)声明的函数或变量)。在Windows平台的MSVC编译器下,只要可执行文件中包含导出符号,编译器就会自动生成对应的导入库(.lib)和导出表文件(.exp)——前者供其他程序链接你的exe使用,后者记录exe的导出符号信息。
PostgreSQL测试程序没有生成这类文件,是因为其代码中不存在任何导出符号。
可能的触发场景:
- 你在
test-mysql.cpp中手动使用了__declspec(dllexport)声明符号。 - 你包含的MySQL头文件中,某些宏被错误定义为
__declspec(dllexport)。比如MySQL的头文件通常会用MYSQL_API这类宏控制符号导入导出,若编译时没有正确设置对应的宏(如MYSQLCLIENT_STATIC),就可能导致符号被意外导出。
解决办法
检查并修正代码中的导出声明
查看test-mysql.cpp,移除手动添加的__declspec(dllexport);如果是引用外部库的符号,改为__declspec(dllimport)。设置正确的MySQL编译宏
在CMake中为MySQL测试目标添加编译定义,确保头文件中的宏正确设置为导入而非导出:target_compile_definitions(test-mysql PRIVATE MYSQLCLIENT_STATIC)该宏会让MySQL头文件将符号标记为静态链接,避免生成导出符号。
临时抑制文件生成(不推荐)
若只是想临时阻止生成.lib和.exp(不推荐,因为会掩盖根源问题),可以在CMake中添加:set_target_properties(test-mysql PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS OFF)注意:该属性默认是关闭的,仅当代码中明确存在导出符号时才会生成额外文件,所以优先解决符号导出的问题。
内容的提问来源于stack exchange,提问作者rwallace

