繁体   English   中英

创建一个 Makefile 以编译文件夹/子文件夹中的所有 .c 文件并将二进制文件发送到其他地方

[英]Create a Makefile to compile all .c files in a folder/subfolder and ship the binaries elsewhere

我目前正在学习 K&R,我想创建一个 Makefile 以自动化编译过程。

我的目录结构如下:

k-r/
    chapter-1/
        exe/
        1-1/
            program1.c
            program2.c
            ...
        1-2/
            program3.c
            program4.c
            ...
    ch1.c
    ch1.h

大多数程序都是独立的,但有些程序需要在 kr/chapter-1/ch1.c 和 kr/chapter-1/ch1.h 中定义的函数。

我想编译 kr/chapter-1/1-1、kr/chapter-1/1-2 等中的所有程序,并将可执行二进制文件发送到 kr/chapter-1/exe。

以下是我到目前为止所拥有的并且它有效,但我想知道是否有更有效的方法来做到这一点,例如不必列出文件名?

CC := clang
CFLAGS := -Wall
LIB := ../ch1.c
BIN := ../exe/

.PHONY: all clean 1-1 1-2

all: 1-1 1-2

1-1:
    cd 1-1 && \
    $(CC) $(CFLAGS) program1.c -o $(BIN)program1.exe && \
    $(CC) $(CFLAGS) program2.c -o $(BIN)program2.exe && \

1-2:
    cd 1-2 && \
    $(CC) $(CFLAGS) program3.c $(LIB) -o $(BIN)program3.exe && \
    $(CC) $(CFLAGS) program4.c $(LIB) -o $(BIN)program4.exe && \

clean:
    rm exe/*

我假设“高效”是指“更通用/自动化”。 这是我能想到的最“有效”的解决方案:

CC := gcc
CFLAGS := -Wall
BIN_DIR := exe
SRC_DIRS := $(wildcard *-*)

.PHONY: all clean $(SRC_DIRS)
all: $(SRC_DIRS)

clean:
    del /s /q $(BIN_DIR)\*

define SETUP_TARGETS
$(1): $$(patsubst $(1)/%.c,$(BIN_DIR)/%.exe,$$(wildcard $(1)/*.c))
$(BIN_DIR)/%.exe: $(1)/%.c $$(wildcard *.c)
    $(CC) $(CFLAGS) $$(addprefix -I ,$$(patsubst %/,%,$$(dir $$^))) $$^ -o $$@
endef

$(foreach target,$(SRC_DIRS),$(eval $(call SETUP_TARGETS,$(target))))

关于makefile的观察:

  • 由于您使用的是文件扩展名.exe ,我假设您在 MS-Windows 上运行 GNU Make。 因此,我使用了命令提示符语法和.exe扩展名。
  • 您必须将 makefile 放在章节的根目录中(在本例中为chapter-1/ )。
  • 当您将代码复制到您的 makefile 时,请注意缩进部分(每个规则的配方)。 每个命令行必须以TAB字符开头,而不是空格。
  • 我假设目录exe/已经存在并且永远存在。
  • makefile 将检测与模式*-*匹配的每个子目录(例如 1-1、1-2、...),并为每个子目录创建一个目标。
  • 命令行make target (target 是一个子目录,例如 1-1, 1-2, ...) 将为目标子目录中的每个源文件在exe/中创建一个可执行文件。 我假设每个源文件都有一个函数main()
  • 每个目标构建还将包含根目录中的每个源文件*.c (在本例中为ch1.c )。 我假设这些来源不包含函数main()
  • 构建中涉及的文件不必以任何特定方式命名。 将检测所有文件。
  • 编译中使用的包含路径与包含所涉及的源的目录相同,即目标子目录和根目录。 因此,您可以将它们中的头文件#include到您的程序中。
  • 命令行makemake all将构建所有目标。
  • 命令行make clean将删除exe/中的每个文件。
  • 创建此 makefile 以最小化构建操作,以便仅构建相对于其依赖源之一过期的可执行文件。 如果您尝试在不修改任何源的情况下重建目标,您将收到类似make: Nothing to be done for '1-1'的警告。
  • 您也可以将此 makefile 用于其他章节,只要它们具有相同的目录结构。

享受 :)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM