zoukankan      html  css  js  c++  java
  • Makefile之清晰认知

    Makefile之清晰认知

    关于Makefile,之前我在初学makefile依旧没有清晰认知。所以这次,我将着重探究一下Makefile文件的编写。

    0.Makefile是什么

    Makefile可以理解为一个脚本的执行器,也可以理解为一种简单语言

    很多人觉得很神奇,包括我也是,第一次接触makefile,觉得这个东西非常神奇,为什么可以自动编译多文件?

    我们可以简单理解为这个文件可以自动帮你执行一些命令,例如Python也可以帮你做运维,这个就类似于运维中的脚本文件

    1.一般使用

    # This is a standard makefile
    main:main.o module1.o module2.o
    	gcc main.o module1.o module2.o -o main
    main.o:main.c head1.h head2.h common_head.h
    	gcc -c main.c
    module1.o:module1.c head1.h
    	gcc -c module1.c
    module2.o:module2.c head2.h
    	gcc -c module2.c
    

    结构为

    [目标文件列表] [分隔符] [依赖文件列表]
    	[命令]
    

    这个Makefile的HelloWorld其实已经困扰了很多人。困扰的点如下:

    1.为什么gcc编译的时候不需要加头文件?

    答:gcc在编译的时候,只需要进行编译C文件。

    h文件的作用仅起到替换的作用。我们在引入#include <stdlib.h>之后,在预编译的过程中,会将stdlib.h中的声明完全替换到本文件中。

    误解:很多人会将#include以为是引入库,但实际不是,这个命令的作用是在预编译过程中将.h文件进行替换,真正要编译的是C文件。

    证明:我们使用gcc -E main.c试一下,查看预编译后的文件,发现,头文件已经替换到了预编译后的文件中

    编写一个max.h文件

    int max(int a, int b);
    

    编写一个main.c文件

    #include <max.h>
    int main() {
        return 0;
    }
    

    编写一个max.c文件

    int max(int a, int b) {
        return a > b ? a : b;
    }
    

    在Linux下进行gcc -E main.c max.c,输出

    # 1 "t.c"
    # 1 "<built-in>" 1
    # 1 "<built-in>" 3
    # 362 "<built-in>" 3
    # 1 "<command line>" 1
    # 1 "<built-in>" 2
    # 1 "t.c" 2
    # 1 "./max.h" 1
    int max(int a, int b);
    # 2 "t.c" 2
    int main() {
        return 0;
    }
    # 1 "max.c"
    # 1 "<built-in>" 1
    # 1 "<built-in>" 3
    # 362 "<built-in>" 3
    # 1 "<command line>" 1
    # 1 "<built-in>" 2
    # 1 "max.c" 2
    int max(int a, int b) {
        return a > b ? a : b;
    }
    

    在预编译过程中,进行了文件替换,在#include语句完全替换成了h文件中的语句,而在文件末也附加了新的max.c,由此我们可以深刻理解这个过程

    2.gcc -c是什么?

    gcc -c 执行了3步操作

    gcc -E进行预处理,gcc -S进行翻译汇编操作,gcc -c进行编译成链接文件(.o文件)

    3.我们为什么需要倒着写?

    问这个问题的人应该已经发现了,我们是需要倒着进行运行命令的,这个是makefile的规范。

    如果熟悉如何用gcc在命令行进行编译多文件,那么直接进行倒着书写makefile即可。

    makefile在进行寻找的过程中,首先执行第一行,发现需要下面模块,再执行下面的,所以看起来倒着,假设a依赖b,c,d三个独立模块,我们测试进行输出,答案是b,c,d,a,案例:

    # This is a Makefile
      
    main:main.o printXX.o printXXX.o
            gcc main.o printXX.o printXXX.o
            echo "a"
    main.o:main.c printXX.h printXXX.h
            gcc -c main.c
            echo "b"
    printXX.o:printXX.c printXX.h
            gcc -c printXX.c
            echo "c"
    printXXX.o:printXXX.c printXXX.h
            gcc -c printXXX.c
            echo "d"
    
    4.第二行报错?

    实际上gcc前面那个空格是一个tab键,如果你按了2下空格,会使其报错。

    如果你想简单实用makefile,了解到这边,其实已经能够清晰的编写makefile文件了。下面是附加性知识。

    2.语法

    1.变量的定义

    我们在使用过程中,会使用到大量的gcc命令,而实际生产中,我们不一定会用gcc进行编译,常见的有cc,g++,都可以进行编译,如果要进行替换,整篇Makefile都得进行替换,那样会极其不便,所以,我们进行了一个变量替换操作。

    我们来看一个例子:

    CC = gcc
    all:
    	echo $(CC)
    

    我们在头部进行了替换操作。

    2.预定义变量

    all:
            echo $(CC) $(CFLAGS) $(MAKE)
    

    我们的cc含有很多预定义变量,如CC、CFLAGS等,我们可以编写一个这样的文件进行打印

    预定义变量如下:

    • CC 默认的cc命令

    • CFLAGS -o执行

    • MAKE make命令的地址

    • MAKEFLAGS make的选项

    • SHELL 默认shell类型

    • PWD 当前makefile的目录

    • AR 库管理

    • ARFLAGS 库管理选项

    • LIBSUFFIXE 库后缀

    • A 库拓展名

    3.动态改变的变量

    我们在查看Makefile的时候,常常看到$@ $% $< $> $? $^ $+ $*

    • $@ 表示目标文件名,Linux中,一般称.a文件为文档文件,或者静态库文件。
    main: a.c b.h
    	gcc a.c
    

    上述makefile的main就是目标文件名,如果我们在makefile中echo $@,则打印的是main

    所以我们可以进行

    main: a.c b.h
    	gcc a.c -o %@
    
    • $% 静态库的第一个成员名,如果链接的第一个静态库是foo.a,则会打印出来,这边不加演示,都可进行echo打印
    • $< 第一个依赖库名
    • $> 值是库名(适用库文件)
    • $? 所有比目标新的依赖文件列表
    • $^ 规则的所有依赖列表,去除重复文件
    • (+ 可素)^ 保留重复文件
    • $* 目标去除后缀,例如 main.o 这个后缀去掉
    4.条件语句
    ifeq(gcc,$(CC))
    	# 执行编译
    else
    	echo "error"
    endif
    

    条件语句可以根据条件进行编译

    5.定义条件
    ifdef foo
    	echo "YES"
    ifndef foo
    	foo = foo
    

    定义条件,判定是否定义

  • 相关阅读:
    js全局变量
    $.getJSON异步请求和同步请求
    让js中的函数只有一次有效调用
    两个div并排显示,当浏览器界面缩小时会出现换行
    jquery获取窗口和文档的高度和宽度
    后台传带引号(")的数据需要注意
    C# dynamic
    (转)数据库函数解析JSON字符串
    Unicode和UTF-8
    用户通过浏览器修改表单隐藏域
  • 原文地址:https://www.cnblogs.com/littlepage/p/12325651.html
Copyright © 2011-2022 走看看