Makefile 可以做到如下简洁, 实际用时只要修改 EXE 和 OBJ 的列表值, 无需关心其它的东西
EXE=\
exe1\
a/exe2\
a/exe3\
OBJ=\
mod1\
liba/mod2\
liba/mod3\
include inc.mak
工程源码 https://github.com/webd90kb/webd/tree/master/codes/c_project_template
1
augustheart 2024-07-08 12:28:18 +08:00
看了一下,分享精神可嘉,不过聊胜于无吧,用处很狭窄。
实际上照本宣科写个 makefile ,目录分好。然后一个通配符也差不多效果了,最后每次就拷贝这 makefile ,修改一下输出目标名。 |
2
w568w 2024-07-08 12:29:08 +08:00 ![]() 要我说 Makefile 这种东西早就应该扔进历史垃圾桶了。
多亏了 Autotools 家族: 1. 直到今天 C/C++ 项目的构建和编译还是充满了不在文档中的命令行参数、不知名的环境变量、随心所欲的模块管理和依赖地狱; 2. 甚至每个项目都不得不自己编写一个 INSTALL 或 BUILD 文档来专门教别人如何编译; 3. Autotools 既不通用也不思进取,直到今天依然和 GCC 、glibc 强绑定,AM 宏语法残缺不全、极难理解,并且只支持「 GNU 认为你只需要」的寥寥几门语言和功能,充满了 quirks ,和其他语言的互操作更是无解问题。说是公共构建工具,更像是一群 geeks 自己开发自娱自乐的产物; 4. Makefile 完全没有考虑不同 Shell 和 Platform 的问题,想要跨平台编译,开发者不得不自己考虑并编写几百行的 boilerplates 来适配新的构建平台(例如 Windows )。 CMake is better, and Meson is even better. 如果你需要一个命令行运行器,你应该用 just 或 ninja 。 |
![]() |
3
zhng920823 OP @w568w #2 所以不用 Autotools 那套东西, 直接用 Makefile, 我这个 Makefile 也可以同时用在 windows 上的 mingw
|
![]() |
4
zhng920823 OP @augustheart #1 这个是从我自己用的项目里抽出来的, 可以一个工程里多个可执行文件, 久而久之这个工程里的东西就越来越多越来越杂, 依赖关系越来复杂, 编译越来越慢. 因为每一个 EXE 依赖所有的 OBJ.
|
5
w568w 2024-07-08 12:41:34 +08:00
@zhng920823 是啊,我知道可以用,我自己也不是没干过这事。后来换到 CMake 、Meson 才发现:干,这些事原来根本不用自己操心维护。Makefile 里判断平台大多是白忙活!
别人写了十几年的轮子了,兼容性自然远高于我们手写的几行 Makefile 。与其遇到一个不兼容问题修复一个,不如直接用现代化构建工具。 另外,只有第 3 个缺点和 autotools 有关啊,1 、2 、4 点 Makefile 都有。 |
![]() |
6
zhng920823 OP |
7
w568w 2024-07-08 12:49:33 +08:00
@zhng920823 #6 CMake 被大公司推行的好处是能统一。另外,Meson 作为纯社区项目,其实没有被大公司裹挟吧?
我也喜欢 xmake ,还贡献过代码。xmake 的问题可能是包装得太深了,想要做一些自定义很困难,以及没有一个 CMake 级别的 behavior reference 文档。 |
![]() |
8
zhng920823 OP @w568w #7 我也觉得 xmake 搞的越来越强大了, 早期简单的版本就够用.
Meson/Ninja 目前看来还行. 个人而言, 还是继续坚持手写 Makefile, 我觉得这样最透彻, (或者说是和已有项目绑定太深) |
![]() |
9
ipwx 2024-07-08 13:19:53 +08:00 ![]() |
10
augustheart 2024-07-08 13:42:58 +08:00
@zhng920823 xmake 是愿景太大了,它想覆盖的每个场景都会有很多具体问题,需要各种针对修正。比如我个人的场合比较非主流,就是 msys2 那套在 win 下面编译,前后就提了好些 issue 。(其实最严重的问题是文档失修)
至于 makefile ,没必要坚持,早改早好。makefile 所代表的那点知识没啥好透彻的。 |
11
GeruzoniAnsasu 2024-07-08 13:55:45 +08:00
我就提一个小问题:
怎么写单元测试? |
![]() |
12
zhng920823 OP @GeruzoniAnsasu #11 再加个 exe, 或者现有的 exe 里面根据参数进入测试分支.
|
![]() |
13
zhng920823 OP @augustheart #10 不是说 makefile 的知识透彻, 而是说这套东西简单透彻,
|
14
GeruzoniAnsasu 2024-07-08 15:58:39 +08:00
@zhng920823
10 个 lib source, 10 个单测 source 我需要写 _ 个 makefile, 每个 makefile 里复制粘贴 _ 行 source 新增 1 个 lib source 的时候 我需要修改 _ 个文件中的 _ 行? |
![]() |
15
zhng920823 OP @GeruzoniAnsasu #14
10 个 lib source, 10 个单测 source 我需要写 1 个 makefile, 每个 makefile 里复制粘贴 20 行 source 新增 1 个 lib source 的时候 我需要修改 1 个文件中的 1 行 不过我还有一套和 IDE 结合的工具, 能把这些工作自动化. 这个 Makefile 是单独提取出来展示给大家的. |
16
cnbatch 2024-07-08 18:08:26 +08:00
虽然我也不那么喜欢 cmake ,但更不喜欢 GNU Makefile ,因为我需要兼顾 BSD 系统( BSD Makefile 稍有不同),所以最后还是要用 cmake 兜底
|
![]() |
17
proxytoworld 2024-07-08 18:27:31 +08:00
我用 xmake 尝试引入 cmake ,但编译错误,搞了半天,太难了,最后还是用了 cmake 的 hunter
|
![]() |
18
424778940 2024-07-08 18:58:31 +08:00
makefile 早就该被淘汰了, 又是写他都不如写个 shell 脚本方便, 或者说这东西就是个特别一点的 shell 脚本
makefile, 尤其是 autotools 沾边的, 语法奇怪, 文档残废, 每次改点啥都要进去看代码, 因为变量名和选项都没有标准 我现在一律使用 cmake, 虽说也没有特别先进, 有些地方还是有"无法指定这个操作到底 config 还是 build 时候执行"的问题, 但配合任何 shell 脚本基本都能解决 90%以上的场景需求了 楼主你这个 makefile, 用 cmake 应该不到一半的行数就能写完 |
![]() |
19
zhng920823 OP @proxytoworld #17 可惜 xmake 不能直接支持 cmake
@424778940 #18 Makefile 肯定比 shell 方便的, 这点不用质疑, 毕竟是专门干这个的. 所以我说 Makefile\可以单独使用, 不碰 autotools 那些东西可以做到很简单的. |
20
augustheart 2024-07-08 19:20:19 +08:00
@proxytoworld 通过 xmake 调用 cmake ,其实只是把传给 cmake 的参数给复制过去就好了,xmake 使用 package.tools.cmake ,等价于通过命令行调用 cmake 。需要注意的只有环境问题( xmake 的执行环境和 cmake 的执行环境并不一定是一样的)。
|
![]() |
21
zhng920823 OP @augustheart #20 我的意思是 xmake 不能在没有 cmake 的情况下编译简单的 cmake 工程, 一直没这个功能
|
22
augustheart 2024-07-08 19:32:50 +08:00
@zhng920823 哦,那是自然的。想替代 cmake 就得解析 cmake 那一大坨东西,这个工作量比 xmake 本身还大
我个人觉得 xmake 现在这个状态已经很合我用了,写个东西各种不同编译方式的库能在同一个方案下面集成到一起,挺方便。 |
![]() |
23
zhng920823 OP |
![]() |
24
yolee599 2024-07-09 09:09:17 +08:00 via Android
我用的 cmake ,就因为 cmake 大家都用,生态比较好,比如 esp-idf ,lvgl ,mbedtls ,lwip …… 都在用
|
![]() |
25
zhng920823 OP @yolee599 # 活捉使用 lwip lvgl 的大佬
|
26
hitmanx 2024-07-09 16:11:46 +08:00
我工作中遇到的项目 cmake 通常都是比较复杂的,各种 custom command 、custom target 乱飞,调用各种工具、python 等等生成中间文件,再由中间文件生成其它的中间文件等等,再加上 cmake 的字符串操作、对文件系统的操作,以及各种平台*feature list 的排列组合等等……需要理解大量业务逻辑才能明白这个工作流程。
相比之下,新增文件时要更新一个文件列表,或者指定一个库的依赖等等,反而是其中最简单的环节,并不需要费太多的脑细胞。 在这种复杂的系统里,用的 build 的语言是否足够“expressive”,让读的人能轻易明白你想干什么变得更关键了。另外就是效率,现在每改一行 cmake ,重新 config 一次要好几分钟…… |
![]() |
27
zhng920823 OP @hitmanx #26 一般太复杂的东西, 我会选择用 shell 或其它语言的脚本进行额外处理, 而不是融合进 build 系统里面.
|