基于i.mx6的linux学习第三章

1 i.mx实践—烧录固件

(1)使用git获取GitHub仓库的数据
git clone 仓库的地址 #就可以获得克隆文件
git pull 仓库文件更新
衍生教程:廖雪峰git教程
https://www.liaoxuefeng.com/wiki/896043488029600

2 安装NFS服务器

(1)NFS文件服务器的功能:实现网络文件共享。
(2)安装过程 sudo apt install nfs-kernel-server -y
打开/etc/exports文件(etc:存放配置文件的文件夹)
sudo vim /etc/exports 再退出
sudo mkdir -p /home/lailin/workdir
添加配置信息
/home/lailin/workdir *(rw,sync,no_root_squash)
(3)ifconfig 可以查看当前网卡信息(比如IP信息)

3 gcc编译器使用教程

(1)gcc编译器(预处理、编译)
binutils工具箱(汇编、链接)
上面两个就组成了GCC编译工具链;
(2)ls -l:可以查看文件的权限
第一个文件是 l:就是链接文件
第一个文件是 d:就是设备文件
第一个文件是 -:就是普通文件
(3)过程:gcc预处理c文件 sudo gcc -E hello.c -0 hello.i(默认使用的工具是:)
gcc编译c文件 sudo gcc -S hello.i -0 hello.s(默认使用的工具是:)
gcc编译汇编 sudo gcc -c hello.s -0 hello.o(默认使用的工具是:)
gcc链接可重定位文件 sudo gcc hello.o -0 hello(动态链接)(默认使用的工具是:)
sudo gcc hello.o -o hello -static(静态链接)
makefile文件处理的默认工具是make
但是一般都是直接使用.o文件编译成目标文件
sudo gcc -c hello.c -o hello.o

补充:which 指令:可以查找指令安装的位置

4 ARM-GCC与交叉编译

(1)ARM-GCC是什么?:就是针对ARM平台的编译器,是GCC编译器的一个分支。
编译工具链和目标程序运行相同的架构平台,就叫本地编译
编译工具链和目标程序运行在不同的架构平台,叫做交叉编译
ARM-GCC是针对arm平台的一款编译器,它是GCC编译工具链的一个分支。
(2)在ubuntu18.04平台上安装arm-linux-gcc交叉编译器
sudo apt install gcc-arm-linux-gnueabihf
(3)在ubuntu18使用gcc编译的程序在开发板的Debian操作系统是无法执行的,只有利用arm-gcc-linux交叉编译器编译才能执行。
arm-linux-gnueabihf-gcc 程序文件名 -o 编译后产生的可执行文件的名字
在开发板执行应用程序使用 ./程序名字

5 linux系统的应用程序分析

  1. 首先把程序预处理成test.i文件,再编译成test.s成为汇编文件,再汇编成为可执行的二进制文件test.o,再链接成一个完整的应用 文件
  2. 再经过执行的时候,可以有两种链接到内存中(1)静态链接:全部把应用程序所需要的内存进行分配,缺点:当所需要的内存特别大的时候,可能分配内存会失败 (2)动态链接:仅仅把处理器此时所需要的数据链接到内存空间中,优点:使程序占用的内存减小。

