kernel开发1:编译openEuler内核以及gdb,make,makefile, qemu相关

编译openEuler内核并用虚拟机启动

本文是开发openEuler内核系列的第一篇,由编译内核和运行内核组成;主要参考了[1]和[7]两篇文章。

编译内核

编译基础知识

  1. GCC与编译知识

    • GCC是在linux系统下常用的C语言编译工具,全称从GNU C Compiler变为GNU Compiler Collection;

      • 它是GNU工具集的一员,这个工具集包含:

        • GNU Compiler Collection (GCC): a compiler suite that supports many languages, such as C/C++ and Objective-C/C++

        • GNU Make: an automation tool for compiling and building applications

        • GNU Binutils: a suite of binary utility tools, including linker and assembler

        • GNU Debugger (GDB)

        • GNU Autotools: A build system including Autoconf, Autoheader, Automake and Libtool

        • GNU Bison: a parser generator (similar to lex and yacc)

    • 编译过程

      • 编译是将高级语言翻译成机器语言,我们在编译原理中所学的是语法分析,解析,语义分析,将高级语言翻译成机器语言并进行优化这几个步骤,这些知识主要是用来写编译器的。而编译器在整个编译过程中是一个组成部分,还有预处理,汇编器,链接器等内容,我们作为一个编译器的使用者更多的关注整体的编译流程,而不是如何写出一个编译器。具体的编译流程如下图所示:

        kernel开发1:编译openEuler内核以及gdb,make,makefile, qemu相关

      • 具体过程

        • 预处理

          • 将#include和#define等展开

            
            cpp hello.c > hello.i
            
            
          • 头文件查找范围

            • -Idir选项

            • CPATH环境变量,C_INCLUDE_PATH和CPLUS_INCLUDE_PATH可以分别来指定C和C++的头文件位置

            • 可以使用“cpp -v”命令查看查找范围

        • 编译器

          • 将高级语言翻译为汇编

            
            gcc -S hello.i
            
            
        • 汇编器

          • 将汇编翻译为机器码

            
            as -o hello.o hello.s
            
            
        • 链接器

          • 分为静态链接和动态链接,默认来说,是采用动态链接

            
            ld -o hello.exe hello.o ...libraries...
            
            
          • 链接查找范围

            • 文件夹

              • -Ldir选项

              • LIBRARY_PATH环境变量

            • 库名

              • Unix下,根据选项-lxxx

              • Windows下,根据选项-lxxx.lib

            • 还可以在Path环境变量下查找

            • 可以打开-v选项观察用了哪些库,其中-L是表示库的路径,-l表示库的名字

    • GCC入门用法

      • 一个常用的选项的示例:

        
        gcc -std=c99 -v -Wall -g -o myprog file1.c file2.c
        
        
      • 常用的选项

        • -std 选项可以指定一个用来表示编译版本的参数

        • -v 选项表示可以将编译的相关信息输出

        • -Wall 选项代表输出所有的warning信息

        • -g 选项表示附带debug信息

        • -o 选项表示输出的应用文件名由-o后面的参数指定

        • -shared 选项可以动态链接

        • 其余的参数视为需要编译的文件,可以指定多个文件

    • GCC进阶用法

      • 编译器会在将高级语言翻译为汇编语言的过程中,展开优化

      • 可以单独将每一步的过程分别运行,而不是合成整体

        • 预处理 gcc -E hello.c -o hello.i

        • 编译,生成汇编代码 gcc -S hello.i -o hello.s

        • 汇编,生成.o汇编文件 gcc -c hello.s -o hello.o

        • 链接生成可执行文件 gcc hello.o -o hello

  2. makefile

    • Make工具是GCC工具集中的一员,主要是利用一个叫做“makefile”的文件,来简化编译生成可执行文件的过程;

    • makefile文件的基本规则与进阶用法

      • 基本规则

        • 语法规则

          
          target1 [target2 ...]: [pre-req-1 pre-req-2 ...]
          
              [command1
          
              command2
          
              ......]
          
          
        • 例子

          
          all: hello.exe
          
          
          
          hello.exe: hello.o
          
              gcc -o hello.exe hello.o
          
          
          
          hello.o: hello.c
          
              gcc -c hello.c
          
              
          
          clean:
          
              rm hello.o hello.exe
          
          
        • 规则讲解

          • target是文件名或者是一个命令

            • 作为文件名出现时,它会出现在另外的pre-req部分,作为一个前置条件来被调用,整个过程是递归的,调用的方法是:如果target代表的这个文件不存在的话,就会考察前置条件是否存在,前置条件不存在的话,递归调用,寻找其它target是否和这些前置条件匹配;如果前置条件存在的话,就调用command部分的命令,生成target表示的这个文件

            • 作为命令出现时,在make命令的参数中传递进来一个参数,来和target进行匹配,执行make all就会调用all命令,具体的命令含义:all命令表示后面将会根据规则执行整个makefile文件,从而作为整个makefile文件的起始;clean命令表示执行编译完成后的清理工作

          • pre-req-n在冒号的右侧出现,表示执行命令前必须拥有的前置条件,就像if判断语句中的条件一样。这个条件是可以被省略的,表示如果想要生成target中文件不需要任何的前置条件

          • command命令前面必须是一个tab键,表示如果满足条件,就会执行的命令

          • 在这个例子中,调用流程如下:调用make all就会执行all部分的命令,前置条件是hello.exe,前置条件缺失,开始寻找;寻找到target为hello.exe的部分,前置条件是hello.o,前置条件缺失,开始寻找;寻找到target为hello.o的部分,前置条件存在;所以依次执行“gcc -c hello.”"和“gcc -o hello.exe hello.o”

          • 如果执行make clean命令,就会执行“rm hello.o hello.exe”

        • 调用方法

          • make命令会自动寻找makefile文件来执行,这个文件可以被命名为makefile,Makefile或者是GNUMakefile

          • make默认表示执行make all,执行文件中的all部分

          • make clean表示执行makefile文件中的clean部分

      • 进阶知识

        • 注释以#开头

        • 可以使用\来隔断太长的命令

        • [6]中给出了一个可以解决makefile每条命令单独执行的方法,尤其是在cd到某个目录执行的情况下

        • 在之前规则讲解部分,所说的寻找前置条件是否存在的过程中,和文件生成的时间也有一定的关系,下面详细讲解:

          • 只有在前置条件的生成日期比target文件的生成日期更加晚的情况下,才会运行command部分的命令来更新target文件

          • 但是如果target表示一个命令,那么就不考虑时间的问题,在满足前置条件的情况下,一定会执行这个命令。

        • makefile文件中可以采用变量进一步简化

          • 变量的定义是采用“文件名=内容”

          • 变量的引用采用“$(变量名)”

          • 可以采用一些特殊的变量

            • $@: target文件名

            • $*: 不加后缀名的target文件名

            • $<: 前置条件中的第一个文件名

            • $^: 去除掉重复的文件名后,用空格分割的前置条件文件名,

            • $+: 和$^相似,但是包含重复的文件名

            • $?: 生成日期比target更近的,用空格分割的前置条件文件名

          • 采用变量重写之前的示例

            
            all: hello.exe
            
            
            
            # $@ matches the target; $< matches the first dependent
            
            hello.exe: hello.o
            
                gcc -o $@ $<
            
            
            
            hello.o: hello.c
            
                gcc -c $<
            
                
            
            clean:
            
                rm hello.o hello.exe
            
            
        • 系统环境变量

          • VPATH

            • 指定文件夹,用来寻找依赖文件和targets,文件夹用逗号分隔

            • 例子

              
              VPATH = src include
              
              
          • vpath

            • 指定文件夹和目标文件的类型,用来寻找依赖文件和targets,文件夹用逗号分隔

              
              vpath %.c src
              
              vpath %.h include
              
              
        • 规则匹配

          • 规则匹配是另一种写makefile的方式,结合了变量,环境变量和%通配符匹配的方式,比基本规则中讲解的方法更为方便,也是我们在实际的makefile中经常见到的一种模式

          • %通配符:匹配不包含后缀的文件名

          • makefile文件示例

            • 示例

              
              # A sample Makefile
              
              # This Makefile demonstrates and explains 
              
              # Make Macros, Macro Expansions,
              
              # Rules, Targets, Dependencies, Commands, Goals
              
              # Artificial Targets, Pattern Rule, Dependency Rule.
              
              
              
              # Comments start with a # and go to the end of the line.
              
              
              
              # Here is a simple Make Macro.
              
              LINK_TARGET = test_me.exe
              
              
              
              # Here is a Make Macro that uses the backslash to extend to multiple lines.
              
              OBJS =  \
              
               Test1.o \
              
               Test2.o \
              
               Main.o
              
              
              
              # Here is a Make Macro defined by two Macro Expansions.
              
              # A Macro Expansion may be treated as a textual replacement of the Make Macro.
              
              # Macro Expansions are introduced with $ and enclosed in (parentheses).
              
              REBUILDABLES = $(OBJS) $(LINK_TARGET)
              
              
              
              # Here is a simple Rule (used for "cleaning" your build environment).
              
              # It has a Target named "clean" (left of the colon ":" on the first line),
              
              # no Dependencies (right of the colon),
              
              # and two Commands (indented by tabs on the lines that follow).
              
              # The space before the colon is not required but added here for clarity.
              
              clean : 
              
                rm -f $(REBUILDABLES)
              
                echo Clean done
              
              
              
              # There are two standard Targets your Makefile should probably have:
              
              # "all" and "clean", because they are often command-line Goals.
              
              # Also, these are both typically Artificial Targets, because they don't typically
              
              # correspond to real files named "all" or "clean".  
              
              
              
              # The rule for "all" is used to incrementally build your system.
              
              # It does this by expressing a dependency on the results of that system,
              
              # which in turn have their own rules and dependencies.
              
              all : $(LINK_TARGET)
              
                echo All done
              
              
              
              # There is no required order to the list of rules as they appear in the Makefile.
              
              # Make will build its own dependency tree and only execute each rule only once
              
              # its dependencies' rules have been executed successfully.
              
              
              
              # Here is a Rule that uses some built-in Make Macros in its command:
              
              # $@ expands to the rule's target, in this case "test_me.exe".
              
              # $^ expands to the rule's dependencies, in this case the three files
              
              # main.o, test1.o, and  test2.o.
              
              $(LINK_TARGET) : $(OBJS)
              
                g++ -g -o $@ $^
              
              
              
              # Here is a Pattern Rule, often used for compile-line.
              
              # It says how to create a file with a .o suffix, given a file with a .cpp suffix.
              
              # The rule's command uses some built-in Make Macros:
              
              # $@ for the pattern-matched target
              
              # $< for the pattern-matched dependency
              
              %.o : %.cpp
              
                g++ -g -o $@ -c $<
              
              
              
              # These are Dependency Rules, which are rules without any command.
              
              # Dependency Rules indicate that if any file to the right of the colon changes,
              
              # the target to the left of the colon should be considered out-of-date.
              
              # The commands for making an out-of-date target up-to-date may be found elsewhere
              
              # (in this case, by the Pattern Rule above).
              
              # Dependency Rules are often used to capture header file dependencies.
              
              Main.o : Main.h Test1.h Test2.h
              
              Test1.o : Test1.h Test2.h
              
              Test2.o : Test2.h
              
              
              
              # Alternatively to manually capturing dependencies, several automated
              
              # dependency generators exist.  Here is one possibility (commented out)...
              
              # %.dep : %.cpp
              
              #   g++ -M $(FLAGS) $< > $@
              
              # include $(OBJS:.o=.dep)
              
              
            • 讲解

              • 定义环境变量(宏)

                • 定义LINK_TARGET,目标的执行文件

                • 定义OBJS,中间生成的文件

                • 定义REBUILDABLES,是可以重新定义的文件

              • 规则

                • clean是用来清理环境中的文件

                • all是用来编译目标文件

                • $(LINK_TARGET)是来生成exe文件

                • 接着用%通配符来匹配文件名,生成.o文件

                • 然后是一些依赖规则,可以用来检测.o文件是否过时,依赖规则需要很精确的写法

                  • 这里首先补充一下依赖规则是如何起作用的[4]

上一篇:嵌入式学习


下一篇:Makefile c与c++多后缀自动推导