如何使用CMake获取到目标的相对路径?

12

我有一个项目,使用CMake生成构建脚本,每个平台都将生成的可执行文件放在不同的位置。我们团队中有一个非程序员,他没有构建工具,我希望能够将运行该项目所需的所有文件、脚本和可执行文件捆绑起来,以便他能运行该项目。

为此,我添加了一个自定义目标,将所有必要的文件打包成zip文件。它还生成了一个非常简单的脚本(包含在zip文件中),他只需要点击它就可以运行脚本并启动可执行文件,如下:

add_custom_target(runcommand
  COMMAND echo '\#!/bin/bash -eu' > run.command &&
          echo 'cd `dirname $$0`' >> run.command &&
          echo './scripts/prerun_script.sh && ${MY_EXECUTABLE}' >> run.command &&
          chmod +x run.command)

这个问题在于MY_EXECUTABLE是我系统上可执行文件的硬编码路径。我希望它是相对路径,这样我就可以将生成的zip文件解压到任何地方并从那里运行它。我希望能够获取相对于我的项目根目录的MY_EXECUTABLE路径,以便该脚本可在任何位置运行。


2
你的问题涉及到CMake中的相对路径。但是,你所描述的问题的解决方案并不是CMake的标准做法。CMake与CPack一起支持安装目标。这些安装目标可以打包成zip、tgz、debian软件包。所有这些都是以平台无关的方式完成的。而你的解决方案是特定于平台的,因为它使用了一个bash脚本。http://cmake.org/Wiki/CMake:Packaging_With_CPack - Joakim
最起码,您应该考虑使用install()命令,然后压缩结果而不是使用自定义目标。 - Alexis Wilke
4个回答

19

你可以使用:

file(RELATIVE_PATH variable directory file)

具体而言,假设 MY_ROOT 包含根目录(可能有一个适当预定义的 CMake 变量),这将把 rel 设置为 MY_EXECUTABLE 的相对路径:

file(RELATIVE_PATH rel ${MY_ROOT} ${MY_EXECUTABLE})

3

如果您想获取相对于项目根目录的路径,可以使用PROJECT_SOURCE_DIR CMake变量:

file(RELATIVE_PATH rel ${PROJECT_SOURCE_DIR} ${MY_EXECUTABLE})

请记住,MY_EXECUTABLE 必须包含文件的完整路径。


1
获取当前源目录的相对路径
file(RELATIVE_PATH relative ${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR})

测试:

message(STATUS "source base: \"${CMAKE_SOURCE_DIR}\"")
message(STATUS "current: \"${CMAKE_CURRENT_SOURCE_DIR}\"")
message(STATUS "relative: \"${relative}\"")

结果:

--source base: "C:/Project/Software/Test/source"
--current: "C:/Project/Software/Test/source/unittest/libs/fsm
--relative: "unittest/libs/fsm"

这个方法很有效!但是如果你和我一样,想要将它打包成一个.deb文件,最好把文件放在一个共享的位置,比如/usr/share/PROJECT/myfile.txt - Mike D.

-2

类似这样的代码可以正常工作:

THISDIR=`pwd`
MY_EXECUTABLE=$THISDIR/test/someexec
REL_EXECUTABLE=${MY_EXECUTABLE##$THISDIR/}
echo $REL_EXECUTABLE 

基本上,这个操作会从$MY_EXECUTABLE中去掉基础路径。在这个例子中,我只是设置了MY_EXECUTABLE作为一个测试来给它一个完整的路径。你想要的一行代码等价于:

${MY_EXECUTABLE##`pwd`/}

我猜这里假设pwd是你的项目根目录。否则,请参考Cmake变量文档。

(顺便说一下,这让我怀念起ksh的日子。)


我马上就要尝试一下。那个##特殊语法是用来截取字符串的一部分吗?这是CMake还是Bash的一部分? - Alex
这是bash。它的意思是截取与字符串匹配的变量前面的部分。%%是截取结尾。您还可以使用,我认为这是最小匹配,如果您重复使用,它会删除最大匹配。 - zerodiff
这并没有回答问题,问题是关于CMake的。 - Joakim
@Joakim,这个问题也标记为bash,并且问题示例正在动态创建一个bash脚本,因此涉及到CMake和bash两者。 - zerodiff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接