makefile
在程序编译工作中,Makefile是一个指示make程序,在软件项目的编译环境,最为重要的是掌握目标和依赖;目标是指要干什么,运行make后生成什么;依赖是告诉make如何实现目标;
在makefile中,目标和依赖是通过规则(rule)来表达的。
准备环境,需要linux环境,make -v 命令验证是否安装make工具
基本命令:
all:
@echo "hello world"
test:
@echo "make test"
@echo是tab键不是空格键,上边是简单示例,可以通过make all , make test 在终端中输出不同的信息
all: main.o foo.o
gcc -o simple main.o foo.o
main.o: main.c
gcc -o main.o -c main.c
foo.o: foo.c
gcc -o foo.o -c foo.c
clean:
rm simple main.o foo.o
all,main.o,foo.o,clean代表目标; 冒号后边,main.o foo.o , main.c, foo.c 代表依赖文件,
gcc -o ……, rm simple…… 代表通过那种规则生成的
make是如何决定是那些目标需要重新编译,是通过文件的时间戳的
假目标,当前文件夹下存在clean文件时,执行make clean命令,总是提示clean文件是最新的,不是预期rm simple ……的操作,这事因为make将clean当作文件,而且当前目录找到了这个文件;
makefile中如何避免这种定义的目标与所存在的文件同名的情况呢?假目标解决了这个问题
采用.PHONY关键字来定义,需要注意必须大写字母
.PHONY: clean 即可
.PHONY: clean
CC = gcc
RM = rm
EXE = simple
OBJS = main.o foo.o
$(EXE): $(OBJS)
$(CC) -o $(EXE) $(OBJS)
main.o: main.c
$(CC) -o main.o -c main.c
foo.o: foo.c
$(CC) -o foo.o -c foo.c
clean:
$(RM) $(EXE) $(OBJS)
这个makefile中,引入了CC和RM变量,一个保存编译器名,另一个删除文件命令;还引入了EXE和OBJS两个变量,一个用于存放可执行文件名,另一个用于防止所有目标文件名
自动变量的引入
$@用于表示一个规则中的目标;当我们的一个规则中的有多个目标时,$@所指的是其中任何造成命令被运行的目标
$^表示规则中的所有先择条件;
$<表示规则中的第一个先决条件;
.PHONY: all
all: first second third
@echo "\$$@ = $@"
@echo "$$^ = $^"
@echo "$$< = $<"
first second third:
输出:
$@ = all
$^ = first second third
$< = first
.PHONY: clean
CC = gcc
RM = rm
EXE = simple
OBJS = main.o foo.o
$(EXE): $(OBJS)
$(CC) -o $@ $^
main.o: main.c
$(CC) -o $@ -c $^
foo.o: foo.c
$(CC) -o $@ -c $^
clean:
$(RM) $(EXE) $(OBJS)
上述的自动变量加入进来看起来会有些不易理解,在实际使用中会变得更加简洁
.PHONY: clean
CC = gcc
RM = rm
EXE = simple
OBJS = main.o foo.o
$(EXE): $(OBJS)
$(CC) -o $@ $^
%.o: %.c
$(CC) -o $@ -c $^
clean:
$(RM) $(EXE) $(OBJS)
与前一版本,将2条构建目标文件规则变成了1条,简化了工作量;
但是实际运行环境中不同的c文件编译目标文件还是需要进行一些调整的
后续的makefile还有很多的使用方法,后续再进行补充
CMAKE介绍
cmake是可以在linux/unix平台,生成makefile文件,简化编译构建过程和编译过程
在CMakeLists.txt配置如下
cmake_minimum_required (VERSION 2.8)
PROJECT(NEWHELLO)
SET(SRC_LIST a.c)
MESSAGE(STATUS "This is BINARY dir " ${PROJECT_BINARY_DIR})
MESSAGE(STATUS "This is SOURCE dir " ${PROJECT_SOURCE_DIR})
ADD_EXECUTABLE(hello ${SRC_LIST})
如果在当前目录下执行cmake . 会产生很多文件,可以创建build文件夹,cd build ,再次执行 cmake ..
那么cmak产生文件只在当前build文件夹下了
cmake_minimum_required (VERSION 2.8)
PROJECT(NEWHELLO)
SET(SRC_LIST a.c)
ADD_SUBDIRECTORY("${CMAKE_CURRENT_SOURCE_DIR}/dir1")
MESSAGE(STATUS "This is BINARY dir " ${PROJECT_BINARY_DIR})
MESSAGE(STATUS "This is SOURCE dir " ${PROJECT_SOURCE_DIR})
ADD_EXECUTABLE(hello ${SRC_LIST})
TARGET_LINK_LIBRARIES(hello dir1)
INSTALL(TARGETS hello RUNTIME DESTINATION ${PROJECT_SOURCE_DIR}/bin)
在dir1目录下添加
AUX_SOURCE_DIRECTORY(. DIR_SRCS) #遍历当前路径下的所有源文件,并将其添加到变量DIR_SRCS中
#ADD_LIBRARY (dir1 ${DIR_SRCS}) # 静态库
ADD_LIBRARY (dir1 SHARED ${DIR_SRCS}) #动态库
以上支持了install,make install 时候会将可执行文件hello复制到当前工程bin目录中;make时候将dir1下所有源文件编译成动态库,与a.c文件进行编译链接生成hello