byhc
1
如题,目前身边同事是直接用vscode,ssh远程到远端机器,甚至是远端开发容器内,然后写代码。不得不佩服,vscode在这方面做的是真好。但我还是想用emacs来写代码,因为vscode定制性和快捷键与emacs差太远了。
目前我遇到的问题有以下几点:
- 项目是老旧的Makefile代码,对应的linux环境还是很老的版本,g++只有4.4.6,无法生成compile_commands.json文件,因为老到连bear都装不上。对此我采用的办法是在不同的工程目录下使用 .clangd文件,类似:
CompileFlags:
Add: [-std=c++0x, -Wall, --target=x86_64-pc-linux-gnu, -Wno-reserved-user-defined-literal,
-nobuiltininc,
-nostdinc++,
-nostdinc,
-cxx-isystem/Users/byhc/work/env/linux_inc/c++,
-stdlib++-isystem/Users/byhc/work/env/linux_inc/c++,
-isystem/Users/byhc/work/env/linux_inc,
-isystem/Users/byhc/work/imdep_common/usr/include,
-D_POSIX_C_SOURCE=201103L,
-D_XOPEN_SOURCE=600,
-DBYTE_ORDER=1,
]
Remove: [-arch]
Compiler: /Users/byhc/.nix-profile/bin/clang++
这样做问题是需要在不同目录下放置 .clangd 文件,因为emacs下lsp有一个常见问题就是如果用 find-definition 之类的方法,从 /path/a/a.cpp 跳到 /path/b/b.cpp 后,b.cpp的分析就需要一个单独的 .clangd 了。
- Mac下头文件缺失,比如缺少 epoll.h 这样的文件,对此我的解决办法是在 .clangd 中包含
-nobuiltininc, -nostdinc++, -nostdinc,
三个编译选项,这样clang就不会去包含mac自己的头文件搜索路径,然后再指定包含我自己写的一套 linux_inc 头文件。 这样做坏处是得自己写全套的linux c/c++头文件。
想知道各位道友有没有遇到过类似问题,是怎样解决的?我自觉自己方法虽然有用,但过于麻烦,想看下有没有更好的使用姿势。
不用emacs + lsp/lsp-bridge做远程,是因为速度响应原因,无论是保存文件还是打开文件、切换buffer,都有较大延迟,此外tramp与本地的一些插件似乎也有兼容问题。
lsp-bridge远程开发没有性能问题,不受tramp影响
byhc
4
这里不是说lsp-bridge有性能问题,是emacs整体在远程开发响应上就不是很好,比如用ivy框架时,如果打开远程文件,补全窗口会跳出来3次才能打开一个文件,然后如果要切换文件,switch-buffer或dired也需要较长时间打开。
另外即使是远程,也存在我上面说的,旧的linux下生成compile_commands.json是比较困难的,还得写.clangd。
lsp-bridge用的是 buffer diff sync 同步的技术, 补全性能和 VSCode 一样。
其实文件管理器和打开文件都可以用类似 lsp-bridge 一样的技术, 先不要全部下载完再打开, 做成流式的, 这样速度就会很快。
可惜我日常远程开发的少, 其实做一个流式的文件管理器和远程文件打开功能, 就全部和VSCode一样快了。
byhc
9
只要有可能,都不想远程开发,因为无论怎样做,速度和响应方面都不如本地。所以我这里想讨论的是,在本地,mac上索引linux上的c/c++代码,有没有什么更好的办法和实践。
1 个赞
在其他环境生成 compile_commands.json 然后复制到此电脑如何。
byhc
11
较高版本的linux无法编译过现在的项目,那个makefile是十多年前的人写的了,除非重新梳理一遍依赖,并改造成cmake项目。
另外就是linux下生成的compile_commands.json,mac上也用不了,有些头文件是没有的。
这个思路之前我试过,弄到一半放弃了,有时间我再折腾下看能不能走通。
这种属于交叉编译了,最好还是在有环境的机器上开发吧。搞个远程协议开emacs感觉比较好
btw 其实vscode也不是不行,我现在有时候就用vscode 做调试,vscode也有magit, vim 这些插件
在 linux 上安装 emacs ,然后 ssh 上去用 emacs -nw,已经在工作中用了一年多了,体验很好
1 个赞
byhc
15
折腾了好几天,走了很多弯路,包括自己写了2000多行伪的c++/c标准库头文件,最后发现自己采用的方法出乎我意料的简单:
把编译容器中的 /usr/include目录打包下载下来,然后在本地解压,然后在项目目录中、本地的 /usr/include目录中都写一个.clangd文件,其中要求clang++不要引用任何标准库头文件,然后把本地的 /usr/include 目录添加进去。
CompileFlags:
Add: [-std=c++0x, -Wall, --target=x86_64-pc-linux-gnu,
-nobuiltininc,
-nostdinc++,
-nostdinc,
-isystem/Users/byhc/work/cpp1/usr/include,
-cxx-isystem/Users/byhc/work/cpp1/usr/include/c++/4.4.4,
-cxx-isystem/Users/byhc/work/cpp1/usr/include/c++/4.4.4/x86_64-redhat-linux,
-isystem/Users/byhc/work/cpp1/usr/include/linux,
-cxx-isystem/Users/byhc/work/cpp1/usr/include/c++/4.4.4/tr1,
-cxx-isystem/Users/byhc/work/cpp1/usr/include/c++/4.4.4/backward,
-D_POSIX_C_SOURCE=201103L,
-D_XOPEN_SOURCE=600,
-DBYTE_ORDER=1,
]
Remove: [-arch]
Compiler: /Users/byhc/.nix-profile/bin/clang++
然后,可能需要修改若干文件,我这里发现只需要修改 cpp1/include/c++/4.4.4/x86_64-redhat-linux/bits/c++config.h
文件,在文件末尾最后一个endif前增加:
typedef long ptrdiff_t;
typedef unsigned long size_t;
typedef __builtin_va_list va_list;
typedef __builtin_va_list __gnuc_va_list;
ptrdiff_t size_t这些类型在g++下应该是作为编译器自带的类弄了,我看头文件中没有明确定义,所以在这里补充。va_list本来挺难搞,因为一定需要编译器扩展,所幸clang++自己有 __builtin_va_list ,只需要定义别名就行。
此外,还需要把一些文件中 GCC 编译器的扩展去掉,我目前只遇到一个:
cpp1/include/c++/4.4.4/exception_ptr.h
中有个
#pragma GCC visibility push(default)
...
#pragma GCC visibility pop
直接删掉就好了。
========================================
以上是实践部分,据我观察,其实大多数头文件,所有系统都是通用的,相差的就是平台相关性的基础类型定义和部分编译器扩展,所幸这部分文件数量不多,我目前就遇到上面两个,改掉后,clangd就可以正常在mac上索引linux下的c++/c项目了,只是还需要编写.clangd文件,不过也还好。
你是在 Mac 的 Emacs 上开发,但是代码在 Linux 上编译?调试怎么办?
为什么不在 Linux 上运行 Emacs?
byhc
17
写的服务器程序,写完编译好要放测试环境测试/调试,本地是无法测试/调试的。
然后工作配发的电脑只有mac,或者windows。
windows的话虽然wsl也挺好用,但是配发的某品牌笔记本非常烂,实在不能忍,所以只能用mac。