7 makefile的学习(重要、重要、重要)

  1. makefile存在的意义:由于一个工程会特别大,如果一直使用gcc hello.c -o hello会很麻烦,而且当只是修改了其中一两个数据,就必须全部重新编译,会浪费很多时间,因此就有了makeflie这个工具。---------用来管理项目

  2. make与makefile之间的关系:
    make工具:make能够找出一个项目程序中被修改的部分,然后找出受影响的相关文件,最后按照规则只修改相应的文件
    makefile文件:记录依赖关系和编译规则。** makefile无论多么复杂的语法,都是为了更好地解决项目之间的依赖关系。**

  3. makefile文件的三要素:目标、依赖、命令

  4. makefile书写格式:
    目标:依赖的文件或者是其他目标
    命令1
    命令2
    ,,,

  5. Makefile文件书写实例(一般Makefile文件第一个字母需要大写):
    targeta:targetb targetc #目标a:依赖b与c文件 ,因此要先执行targetb,再执行targetc,最后才能执行targetc
    echo “targeta”
    targetb:
    echo “targetb”
    targetc:
    echo “targetc”

  6. (1)执行make指令:就会按照makefile文件进行执行命令 sudo make(如果发现文件并没有改动,就不会再次执行指令)
    需要make指定文件的时候: sudo make -f 自定义makefile文件名
    (2)也可以单独执行其中某个目标文件:sudo make targetb (要已经定义了目标,比如可以是伪目标 .PHONY:clear
    (3)可以使用伪目标:在Makefile文件中:.PHONY:targetc #此时make工具就不会再次检查targetc目标是否已经编译过,会直接编译,执行命令
    (4)Makefile的变量与模式匹配
    1)变量 :makefile文件中要使用变量都是用 $(变量名)

    **系统变量**     
    就是makefile文件自带的变量,比如CC、AS、MAKE等,代表预处理器,汇编器,链接器等等,比如echo "$(CC)"
    	
    	**自定义变量**
    			          1:     = “是延迟赋值,就是在被命令调用的时候,才会赋值”
    			          #例子在一个makefile中
    			          A=123
    			          B=$(A)
    			          A=456
    			         .PHONY:all
    			         all:
    			         <tab>echo "$(B)"  #分析,由于延迟赋值,开始的时候并不会对B赋值(对于A,由于是数字,就是立即赋值了),当执行指令echo的时候,由于A=456,因此输出B=456;
    			         2:     :=立即赋值   
    			         	   A=123
    				          B := $(A) #此时是立即赋值
    				          A=456 
    				          #此时输出为123
    			        3:    ?=空赋值(就是只有变量为空的时候才能赋值)
    			             A ?= 123
    			             A ?= 456
    			            因此此时A的值是123
    			        4:    +=追加赋值(就是不修改变量之前的数据,只是在后面追加)
    			             A ?= 123
    			             A += 456
    			            因此此时A的值是123 456
    		**自动化变量**
    		
    						 1.   $<   :第一个依赖文件
    						#例子:在makefile中
    						mp3:targeta targetb
    						<tab>echo "$<"  #此时输出targeta(因为targeta是第一个依赖文件)
    				       2.   $^   :全部的依赖文件
    						#例子:在makefile中
    						mp3:targeta targetb
    						<tab>echo "$^"  #此时输出targeta targetb
    						 3.   $@   :代表编译的目标
    						 4. 打印出目标的名字
    						#例子:在makefile中
    						mp3:targeta targetb
    						<tab>echo "$@"  #此时输出mp3
    

