cmake:导出给target_link_library(私有)的绝对lib pathnames出现在生成的Interface_link_libraries中。我怎么样?

发布于 2025-02-12 11:30:51 字数 2281 浏览 1 评论 0 原文

在大型CMAKE/C ++项目中,我们正在添加主要库目标 foo 。它具有许多静态链接的依赖项,这些依赖项作为 target_link_libraries()提供了绝对路径。现在,我正在编写CMAKE来导出该库一旦构建的导出,其中包括生成的CMAKE,因此库消费者可以简单地使用cmake find_package()。但是,生成的 footArgets.cmake 正在嵌入链接填充物的绝对路径,而不仅仅是库名。

此外,我已经创建了一个 add_library(barcommon界面),以分别结束引用的第三方静态液体,并且似乎在起作用,并且客户端应用程序消耗了它。这占FOO也提到的图书馆的90%。因此,真正的Foo的导出 Interface_link_libraries 应该是3个文件名,而不是40个绝对Pathnames。

  1. 我很困惑,为什么 target_link_libraries(foo private $ {libs} 正在定义导出的'Interface_link_libraries的属性?

  2. ?仅是图书馆的文件名,并且最终对其中的文件名进行了最佳控制。

代码:

在一个用于生成目标的大CMAKE宏内我们有: -

  • 我称其为创建库/目标foo。
  • _target_args_lib_deppers 将解决绝对文件路径名,大约为40个静态链接的库依赖项。
add_library(${TargetName} STATIC ${AllSources} ${_TARGET_ARGS_OBJ_FILES})

  <snip>

target_link_libraries(${TargetName}
    PRIVATE
        $<${GCC}:-Wl,--start-group>
        ${_TARGET_ARGS_LIB_DEPENDS}
        $<${GCC}:-Wl,--end-group>
    )

在我刚刚添加了这些块的情况下,漫长的功能返回:

target_link_directories(FOO
    INTERFACE
        $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
        $<INSTALL_INTERFACE:foo/lib>
    )

target_include_directories(FOO
    INTERFACE
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
        $<INSTALL_INTERFACE:foo/include>
    )

install(TARGETS Foo
    EXPORT
        FooTargets
    DESTINATION
        foo/lib
    )    

在我的cmakelists末尾还有一些“安装”样板.txt 运行cmake后,构建项目并运行从Visual Studio生成的“安装”目标CMAKE我可以检查生成的文件: local_install \ windows \ windows \ fool \ foo \ lib \ lib \ cmake \ foo \ foodargets.cmakes.cmakes.cmake 显示:(

set_target_properties(Nexidia.Workbench.StaticLib.StaticLib PROPERTIES
  INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/Foo/include"
  INTERFACE_LINK_DIRECTORIES "${_IMPORT_PREFIX}/Foo/lib"
  INTERFACE_LINK_LIBRARIES "\$<LINK_ONLY:\$<0:-Wl,--start-group>>;C:/full/path/to/libA.lib;C:/full/path/to/libB.lib \$<LINK_ONLY:\$<0:-Wl,--end-group>>"
)

带有大约40个库的完整路径)。


PS。我正在阅读Professional Cmake:实用指南,因此,如果有人可以引用回答此问题的章节/小节,则可能会有所帮助。

In a large CMake/C++ project our major library target Foo is being added. It has many statically linked dependencies that are provided as absolute-paths to target_link_libraries(). Now I'm writing the CMake to export this library once built, including the generated CMake so a library consumer can simply use CMake find_package(). However the generated FooTargets.cmake is embeding the absolute-paths of the link-libraries instead of just the library names.

Additionally, I've already created an add_library(BarCommon INTERFACE), to wrap up the referenced 3rd-party static libs separately and that seems to be working and the client-application consumed it. That accounts for 90% of the libraries also mentioned by FOO. So really FOO's exported INTERFACE_LINK_LIBRARIES should be about 3 file names instead of 40 absolute-pathnames.

  1. I'm confused, why is the target_link_libraries(FOO PRIVATE ${libs} is defining the exported 'INTERFACE_LINK_LIBRARIES' property?

  2. I would like that generated INTERFACE_LINK_LIBRARIES property to be only library filenames, and optimally have finer control over which filenames end up in it. How do I control this?


Code:

Inside a large CMake Macro for generating targets we have this:
-

  • I call it to create library/target FOO.
  • _TARGET_ARGS_LIB_DEPENDS will resolve to ABSOLUTE FILE PATHNAMES for about 40 statically linked library dependencies.
add_library(${TargetName} STATIC ${AllSources} ${_TARGET_ARGS_OBJ_FILES})

  <snip>

target_link_libraries(${TargetName}
    PRIVATE
        
lt;${GCC}:-Wl,--start-group>
        ${_TARGET_ARGS_LIB_DEPENDS}
        
lt;${GCC}:-Wl,--end-group>
    )

where that longish function returns I have just added these blocks:

target_link_directories(FOO
    INTERFACE
        
lt;BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
        
lt;INSTALL_INTERFACE:foo/lib>
    )

target_include_directories(FOO
    INTERFACE
        
lt;BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
        
lt;INSTALL_INTERFACE:foo/include>
    )

install(TARGETS Foo
    EXPORT
        FooTargets
    DESTINATION
        foo/lib
    )    

There is some more 'install' boilerplate at the end of my CMakeLists.txt
After I run CMAKE, build the project and run the 'INSTALL' target CMake generated from Visual Studio I can examine generated file: local_install\Release\Windows\Foo\lib\cmake\Foo\FooTargets.cmake shows:

set_target_properties(Nexidia.Workbench.StaticLib.StaticLib PROPERTIES
  INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/Foo/include"
  INTERFACE_LINK_DIRECTORIES "${_IMPORT_PREFIX}/Foo/lib"
  INTERFACE_LINK_LIBRARIES "\
lt;LINK_ONLY:\
lt;0:-Wl,--start-group>>;C:/full/path/to/libA.lib;C:/full/path/to/libB.lib \
lt;LINK_ONLY:\
lt;0:-Wl,--end-group>>"
)

(with the full paths to about 40 libraries).


PS. I'm reading Professional CMake: A Practical Guide, so if someone could cite the chapter/sub-section that answers this it might help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

白云不回头 2025-02-19 11:30:52

这是因为您的库是 static ,因此如果不包括其对消费者链接线的依赖性,它就无法正确链接到消费者。共享库的共享依赖关系也会发生同样的事情。共享库的静态依赖性被完全“吸收”到共享库中,因此不会出现。

Cmake意识到了这一切,因此为了尊重私有的其他语义,它插入了 $&lt; link_only:...&gt; Generator Expression。这样可以确保库仅用于链接 ,并且任何关联的接口_*属性不传播。

换句话说,CMAKE在这里表现正确。

您应该通过创建并链接到 targets libb 和朋友可以作为主要构建的一部分导出,或者通过当然,在您的分布式软件包中以及库本身中,find_dependency

我可以给您的最好的建议是始终 目标 从不通向路径或原始库标志。

This is because your library is static and so it cannot be correctly linked to consumers without including its dependencies on consumers' link lines. The same thing happens with the shared dependencies of shared libraries. Static dependencies of shared libraries are fully "absorbed" into the shared library and so they don't appear.

CMake is aware of all this, and so to respect the other semantics of PRIVATE, it inserts the $<LINK_ONLY:...> generator expression. This ensures that the libraries are used for linking only and that any associated INTERFACE_* properties are not propagated.

In other words, CMake is behaving correctly here.

You should resolve this by creating and linking to targets for libB and friends that you can either export as part of your main build or import into both your main build and via find_dependency in your distributed package, along with the libraries themselves, of course.

The best advice I can give you is to always link to targets in CMake, never to paths or raw library flags.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文