我想要在 CMakeLists.txt
中重命名某些可执行文件,但又希望在新文件中保留旧名称的符号链接以实现向后兼容。如何在支持符号链接的系统上实现此目标?
如果系统不支持符号链接,则有哪些替代方法?
我想要在 CMakeLists.txt
中重命名某些可执行文件,但又希望在新文件中保留旧名称的符号链接以实现向后兼容。如何在支持符号链接的系统上实现此目标?
如果系统不支持符号链接,则有哪些替代方法?
另一种方法:
INSTALL(CODE "execute_process( \
COMMAND ${CMAKE_COMMAND} -E create_symlink \
${target} \
${link} \
)"
)
这样做符号链接将只会在make install
期间完成。
make all
是“构建”,而 make install
则取决于你如何处理它:部署、打包步骤、分发步骤或构建工件的形成等等。你可以使用一个微不足道的 IF(NOT EXISTS ${target})
来跳过在 make install
时重新创建符号链接,但我强烈建议不要这样做。这将是违反 KISS 的“意外智能”;你很可能会被陈旧的符号链接所困扰,而且更有可能是你的同事和/或后继者。不要这样做,找到另一个解决方案。 - ulidtkomake install
多次(在源代码进行了一些更改之后...)可能会比一个过期的符号链接创建更大的问题,除非 cmake 的 create_symlink
命令在已经存在时重新创建链接? - Alexis Wilke您可以创建自定义目标,并使用CMake创建符号链接。
ADD_CUSTOM_TARGET(link_target ALL
COMMAND ${CMAKE_COMMAND} -E create_symlink ${target} ${link})
这仅适用于支持符号链接的系统,请参见文档。
在CMake v3.14之前,这在Windows上无法工作。在v3.13中,添加了对Windows的支持。
另一种方法略微冗长,并且仅在安装时运行:
macro(install_symlink filepath sympath)
install(CODE "execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ${filepath} ${sympath})")
install(CODE "message(\"-- Created symlink: ${sympath} -> ${filepath}\")")
endmacro(install_symlink)
像这样使用它(类似于ln -s):
install_symlink(filepath sympath)
if(WIN32)
get_filename_component(real_path "${dirname}" REALPATH)
string(REPLACE "/" "\\" target_path "${real_path}")
execute_process(
COMMAND cmd /C mklink /J ${dirname} "${target_path}"
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
)
else()
execute_process(COMMAND "ln -s ${CMAKE_CURRENT_SOURCE_DIR}/${dirname} ${CMAKE_CURRENT_BINARY_DIR}/${dirname}")
endif()
compile_commands.json
的符号链接。这有助于clangd和vscode的智能提示。add_custom_command
是创建符号链接的命令。cmake_minimum_required(VERSION "3.1.0")
# project name
project("a-s-i-o")
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -std=c++17 -pthread -Wall -Wextra -Werror -pedantic -Wno-unused-parameter -Wno-unused-variable -Wno-unused-function -Wno-unused-private-field"
)
# Create `compile_commands.json` file.
#
# This is required by `clangd` to find the header files. For this to work, this
# file must be in the root of the project. Therefore, we create a symbolic link in the root that
# points to the `compile_commands.json` file created by CMake in the `build` directory.
#
# This specific commands creates the file in the build directory. The command `add_custom_command`
# creates the symbolic link in the root directory.
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_executable(x main.cpp)
target_include_directories(x PUBLIC "/usr/local/include/asio-1.20.0/include")
# When target `x` is built, a symlink will be created to
# `build/compile_commands.json`. This is required for clangd to be able to find
# the header files included in the project.
add_custom_command(TARGET x
COMMAND ${CMAKE_COMMAND} -E create_symlink "${CMAKE_CURRENT_BINARY_DIR}/compile_commands.json" "../compile_commands.json"
DEPENDS compile_commands.json
VERBATIM ON
)
# Print success message to the console
add_custom_command(TARGET x POST_BUILD
COMMAND echo "Created symlink pointing to `compile_commands.json`"
DEPENDS compile_commands.json
VERBATIM ON
)
自CMake 3.14起有file(CREATE_LINK <original> <linkname> SYMBOLIC)
。它在配置时创建一个符号链接。
不确定这是否是OP所要求的,但这是我在找到这个问题时寻找的内容。
install(CODE "if (NOT EXISTS ${link})
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink \
${target} \
${link})
endif()" )
install(
FILES
.../libmpi.so.12.0
DESTINATION lib
)
install(CODE
"EXECUTE_PROCESS( ${CMAKE_COMMAND} -E create_symlink lib/libmpi.so.12.0 lib/libmpi.so.12)")
这对我也不太起作用。我成功的方法是这样的。
install(FILES
.../libmpi.so.12.0
RENAME libmpi.so.12
DESTINATION lib
)
不是“完全”一样,但足够了。不要打败问题,解决问题。
如果您正在寻找根据版本号生成可执行文件和库文件的链接,您可以让CMake来为您处理,通过在目标上设置适当的属性SOVERSION
和VERSION
:
以下是CMakeLists.txt文件内容:
cmake_minimum_required(VERSION 3.20)
project(version_links C)
add_library(mylib SHARED lib.c)
set_target_properties(mylib PROPERTIES
PUBLIC_HEADER lib.h
VERSION 3.2.1
SOVERSION 3.2
)
add_executable(exec exec.c)
target_link_libraries(exec PRIVATE mylib)
set_target_properties(exec PROPERTIES
VERSION 3.2.1
)
install(TARGETS mylib exec)
会在 CMAKE_INSTALL_PREFIX
目录下生成以下树形结构:
${CMAKE_INSTALL_PREFIX}
├── bin
│ ├── exec -> exec-3.2.1
│ └── exec-3.2.1
├── include
│ └── lib.h
└── lib
├── libmylib.so -> libmylib.so.3.2
├── libmylib.so.3.2 -> libmylib.so.3.2.1
└── libmylib.so.3.2.1
参考资料: