[英]How do I build a parameterized third-party library in cmake?
I have a project in which I have a third party library checked out as a git submodule.我有一个项目,其中我有一个第三方库作为 git 子模块签出。 The third party library is just source code with no build system.第三方库只是没有构建系统的源代码。 In addition, The third party library must configured on a per-executable basis by way of compiler definitions and selectively compiling only the parts of the library that I need.此外,第三方库必须通过编译器定义在每个可执行的基础上进行配置,并有选择地只编译我需要的库的部分。 I use this library in a lot of different repositories, so I want to make a reusable component to generate an instantiation of the library for any particular executable.我在很多不同的存储库中使用这个库,所以我想制作一个可重用的组件来为任何特定的可执行文件生成库的实例化。
The way I've currently attempted this is by creating a generate_thirdparty.cmake<\/code> .
我目前尝试的方法是创建一个
generate_thirdparty.cmake<\/code> 。
This file looks something like this:这个文件看起来像这样:
function(generate_thirdparty parameters)
# several calls to add_library for the different components of this third party library
# the generated libraries depend on the parameters argument
# the parameters configure compile definitions and which source files are compiled
endfunction()
Let's sum up:让我们总结一下:
I think you're pretty much taking the right approach.我认为你几乎采取了正确的方法。 Let's call the third-party library libFoo<\/code> for brevity.
为简洁起见,我们将第三方库
libFoo<\/code> 。
Here's what I think you should do...这是我认为你应该做的...
Create a wrapper<\/em> repository for libFoo<\/code> that contains a FindFoo.cmake<\/code> file and the actual foo<\/code> repository submodule next to it.
为libFoo<\/code>创建一个包装<\/em>存储库,其中包含一个FindFoo.cmake<\/code>文件和它旁边的实际foo<\/code>存储库子模块。
This is to avoid the contents of FindFoo.cmake<\/code> from being independently versioned across your various projects.
这是为了避免FindFoo.cmake<\/code>的内容在您的各个项目中独立进行版本控制。
<\/li>
Include the wrapper<\/em> as your submodule in dependent projects, say in the directory third_party\/foo_wrapper<\/code>
将包装器<\/em>作为子模块包含在依赖项目中,例如在目录third_party\/foo_wrapper<\/code>
<\/li>
In those dependent projects, write:在那些依赖项目中,写:<\/li><\/ol>
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}\/third_party\/foo_wrapper") find_package(Foo REQUIRED) generate_foo(config1 ...) generate_foo(config2 ...) add_executable(app1 src\/app1\/main.cpp) target_link_libraries(app1 PRIVATE foo::config1) add_executable(app2 src\/app2\/main.cpp) target_link_libraries(app2 PRIVATE foo::config2)<\/code><\/pre>
- The contents of
FindFoo.cmake<\/code> will simply be:
FindFoo.cmake<\/code>的内容将是:
<\/li><\/ol> cmake_minimum_required(VERSION 3.18) function(generate_foo target) # Use CMAKE_CURRENT_FUNCTION_LIST_DIR to reference foo's source files # for example: set(sources "src\/src1.cpp" "src\/src2.cpp" ...) list(TRANSFORM sources PREPEND "${CMAKE_CURRENT_FUNCTION_LIST_DIR}\/foo\/") add_library(${target} ${sources}) add_library(foo::${target} ALIAS ${target}) # Do other things with ARGN endfunction() # Define a version for this dependency + script combo. set(Foo_VERSION 0.1.0) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Foo VERSION_VAR Foo_VERSION HANDLE_COMPONENTS)<\/code><\/pre> The CMAKE_CURRENT_FUNCTION_LIST_DIR<\/code> is the absolute path to the file containing the function being called.
CMAKE_CURRENT_FUNCTION_LIST_DIR<\/code>是包含被调用函数的文件的绝对路径。
Remember that this is the root of your wrapper<\/em> repository, so the actual sources for libFoo<\/code> will be in the adjacent foo<\/code> directory.
请记住,这是包装<\/em>存储库的根目录,因此libFoo<\/code>的实际源代码将位于相邻的foo<\/code>目录中。
list(TRANSFORM)<\/code> lets us write relative paths in the sources list that get converted to absolute paths for the sake of add_library<\/code> (passing a relative path to add_library<\/code> would be relative to the caller's<\/em> source directory).
list(TRANSFORM)<\/code>让我们在源列表中写入相对路径,这些相对路径为了add_library<\/code>而被转换为绝对路径(将相对路径传递给add_library<\/code>将相对于调用者的<\/em>源目录)。
I also create an ALIAS<\/code> target so that callers of generate_foo<\/code> can link to the alias.
我还创建了一个ALIAS<\/code>目标,以便generate_foo<\/code>的调用者可以链接到别名。
This is important because CMake considers names that contain ::<\/code> to be targets when a library is expected.
这很重要,因为 CMake 将包含::<\/code>的名称视为预期库时的目标。
This very helpfully turns typos from unintended linker flags into configure-time "target not found" errors.这非常有助于将意外链接器标志中的拼写错误转变为配置时“未找到目标”错误。
Then we define the function like normal and call the find_package_handle_standard_args<\/code> to handle find_package<\/code> arguments like REQUIRED<\/code> , COMPONENTS<\/code> (even just to check that none were incorrectly specified), and VERSION<\/code> .
然后我们像正常一样定义函数并调用find_package_handle_standard_args<\/code>来处理find_package<\/code>参数,如REQUIRED<\/code> 、 COMPONENTS<\/code> (甚至只是检查没有错误指定)和VERSION<\/code> 。
See the docs for it, here: https:\/\/cmake.org\/cmake\/help\/latest\/module\/FindPackageHandleStandardArgs.html<\/a>在此处查看文档: https<\/a> :\/\/cmake.org\/cmake\/help\/latest\/module\/FindPackageHandleStandardArgs.html
"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.