【3】DongshanPI-Seven 应用开发_GCC&Makefile

本文详细介绍了Hello程序的源码和编译过程,包括GCC编译选项、交叉编译、使用动态库和静态库的方法,以及Makefile的规则、语法和通用用途。
摘要由CSDN通过智能技术生成

1.hello 程序

1.1 hello应用程序源码

#include <stdio.h>

/* 执行命令: ./hello madao1234
* argc = 2
* argv[0] = ./hello
* argv[1] = madao1234
*/

int main(int argc, char **argv)
{
 	if (argc >= 2)
		printf("Hello, %s!\n", argv[1]);
	else
		printf("Hello, world!\n");
	return 0;
}

说明:
1、main函数包含2个参数:

  • int argc:(argument count,参数个数)
  • char **argv(argument value,参数值指针)
    如执行命令 ./hello madao1234
    argc = 2
    argv[0] = hello
    argv[1] = madao1234

2、#include <stdio.h> 头文件位置:

  • 默认路径:在交叉编译器目录的一个include目录下,可以通过 find -name “stdio.h” 命令查找。
  • 编译时用 -I <头文件目录> 可以指定头文件目录。

3、包含printf函数的库文件位置:

  • 默认路径:编译器中的lib目录
  • 编译时用 -L <库文件目录> 选项可以指定目录
  • -labc 这样的选项,用来指定库文件 libabc.so

1.2 交叉编译

想要编译的APP程序可以在开发板上运行,需要使用交叉编译工具链:arm-buildroot-linux-gnueabihf-gcc

arm-buildroot-linux-gnueabihf-gcc -o hello hello.c

通过file 命令可以查看编译后的文件的信息。可以看到这个程序是为ARM编译的程序。
在这里插入图片描述
直接用gcc编译的文件信息,可以看到是为X86-64平台编译的程序。
在这里插入图片描述

2. GCC编译

2.1 gcc 编译过程

① 预处理
② 编译
③ 汇编
④ 链接
在这里插入图片描述
注意:程序中的语法错误是在编译阶段被发现。

2.2 常用编译选项

常用选项说明
-E预处理,开发过程中想快速确定某个宏可以使用“-E -dM”
-c把预处理、编译、汇编都做了,但是不链接
-o指定输出文件
-I(大i)指定头文件目录
-L指定链接时库文件目录
-l指定链接哪一个库文件

说明:

  1. -c 先编译最后再链接的方式,在编译多个文件时很有用。若修改了其中某一个文件,不必将其他所有的文件都重新编译,只需编译改变的文件即可。
  2. “ ”包含的头文件,会在当前目录下查找;< >包含的头文件会在工具链的默认路径中查找。

2.3 制作使用动态库

gcc -c -o main.o main.c
gcc -c -o sub.o sub.c
gcc -shared -o libsub.so sub.o sub2.o //(可以使用多个.o生成动态库)
gcc -o test main.o -lsub -L /libsub,so所在目录	// -l 省略吊lib前缀和.so

运行:libsub.so 在/a 目录下,将这个目录导出到环境变量,执行如下命令,然后再执行test程序就可以了

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/a

2.4 制作使用静态库

gcc -c -o main.o main.c
gcc -c -o sub.o sub.c
ar crs libsub.a sub.o sub2.o sub3.o //(可以使用多个.o 生成静态库)
gcc -o test main.o libsub.a // (如果.a 不在当前目录下,需要指定它的绝对或相对路径)

运行不需要把静态库libsub.a放到开发板上。
注意:执行 arm-buildroot-linux-gnueabihf-gcc -c -o sub.o sub.c 交叉编译需要在最后面加上-fPIC参数。

2.5 很有用的选项

gcc -E main.c // 查看预处理结果,比如头文件是哪个
gcc -E -dM main.c > 1.txt // 把所有的宏展开,存在 1.txt 里
gcc -Wp,-MD,abc.dep -c -o main.o main.c // 生成依赖文件 abc.dep,后面 Makefile 会用
echo 'main(){}'| gcc -E -v - // 它会列出头文件目录、库目录(LIBRARY_PATH)

3. Makefile

使用Makefile主要是想通过简单的命令实现文件编译。修改源文件或头文件只要重新编译涉及到的文件即可。

3.1 Makefile规则

目标:依赖1 依赖2 ...
<tab> 命令

说明:
1.如果“依赖文件”比“目标文件”更加新(比较文件时间),那么执行命令来重新生成“目标文件”。
2.命令被执行的2个条件:1)依赖文件比目标文件新;2)目标文件还没生成。

测试

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

在这里插入图片描述

3.2 Makefile 语法

1)通配符:%

$@ : 目标文件
$< :1个依赖文件
$^ : 所有的依赖文件

2)假想目标:.PHONY
避免同名文件 clean存在时,无法执行make clean。

clean:
	rm *.o
.PHONY: clean   // 假想目标,不再判断同名文件是否存在

make clean即 make [目标名]
当使用make 不带目标名时,则默认生成第一个目标文件

3)即时变量、延时变量

A := xxx # 即时变量,定义时就确定了
B = xxx  # 延时变量,使用时才确定

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

4)常用函数

a. $(foreach var,list,text)			# 对list中的每一个变量,执行text操作
b. $(filter pattern...,text)		# 在text中取出符合pattern格式的值
   $(filter-out pattern...,text)	# 在text中取出不符合pattern格式的值
c. $(wildcard pattern)				# pattern定义文件名的格式
									# wildcard 取出其中存在的文件
									
d. $(patsubst pattern,replacement,$(var))	# 从列表中取出每一个值
											# 如果符合pattern格式则替换为replacement格式

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

objs = a.o b.o c.o

dep_files := $(patsubst %,.%.d, $(objs))
dep_files := $(wildcard $(dep_files))

CFLAGS = -Werror -Iinclude		// 编译参数:-Werror:warning 都当作error。-Iinclude 指定头文件路径

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

ifneq ($(dep_files),)			// 包含依赖的头文件(.%.d文件),头文件修改时进行重新编译
include $(dep_files)
endif

%.o : %.c
	gcc $(CFLAGS) -c -o $@ $< -MD -MF .$@.d  // 编译*.o,把依赖写入文件*.o.d 

clean:
	rm *.o test

distclean:
	rm $(dep_files)
	
.PHONY: clean	

3.3 通用Makefile

通用Makefile在01_all_series_quickstart\04_嵌入式Linux应用开发基础知识\source\05_general_Makefile\Makefile_and_readme 下有使用说明,可参考使用。


To Be Continue …

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

madao1024

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值