有一个名为revolta的静态库正在构建中,然后安装到sysroot中:
set( CMAKE_INSTALL_PREFIX <path to sysroot> )
# ReVolta c++ library name
set( TARGET_LIBREVOLTA "revolta" )
add_library( ${TARGET_LIBREVOLTA} STATIC )
target_include_directories( ${TARGET_LIBREVOLTA}
PUBLIC
# Once the librevolta targets are being exported, this include directory in which the lib is installed is used
$<INSTALL_INTERFACE:${CMAKE_INSTALL_PREFIX}/include>
PRIVATE
# Include directory used privately just to build the library itself
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}>
)
target_sources( ${TARGET_LIBREVOLTA}
PUBLIC
...
)
稍后,一旦构建了librevolta,就使用以下命令将其安装到sys根目录中:
# Install all the revolta headers into include directory and copy the built library
install( TARGETS ${TARGET_LIBREVOLTA} EXPORT ${TARGET_LIBREVOLTA}
FILE_SET HEADERS DESTINATION "${CMAKE_INSTALL_PREFIX}/include"
ARCHIVE DESTINATION "${CMAKE_INSTALL_PREFIX}/lib"
)
和连接的自定义命令:
# Once the librevolta is built, install it to the sysroot as specified by 'install()' commands
add_custom_command( TARGET ${TARGET_LIBREVOLTA} POST_BUILD COMMAND ${CMAKE_COMMAND} ARGS --install . )
到目前为止一切顺利。这按预期工作,一旦CMake构建了“revolta
“目标,它就会像使用${CMAKE_INSTALL_PREFIX}
安装的那样构建并安装到sysroot中。
我的问题是,一旦我尝试将目标作为链接的目标添加到其他lib/executable中,它会自动将librevolta源路径包含到include中,并使用build目录中的相对路径链接库,而不是像在librevolta构建之后的步骤中执行的那样安装到sysroot中。
其他一些库/可执行文件:
target_link_libraries( ${APP_EXECUTABLE}
PRIVATE
revolta
)
构建完成后,将添加包含路径-I/home/martin/git/revolta/source/librevolta
(源位置),尽管在上面的代码片段中它被声明为PRIVATE:
PRIVATE
# Include directory used privately just to build the library itself
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}>
只有${CMAKE_INSTALL_PREFIX}/include
是公开的。
此外,库是从构建树而不是从其安装位置获取的:
../../librevolta/librevolta.a
代替
/home/martin/git/revolta/sysroot/lib/librevolta.a
您能告诉我如何正确设置revolta
目标,使其正确使用其源代码来构建自身,但一旦在其他地方使用,它将从同一位置(考虑标准位置)提供sysroot安装头文件和构建库吗?
提示:我还尝试从应用程序中完全删除revolta目标,指定仅使用sys根(gcc选项--sysroot=/home/martin/git/revolta/sysroot
),它工作正常,使用了正确的标头和lib,但一旦未构建和安装librevolta
,则在应用程序构建之前不会运行目标,因为随后未定义依赖项...
1条答案
按热度按时间kqqjbcuj1#
TL; DR:您需要执行此处所做的操作:
∮ ∮ ∮ ∮
我看到这些
CMakeLists.txt
文件有一些问题,但它们与您的问题无关,因为如果我正确理解了您在这里尝试做什么,那么就没有问题,它按预期使用。让我澄清一下:
CMakeLists.txt
,您可以在其中定义目标revolta
CMakeLists.txt
,您在其中定义可执行目标**,然后通过add_subdirectory()
和target_link_libraries(my_executable revolta)
添加revolta
目标**如果是这样的话,那就太糟糕了:
强制您的构建自动安装这个库永远都不是一个好办法(例如,您首先需要提升特权才能构建它,因为这个命令会带来安全风险)。
话虽如此,发生的事情是非常好的,因为从
my_executable's CMakeLists.txt
的Angular 来看,你仍然在构建,也就是说,你使用的是BUILD_INTERFACE
,但这是你不想做的事情。您要做的是:
为
revoltaConfig.cmake
文件创建生成器文件。为此,我将参考本教程:How to create a ProjectConfig.cmake file
在你创建了这样的文件之后,也就是在构建和安装
revolta
之后,你也将(在这个过程中)创建一个revoltaConfig.cmake
文件,它可以帮助你通过find_package(revolta)
填充my_executable
项目。以上大概是你感兴趣的。
用于区分
BUILD_INTERFACE
和INSTALL_INTERFACE
的生成器表达式主要用于头文件位置(或其他链接库),因为当您构建库时,头文件的结构可能与安装库时不同(正如您所知),因此在CMakeLists.txt
中运行良好,因为当您考虑它时:因此,总结一下(使用旧的
CMakeLists.txt
)这里最可能发生的情况是add_subdirectory
添加目标库作为依赖项的可执行文件时,您就隐式地使用了BUILD_INTERFACE
,因为您正在构建。INSTALL_INTERFACE
。您可以在没有projectConfig文件的情况下使用相同的生成器表达式,通过混合它们来破解它,但我不推荐这样做,因为如果事先不做一些奇怪的步骤,
CMakeLists.txt
将无法工作。