一、通用示例
CC = gcc
CFLAGS = -lpthread -L ./tlACSClib -lNetDEVSDK
GFLAGS = -g -Wall -O3
TARGET = tlACSC
SRCS = $(wildcard *.c)
OBJS = $(patsubst %c, %o, $(SRCS))
$(TARGET) : $(OBJS)
$(CC) $(GFLAGS) $^ -o $(TARGET) $(CFLAGS)
%.o : %.c
$(CC) $(GFLAGS) -c $< -o $@
.PHONY : clean
clean:
rm -rf $(OBJS) $(TARGET)
二、= 和 :=
1、“=”
make会将整个makefile展开后,再决定变量的值。也就是说,变量的值将会是整个makefile中最后被指定的值。看例子:
x = foo
y = $(x) bar
x = xyz
在上例中,y的值将会是 xyz bar ,而不是 foo bar 。
2、“:=”
“:=”表示变量的值决定于它在makefile中的位置,而不是整个makefile展开后的最终值。
x := foo
y := $(x) bar
x := xyz
在上例中,y的值将会是 foo bar ,而不是 xyz bar 了。
3、
other= 是最基本的赋值
:= 是覆盖之前的值
?= 是如果没有被赋值过就赋予等号后面的值
+= 是添加等号后面的值
4、include、-include、sinclude
include包含其他的Makefile文件或者.mk文件。从而可以使用包含文件中的变量。
-include是指定编译器,即使没有这个文件也照常编译,不报错。编译继续进行。
sinclude和-include的效果一样
5、命令前加@和-
如果make
执行的命令前面加了@字符,则不显示命令本身而只显示它的结果;
通常make
执行的命令如果出错(该命令的退出状态非0)就立刻终止,不再执行后续命令,但如果命令前面加了-
号,即使这条命令出错,make
也会继续执行后续命令
6、多级目录make -C
确实,当一个Makefile包含另一个Makefile时,可以实现递归构建,这在管理多目录项目时非常有用。这种方法允许你将大型项目分解成更小的、更易于管理的部分,每个部分都有自己的Makefile。然后,主Makefile可以调用这些子Makefile来构建整个项目。
递归构建通常通过以下方式实现:
在主Makefile中使用make -C命令:-C
选项告诉make切换到指定的目录,并在那里执行Makefile。这允许你从项目的顶层Makefile中调用位于子目录中的Makefile。例如,如果你的项目结构如下:
project/
├── Makefile # 主Makefile
├── src/
│ └── Makefile # 子Makefile
└── include/
└── …
你可以在顶层Makefile中这样写:
all:
make -C src
这将切换到src
目录并执行那里的Makefile。
在子Makefile中定义目标:
每个子Makefile应该定义它自己的构建目标,这些目标可以被顶层Makefile调用。这样,你可以在每个子目录中独立地管理构建过程。
传递变量:
有时,你可能需要在子Makefile中使用顶层Makefile中定义的变量。你可以使用make
的命令行参数来传递这些变量。例如,在顶层Makefile中:
COMMON_FLAGS = -Wall -g
all:
make -C src COMMON_FLAGS=”$(COMMON_FLAGS)”
然后在子Makefile中,你可以这样使用这些变量:
gcc $(COMMON_FLAGS) -o my_program my_program.c
递归深度:
注意,递归构建可能会增加构建的复杂性,特别是当项目非常大且包含许多子目录时。确保你的Makefile结构清晰,并且每个子Makefile都明确其职责,以避免不必要的复杂性。
使用include
指令:
虽然include
指令本身不直接支持递归构建,但它可以用于将公共的Makefile片段(如变量定义、规则等)包含到多个Makefile中,从而减少重复代码并提高可维护性。
递归构建是多目录项目管理中的一种强大工具,但也需要谨慎使用,以确保构建过程的清晰性、可维护性和效率。
7、在Makefile的上下文中,由于每行通常都被视为一个独立的命令
在Makefile中使用if
语句时,为了可读性和维护性,通常建议将if
语句的各个部分(如条件判断、then
子句、else
子句和fi
结束标记)写成多行。
Makefile中的if
语句实际上是通过调用shell脚本来实现的,因此它们遵循shell脚本的语法规则。在shell脚本中,if
语句可以跨越多行,而Makefile只是提供了一个执行这些脚本的环境。
为了将if
语句写成多行,你可以使用反斜杠(\
)来指示当前行的继续,或者在每个逻辑行的末尾使用换行符。然而,在Makefile的上下文中,由于每行通常都被视为一个独立的命令,因此你通常需要使用反斜杠来明确指示if
语句的跨行继续。
以下是一个Makefile中使用if
语句并写成多行的示例:
target:
@if [ "$(SOME_VARIABLE)" = "some_value" ]; then \
echo "SOME_VARIABLE is set to some_value"; \
else \
echo "SOME_VARIABLE is not set to some_value"; \
fi
在这个例子中,if
语句被分成了多行,每行的末尾都使用了反斜杠来指示下一行是当前逻辑行的继续。这样做提高了代码的可读性,使得其他开发者更容易理解你的意图。
因此,尽管技术上可能将if
语句的所有部分压缩到同一逻辑行(通过省略反斜杠并使用分号分隔命令),但这样做通常是不推荐的,因为它会牺牲代码的可读性和可维护性。最佳实践是将if
语句写成多行,以清晰地表达条件逻辑和相应的操作。