@
SSang 对呀道理是这样的,但是我的意思就是,IDE 不会做什么额外的配置,也不会帮你编译什么。它本身只在你现有的环境上修改,并且修改后的环境在脱离 IDE 之后仍然是可以独立运行的。
你可能理解成 IDE 作为一个项目依赖了,我说的是相反的,就是因为有 IDE 所以他成不了项目依赖。比如你说的用 IDE 编译,但是 IDE 也只是在调用 gradle 、cargo 、cmake 命令而已。我在 IDE 上点击编译按钮,所发生的事情也只是 IDE 去调用这些工具去编译。
只不过这些放到 go 上就会显得很奇怪,go 本身没有像 gradle 、cargo 、cmake 这些工具,你确实只能写 makefile 或者 shell 去组织项目的编译流程,在这种情况下 make 和 shell 就是项目依赖了,我用非 unix 的环境打开这样的项目就要先去配 make 和 bash 这些,也是一种心智负担。
并且在有 gradle 、cargo 、cmake 这些工具的情况下,我用 IDE 打开一个项目之后,IDE 天然就对这些工具支持的很好,会自动扫描然后创建对应的 run configuration ,这样我在编译按钮旁边就能直接看到这个项目有哪些 target ,点击就可以编译运行调试,这和你直接在 CI 或者 shell 里面编译是一样的,谁来编译出来的都是一样的,除非需要什么环境变量之类的额外配置。但是如果是用 makefile 组织的项目,makefile 可以写的很花也可以写的很简单,并没有什么强制的规范,甚至还可以在 makefile 里面覆盖工具链的路径和版本,大部分时候只会影响 IDE 或者 editor 的扫描,最终形成我在 shell 直接 make 可以编译,但是我用 IDE 因为扫描不到工具链或者不匹配,而导致代码补全等功能完全失效,IDE 也不知道这个项目有哪些 target ,我要自己去读 makefile 才能找到。
我并不反对工程化也不反对 shell 和 makefile ,但这些不应该成为项目的唯一启动方式,也不应该干扰 IDE 和 editor ,他们可以通过设定需要的配置来做到 reproducible build ,但是在没办法使用他们的时候项目也应该要能正常编译。
比如说如果我的项目需要先生成 protobuf 的文件,那么我会把编译.proto 的步骤放到 gradle 、
build.rs 、cmake 自定义 target 里面,除非迫不得已是不会写 shell 和 makefile 的,这样 IDE 和 LSP 可以无痛启动项目,生产环境编译的时候也可以直接出成品。
再比如 Linux 内核全是 makefile 和 kbuild ,你可以在任何时候用 make 来生成产物,如果要开发的话,使用
https://github.com/torvalds/linux/blob/c2f2b01b74be8b40a2173372bcd770723f87e7b2/scripts/clang-tools/gen_compile_commands.py 这个脚本生成 compile_commands.json ,对于大部分 IDE 和 editor 都可以直接进入开发状态。