(5)Makefile管理项目:
1)简单管理版本:
vim mp3.c #创建MP3文件
vim main.c
在Makefile文件中创建:
vim Makefile
{
##这是在Makefile文件中
MP3:main.o mp3.o #此时要生成目标文件mp3,需要依赖main.o与mp3.o (因为此时不用依赖main.c与mp3.c,因此只要这两个文件不修改,就不会重复编译)
gcc main.o mp3.o -o mp3
main.o:
gcc -c main.c -o main.o
mp3:
gcc -c mp3.c -o mp3.o
.PHONE:clean

		clean:
		<tab>rm mp3
		   }
		
		2)综合Makefile复杂项目管理
		(文件夹里面有mp3.c与main.c文件,要生成目标mp3程序文件)
		
		#定义自定义变量
		#以下是在makefile中
		cc=gcc  #指定编译器为gcc
		TARGET=mp3  #指定编译目标为mp3(编译目标就是生成的对象目标名字)
		OBJS=main.o mp3.o #编译需要的依赖文件
		
		$(TARGET):$(OBJS)
		<tab>$(cc) $^ -o $@   #就是gcc main.o mp3.o -o mp3
		main.o:main.c
		<tab>$(gcc) -c main.c -o main.o
		mp3.o:mp3.c
		<tab>$(gcc)  -c mp3.c -o mp3.o
		
		.PHONY:clean  #设置虚拟编译目标,每次都能执行的指令(因为其他的目标可能会由于make检查到没有修改,而不执行)
		clean:
		<tab>rm mp3
		
		**模式匹配**
		1)匹配任意多个非空字符:% (可以使用这个%符号替换很多文件名)与指令中的*类似
		
		#定义自定义变量
		cc=gcc  #指定编译器为gcc
		TARGET=mp3  #指定编译目标为mp3(编译目标就是生成的对象目标名字)
		OBJS=main.o mp3.o #编译需要的依赖文件
		
		$(TARGET):$(OBJS)
		<tab>$(cc) $^ -o $@   #就是gcc main.o mp3.o -o mp3
		
		  %.o:%.c     #此时就用的模式匹配中的%来代替文件名
		<tab>$(cc) -c $< -o $@
		
		.PHONY:clean  #设置虚拟编译目标,每次都能执行的指令(因为其他的目标可能会由于make检查到没有修改,而不执行)
		clean:
		<tab>rm mp3
		
		**默认规则**
		.o文件都是使用.c文件进行编译过来的
		因此可以直接不需要把main.c编译成main.o
		因此上面就可以直接变成
		
		#定义自定义变量
		cc=gcc  #指定编译器为gcc
		TARGET=mp3  #指定编译目标为mp3(编译目标就是生成的对象目标名字)
		OBJS=main.o mp3.o #编译需要的依赖文件
		
		$(TARGET):$(OBJS)
		<tab>$(cc) $^ -o $@   #就是gcc main.o mp3.o -o mp3
		
		.PHONY:clean  #设置虚拟编译目标,每次都能执行的指令(因为其他的目标可能会由于make检查到没有修改,而不执行)
		clean:
		<tab>rm mp3

(6)Makefile条件分支:

`分支一``
ifeq  (var1,var2)   #如果var1与var2相等的话就执行代码段一,否则就执行代码段二
,,,,,代码段一,,,,,,,,
else
,,,,,代码段二,,,,,,,,
endif```


ifneq (var1,var2)
,代码段一,
else
,代码段二,
endif


可以使用上面的条件分支判断使用什么编译器
ARCH  ?= X86  #使用了空赋值

ifeq ($(ARCH),X86)
<tab>cc=gcc                                   #使用X86的gcc编译器编译
else
<tab>cc=arm-linux-gnueabihf-gcc  #使用arm的gcc交叉编译器编译

TARGET=mp3  #指定编译目标为mp3(编译目标就是生成的对象目标名字)
OBJS=main.o mp3.o #编译需要的依赖文件

$(TARGET):$(OBJS)
<tab>$(cc) $^ -o $@   #就是gcc main.o mp3.o -o mp3

.PHONY:clean  #定义伪目标clean(每次make都能够执行)
clean:
<tab>rm mp3 *.o    #就是删除MP3文件与所有以.o结尾的文件

在终端下执行 sudo make ARCH=arm  (此时就是使用arm的交叉编译器进行编译)

(7)**Makefile常用的函数:**
 
 1)patsubst函数:模式替换函数:
 原型:$(patsubst  %.c,$(BUILD_DIR)/%.o,x.c.c bar.c)  #分析:就会在x.c.c中找到最后的.c,直接替换成x.c.o 与bar.o,并且放入BUILD_DIR文件夹中
 最后输出x.c.o bar.o  》》BUILD_DIR
 2)notdir函数:文件夹去除函数:
原型: $(notdir src/foo.c)  #分析:就是把文件夹的路径去掉  
 最后输出foo.c
  3)wildcard函数:获取匹配模式文件名函数 :
