首页 > 其他分享 >交叉编译&Makefile基础

交叉编译&Makefile基础

时间:2024-07-31 13:40:17浏览次数:14  
标签:文件名 target GNU 交叉 Makefile 编译 test 变量

1 交叉编译简介

1.1 什么是交叉编译

  1. 本地编译:在当前编译平台下,编译出来的程序只能放到当前平台下运行
  2. 在当前编译平台下,编译出来的程序运行在体系结构不同的另外一种目标平台上,但是编译平台 本身不能运行该程序

1.2 为什么会有交叉编译

  • Speed:目标平台的运行速度比主机慢很多,嵌入式的硬件没有太高的性能

  • Capability:编译过程非常消耗资源,嵌入式系统没有足够的内存或磁盘来完成编译

  • Availability:即使资源充足,但是第一个目标平台的运行的编译器也需要交叉编译获得

  • Flexibility:一个完整的编译环境有很多依赖包,会占用目标平台的资源,交叉编译使我们不需要花时间将各种 支持包移植到目标平台上

1.3 交叉编译链

交叉编译链

一系列软件开发工具的集合,通常包含以下组件:

  1. 编译器:在嵌入式开发里,通常指的就是GCC
  2. Binutils:一些二进制工具的集合,比如链接器ld,汇编器as
  3. C library:常见的C库实现有,glibc,uClibc,musl
  4. 调试器:GDB

SDK中通常包含预编译好的工具链

如果要改变C库的某些特性,则需要修改配置并重新编译工具链

2 GCC与编译基础

2.1 GCC简介

  • GCC的前身是 GNU C Compiler,随着时间的推移, 已经发展到支持许多语言,如C(gcc)、C++ (g++)、Objective-C、Java(gcj)。它现在被称 为 GNU Compiler Collection

  • GCC是“GNU Toolchain”的一个关键组成部分,GNU Toolchain包括以下的这些工具:

    1. GNU Compiler Collection (GCC):一个支持许多语言的编译器套件,如C/C++和 Objective-C/C++
    2. GNU Make:一个用于编译和构建应用程序的自动化工具
    3. GNU Binutils: 一套二进制实用工具,包括链接器和汇编器
    4. GNU Debugger(GDB)
    5. GNU Autotools: 一个构建系统,包括 Autoconf, Autoheader, Automake 和 Libtool
    6. GNU Bison: 一个parser生成器(类似于lex和yacc)
  • GCC是可移植的,可以在许多操作平台上运行

    • 所有类Unix操作系统
    • windows
    • 交叉编译

2.2 GCC的使用

  • gcc test.c: 会自动生成a.out可执行文件,使用时.a.out
  • gcc test.c -o test:指定gcc输出的文件名,使用时./test
  • gcc -I -L -l
    • -I指定头文件搜索路径
    • -L指定头文件搜索路径
    • -l指定库文件

2.3 GCC编译过程

  1. 预处理(Preprocessing):cpp xxx.c > xxx.i,预处理后生成.i文件
  2. 编译(Compiler):gcc –S xxx.i编译后生成.s文件
  3. 汇编(Assembler):as -o xxx xxx.s编译后生成.o文件
  4. 链接(Linker):ld xxx xxx.o library,链接后生成可执行文件

3 Makefile基础

3.1 什么是Make

  • GNU Make是一个构建自动化(build automation)工具,可以从源代码自动构建生成

  • 可执行程序 Make定义了一种用于描述源代码、中间文件和可执行文件之间关系的语言

  • 这些描述关系保存在一个名为Makefile的文件里面

