这似乎是一个没有明确答案的常见问题。
情况是:我们有一个第 3 方依赖项,我们希望在构建依赖它的目标时在构建时安装它。大致是这样:
ExternalProject_Add(target-ep
DOWNLOAD_COMMAND <whatever>
BUILD_COMMAND ""
INSTALL_COMMAND ""
CONFIGURE_COMMAND "")
add_library(target-imp STATIC IMPORTED)
set_target_properties(target-imp PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES /path/to/install/include
IMPORTED_LOCATION /path/to/install/lib/libwhatever.a)
add_library(target INTERFACE)
target_link_libraries(target INTERFACE target-imp)
add_dependencies(target target-ep)
Run Code Online (Sandbox Code Playgroud)
(由于cmake 问题 15052 ,这里需要三个探戈)
当使用 Unix Makefiles 作为生成器时,这很好用。仅按需安装依赖项,所有构建都能正常工作。
但是,在 Ninja 上,这会立即失败,如下所示:
ninja: error: '/path/to/install/lib/libwhatever.a', needed by 'something', missing and no known rule to make it
Run Code Online (Sandbox Code Playgroud)
这是因为 Ninja 扫描依赖项的方式与 Make 不同(请参阅ninja issue 760)。所以我们要做的其实就是告诉 Ninja 这个外部依赖是存在的。我们能做到这一点:
ExternalProject_Add(target-ep
DOWNLOAD_COMMAND <whatever>
BUILD_BYPRODUCTS /path/to/install/lib/libwhatever.a
BUILD_COMMAND ""
INSTALL_COMMAND ""
CONFIGURE_COMMAND "")
Run Code Online (Sandbox Code Playgroud)
不幸的是,它也失败了:
No build step for 'target-ep'ninja: error: mkdir(/path/to/install): Permission denied
Run Code Online (Sandbox Code Playgroud)
这是因为我的下载步骤具有写入该路径的权限,但是mkdir底层add_custom_command()from with正在运行的任何命令ExternalProject_Add()都没有。
所以:
BUILD_BYPRODUCTS,是否有一种方法可以简单地传达将要安装的整个目录是副产品?也就是说,/path/to/install/*是副产品吗?的隐藏mkdir步骤ExternalProject(所有其他步骤直接或间接依赖)总是尝试创建完整的目录集,即使它们不会被使用。你可以在这里看到这个。作为参考,它这样做:
ExternalProject_Add_Step(${name} mkdir
COMMENT "Creating directories for '${name}'"
COMMAND ${CMAKE_COMMAND} -E make_directory ${source_dir}
COMMAND ${CMAKE_COMMAND} -E make_directory ${binary_dir}
COMMAND ${CMAKE_COMMAND} -E make_directory ${install_dir}
COMMAND ${CMAKE_COMMAND} -E make_directory ${tmp_dir}
COMMAND ${CMAKE_COMMAND} -E make_directory ${stamp_dir}${cfgdir}
COMMAND ${CMAKE_COMMAND} -E make_directory ${download_dir}
COMMAND ${CMAKE_COMMAND} -E make_directory ${log_dir} # This one only since CMake 3.13
)
Run Code Online (Sandbox Code Playgroud)
Unix 系统上的默认安装位置可能是 /usr/local,因此如果您没有对它尝试创建的所有目录的写权限,那么这可能与您的问题有关。我建议您检查每个位置的权限,并确保它们已经存在或可写。或者,您可以指定构建树本地的安装目录,这样即使不会使用它,也至少可以始终创建它(请参见下面的示例)。
如果你使用 Ninja,它的依赖检查会比 make 更严格。您已经target-ep进行了提供 的下载libwhatever.a,因此您确实需要BUILD_BYPRODUCTS告诉 Ninjatarget-ep是创建该文件的原因。正如您所发现的,如果您不这样做,target-imp则会指向一个最初不存在的库,而 Ninja 正确地抱怨它丢失了并且不知道如何创建它。如果您提供BUILD_BYPRODUCTS,则构建步骤不应该为空是有道理的,因此您可能需要做一些构建步骤,即使它只是BUILD_COMMAND实际上并没有做任何有意义的事情。
以下修改后的定义target-ep应该有望为您服务:
ExternalProject_Add(target-ep
INSTALL_DIR ${CMAKE_CURRENT_BUILD_DIR}/dummyInstall
DOWNLOAD_COMMAND <whatever>
BUILD_BYPRODUCTS /path/to/install/lib/libwhatever.a
BUILD_COMMAND ${CMAKE_COMMAND} -E echo_append
INSTALL_COMMAND ""
CONFIGURE_COMMAND "")
Run Code Online (Sandbox Code Playgroud)
您的原始问题还会导致对错误目标的依赖。target-imp应该依赖target-ep,但你却target依赖了target-ep。正确的依赖关系可以这样表达:
add_dependencies(target-imp target-ep)
Run Code Online (Sandbox Code Playgroud)
有了这个BUILD_BYPRODUCTS选项,Ninja 已经知道上面的依赖,但是其他生成器需要它,包括 make。
您尚未指定<whatever>下载命令的用途,但我假设它负责确保库在/path/to/install/lib/libwhatever.a执行时存在。您也可以尝试制作DOWNLOAD_COMMAND空的并<whatever>作为BUILD_COMMAND替代。
要解决您的具体问题:
- 使用 Ninja 和 CMake 可以做到吗?(版本不是问题,如果可以解决问题,我可以使用最新的 CMake)
是的,我验证了上述方法适用于 Ninja 1.8.2,用于使用 CMake 3.11.0 在 macOS 上的虚拟测试项目。我希望它可以与 CMake 3.2 或更高版本一起使用(那时BUILD_BYPRODUCTS添加了对该选项的支持)。
- 如果有某种方法可以解决明确列出 BUILD_BYPRODUCTS 的方法,是否有一种方法可以简单地传达将要安装的整个目录是副产品?也就是说,/path/to/install/* 是副产品?
不太可能。Ninja 如何知道这样一个目录中的内容?获得可靠依赖项的唯一方法是明确列出预期存在的每个文件,您BUILD_BYPRODUCTS在您的情况下会使用这些文件。
如果您愿意在配置时下载,您可以按照这篇文章进行操作。它使用 google-test 作为示例,但我对其他依赖项使用了相同的技术。只需将ExternalProject代码放在一个单独的文件中,输入“CMakeLists.txt.dependency”,然后使用execute_process. 我configure_file首先使用将配置信息注入外部项目并将其复制到构建树中。
configure_file(CMakeLists.txt.dependency.in dependency/CMakeLists.txt)
execute_process(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/dependency" )
execute_process(COMMAND "${CMAKE_COMMAND}" --build .
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/dependency" )
Run Code Online (Sandbox Code Playgroud)
我在配置时执行此操作,因此find_package命令find_library可以对依赖项起作用。
现在,您使用什么发电机并不重要。
| 归档时间: |
|
| 查看次数: |
1732 次 |
| 最近记录: |