我有一个库,它是作为我项目的一部分构建和链接的。我想提供OPTIONALLY设施在系统范围内安装库(或者设置$ {CMAKE_INSTALL_PREFIX}的地方)。否则,默认情况下,项目的最终构建产品将静态链接到库,前者已安装,但库二进制文件仍保留在构建目录中。
换句话说:
$ make
$ make install
将构建和安装程序,但仅限于
$ make install.foo
将库安装到$ {CMAKE_INSTALL_PREFIX},如果需要,首先构建它。
到目前为止我有类似的东西(从实际脚本中简化,因此可能存在错误):
INCLUDE_DIRECTORIES( "${CMAKE_CURRENT_LIST_DIR}")
SET (FOO_LIBRARY "foo")
# Following builds library and makes it available to
# be linked other targets within project by:
# TARGET_LINK_LIBRARIES(${progname} ${FOO_LIBRARY})
ADD_LIBRARY(${FOO_LIBRARY}
foo/foo.cpp # and other sources ...
)
###########################################################
# Approach #1
# -----------
# Optionally allow users to install it by invoking:
#
# cmake .. -DINSTALL_FOO="yes"
#
# This works, but it means that users will have to run
# cmake again to switch back and forth between the libary
# installation and non-library installation.
#
OPTION(INSTALL_FOO "Install foo" OFF)
IF (INSTALL_FOO)
INSTALL(TARGETS ${FOO_LIBRARY} DESTINATION lib/foo)
SET(FOO_HEADERS foo/foo.h)
INSTALL(FILES ${FOO_HEADERS} DESTINATION include/foo)
UNSET(INSTALL_FOO CACHE)
ENDIF()
###########################################################
###########################################################
# Approach #2
# -----------
# Optionally allow users to install it by invoking:
#
# make install.foo
#
# Unfortunately, this gets installed by "make install",
# which I want to avoid
SET(FOO_INSTALL "install.foo")
ADD_CUSTOM_TARGET(${FOO_INSTALL}
COMMAND ${CMAKE_COMMAND}
-D COMPONENT=foo
-P cmake_install.cmake)
ADD_DEPENDENCIES(${FOO_INSTALL} ${FOO_LIBRARY})
INSTALL(TARGETS ${FOO_LIBRRARY}
DESTINATION lib/foo COMPONENT foo)
SET(FOO_HEADERS foo/foo.h)
INSTALL(FILES ${FOO_HEADERS}
DESTINATION include/foo COMPONENT foo)
###########################################################
可以看出,方法#1有点可行,但安装库所需的步骤是:
$ cmake .. -DINSTALL_FOO="yes"
$ make && make install
然后,要返回“正常”版本,用户必须记住在没有“-DINSTALL_FOO”选项的情况下再次运行cmake,否则库将安装在下一个“make install”上。
当我运行“make install.foo”时,第二种方法有效,但如果我运行“make install”,它也会安装库。我想避免后者。
有没有人对如何实现这一目标有任何建议?
答案 0 :(得分:4)
你采用方法#2走在正确的轨道上。您可以使用install命令的FOO
开关来欺骗CMake避免安装OPTIONAL
相关文件。
对于FOO
库目标,必须按以下方式修改命令:
SET (FOO_LIBRARY "foo")
ADD_LIBRARY(${FOO_LIBRARY} EXCLUDE_FROM_ALL
foo/foo.cpp
)
INSTALL(TARGETS ${FOO_LIBRARY}
DESTINATION lib/foo COMPONENT foo OPTIONAL)
EXCLUDE_FROM_ALL
已添加到ADD_LIBRARY
,以防止在运行普通make
时构建库。通过添加FOO_LIBRARY
开关,OPTIONAL
的安装是可选的。
安装FOO_HEADERS
可选项需要进行以下更改:
SET(FOO_HEADERS foo/foo.h)
SET(BINARY_FOO_HEADERS "")
FOREACH (FOO_HEADER ${FOO_HEADERS})
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${FOO_HEADER}
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/${FOO_HEADER} ${CMAKE_CURRENT_BINARY_DIR}/${FOO_HEADER}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${FOO_HEADER})
LIST (APPEND BINARY_FOO_HEADERS ${CMAKE_CURRENT_BINARY_DIR}/${FOO_HEADER})
ENDFOREACH()
INSTALL(FILES ${BINARY_FOO_HEADERS}
DESTINATION include/foo COMPONENT foo OPTIONAL)
FOREACH
循环设置自定义命令,将FOO_HEADERS
逐字复制到相应的二进制目录。 INSTALL(FILES ...
命令不是直接使用当前源目录中的标头,而是从二进制目录中获取复制的标头。二进制目录中标头的路径收集在变量BINARY_FOO_HEADERS
中。
最后,必须按以下方式设置FOO_INSTALL
目标:
SET(FOO_INSTALL "install.foo")
ADD_CUSTOM_TARGET(${FOO_INSTALL}
COMMAND ${CMAKE_COMMAND}
-D COMPONENT=foo
-P cmake_install.cmake
DEPENDS ${BINARY_FOO_HEADERS})
ADD_DEPENDENCIES(${FOO_INSTALL} ${FOO_LIBRARY})
添加了自定义FOO_INSTALL
,并依赖BINARY_FOO_HEADERS
来触发头文件的复制。当您运行FOO_LIBRARY
时,目标级依赖make install.foo
会触发库的构建。
配置CMake后会发出警告Target "foo" has EXCLUDE_FROM_ALL set and will not be built by default but an install rule has been provided for it.
无论如何,CMake会做正确的事情。
运行make install.foo
后,make install
命令也将安装所有FOO
相关文件,因为构建的FOO
库和标题存在于二进制目录。
答案 1 :(得分:0)
检查this solution是否适合您。
你必须对你想要使用的那些命令使用不同的命令,但我认为它能很好地解决这个问题。