3.2 Makefile示例

  • Makefile包含了一系列用于编译的描述规则(rule)

  • 每个规则包含了3个部分:

    • 目标 target
    • 依赖项 prerequisites
    • 指令 commands(tab缩进)
    target: prereq1 rereq2
        commands
    
  • Make当make在解析makefile的时候,遵循如下的逻辑

    1. 如果在命令行调用make时,没有指定target,默认从第一条规则开始解析(test)
    2. 在解析每条规则时,先检查是否有跟prerequisite相关的规则
    3. 若有,则先解析prerequisite规则(test.o)
    4. 解析完所有prerequisite规则后,再回来解析target对应的规则(test)
  • 当make在解析每条规则时(以test.o为例),遵循以下逻辑

    • 如果存在某个prerequisite存在更新(修改时间比较比target新,或target不存在),则按照command更新target(gcc -c test.c)
    • 若没有prerequisite存在更新,则什么都不执行,直接返回
  • 逻辑自上而下,执行自下而上(递归)

3.3 Makefile基本规则

  • Make默认会打印每条command,如果不希望看到,可以在每条 command前加@
  • makefile的文件名可以取名为:makefile、Makefile、GNUMakefile
  • 当我们执行make指令时,默认读取同目录下的makefile
  • 每一条command必须用一个tab进行缩进(不能是空格)
  • 注释以 # 开头
  • 一条语句比较长的情况下,可以使用 \ 进行换行

3.4 Makefile语法规则

3.4.1 伪目标

  • 不代表具体文件的target,称之为伪目标(Phony target):比如all、clean等

  • 伪目标必定每次都会执行更新(因为伪目标不会生成对应的文件)

  • 如果有一个文件名为clean,要怎么处理:使用特殊目标 .PHONY,显示的告诉make那些目标是伪目标

    .PHONY: all clean
        
    all: test
        
    test:test.c
        gcc -o test test.c
        
    clean:
    	rm test
    
  • 一些约定俗称的伪目标:

    1. all:执行建立应用程序的所有任务
    2. install:把编译的二进制文件安装到系统中
    3. clean:删除从源代码生成的二进制文件
    4. distclean:删除所有不属于源文件的生成文件
    5. TAGS:创建一个供编辑使用的标签表
    6. info:从Texinfo源码中创建GNU信息文件
    7. check:运行与该应用程序相关的测试

3.4.2 自动变量

  • 自动变量(Automatic Variables)
    • $@ target文件名
    • $* 去掉后缀的target文件名
    • $< 第一个prerequisite文件名
    • $^ 所有prerequisite文件名,并去掉重复的文件名
    • $+ 所有prerequisite文件名
    • $? 所有比target更新的prerequisite

3.4.3 模式规则

  • 模式规则(Pattern Rules):通过后缀名去匹配文件,一条规则就能描 述所有c文件与o文件的关系

    all: test
    
    %: %.c
    	gcc -o $@ $<
    	
    clean:
    	rm test
    

3.4.4 预设变量

  • 可以通过设置预设变量的值,改变默认规则的行为

    COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
    CC = gcc
    OUTPUT_OPTION = -o $@
    
    %.o: %.c
    	$(COMPILE.c) = $(OUTPUT_OPTION) $<
    
    • CC:C编译器的名称,默认gcc
    • CFLAGS:C编译器的选项,也指定头文件(.h文件)的路径,无默认值
      • CFLAGS = -g -O2 -Wall -Werror
      • CFLAGS = -I /usr/include –I /path/include
    • CPPFLAGS:C预编译器的选项,无默认值
      • CPPFLAGS = " -Werror -Wno-unused-but-set-variable" || exit 1
    • LDFLAGS:指定库路径和库文件
      • LDFLAGS = -L /var/xxx/lib –L /opt/mysql/lib -Wl,R /var/xxx/lib -Wl,R /opt/mysql/lib

