(嵌入式Linux 2 )arm-linux-gcc和Makefile

gcc和arm-linux-gcc的常用选项

gcc的使用方法:

gcc [选项] 文件名

gcc常用选项:

-v:查看gcc编译器的版本,显示gcc执行时的详细过程

-o <file>                Place the output into <file>                      
              	             指定输出文件名为file,这个名称不能跟源文件名同名

-E                       Preprocess only; do not compile, assemble or link                         
	          只预处理,不会编译、汇编、链接

-S                       Compile only; do not assemble or link                          
	          只编译,不会汇编、链接

 -c                       Compile and assemble, but do not link                          
	           编译和汇编,不会链接   

================================================

gcc -v:查看gcc编译器的版本

gcc的编译过程

方式1:
gcc hello.c 输出一个a.out,然后./a.out来执行该应用程序。

gcc -o hello hello.c 输出hello,然后./hello来执行该应用程序。

方式2:
gcc -E -o hello.i hello.c 预处理(包含include等过程)
gcc -S -o hello.s hello.i 汇编
gcc -c -o hello.o hello.s 编译
gcc -o hello hello.o 链接可执行文件

.o:object file(OBJ文件)

小结:
1)输入文件的后缀名和选项共同决定gcc到底执行那些操作。
2)在编译过程中,除非使用了-E、-S、-c选项(或者编译出错阻止了完整的编译过程)
否则最后的步骤都是链接。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-um57a2Ka-1571141047155)(./1571103558111.png)]

方式3:
gcc -c -o hello.o hello.c

gcc -o hello hello.o

gcc会对.c文件默认进行预处理操作,-c再来指明了编译、汇编,从而得到.o文件
再通过gcc -o hello hello.o将.o文件进行链接,得到可执行应用程序。

链接就是将汇编生成的OBJ文件、系统库的OBJ文件、库文件链接起来,
最终生成可以在特定平台运行的可执行程序。

crt1.o、crti.o、crtbegin.o、crtend.o、crtn.o是gcc加入的系统标准启动文件,
对于一般应用程序,这些启动是必需的。

-lc:链接libc库文件,其中libc库文件中就实现了printf等函数。

gcc -v -nostdlib -o hello hello.o会提示因为没有链接系统标准启动文件和标准库文件,而链接失败。
这个-nostdlib选项常用于裸机/bootloader、linux内核等程序,因为它们不需要启动文件、标准库文件。

一般应用程序才需要系统标准启动文件和标准库文件。
裸机/bootloader、linux内核等程序不需要启动文件、标准库文件。

动态链接使用动态链接库进行链接,生成的程序在执行的时候需要加载所需的动态库才能运行。
动态链接生成的程序体积较小,但是必须依赖所需的动态库,否则无法执行。

静态链接使用静态库进行链接,生成的程序包含程序运行所需要的全部库,可以直接运行,
不过静态链接生成的程序体积较大。

小结

gcc -c -o hello.o hello.c

gcc -o hello_shared hello.o

gcc -static -o hello_static hello.o

MakeFile

Makefile的核心—规则 :

目标 : 依赖1 依赖2 ...
[TAB]命令

当"目标文件"不存在, 
或
某个依赖文件比目标文件"新",
则: 执行"命令"

比如两个.c文件:
a.c

#include <stdio.h>

int main()
{
	func_b();
	return 0;
}

b.c


void func_b()
{
	printf("THIS IF B\n");
}

Makefile:

test:a.o b.o
	gcc -o test a.o b.o
	
a.o : a.c
	gcc -c -o a.o a.c

b.o : b.c
	gcc -c -o b.o b.c

gcc前面是Tab,a:o与":"中有空格
makefile中,如果a.o b.o时间比test新,则执行gcc -o test a.o b.o,如果需要a.o,向下查找规则,找到a.o:a.c,同样如果a.c比a.o新,则执行gcc -c -o a.o a.c。这样文件在编译的时候只执行了修改过的文件,没有修改过的文件就不会执行编译。

Makefile自动化变量:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wYvmt2M7-1571141047158)(./1571103990251.png)]

如果加上c.c

void func_c()
{
	printf("THIS IS C\n");	
}

上述makefile可以写成:

test:a.o b.o c.o
	gcc -o test $^
	
%.o:%.c
	gcc -c -o $@ $<

