GCC和Makefile

GCC和Makefile

2023-02-18
c语言

GCC #

GCC编译 #

#预处理
gcc -E -o hello.i hello.c
#编译(包含预处理)
gcc -S -o hello.s hello.i
#汇编(包含预处理和编译)
gcc -c -o hello.o hello.s
#链接(包含上面的步骤)
gcc -o hello hello.o

预处理 #

  • 源文件中以"#“开头的命令被称为预处理命令,如”#include"、"#define"、"#ifdef"等,预处理是将要包含的文件插入到原文件中,将宏定义展开、根据条件选择要使用的代码,最后将结果输出到一个文件中等待后续处理。

编译 #

  • 编译是将预处理后的文件翻译成汇编代码,用到的工具为cc1。

汇编 #

  • 汇编试讲汇编代码翻译成机器码,在linux上一般表现为ELF目标文件(OBJ文件),用到的工具为as。

链接 #

  • 链接是将生成的OBJ代码和系统库的OBJ文件、库文件链接起来,最终生成了可以在特定平台运行的可执行文件,用到的工具为ld或collect2.

常用选项 #

参数 描述
-E 预处理
-c 把预处理、编译、汇编都做的,但是不链接
-o 指定输出文件
-I 指定头文件目录
-L 指定链接时使用库文件的目录
-l(小L) 指定链接哪一个库文件,如-labc就是链接libabc.so
-v 显示编译器驱动程序、预处理器、编译器办吧等信息。
-Wall 打开所有需要注意的警告信息
#include <xxx> //在标准库的目录开始搜索(包括使用-Idir定义的目录)
#include "xxx" //先从用户的工作目录开始搜索,再搜索标准库目录

#

  • 动态库
#创建动态链接库
gcc -shared -o libsub.so sub.o sub1.o
#使用当前目录下得sub库
gcc -o test main.o -lsub -L ./

#运行时需要指定动态库的位置,可以将libsub.so移动到/lib目录下,或者配置一个环境变量
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/xiaox
  • 静态库
#生成静态库
ar crs libsub.a sub.o sub2.o
#将静态库打包到程序里
gcc -o tet main.o libsub.a

命令 #

#列出头文件目录、库目录(LIBRARY_PATH)等
echo 'main(){}'| gcc -E -v -

Makefile #

  • 格式如下:
target : prerequires1 prerequires2 ...
	command1
	command2
	...

变量 #

A := XXX //立即变量
B = XXX //延时变量,在使用时才生效
C += yyy //拼接字符串
D ?= xxx //如果D之前定义过,则此语句无效;如果之前定义值,此语句定义。

#

A := $(C)
B = $(C)
C = abc
D ?= weidongshan
all:
@echo A = $(A)
@echo B = $(B)
@echo D = $(D)
C += 123

#结果
#A = 立即变量定义式就确定,所以A的值为空
#B = abc 123 延时变量只有在用到时才确定,当执行make时,会解析Makefile里面的所有变量。
#D = weidongshan 因为D在前面没有定义,所以是此值。

通配符 #

  • *.c 表示所有的.c结尾的文件。
  • $@表示target。
  • $<表示第一个依赖文件。
  • $^表示所有的依赖文件。

假想目标.PHONY #

  • target并非只要求是文件,也可以是个标记(假想目标),声明要采取的动作。
clean :
	rm -rf *.o

.PHONY : clean

函数 #

  • foreach
#对于list中的每一个var,执行text的动作
$(foreach var,list,text)

#例
A := a b c
B := $(foreach f, $(A), $(f).c)
all : 
	@echo B = $(B)
  • filter/filter-out
$(filter pattern...,text) # 在text中取出符合patten格式的值
$(filter-out pattern...,text) # 在text中取出不符合patten格式的值

#例
A := a b c dxx
B := $(filter %xx, $(A))

all :
	@echo $(B)
#结果为dxx
  • patsubst
#如果var中的值匹配pattern,就将它替换为replacement
$(patsubst pattern, replacement, $(var))

#例
files := a.c b.c c.c d.c e.c abc
dep_files := $(patsubst %.c,%.d,$(files))
all :
	@echo dep_files = $(dep_files)
#结果为 dep_files = a.d b.d c.d d.d e.d abc

头文件依赖 #

  • 通过命令,自动生成依赖的的头文件,当头文件发生变化时,重新生成对应的文件。
#-M获取c.c依赖的头文件
#-MF将依赖输出的c.d的文件
gcc -M -MF c.d c.c

#

objs = a.o b.o c.o
dep_files := $(patsubst %,.%.d, $(objs))
dep_files := $(wildcard $(dep_files))

test : $(objs)
	gcc -o test $^

%.o : %.c
	gcc -c -o $@ $< -M -MF .$@.d

ifneq ($(dep_files),)
	include $(dep_files)
endif

clean:
	rm *.o test
	rm $(dep_files)

.PHONY: clean