3.5 变量与宏

  • 变量定义:直接对变量 进行赋值(变量的值包 含右边的所有字符,头部的空格会被删除,尾部的空格会被保留)

    LIBRARY = libio.a
    missing_file:
    	touch $(LIBRARY)
    	ls -l | grep '$(LIBRARY)'
    
  • 变量展开:要获取变量 的值,需要把变量名包 裹在\(()里面(也可以使用\){},但多见于旧 Makefile中

  • 简单赋值(:=)- 立即展开

  • 递归赋值(=) - 变量被使用时展开

  • 条件赋值(?=)- 变量未被定义时展开

  • 追加赋值(+=)- 追加到原变量值的尾部

    var1 = hello $(word)
    var2 := hello $(word)
    var3 = hello
    var3 += $(word)
    word := world
    
    hello:
            @echo var1 = $(var1)
            @echo var2 = $(var2)
            @echo var3 = $(var3)
    
  • 宏事实上只是定义变量的另外一种方式, 它们的本质是一样的

  • 为了便于区分,我们称通过赋值符号定义 的为变量,通过define定义的为宏

    define print_hello
    @echo "hello world"
    endef
    
    hello:
    	$(print_hello)
    
  • 变量主要用在条件语句中,通过不同的取值,控制编译的行为

  • make提供4种可用的条件语句

  • 包含语句:Make支持通过include语句把其它的makefile包含进来

  • 要注意变量或宏之间的覆盖关系

3.6 函数

  • Make提供了一系列内置函数以及支持用户自定义函数

  • 函数跟变量的调用跟变量引动的形式类似,但包括一个或者多个参数,用逗号分隔

    $(function-name arg1[, argn])

3.6.1 字符函数

  • $(filter pattern ...,text)

    • 返回text中与任何pattern相匹配的词,删除任何不 匹配的词,起到过滤的作用。text包含多个以空格分 隔的字符串
    • filter函数可用于在一个变量中分离出不同类型的字 符串(如文件名)
    sources := foo.c bar.c baz.s ugh.h
    foo: $(sources)
    	cc $(filter %.c %.s,$(sources)) -o foo
    
  • $(subst search-string,replace-string,text)

    • 起到文本替换的作用。可用于.c和.o文件名之间的替换
    sources := count_words.c counter.c lexer.c
    objects := $(subst .c,.o,$(sources))
    
  • $(findstring string, text)

    • 在text中查找string,如果能找到,则返回string,否 则返回为空
  • $(strip text)

    • 去除text头部和尾部的空格,同时若text内部出现连续 多个空字符,会将之合并成一个

3.6.2 文件名函数

  • $(wildcard pattern...):返回与pattern匹配的文件名
  • $(suffix name...):从name中提取每一个文件名的后缀
  • $(basename name...):从name中提取每一个文件名,并去掉后缀
objects := $(subst .c,.o,$(wildcard *.c))

foo: $(objects)
	$(CC) -o foo $(objects)

3.6.3 流程控制函数

  • $(if condition,then-part,else-part):若condition为非空字符串,则返回then-part,否则返回else-part
  • $(error text):出发编译错误并把text中的内容打印出来
  • $(foreach variable,list,body):对于list中每一个字符串,调用一次body,并把在调用body前把此字符串赋值给variable

3.6.4 shell函数

  • $(shell command):在shell中执行command中包含的指令,并返回指令的输出结果
DATE := $(shell date)

print_date:
	@echo $(DATE)

3.6.5 自定义函数

  • $(call macro-name[, param1...])
    • 自定义函数其实只是宏定义的一种特殊形式,通过使用call函数调用宏, 可以增加参数列表
    • 每一个参数通过\((1),\)(2)...这种形式进行引用
define print_func
@echo "param1 = $(1)"
@echo "param2 = $(2)"
endef

hello:
	$(call print_func,hello,world)

标签:文件名,target,GNU,交叉,Makefile,编译,test,变量
From: https://www.cnblogs.com/mobbu/p/18334436

相关文章

  • MBD软件开发之条件编译
    汽车行业流行平台化开发,希望通过一套软件对付一系列车型,当然这一系列车型的软件基本上一致,不同配置之间可能有很少一点差别,怎么办?C语言开发中有条件编译,同一份源代码,可以通过设置不同的参数,编译出来不同的软件,而无需编译冗余的软件。使用模型开发算法,是否也可以让模型生成的代......
  • 这本vue3编译原理开源电子书,初中级前端竟然都能看懂
    前言众所周知vue提供了很多黑魔法,比如单文件组件(SFC)、指令、宏函数、cssscoped等。这些都是vue提供的开箱即用的功能,大家平时用这些黑魔法的时候有没有疑惑过一些疑问呢。我们每天写的vue代码一般都是写在*.vue文件中,但是浏览器却只认识html、css、js等文件类型,明显是不认......
  • Java编译和运行的命令
    在Java中,编译和运行Java程序主要使用两个命令:javac用于编译Java源代码,java用于运行编译后的Java字节码。编译Java程序要使用javac命令编译Java程序,你需要在命令行(终端或命令提示符)中导航到包含你的Java源代码文件的目录。然后,运行以下命令:bash复制代码javacYourProgram.ja......
  • 学习makefile(一)
    1、makefile基础对于从事嵌入式开发的朋友们,学会MK非常重要。对于部分朋友在别人已经搭建好的开发平台上扩展一些功能的开发工作,上手很快。但是一但遇到编译相关的问题,就显得束手无策。(本人也是基于这个原因,此次开始系统学习Makefile)。关于编译问题主要有两个方面1:代码的语法......
  • ambari2.8+ambari-metrics3.0+bigtop3.2编译、打包、安装
    bigtop编译资源说明:软件及代码镜像开发包镜像github访问编译相关知识技术知识bigtop编译流程及经验总结各模块编译难度及大概耗时(纯编译耗时,不包含下载文件和排错时间)centos真机编译branch-3.2硬件说明:编译步骤下载代码并切换分支国内镜像配置基础环境......
  • java编译错误,找不到包的解决办法
    异常:D:\AC2024\20240729\delphiJIN_JAVA\JavaTest\bin\x64>javaMYclasses.JavaClassForDelphiTestExceptioninthread"main"java.lang.NoClassDefFoundError:com/sltas/front/third/util/CryptionUtilatMYclasses.JavaClassForDelphiTest.main(Jav......
  • Python 类交叉引用
    我用Python创建了一个数独游戏。我有一个:单元格类-“保存”数字可能性单元格组-保存单元格类实例我使用这些组在数独中运行行、列和正方形功能。每个单元格包含所有组,他属于classCell:def__init__(groups):self.groups=groupscla......
  • 关于嵌入式QML dict_pinyin.dat的编译更新
    硬件平台:全志的A40I-H 软件平台:Linux内核版本3.10.65QT版本:5.9.0 重新编译dict_pinyin.dat的作用 1.解决输入"nss"导致输入法崩溃的问题2.解决输入某些嵌入式平台不支持的字体,例如“捃”,导致程序崩溃的问题 源码路径:~/qt-everywhere-opensource-src-5.9.0/qtvirtual......
  • 解决ubuntu 22.04新内核6.5.0-15无法编译NVIDIA显卡驱动
    这里的新内核应该包括6.5.*系列的遇到的问题:在安装NVIDIA显卡驱动发现了一个问题,主要日志如下所示:make[3]:***[scripts/Makefile.build:251:/tmp/selfgz1310041/NVIDIA-Linux-x86_64-550.54.14/kernel/nvidia/nvlink_linux.o]Error1make[3]:Target'/tmp/selfgz131004......
  • 编译期链接时共享库搜索路径优先级实验
    目录前言实验环境目录说明准备工作单独测试不配置路径默认路径LIBRARY_PATH-L优先级测试默认路径和LIBRARY_PATH-L和默认路径DEBUG模式编译器配置详细信息链接器详细信息DEBUG总结验证默认路径>LIBRARY_PATH原因附录库文件源码主程序源码makefile前言《共享库链接和加载时的路径......