CMAKE如何获取目标文件位置

8
我正在尝试获取另一个项目的静态库位置。我尝试使用get_property(target_name TARGET Test PROPERTY LOCATION),但是CMAKE会给出以下错误。
CMake Error at project.cmake:6 (get_property):
The LOCATION property may not be read from target "A".
Use the target name directly with add_custom_command, or use the generator
expression $<TARGET_FILE>, as appropriate.

我试图使用错误消息中提到的生成器表达式,但并没有成功。
MESSAGE($<TARGET_FILE:A>)

只是输出完全相同的字符串,因此生成器表达式似乎根本没有被评估:

$<TARGET_FILE:A>

我看过了文档。在第一行中提到:
生成器表达式在构建系统生成期间进行评估,以产生特定于每个构建配置的信息。
如果我理解正确,那么当消息函数得到评估时,生成器表达式就不再进行评估了?那么在这种情况下我应该做什么?
我在GitHub上提交了这个问题的最小示例。
编辑:
很抱歉以这样迂回的方式提出问题,并没有清晰地说明我的意图:
我的目标是让CMake为我的项目构建一个单一 (!) 静态库,这个静态库可以被其他人(不使用CMake的人)使用。我仍然会使用“正常”的依赖关系解析来构建我的项目,但另一个人——不使用CMake——将不得不手动链接多个库到他的项目中,这有些不方便。一个单独的库将解决这个问题。
在尝试将CMake静态链接两个静态库的过程中,我在某个地方读到(抱歉,我没有保存链接),至少在使用Visual Studio作为编译器时,如果将要链接的静态库的完整路径附加到静态链接器标志中,就可以得到我想要的结果:
set_target_properties(B PROPERTIES STATIC_LIBRARY_FLAGS >>>INSERT_PATH_HERE<<<)

实际上这有效。但现在我必须手动插入变量的完全限定路径。
set_target_properties(B PROPERTIES STATIC_LIBRARY_FLAGS "/path/to/library.lib")

对我来说,这似乎不是一种“好”的方式。因此,我尝试使用生成器表达式,并得出了以下结论:

set_target_properties(B PROPERTIES STATIC_LIBRARY_FLAGS $<TARGET_FILE:A>)

由于我并没有完全理解,所以它无法正常工作。我猜测set_target_properties不支持生成器表达式。在尝试使我的项目正常工作时,我尝试了以下方法。
MESSAGE($<TARGET_FILE:A>)

如上所述,我认为如果我能让那个陈述句起作用,就可以解决我的实际问题。这就是我提出上面问题的原因。我没有意识到这会导致回答我的人感到困惑。


1
消息不能使用生成器表达式。因为它们针对每个构建配置进行生成,与普通变量相比,它们的行为非常奇怪。所以问题实际上是,您试图在哪里使用目标属性位置? - IdeaHat
我想生成一个链接器标志,将静态库A链接到另一个静态库B中,如下所示:set_target_properties(B PROPERTIES STATIC_LIBRARY_FLAGS $<TARGET_FILE:A>)但这并不起作用。它会导致$<TARGET_FILE:A>生成到项目文件中,而不是其结果。使用message()是我调试问题的手段。我猜当我用message()解决了问题后,set_target_properties()也应该能够正常工作。 - Dirk
1个回答

1
如果您想在另一个库中使用某个库,您应该使用target_link_libraries函数:
target_link_libraries(B A) 
target_link_libraries的签名会自动将A传递到所有直接或间接使用B的非静态库和可执行文件中。
使用B的静态库知道它们依赖于A,但是它们不会在自己内部拥有来自A的对象文件的副本。依赖信息存储在库的INTERFACE_LINK_LIBRARIESLINK_LIBRARIES目标属性中。
按设计,静态库只是一组对象文件的归档文件。如果您只想在CMake项目中使用库,则无需手动混合来自不同库的对象文件。 CMake将使用需要链接到的库列表和库的正确顺序指示链接器。链接器将从提供的静态库中解析所有符号所在的对象文件。
如果仍然需要精确控制混合对象文件,则可以考虑使用OBJECT library type
# Create plain objects library which essentially is a set of object files
add_library(zipobj OBJECT zip.cpp)
# Archive all objects from zipobj. Recompilation of zip.cpp won't take place.
add_library(zip STATIC $<TARGET_OBJECTS:zipobj>)

add_library(lzmaobj OBJECT lzma.zpp)
add_library(lzma STATIC $<TARGET_OBJECTS:lzmaobj>)

# Create a library which contains object files from both zipobj and lzmaobj
add_library(archive STATIC $<TARGET_OBJECTS:zipobj> $<TARGET_OBJECTS:lzmaobj>)

编辑: 另外你可以尝试使用merge_libraries函数: http://www.mail-archive.com/cmake@cmake.org/msg28670.html


感谢您的回答,roolebo。但据我所知,那只是意味着使用cmake“如果有人链接到B,则自动链接A”。我想要将A真正地包含在B中,这样如果我将库用于其他地方,所有内容都会被包含在其中。 - Dirk
@Dirk,我已经澄清了答案。可能对象库类型是您要寻找的东西。 - roolebo
再次感谢您的回答。看来我没有清楚地表达我的意图。我在上面澄清了我的问题。我只想要一个单独的CMake来构建静态库,其中包含所有符号,而不会弄乱我的库结构。 - Dirk
@Dirk,我认为还有另一个答案在这里:https://dev59.com/blLTa4cB1Zd3GeqPbpSl此外,CMake邮件列表上也有关于这个问题的讨论:http://www.cmake.org/pipermail/cmake/2012-September/052109.html - roolebo
@Dirk,这是一个使用OBJECT库类型完成任务的示例:https://gist.github.com/anonymous/63ed37e60f4063dfadcc - roolebo
非常感谢。你提出的方法可行。虽然有一些额外的“对象目标”,但我可以接受。你提到的merge_libraries函数似乎正是我想要的,但我无法在几分钟内运行它。当我有更多时间时,我可能会再次查看它。 - Dirk

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