zoukankan      html  css  js  c++  java
  • 【C编程基础】make命令和makefile文件

    1.关于程序的编译和链接

    一般来说,无论是C、C++首先要把源文件编译成中间目标文件即 Object File(windows为.obj文件,unix为.o文件),这个动作叫做编译(compile)。然后再把大量的Object File合成执行文件,这个动作叫作链接(link)。

    1.1编译

    编译时编译器只检查语法是否正确,函数与变量的声明是否正确。如果函数未被声明,编译器会给出一个警告,但可以生成Object File。一般来说,每个源文件都应该对应于一个中间目标文件(O文件或是OBJ文件)。

    cc -c foobar.c         ==>将源文件编译但不链接,成目标文件foobar.o
    cc foobar.c -o foobar ==>将源文件编译并链接,生成可执行文件foobar

    1.2链接

    链接时主要是链接函数和全局变量。链接器会在所有的Object File中找寻函数的实现,如果找不到,那到就会报链接错误码(Linker Error)。

    cc -o foobar foobar.c  ==>链接生成可执行文件foobar

    1.3自定义函数库(打包中间目标文件)ar命令

    如果需要链接中间目标文件太多,链接时需要明显地指出所有中间目标文件名,十分不便。可以给中间目标文件打个包,在Windows下这种包叫“库文件”(Library File),也就是 .lib 文件,在UNIX下,是Archive File,也就是 .a 文件静态库。

    PS:我们可以使用中间目标文件(O文件或是OBJ文件)或静态库文件来链接我们的应用程序。

    ar crv libtest.a *.o  ==>将该目录下的所有目标文件打包生成了libtest.a文件静态库

    2.make命令

    make是一个命令工具,是一个解释Makefile中指令的命令工具。在命令行输入make命令后,会查找当前目录下的Makefile文件来执行,根据Makefile文件编译源代码生成中间目标文件、链接后生成可执行文件。

    一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。使用示例(其中all、install和clean均为Makefile文件中定义的伪目标):

    make          ==>默认找到Makefile中第一个目标,进行编译链接
    make
    all make clean

    3.Makefile文件

    make命令执行时,需要一个 Makefile 文件,告诉make命令需要怎么样的去编译和链接程序。Makefile带来的好处就是“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。

    Makefile中除了编译链接目标外,还可以使用伪目标。通常情况下,为了规范和统一,会参考Linux源码的Makefile规则来书写我们的Makefile中的伪目标,这些伪目标都是GNU开源软件定义和采用的。

    “all”—— 这个伪目标是所有目标的目标,其功能一般是编译所有的目标。
    “clean” —— 这个伪目标功能是删除所有被make创建的文件。
    “install” —— 这个伪目标功能是安装已编译好的程序,其实就是把目标执行文件拷贝到指定的目标中去。
    “print” —— 这个伪目标的功能是例出改变过的源文件。
    “tar” —— 这个伪目标功能是把源程序打包备份。也就是一个tar文件。
    “dist” —— 这个伪目标功能是创建一个压缩文件,一般是把tar文件压成Z文件,或是gz文件。
    “TAGS” —— 这个伪目标功能是更新所有的目标,以备完整地重编译使用。
    “check”和“test” —— 这两个伪目标一般用来测试makefile的流程。

    3.1 Makefile规则

    target... : prerequisites ...
              command
              ...

     target:是一个目标,可以是目标文件Object File,也可以是执行文件,还可以是一个标签(伪目标)。

    prerequisites:是要生成那个target所需要的文件或目标。

    command:也就是make需要执行的命令(任意的Shell命令,一定要以Tab键开头)

    3.2 Makefile规则示例

    仅做编译:main.o是我们的第一个目标,main.c和defs.h是目标所依赖的源文件,而执行命令为“cc -c main.c”

    编译链接:main是我们的第二个目标,main.c和defs.h是目标所依赖的源文件,而执行命令为“cc  main.c -o main”

    main.o : main.c defs.h 
            cc -c -o main.o main.c 
    main: main.c defs.h
            cc main.c -o main

     3.3 Makefile规则示例(自动推导)

    GNU的make很强大,它可以自动推导依赖c文件以及编译命令。以main.c为例

    仅做编译:make看到一个[main.o]目标,它会自动的把[main.c]文件加在依赖关系中,并自动推导出cc -c -o  main.o main.c

    编译链接:make看到一个[main]目标,它会自动把[main.c]文件加在依赖关系中,并自动推导出cc  main.c -o main

    Makefile中如下定义

    main.o: defs.h
    main: defs.h

    等同于

    main.o : main.c defs.h 
            cc -c -o main.o main.c 
    main: main.c defs.h
            cc main.c -o main

    3.4 清空目标文件规则示例

    每个Makefile中都应该写一个清空目标文件(执行文件和.o目标文件)的规则,这不仅便于重编译,也很利于保持文件的清洁。规矩:使用clean伪目标,且永远放在Makefile文件的最后

    目标:清理可执行文件main和目标文件mian.o

    一般常用写法:

    clean :
          rm main main.o

    更健壮写法:

    .PHONY : clean
    clean :
          -rm main main.o 

    .PHONY表示clean是一个“伪目标”。在rm命令前面加了一个小减号,标识忽略文件出现的问题,继续执行。

    3.5 Makefile变量定义示例

    目标:生成可执行文件main,引用多个目标文件

    objects = main.o kbd.o 
    insert.o search.o files.o utils.o main: $(objects)
    cc -o main $(objects)

    定义变量objects后,引用变量使用$(objects) 。.反斜杠()是换行符的意思,这样比较便于Makefile的易读。

    3.6 Makefile经典示例

    目标:一个工程包含有3个头文件和8个C文件,需要编译链接成可执行文件edit。

    objects = main.o kbd.o command.o display.o 
                 insert.o search.o files.o utils.o
    .PHONY : all all: $(objects)
    cc -o edit $(objects) main.o : defs.h kbd.o : defs.h command.h command.o : defs.h command.h display.o : defs.h buffer.h insert.o : defs.h buffer.h search.o : defs.h buffer.h files.o : defs.h buffer.h command.h utils.o : defs.h .PHONY : clean clean : -rm edit $(objects)

    3.7 测试使用源文件main.c

    #include <stdio.h>
    int main(void)
    {
        printf("Hello world/n");
        return 0;
    }

     

    参考文档:

    make all、make clean、make install 等命令的来源

    Makefile经典教程

    Linux 如何使用GCC编译器将一个文件夹下的100个.o文件打包成一个静态库文件(.a)

    cc,gcc命令解释

    gcc的使用简介与命令行参数说明

  • 相关阅读:
    hdu4277 暴力
    hdu4271 Find Black Hand 2012长春网络赛E题 最短编辑距离
    poj3356 字符串的最小编辑距离 dp
    HDU4267 A Simple Problem with Integers 线段树/树状数组
    树链剖分 模版
    SPOJ375 Query on a tree 树链剖分
    Orz_panda cup I题 (xdoj1117) 状压dp
    27号的十道离线线段树
    The 2015 "Orz Panda" Cup Programming Contest
    codeforces #274 C. Riding in a Lift dp+前缀和优化
  • 原文地址:https://www.cnblogs.com/badboy200800/p/9928458.html
Copyright © 2011-2022 走看看