本地开发远程编译有什么好方法?

背景:工作中有一些 C/C++ 项目比较古老,编译工具链版本比较低,且有很多专有的库依赖;编译环境相比各种 Linux 发行版,要么工具比较旧,要么没有一些新工具,比如 ag/rg ,且一般我也没有从仓库安装程序的权限。

目前我是在 Windows 中搞了一个 vbox fedora 虚拟机,用来跑 Emacs 写代码,有什么缺少的工具就 dnf install 。 当写完代码之后,再 rsync 同步工程到编译环境,在终端程序中 make 编译。 这时问题来了,如果编译有问题需要来回切换 Emacs 和终端窗口,找到文件、行号再修复,效率低下,体验差。

为改进这里的工作流,利用 compilation mode 应该是一个方向,那么有两种思路:

  1. 开发和编译都在编译环境进行

    编译环境中工具的不完善,使得无论是(从 vbox ) tramp 还是编译环境直接运行 Emacs 都不太可用,另外多个编译环境维护相同的 Emacs 配置也比较困难。

  2. 本地开发,远程编译

    维持目前在本地开发的方式不变,只需要维护一个 Emacs 环境比较省心; 只需要优化编译这个环境的工作流即可。 尝试找过这方面的资料,但没有看到有什么确切或者直接可用的方案 0 。

    最近想到一个方法(其实也很直接),通过 M-x compile 触发,执行以下几个步骤:

    1. rsync 同步工程
    2. ssh 命令中登录编译机器编译
    3. 转换上一步中输出的路径

    这样 Emacs 就“以为”是本地编译了,能够正确识别编译错误的位置,方便通过命令 M-x next-error 自动定位文件位置。

不知道大家是否有这样的需求,有什么更好的方法吗?

[0] Remote compiling in Emacs | Marc Abramowitz rcompile 已经废弃,原理是 ssh 到远程机器编译,没有同步功能。

2 个赞

只是因为环境问题的话,我直接用docker,把项目挂在到容器中编译。(window上没试过)

如果是因为复杂度的问题,需要分布式编译之类的方式加速编译,我使用你的第二种方式。

同步文件其实方法很多,比如 git 勾子,inotify 等等。感觉 flycheck 才是最麻烦的

程序不一定要从仓库安装, 手动编译一个, 放在用户目录下, PATH修改一下就能用. 如果只是三四个工具程序, 完全可以这么做.

不知道你的编译环境有多老, 有centos 6老吗? 我装过centos 6的桌面, 用起来挺不错, 可以虚拟一个用.

使用本地新系统可以用flycheck, 把编译环境里专有库的头文件拷贝到本地, 确保代码在本地flycheck没问题(可以指定编译选项, 让它用老一点的c++标准来检查代码), 然后同步到编译环境中编译, 编译成功率就很高, 错误会很少.

docker 还没接触过,有空我了解下。

同步文件其实不是必须的,只是为了在那个环境上编译验证。但是一般自己的代码要编译过了再 push 比较合适, git 钩子就不合适了吧?

因为编译环境不同, flycheck 还没去整,后面我试下能不能开起来。

嗯,是可以自己手动编译安装,但依赖一多的话比较麻烦,而且有时候编译所需的依赖也不一定有。

好像是 gcc 4.4 ,不支持 C++ 11 。

看来大家都用 flycheck ,这个我看下能不能搞起来,在开发环境能把基本的错误检查出来也可以。

用 gcc 4.4 编译一个支持的保证行。

如果目标环境很旧的话,你的第二方案就很好。

rcompile 虽然废弃了,看它还能不能用,能用的话拿来改造一下,加上同步功能:

(define-advice rcompile (:before (&rest _) sync)
  ...do-sync)

这样是最省事的。如果不能用,就看现有的 compile 方法能不能扩展了。

用 Docker 本质上也是透过 SSH。你仍然需要把“远程”编译出错信息里的路径,转换成“本地”,才能 nex-error。所以,Docker 并没有解决这个问题。

不用 git 那就 inotify 配合 rsync 来同步

这个能否说的详细点,是在我的 vbox 中编译出一个完整的 4.4 工具链吗?

嗯,这个确实也是一种办法。前几天折腾了一种 Expect + rsync over ssh + ssh 的方法,我再结合 rcompile 看看。

另外,多谢指点 Docker ,相对来说似乎是一个独立的、自己可控的环境。

原来是用于自动触发同步,手动触发对我来说倒也可以接受,不是很麻烦。

我是针对你之前说的不支持C++11说的,gcc 4.4 也能编译出之后的 gcc 或者 clang。我亲自编译过 clang 3.3 是支持C++11的。

我觉得你就在远程开发可能比较好。

在服务器上搭个虚拟机,然后互相ssh (User mode with redirecting ports),不需要su。

编译环境资源有限,又是很多人在用,虚拟机估计带不起来 :joy:

正向 ssh 其实就够了,只要我在一处开发,一般不需要从编译环境反过来连到我的开发 vbox 。

kvm的性能其实还行吧,CPU效率差容器不多,网络性能和真机无异。Memory的话,运行时是可变的。

1 个赞

不仅仅是自动触发同步,你用 rsync 再写个勾子,自动触发编译,都可以

我也有类似的需求,本地开发,然后远端编译,运行,进行一些测试,也没找到好方法呢

我现在可以编译,然后在本地 next-error 定位下一步错误,可以不用肉眼手工定位到某文件某行了,略爽。待有空时我整理下分享出来。

运行调试没想好怎么结合。

2 个赞

新出的 vs code server 感觉有点意思

有意思是需要前提的。当远程环境很古老就没意思了。

远程编辑的时候,本地充当的仅仅是编辑和显示的角色,所有指令必须从本地发往远程执行,本地工具链再完善也用不上。

所以,要想有意思,首先就要问 code server 能否远程环境跑起来,兼容性这点我认为 Emacs 比 VSCode 有优势。毕竟 Emacs 有历史包袱,VCode 起点很新,不大可能回过头去支持老旧系统和CPU架构

可别认为 code server 是个简单的命令,它必须是一个 headless 版的编辑器,除了没有界面,其他功能都必须具备,就像 PhantomJS 之于 Google Chrome (Chrome 现在也自带 headless 模式了)。

其次要问 code server 配套的扩展/插件(例如 lsp,lint)是否能在远程环境下跑起来,比如 cquery / ccls 依赖最新的 llvm,这对老旧系统来说又是一大难题。我感觉这些扩展和插件支持老旧系统和CPU架构的意愿更低,因为并非所有项目都像 VScode 一样有富爸爸,甚至很多是个人项目。

总而言之,远程的环境,必须能跑一个全功能headles版的编辑器,还要能跑所需的扩展/插件,远程编辑才有意义(或意思)

2 个赞