为什么项目无法使用符号链接进行编译

为什么项目无法使用符号链接进行编译

我在一个开发 C++ (ROS) 项目的团队中工作。

由于某些原因,我们没有良好的 git 管理。

我们有几个 git 分支。为了编译该项目,我必须git clone从每个分支中获取代码并重新排列目录结构。

首先,我mkdir -p /home/me/repo,然后我git clone从每个分支的代码并将它们全部放入/home/me/repo.

现在我需要重新安排结构,这是我所做的:

#!/bin/sh

mkdir -p /home/me/project/src
cd /home/me/project/src
catkin_init_workspace   # command of ROS to initialize a workspace

cp -r /home/me/repo/robot_dev/control .
cp -r /home/me/repo/robot_dev/control_algo .
cp -r /home/me/repo/sim/third_party .
cp -r /home/me/repo/planning .
cp -r /home/me/repo/robot_dev/cognition/hdmap .

cd ..
catkin_make    # command of ROS to compile the project

我创建了这样一个脚本来编译该项目并且它有效。正如你所看到的,我只是复制并重新排列了一些目录并编译。

现在我认为这cp -r不是一个好主意,因为它花费了太多时间。我想用ln -s做同样的事情。所以我写了另一个脚本如下:

#!/bin/sh

mkdir -p /home/me/project2/src
cd /home/me/project2/src
catkin_init_workspace   # command of ROS to initialize a workspace

ln -s /home/me/repo/robot_dev/control control
ln -s /home/me/repo/robot_dev/control_algo control_algo
ln -s /home/me/repo/sim/third_party third_party
ln -s /home/me/repo/planning planning
ln -s /home/me/repo/robot_dev/cognition/hdmap hdmap

cd ..
catkin_make    # command of ROS to compile the project

但是,我收到一个错误:

CMake Error at /opt/ros/kinetic/share/catkin/cmake/catkin_package.cmake:297 (message):
  catkin_package() absolute include dir
  '/home/me/project2/src/hdmap/../third_party/ubuntu1604/opencv-3.3.1/include'

我查了一下cd /home/me/project2/src/hdmap/../third_party/ubuntu1604/opencv-3.3.1/include,确实存在。

是不是有什么原因cp -r可以编译但是ln -s不能编译呢?

答案1

..当涉及符号链接时,访问并没有真正按照您的预期工作......

当您在 bash 中尝试这样做时,bash 会尝试“提供帮助”并为您修复它,因此问题不会变得明显。

但是,简而言之,当您转到 时/home/me/project2/src/hdmap/../third_party,内核将首先解析“hdmap”的符号链接,到达/home/me/repo/robot_dev/cognition/hdmap,然后查找..这意味着 的父目录hdmap 目录,因此/home/me/repo/robot_dev/cognition它会尝试在那里找到third_party。

考虑到/home/me/repo/robot_dev/cognition/third_party不存在(或者,如果存在,它与您想要的不一样/home/me/repo/sim/third_party),您会收到文件未找到错误。

Bash 保留一个$PWD变量,并将路径存储为字符串,因此它可以..在向内核传递路径之前帮助“解析”shell 本身中的引用...这样,它将向您隐藏这些详细信息。

您可以在 bash 中使用set -P(或) 来禁用该行为。 set -o physical(有关更多详细信息,请参阅 bash 手册页。)


为了帮助您解决根本问题...也许一个不错的解决方案是使用cp -rl复制树。创建硬链接-l的选项cp。在这种情况下,这应该不是问题,特别是因为我想您不希望修改文件。它仍然必须遍历数据结构并单独创建每个对象,但它不必创建任何内容......

如果您正在使用现代文件系统(例如 Btrfs),您还可以尝试cp -r --reflink创建 CoW(写时复制)副本。它本质上是一个硬链接,但稍微好一点,因为两个名称之间没有联系,它们只是在后端共享块,触摸其中一个文件实际上会将它们分叉成两个单独的文件。 (但我想硬链接可能对你来说已经足够了。)

也许你可以使用 git 做一些技巧,以便在每个步骤中公开你需要的目录...所以你实际上可以克隆你需要的部分...但这可能更难完成或维护..希望cp -rl对你来说足够了!

相关内容