zoukankan      html  css  js  c++  java
  • Linux学习:Makefile简介及模板

    一、基本概念介绍:

       Makefile 文件就是告诉make命令需要怎么样的去编译和链接程序。
      编写Makefile的基本规则:
      1.如果这个工程没有编译过,那么我们的所有C文件都要编译并被链接。
      
    2.如果这个工程的某几个C文件被修改,那么我们只编译被修改的C文件,并链接目标程序。
      3.如果这个工程的头文件被改变了,那么我们需要编译引用了这几个头文件的C文件,并链接目标程序。

      $@--目标文件,$^--所有的依赖文件,$<--第一个依赖文件。

    1 直观方式

     举个例子:一个工程有3个头文件,和8个C文件,根据规则编写Makefile如下:

    edit : main.o kbd.o command.o display.o insert.o search.o files.o utils.o
           cc -o edit main.o kbd.o command.o display.o insert.o search.o files.o utils.o

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

    kbd.o : kbd.c defs.h command.h
           cc -c kbd.c

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

    display.o : display.c defs.h buffer.h
           cc -c display.c

    insert.o : insert.c defs.h buffer.h
           cc -c insert.c

    search.o : search.c defs.h buffer.h
           cc -c search.c

    files.o : files.c defs.h buffer.h command.h
           cc -c files.c

    utils.o : utils.c defs.h
           cc -c utils.c
    clean :
           rm edit main.o kbd.o command.o display.o insert.o search.o files.o utils.o

      在这个makefile中,目标文件(target)包含:可执行文件 edit 和 中间目标文件(*.o),依赖文件(prerequisites)就是冒号后面的那些 .c 文件和 .h文件。每一个 .o 文件都有一组依赖文件,而这些 .o 文件又是执行文件 edit 的依赖文件。

      输入make指令后的执行内容如下:

    1.   make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
    2.   如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“edit”这个文件,并把这个文件作为最终的目标文件。
    3.   如果edit文件不存在,或是edit所依赖的后面的 .o 文件的文件修改时间要比edit这个文件新,那么,他就会执行后面所定义的命令来生成edit这个文件。
    4.   如果edit所依赖的.o文件也存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件。(这有点像一个堆栈的过程)
    5.   当然,C文件和H文件肯定存在,于是make会生成 .o 文件,然后再用 .o 文件声明make的终极任务,也就是执行文件edit了。

     

    1.1 进阶1:使用变量 

     在上面的例子中,可以看到[.o]文件的字符串被重复了两次,如果工程需要加入一个新的[.o]文件,需要在各个依赖了该[.o]文件的地方添加,如果工程比较复杂会很麻烦,所以为了makefile的易维护,在makefile中可以使用变量。
     比如,声明一个变量叫objects,也就叫 OBJECTS, objs, OBJS, obj, 或是 OBJ,只要能够表示obj文件就行。在makefile一开始就这样定义:

    objects = main.o kbd.o command.o display.o insert.o search.o files.o utils.o

     于是,在makefile中以“$(objects)”的方式来使用这个变量了。
     进阶版本1:

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

     于是如果有新的 .o 文件加入,只需添加到 objects 变量中即可。

    1.2 进阶2:让make自动推导

     GNU的make很强大,它可以自动推导文件以及文件依赖关系后面的命令,于是我们就没必要去在每一个[.o]文件后都写上类似的命令,只要make看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中,并且 cc -c xx.c 也会被推导出来。
     进阶版本2:

    objects = main.o kbd.o command.o display.o insert.o search.o files.o utils.o
    
    edit : $(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)

     这种方法,也就是make的“隐晦规则”。上面文件内容中,“.PHONY”表示,clean是个伪目标文件。

        即然make可以自动推导命令,那堆[.o]和[.h]的依赖同样可以收拢起来。进阶2.1:

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

      上面2.1的版本使makefile变得更简单,但文件依赖关系就显得有点凌乱,鱼和熊掌不可兼得,各取所好。

    清空目标文件的规则

       每个Makefile中都应该写一个清空目标文件(.o和执行文件)的规则,这不仅便于重编译,也很利于保持文件的清洁。一般的风格都是:
    clean:
      rm edit $(objects)

     更为稳健的做法是:

    .PHONY : clean
    clean :
         -rm edit $(objects)

     前面说过,.PHONY意思表示clean是一个“伪目标”,不声明伪目标的话,如果当前目录有个名为clean的文件,就会认为目标已存在,导致后面规则不执行了。而在rm命令前面加了一个小减号的意思就是,也许某些文件出现问题,但不要管,继续做后面的事。

     

    二、模板:

    1、编译动态库

        #############################################################   
        # Makefile for shared library.  
        # 编译动态链接库  
        #############################################################  
        #set your own environment option  
        CC = g++  
        CC_FLAG = -D_NOMNG -D_FILELINE  
          
        #set your inc and lib  
        INC =   
        LIB = -lpthread -L./ -lsvrtool  
          
        #make target lib and relevant obj   
        PRG = libsvrtool.so  
        OBJ = Log.o  
          
        #all target  
        all:$(PRG)  
          
        $(PRG):$(OBJ)  
            $(CC) -shared -o $@ $(OBJ) $(LIB)  
          
        .SUFFIXES: .c .o .cpp  
        .cpp.o:  
            $(CC) $(CC_FLAG) $(INC) -c $*.cpp -o $*.o  
          
        .PRONY:clean  
        clean:  
            @echo "Removing linked and compiled files......;  
            rm -f $(OBJ) $(PRG)  

    2、编译静态库

        #############################################################  
        # Makefile for static library.  
        # 编译静态链接库  
        #############################################################  
        #set your own environment option  
        CC = g++  
        CC_FLAG = -D_NOMNG -D_FILELINE  
          
        #static library use 'ar' command   
        AR = ar  
          
        #set your inc and lib  
        INC =   
        LIB = -lpthread -L./ -lsvrtool  
          
        #make target lib and relevant obj   
        PRG = libsvrtool.a  
        OBJ = Log.o  
          
        #all target  
        all:$(PRG)  
        $(PRG):$(OBJ)  
            ${AR} rv ${PRG} $?  
          
        .SUFFIXES: .c .o .cpp  
        .cpp.o:  
            $(CC) $(CC_FLAG) $(INC) -c $*.cpp -o $*.o  
          
        .PRONY:clean  
        clean:  
            @echo "Removing linked and compiled files......"  
            rm -f $(OBJ) $(PRG)  

    3、可执行程序

        ###########################################  
        #Makefile for simple programs  
        ###########################################  
        INC=  
        LIB= -lpthread  
          
        CC=CC  
        CC_FLAG=-Wall  
          
        PRG=threadpooltest  
        OBJ=CThreadManage.o CThreadPool.o CThread.o CWorkerThread.o threadpooltest.o  
          
        $(PRG):$(OBJ)  
            $(CC) $(INC) $(LIB) -o $@ $(OBJ)  
              
        .SUFFIXES: .c .o .cpp  
        .cpp.o:  
            $(CC) $(CC_FLAG) $(INC) -c $*.cpp -o $*.o  
          
        .PRONY:clean  
        clean:  
            @echo "Removing linked and compiled files......"  
            rm -f $(OBJ) $(PRG)  
  • 相关阅读:
    oracle常用hint的用法
    浅谈reverse函数与django哲学
    javascript console
    python os.path模块
    删除列表元素
    Python模块学习 pickle, cPickle 对象序列化/反序列化
    Python中zip()函数用法举例
    Python 字符串方法详解
    常用正则验证
    python中下划线的用法
  • 原文地址:https://www.cnblogs.com/blogs-of-lxl/p/11244008.html
Copyright © 2011-2022 走看看