这里写目录标题
1 makefile原理
编译过程是将高级语言(如C、C++等)源代码转换为可执行程序的过程。这个过程通常包括预处理、编译、汇编和链接四个主要阶段。下面将详细解释每个阶段的任务和过程:
-
预处理(Preprocessing)
预处理是编译过程的第一步,它主要处理源代码中的预处理指令,如宏定义(#define)、条件编译(#if、#elif、#else、#endif)和文件包含(#include)等。预处理器的输出是一个纯文本文件,通常具有.i或.ii扩展名,这个文件已经去除了注释、宏定义被展开、条件编译指令被处理,并且包含了所有被#include指令指定的文件内容。 -
编译(Compilation)
编译阶段将预处理后的源代码转换成汇编语言代码。这个过程可以分为几个子步骤:扫描(Scanning):将源代码分解成一系列的单词(tokens),如标识符、保留字、常数、运算符和界符。
语法分析(Parsing):根据语言的语法规则,将tokens组织成语法树(syntax tree)的形式,以表示源代码的语法结构。
语义分析(Semantic Analysis):检查语法树的语义正确性,包括类型检查、控制流检查等,并为语法树节点标注类型信息。
源代码优化(Source Code Optimization):对语法树进行优化,以提高代码的执行效率。
代码生成(Code Generation):将优化后的语法树转换成汇编代码。
目标代码优化(Target Code Optimization):对生成的汇编代码进行进一步的优化,以适应不同CPU架构的特性。 -
汇编(Assembly)
汇编阶段将编译生成的汇编代码转换成机器语言指令,即二进制代码。汇编器的输出是一个目标文件(object file),通常具有.o或.obj扩展名。这个文件包含了程序的二进制代码,但还不能直接执行,因为它可能还包含了未解析的外部引用(如对其他程序或库函数的调用)。 -
链接(Linking)
链接阶段将多个目标文件以及所需的库文件合并成一个可执行文件(executable file)。这个过程包括:
合并各个.obj文件的section:将不同目标文件中的代码段、数据段等合并到同一个可执行文件中。
合并符号表:将所有目标文件和库文件中的符号(如函数名、变量名)合并到一个统一的符号表中。
符号解析:解决目标文件中未解析的外部引用,即将符号表中的符号与实际的代码或数据地址关联起来。
符号地址重定位:调整程序中所有符号的地址,以确保它们在可执行文件中的位置是正确的。
最终,链接器生成一个可执行文件,该文件包含了程序运行所需的所有代码和数据,并且可以在目标操作系统上直接执行。
综上所述,编译过程是一个复杂而精细的过程,它涉及多个阶段和多个工具(如预处理器、编译器、汇编器和链接器)的协同工作。通过这个过程,高级语言的源代码被转换成机器可以直接执行的二进制代码。
2 MakeFile步骤
- 1 运行cygwin环境
- 2 运行make指令将搜索当前路径下makefile文件并执行第一个目标
- 3 预处理:生成预处理后的代码(可选地保存为.i文件)
- 4 编译+汇编(隐式):生成对象文件(.o或.obj)
- 5 链接:生成可执行文件(如.exe、.elf),然后可以转换为其他格式(如.hex)以用于特定目的
3 多文件多子目录Makefile实例
文件结构
其中OpenCygwin.bat用于再windows上运行unix环境,makefile文编译文件其中将会指定编译器路径,这里使用的是Gcc;bin 存放中间文件 inc存放代码头文件;src存放.c文件;main.c将会调用两个子文件中的函数
- OpenCygwin.bat
@echo off
:: 定义Cygwin bash的路径
set CYGWIN_BASH=E:\GRC\Tools\cywin64\cygwin64\cygwin64\bin\bash
:: 构造bash命令,切换到批处理文件所在的目录(转换为Cygwin路径)
:: 注意:%~dp0给出批处理文件的目录(不包括文件名),但需要转换为/cygdrive/e/形式
set CYGWIN_PATH='%~dp0'
:: 启动bash,以登录shell和交互式模式运行,并执行cd命令和exec bash
%CYGWIN_BASH% --login -i -c "cd %CYGWIN_PATH%; pwd; exec bash"
:: 注意:pwd命令用于显示当前目录,以验证是否成功切换
- makefile
# 定义编译器和编译选项
CXX=gcc
CXXFLAGS=-I./inc -Wall -g
# 定义目录
SRCDIR=src
BINDIR=bin
OBJDIR