【问题标题】:A Makefile with Multiple Executables具有多个可执行文件的 Makefile
【发布时间】:2013-05-21 00:53:44
【问题描述】:

我正在尝试编写一个使用宏从多个文件一次创建多个可执行文件的生成文件。我尝试搜索以前回答过的问题,但是因为我对 C 编程以及使用 gcc 还很陌生,所以我无法找到我的问题的答案。

这是我目前所拥有的:

CC=gcc
CFLAGS=-I.
OBJ = ex1.c ex3.c
EXECUTABLE = ex1 ex3

$(EXECUTABLE): $(OBJ)
    gcc -o $@ $^ $(CFLAGS)

clean:
    rm -f $(EXECUTABLE)

我想要这条线

$(EXECUTABLE): $(OBJ)

分别从文件 ex1.c ex3.c 创建可执行文件 ex1 和 ex3。

【问题讨论】:

    标签: c makefile


    【解决方案1】:

    对于这种特殊情况,每个可执行文件都有一个带有 .c 扩展名的源文件,您只需要一行 Makefile:

    all: ex1 ex3
    

    make 的内置默认规则已经生效:

    $ make
    cc -O2 -pipe   ex1.c  -o ex1
    cc -O2 -pipe   ex3.c  -o ex3
    

    在幕后,make 正在使用POSIXly mandated built-in single suffix rule

    .c:
        $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
    

    使用make CC=gcc CFLAGS=-O2 LDFLAGS=-s 和类似命令根据自己的喜好改变命令。

    每日琐事:事实上,如果您愿意在调用 make 时命名目标,您可以使用空的,甚至可以在没有任何 Makefile 的情况下运行

    $ make -f /dev/null CC=gcc CFLAGS=-O2 LDFLAGS=-s ex1 ex3
    gcc -O2 -s ex1.c  -o ex1
    gcc -O2 -s ex3.c  -o ex3
    $ rm -f Makefile ex1 ex3
    $ make CC=gcc CFLAGS=-O2 LDFLAGS=-s ex1 ex3
    gcc -O2 -s ex1.c  -o ex1
    gcc -O2 -s ex3.c  -o ex3
    

    创造奇迹!

    根据经验,不要重新发明轮子(或规则),使用已经存在的规则。它大大简化了您的生活。这使得小而性感的 makefile 给女士们留下了深刻的印象:-)

    【讨论】:

    • 非常有帮助!感谢您深入了解 make 命令的内部工作原理。
    【解决方案2】:

    一些建议(假设您使用 GNU make,而不是其他)

    首先,运行一次make -p,您将了解make 所知道的内置规则。特别注意COMPILE.cLINK.c

    那么,我建议

     CFLAGS= -g -Wall -I.
    

    (因为您确实希望 -g 进行调试,而 -Wall 获得大多数警告)

    你可能不需要

    $(EXECUTABLE): $(OBJ)
        gcc -o $@ $^ $(CFLAGS)
    

    不过,我建议在大多数其他规则之前添加

    .PHONY: all clean
    
    all: $(EXECUTABLES)
    

    实际上,我会将您的Makefile(对于 GNU make!)编码如下

    # file Makefile
    CC= gcc
    RM= rm -vf
    CFLAGS= -Wall -g
    CPPFLAGS= -I.
    SRCFILES= ex1.c ex2.c ## or perhaps $(wildcard *.c)
    OBJFILES= $(patsubst %.c, %.o, $(SRCFILES))
    PROGFILES= $(patsubst %.c, %, $(SRCFILES))
    
    .PHONY: all clean
    
    all: $(PROGFILES)
    clean:
         $(RM) $(OBJFILES) $(PROGFILES) *~
    ## eof Makefile
    

    请记住,tabMakefile-s 中的重要字符(rules 的操作部分)。在这个答案中,至少以四个空格开头的行应该真正以 tab 字符开头。

    调试完所有内容后,考虑运行make clean 清理所有内容,然后运行make -j CFLAGS=-O2 all 并行编译所有内容并进行优化。

    最后,我推荐使用remake并运行remake -x来调试复杂的Makefile-s

    当然,我假设你的目录只有单文件程序。

    顺便说一句,还有其他 build automation 工具。也许您可以考虑使用omakeninja。对于构建大型程序(数百万行源代码行),还可以考虑automakeccachecmakeicecream。在某些情况下,考虑使用GPPGNU bisonSWIG 等...或使用您自己的PythonGuile 脚本(或C 元程序)生成一些C 代码。另请参阅this draft 报告。

    不要忘记为您的源文件使用像git 这样的版本控制系统。也是时候学习这样的工具了。

    【讨论】:

    • COMPILE.cLINK.c 是 GNUisms;您在这里假设 OP 正在使用 GNU make。更好(便携)的想法是使用 .c 的内置单后缀规则。
    • 是的,我提到了 GNU make
    • 感谢您的建议以及对 git 和 omake 的建议。
    【解决方案3】:

    以下答案包括多个可执行文件,例如initial、process1、process2、...、process4。

    LOCAL_INCLUDE=./
    
    all: clean process_first process_second init
    
    process_first:
        gcc -g -o process1  -I$(LOCAL_INCLUDE) process1.c  -lzmq  -L. -L./.
        gcc -g -o process2  -I$(LOCAL_INCLUDE) process2.c  -lzmq  -L. -L./.
    
    process_second:
        gcc -g -o process3  -I$(LOCAL_INCLUDE) process3.c  -lzmq  -L. -L./.
        gcc -g -o process4  -I$(LOCAL_INCLUDE) process4.c  -lzmq  -L. -L./.
    
    init:
        gcc -g -o initiate -I$(LOCAL_INCLUDE) initiate.c -lzmq -lconfig -lpthread -L. -L./. -ldl -lrt
    
    clean:
        rm -rf init_manager.o init_manager
        rm -rf process1 process2 process3 process4
    

    注意:最好在重新制作之前清理并触摸所有可执行文件。

    【讨论】:

      【解决方案4】:

      你已经接近了,但你需要一个模式规则:

      $(EXECUTABLE): % : %.c
      

      然后是一个默认规则使其同时构建:

      all: $(EXECUTABLE)
      

      【讨论】:

      • 像这样的模式规则是它会出现的 GNU 主义。 .c 后缀的内置单后缀规则已经解决了问题。
      • 我现在正在研究模式规则。谢谢。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-07
      相关资源
      最近更新 更多