CMake生成VS解决方案编译成功后未找到输出的libShadows库文件
问题:CMake生成VS解决方案编译成功但无库文件输出
我使用CMake项目生成Visual Studio解决方案后执行编译操作,编译流程显示成功但始终找不到生成的库文件,检索整个项目文件夹,未发现任何库文件输出,相关配置和日志如下:
项目根目录CMake配置
cmake_minimum_required(VERSION 3.22) project(ShadowContainers) set(CMAKE_CXX_STANDARD 23) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) include_directories(include/) add_subdirectory(library) ...
library子目录CMake配置
add_library(libShadows shadows.tpp ../include/shadows.hpp) set_target_properties(libShadows PROPERTIES LINKER_LANGUAGE CXX) # a tpp and an hpp aren't enough to make the system certain it's c++ target_compile_features(libShadows PRIVATE cxx_std_23)
MSBuild输出日志片段
Done Building Project "C:\Users\[..]\projects\Shadow Array\library\libShadows.vcxproj" (default targets). Done Building Project "C:\Users\[..]\projects\Shadow Array\library\libShadows.vcxproj.metaproj" (default targets).
即便libShadows是项目内唯一构建目标,在整个项目目录下也无法检索到对应输出文件。
补充说明
尝试了两种不同的编译流程,均得到相同结果,仅VS和CMake生成的中间文件存放位置有区别,两种方式都没有库文件输出:
- 常规编译流程(工作目录为项目根目录):
cmake . msbuild ShadowContainers.sln
- 独立build目录编译流程(工作目录同样为项目根目录):
mkdir build cd build cmake .. cmake --build .
原因分析与解决方案
核心诱发原因
add_library调用没有传入任何可编译的源文件(.cpp/.cc等实现文件),仅传入了模板实现文件.tpp和头文件.hpp,这类文件不会被MSVC编译器单独编译生成目标文件,最终链接阶段没有任何输入目标文件,自然不会生成.lib静态库或者.dll动态库文件。
手动设置LINKER_LANGUAGE CXX只是强制CMake跳过了「未检测到可编译C源文件」的报错检查,相当于告诉CMake「我确定这是C目标,你别报错」,但实际编译阶段没有任何需要编译的单元,构建系统会判定目标无实际产出,直接标记构建完成,不会抛错。
排查步骤
- 打开生成的
libShadows.vcxproj项目文件,查看其中的ClCompile条目,会发现里面没有任何被标记为需要编译的源文件,只有被标记为ClInclude的头文件/tpp文件,这就是没有产出的直接证据。 - 把MSBuild的输出日志级别调到详细,重新编译,会看到libShadows目标完全没有执行编译、链接的相关步骤,只有项目加载完成的标记。
修复方案
根据项目类型选择对应处理方式:
- 如果要做纯头文件/模板库:不需要编译生成二进制库文件,把
add_library改成接口库即可:
接口库不会产出任何二进制文件,仅用来传递头文件路径、编译特性等依赖属性,其他目标链接这个库的时候会自动拿到对应的头文件包含路径和C++标准配置。add_library(libShadows INTERFACE) target_include_directories(libShadows INTERFACE ${PROJECT_SOURCE_DIR}/include) target_compile_features(libShadows INTERFACE cxx_std_23) - 如果要做需要编译的静态/动态库:把对应功能的
.cpp实现文件加入add_library的源文件列表,不要只传头文件和tpp文件。比如存在shadows.cpp实现文件,就改成:
有了可编译的cpp文件后,编译器会先把cpp编译成obj目标文件,再链接生成对应的lib库文件,输出到之前设置的add_library(libShadows shadows.cpp shadows.tpp ../include/shadows.hpp) target_compile_features(libShadows PRIVATE cxx_std_23)CMAKE_ARCHIVE_OUTPUT_DIRECTORY路径下。
额外注意:用MSVC编译的时候,默认编译的是Debug配置,未修改输出路径规则时,Debug版本的库会放在
<build目录>/Debug/下,Release版本在<build目录>/Release/下,之前设置的三个全局输出目录变量会覆盖这个默认规则,把所有配置的产出都放到build根目录,修复源文件问题后直接去build根目录查找即可。
内容的提问来源于stack exchange,提问作者user9329905
相关产品推荐
相关产品推荐