$@表示目标文件,$<表示第一个依赖文件,$^表示所有依赖
清除命令:

test:a.o b.o c.o
	gcc -o test $^
	
%.o:%.c
	gcc -c -o $@ $<

clean:
	rm *.o test

make [目标命令]
在终端中调用时如果要用到clean,则输入make clean,如果只输入make,默认调用第一个命令。

假想目标

如果当前文件夹中有clean的文件,则无法执行上述命令
则需要定义假象目标,使用PHONY

test:a.o b.o c.o
	gcc -o test $^
	
%.o:%.c
	gcc -c -o $@ $<

clean:
	rm *.o test
	
.PHONY: clean

变量

c. 即时变量、延时变量, export
简单变量(即时变量) :
A := xxx # A的值即刻确定,在定义时即确定
B = xxx # B的值使用到时才确定

:= # 即时变量
= # 延时变量
?= # 延时变量, 如果是第1次定义才起效, 如果在前面该变量已定义则忽略这句
+= # 附加, 它是即时变量还是延时变量取决于前面的定义

例程:

A :=$(C)
B =$(C)
C =abc

D=100ask
D?=weidonhsjamn  #D不会执行
all:
	@echo A=$(A) #echo前加@可以不显示echo命令本身
	@echo B=$(B)
	@echo D=$(D)
C +=123

输出:
A=
B=abc 123
D=100ask

常用函数

a. $(foreach var,list,text)      #对于list里面的每个变量执行text操作
b. $(filter pattern...,text)      # 在text中取出符合patten格式的值
   $(filter-out pattern...,text)  # 在text中取出不符合patten格式的值

c. $(wildcard pattern)            # pattern定义了文件名的格式,
                                  # wildcard取出其中存在的文件
d. $(patsubst pattern,replacement,$(var))  # 从列表中取出每一个值符合pattern的值替换为replacemenet格式
					

举例:


A=a b c
B=$(foreach f,$(A),$(f).o)

C=a b c d/

D=$(filter %/,$(C))  #在变量C中取出地址/
E=$(filter-out %/,$(C)) #在变量C中取出不是地址/的值

files=$(wildcard *.c)  #筛选.c的文件

files2=a.c b.c c.c d.c e.c 
files3=$(wildcard $(files2))  #筛选真实存在的文件

dep_files=$(patsubst %.c,%.d,$(files2))
all:
	@echo B=$(B)
	@echo D=$(D)
	@echo E=$(E)
	@echo files=$(files)
	@echo files3=$(files3)
	@echo dep_files=$(dep_files)

输出:
B=a.o b.o c.o
D=d/
E=a b c
files=a.c c.c b.c
files3=a.c b.c c.c
dep_files=a.d b.d c.d d.d e.d

实例

如果.c文件有很多不一样的依赖文件,可以使用gcc生成.c文件的所有依赖,写入另一个文件 保存
如:

gcc -M c.c // 打印出依赖

gcc -M -MF c.d c.c  // 把依赖写入文件c.d

gcc -c -o c.o c.c -MD -MF c.d  // 编译c.o, 把依赖写入文件c.d

示例makefile注释

#定义目标文件
objs = a.o b.o c.o
#将objs中的文件取出建立新的格式文件  .a.o.d   .b.o.d  .c.o.d
dep_files := $(patsubst %,.%.d, $(objs))
#取出真实存在的dep_files文件,相当于剔除不存在的文件
dep_files := $(wildcard $(dep_files))

#-Werror表示如果有警告也当作错误显示
#-I表示头文件包含的指定目录include
CFLAGS = -Werror -Iinclude

#$^所有依赖文件
test: $(objs)
	gcc -o test $^

#ifneq如果不相等,如果dep_files的值不等于空,则执行下面语句(包含依赖).对应的还有ifeq,如果相等
ifneq ($(dep_files),)
include $(dep_files) 
endif

#$@规则中的目标集合  
#$<规则中第一个依赖   
#-MD -MF .$@.d 生成依赖并且写入.$@.d格式的文件中
%.o : %.c
	gcc $(CFLAGS) -c -o $@ $< -MD -MF .$@.d

#清除文件
clean:
	rm *.o test

#清除依赖
distclean:
	rm $(dep_files)

#防止同名clean
.PHONY: clean	
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值