V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zhng920823
V2EX  ›  C

一个简单实用的 C 工程示例, 附简洁的 Makefile

  •  
  •   zhng920823 · 2024-07-08 12:06:48 +08:00 · 3990 次点击
    这是一个创建于 411 天前的主题,其中的信息可能已经有所发展或是发生改变。

    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

    27 条回复    2024-07-09 17:53:37 +08:00
    augustheart
        1
    augustheart  
       2024-07-08 12:28:18 +08:00
    看了一下,分享精神可嘉,不过聊胜于无吧,用处很狭窄。
    实际上照本宣科写个 makefile ,目录分好。然后一个通配符也差不多效果了,最后每次就拷贝这 makefile ,修改一下输出目标名。
    w568w
        2
    w568w  
       2024-07-08 12:29:08 +08:00   ❤️ 4
    要我说 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 。
    zhng920823
        3
    zhng920823  
    OP
       2024-07-08 12:37:12 +08:00
    @w568w #2 所以不用 Autotools 那套东西, 直接用 Makefile, 我这个 Makefile 也可以同时用在 windows 上的 mingw
    zhng920823
        4
    zhng920823  
    OP
       2024-07-08 12:39:49 +08:00
    @augustheart #1 这个是从我自己用的项目里抽出来的, 可以一个工程里多个可执行文件, 久而久之这个工程里的东西就越来越多越来越杂, 依赖关系越来复杂, 编译越来越慢. 因为每一个 EXE 依赖所有的 OBJ.
    w568w
        5
    w568w  
       2024-07-08 12:41:34 +08:00
    @zhng920823 是啊,我知道可以用,我自己也不是没干过这事。后来换到 CMake 、Meson 才发现:干,这些事原来根本不用自己操心维护。Makefile 里判断平台大多是白忙活!

    别人写了十几年的轮子了,兼容性自然远高于我们手写的几行 Makefile 。与其遇到一个不兼容问题修复一个,不如直接用现代化构建工具。

    另外,只有第 3 个缺点和 autotools 有关啊,1 、2 、4 点 Makefile 都有。
    zhng920823
        6
    zhng920823  
    OP
       2024-07-08 12:47:11 +08:00
    @w568w #5 一直不太喜欢 cmake 等这种"大"公司推行的东西
    我觉得 xmake 非常好, @waruqi 但是 xmake 没有很广泛流行开来.
    w568w
        7
    w568w  
       2024-07-08 12:49:33 +08:00
    @zhng920823 #6 CMake 被大公司推行的好处是能统一。另外,Meson 作为纯社区项目,其实没有被大公司裹挟吧?

    我也喜欢 xmake ,还贡献过代码。xmake 的问题可能是包装得太深了,想要做一些自定义很困难,以及没有一个 CMake 级别的 behavior reference 文档。
    zhng920823
        8
    zhng920823  
    OP
       2024-07-08 12:55:08 +08:00
    @w568w #7 我也觉得 xmake 搞的越来越强大了, 早期简单的版本就够用.
    Meson/Ninja 目前看来还行.
    个人而言, 还是继续坚持手写 Makefile, 我觉得这样最透彻, (或者说是和已有项目绑定太深)
    ipwx
        9
    ipwx  
       2024-07-08 13:19:53 +08:00   ❤️ 1
    @zhng920823 我曾经也排斥用别人包了一层又一层的东西,觉得什么东西都自己写底层很舒服。

    直到我毕业了,从兴趣驱动到工资驱动……
    augustheart
        10
    augustheart  
       2024-07-08 13:42:58 +08:00
    @zhng920823 xmake 是愿景太大了,它想覆盖的每个场景都会有很多具体问题,需要各种针对修正。比如我个人的场合比较非主流,就是 msys2 那套在 win 下面编译,前后就提了好些 issue 。(其实最严重的问题是文档失修)
    至于 makefile ,没必要坚持,早改早好。makefile 所代表的那点知识没啥好透彻的。
    GeruzoniAnsasu
        11
    GeruzoniAnsasu  
       2024-07-08 13:55:45 +08:00
    我就提一个小问题:

    怎么写单元测试?
    zhng920823
        12
    zhng920823  
    OP
       2024-07-08 14:50:41 +08:00
    @GeruzoniAnsasu #11 再加个 exe, 或者现有的 exe 里面根据参数进入测试分支.
    zhng920823
        13
    zhng920823  
    OP
       2024-07-08 14:51:27 +08:00
    @augustheart #10 不是说 makefile 的知识透彻, 而是说这套东西简单透彻,
    GeruzoniAnsasu
        14
    GeruzoniAnsasu  
       2024-07-08 15:58:39 +08:00
    @zhng920823

    10 个 lib source, 10 个单测 source

    我需要写 _ 个 makefile, 每个 makefile 里复制粘贴 _ 行 source

    新增 1 个 lib source 的时候 我需要修改 _ 个文件中的 _ 行?
    zhng920823
        15
    zhng920823  
    OP
       2024-07-08 16:13:00 +08:00
    @GeruzoniAnsasu #14
    10 个 lib source, 10 个单测 source
    我需要写 1 个 makefile, 每个 makefile 里复制粘贴 20 行 source
    新增 1 个 lib source 的时候 我需要修改 1 个文件中的 1 行

    不过我还有一套和 IDE 结合的工具, 能把这些工作自动化. 这个 Makefile 是单独提取出来展示给大家的.
    cnbatch
        16
    cnbatch  
       2024-07-08 18:08:26 +08:00
    虽然我也不那么喜欢 cmake ,但更不喜欢 GNU Makefile ,因为我需要兼顾 BSD 系统( BSD Makefile 稍有不同),所以最后还是要用 cmake 兜底
    proxytoworld
        17
    proxytoworld  
       2024-07-08 18:27:31 +08:00
    我用 xmake 尝试引入 cmake ,但编译错误,搞了半天,太难了,最后还是用了 cmake 的 hunter
    424778940
        18
    424778940  
       2024-07-08 18:58:31 +08:00
    makefile 早就该被淘汰了, 又是写他都不如写个 shell 脚本方便, 或者说这东西就是个特别一点的 shell 脚本
    makefile, 尤其是 autotools 沾边的, 语法奇怪, 文档残废, 每次改点啥都要进去看代码, 因为变量名和选项都没有标准

    我现在一律使用 cmake, 虽说也没有特别先进, 有些地方还是有"无法指定这个操作到底 config 还是 build 时候执行"的问题, 但配合任何 shell 脚本基本都能解决 90%以上的场景需求了

    楼主你这个 makefile, 用 cmake 应该不到一半的行数就能写完
    zhng920823
        19
    zhng920823  
    OP
       2024-07-08 19:06:01 +08:00
    @proxytoworld #17 可惜 xmake 不能直接支持 cmake

    @424778940 #18 Makefile 肯定比 shell 方便的, 这点不用质疑, 毕竟是专门干这个的.
    所以我说 Makefile\可以单独使用, 不碰 autotools 那些东西可以做到很简单的.
    augustheart
        20
    augustheart  
       2024-07-08 19:20:19 +08:00
    @proxytoworld 通过 xmake 调用 cmake ,其实只是把传给 cmake 的参数给复制过去就好了,xmake 使用 package.tools.cmake ,等价于通过命令行调用 cmake 。需要注意的只有环境问题( xmake 的执行环境和 cmake 的执行环境并不一定是一样的)。
    zhng920823
        21
    zhng920823  
    OP
       2024-07-08 19:22:23 +08:00
    @augustheart #20 我的意思是 xmake 不能在没有 cmake 的情况下编译简单的 cmake 工程, 一直没这个功能
    augustheart
        22
    augustheart  
       2024-07-08 19:32:50 +08:00
    @zhng920823 哦,那是自然的。想替代 cmake 就得解析 cmake 那一大坨东西,这个工作量比 xmake 本身还大
    我个人觉得 xmake 现在这个状态已经很合我用了,写个东西各种不同编译方式的库能在同一个方案下面集成到一起,挺方便。
    zhng920823
        23
    zhng920823  
    OP
       2024-07-08 19:56:59 +08:00
    @augustheart #22 也没必要支持 cmake 的全部特性, 一些项目的 CMakelists.txt 看着非常简单的, 只要能支持这种的编译就行.

    那些导出各种工程的功能很少用的
    yolee599
        24
    yolee599  
       2024-07-09 09:09:17 +08:00 via Android
    我用的 cmake ,就因为 cmake 大家都用,生态比较好,比如 esp-idf ,lvgl ,mbedtls ,lwip …… 都在用
    zhng920823
        25
    zhng920823  
    OP
       2024-07-09 11:24:46 +08:00
    @yolee599 # 活捉使用 lwip lvgl 的大佬
    hitmanx
        26
    hitmanx  
       2024-07-09 16:11:46 +08:00
    我工作中遇到的项目 cmake 通常都是比较复杂的,各种 custom command 、custom target 乱飞,调用各种工具、python 等等生成中间文件,再由中间文件生成其它的中间文件等等,再加上 cmake 的字符串操作、对文件系统的操作,以及各种平台*feature list 的排列组合等等……需要理解大量业务逻辑才能明白这个工作流程。

    相比之下,新增文件时要更新一个文件列表,或者指定一个库的依赖等等,反而是其中最简单的环节,并不需要费太多的脑细胞。

    在这种复杂的系统里,用的 build 的语言是否足够“expressive”,让读的人能轻易明白你想干什么变得更关键了。另外就是效率,现在每改一行 cmake ,重新 config 一次要好几分钟……
    zhng920823
        27
    zhng920823  
    OP
       2024-07-09 17:53:37 +08:00
    @hitmanx #26 一般太复杂的东西, 我会选择用 shell 或其它语言的脚本进行额外处理, 而不是融合进 build 系统里面.
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   924 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 20:10 · PVG 04:10 · LAX 13:10 · JFK 16:10
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.