CMake:能否仅使用静态库而不使用源代码构建可执行文件?

23

我希望只使用静态库(即.a文件)构建可执行文件。这是可能的,因为main()函数包含在其中一个库中。

add_executable()函数要求我提供至少一个源文件。但这不是我想做的。


2
你可以添加一个不定义任何符号的微不足道的源文件? - Chris Beck
2个回答

26

没有办法在不使用hack的情况下完成它。 您需要至少一个*.c或*.cpp文件。

我的做法是制作一个虚拟的null.cpp文件(零字节)并使用它。 您也可以使用/dev/null,但这仅适用于Linux。

file(WRITE null.cpp "")

add_executable(tester
    null.cpp
)

target_link_libraries(tester
    -Wl,--whole-archive
    libtest1
    libtest2
    libtest3
    libtest4
    -Wl,--no-whole-archive
    gtest_main
)

我原以为会有一种“标准化”的CMake方法来解决这个问题。但是这个解决方法也很有效。感谢你的回答! - dubbaluga
4
通过使用"${CMAKE_CURRENT_BINARY_DIR}/null.cpp"而不是仅仅使用null.cpp,你可以保持你的源代码树的清洁。 - Max Truxa
每次构建都会强制重新编译/链接null.cpp。 - Spongman

14

为什么 CMake 强制要求对源文件进行编译主要有两个原因:

  1. 从文件结尾中确定 LINKER_LANGUAGE
  2. 并非所有编译器都支持仅对象/库链接步骤(详情请见下文)

如果将 main() 函数移到库中,请记住以下内容:为什么链接库的顺序有时会导致 GCC 出现错误?

因此,如果您在同一项目中使用 CMake 构建库,则建议将您的库(至少包含 main() 函数的库)更改为对象库

cmake_minimum_required(VERSION 2.8.8)

project(NoSourceForExe)

file(WRITE main.cc "int main() { return 0; }")

add_library(MyLibrary OBJECT main.cc)
add_executable(MyExecutable $<TARGET_OBJECTS:MyLibrary>)

add_library()文档中提到一个警告:

一些本地构建系统可能不喜欢仅包含目标文件的对象,因此请考虑向引用$<TARGET_OBJECTS:objlib>的任何目标添加至少一个真实源文件。

但那些情况很少,并且在Tests/ObjectLibrary/CMakeLists.txt中列出:

# VS 6 and 7 generators do not add objects as sources so we need a
# dummy object to convince the IDE to build the targets below.
...
# Xcode does not seem to support targets without sources.

不知道你要针对哪个主机操作系统,可以试一试。

参考资料


非常有用。我曾经看过这个教程 https://cmake.org/Wiki/CMake/Tutorials/Object_Library,但从未想过它也可以以非常整洁的方式添加可执行文件。 - Sanjit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接