原型: $(wildcard  文件夹/*.c)  #分析:就是获取文件夹目录下的所有.c源文件列表  
 最后输出mp3.c main.c
 
   4)foreach函数:循环函数,类似shell中for语句 :
原型: $(foreach  VAR,LIST,TEXT)  
举例:
dirs :=  a b c d 
files :=$(foreach  dir,$(dirs),$(wildcard  $(dir)/*))
 最后输出files := $(wildcard  a/* b/* c/* d/*),就是找到a目录下的文件,b目录下的文件

**补充小技巧**   !!是执行上次的指令
比如 sudo  !! (假如上次执行的时候提示权限不够的时候make  -f makefile_function)

(8)**Makefile终极项目管理版本:**

```powershell
ARCH ?= X86                              #使用了空赋值

ifeq ($(ARCH),X86)
<tab>cc=gcc                              #使用X86的gcc编译器编译
else
<tab>cc=arm-linux-gnueabihf-gcc  #使用arm的gcc交叉编译器编译

TARGET=mp3                                #指定编译目标为mp3(编译目标就是生成的对象目标名字)
BUILD_DIR=build                           #生成编译目标的文件夹(包括.o与目标文件mp3)
SRC_DIR=moudle1 moudle2                    #存放源文件的文件夹
SOURCE=$(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.c))                #这个是利用wildcard 函数在源文件夹中寻找源文件,
                                                                       #此时文件中有文件夹的东西 比如/moudle1/main.c
OBJS=$(patsubst %.c,$(BUILD_DIR)/%.o,$(notdir $(SOURCE)))             #首先去掉目标文件中的文件夹,再找到编译需要的.o依赖文件
VPATH=$(SRC_DIR)                                                      #编译器必须要的VPATH,是源文件目录

$(BUILD_DIR)/$(TARGET):$(OBJS)
<tab>$(cc) $^ -o $@               #就是gcc main.o mp3.o -o mp3

$(BUILD_DIR)/%.o:%.c | creat_build
<tab>$(cc) -c $< -o $@            #就是gcc -c main.c  -o main.o

.PHONY:clean creat_build                      #定义伪目标clean(每次make都能够执行)
clean:
<tab>rm -r $(BUILD_DIR)                      #就是删除MP3文件与所有以.o结尾的文件

creat_build:
<tab>mkdir -p $(BUILD_DIR)                   #没有错误就创建build文件夹

(9)Makefile解决头文件依赖问题:
需要把头文件也添加进项目中去,并且当头文件被修改的时候,应该需要重新编译相关所有文件。
1.需要往gcc编译器中添加专门存放头文件的目录
命令:gcc -i +头文件夹

############下面是完整的一个makefile文件的框架
ARCH ?= X86                              #使用了空赋值

ifeq ($(ARCH),X86)
<tab>cc=gcc                              #使用X86的gcc编译器编译
else
<tab>cc=arm-linux-gnueabihf-gcc  #使用arm的gcc交叉编译器编译

TARGET=mp3                                #指定编译目标为mp3(编译目标就是生成的对象目标名字)
BUILD_DIR=build                           #生成编译目标的文件夹(包括.o与目标文件mp3)
SRC_DIR=moudle1 moudle2                    #存放源文件的文件夹
SOURCE=$(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.c))                #这个是利用wildcard 函数在源文件夹中寻找源文件,
                                                                       #此时文件中有文件夹的东西 比如/moudle1/main.c
OBJS=$(patsubst %.c,$(BUILD_DIR)/%.o,$(notdir $(SOURCE)))             #首先去掉目标文件中的文件夹,再找到编译需要的.o依赖文件
VPATH=$(SRC_DIR)                                                      #编译器必须要的VPATH,是源文件目录
INC_DIR=include                                                            #项目头文件夹
CFLAGS=$(patsubst  %,-I%,$(INC_DIR))                   #cflags是gcc编译器的一个选项参数  gcc -i 头文件夹
INCLUDE=$(foreach dir,$(INC_DIR),$(wildcard $(dir)/*.h))     #在头文件中寻找.h的头文件

$(BUILD_DIR)/$(TARGET):$(OBJS)
<tab>$(cc) $^ -o $@               #就是gcc main.o mp3.o -o mp3

$(BUILD_DIR)/%.o:%.c  $(INCLUDE)  | creat_build
<tab>$(cc) -c $< -o $@  $(CFLAGES)            #就是gcc -c main.c  -o main.o -i include

.PHONY:clean creat_build                      #定义伪目标clean(每次make都能够执行)
clean:
<tab>rm -r $(BUILD_DIR)                      #就是删除MP3文件与所有以.o结尾的文件

creat_build:
<tab>mkdir -p $(BUILD_DIR)                   #没有错误就创建build文件夹

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值