zoukankan      html  css  js  c++  java
  • 如何写一个makefile

    最近因为编译需求,需要更改一些编译条件,顺带看了一些Makefile相关的知识,介绍的很详细,但是例子很少,拆分的比较零碎。初学的话,确实有点压力,我还是喜欢直接在原有的基础上改一些东西,然后遇到问题再进行查找。

    GCC := gcc
    GXX := g++
    
    SRC_DIR := source
    OUT_DIR := build
    
    ##依赖的头文件目录
    INC_DIR := /usr/include
    INC_DIR += ./include 
    
    ##依赖的库文件目录
    LIB_DIR := /usr/lib/debug/linux_x32/lib
    LIB_DIR += /usr/lib/debug/linux_x64/lib
    
    ##遍历头文件目录中的每一个文件
    CFLAGS  := $(foreach a, $(INC_DIR), -I$(a))
    
    ##遍历库文件目录中的每一个库
    LDFLAGS := $(foreach a, $(LIB_DIR), -L$(a))
    
    ##OBJ(.o)文件名称
    OBJS :=  mcmerge.o
    
    ##遍历编译出来的OBJ(.o)文件
    FINAL_OBJS := $(foreach obj, $(OBJS), $(OUT_DIR)/$(obj))
    
    ##列举所需要的库文件
    LIBS := yuv 
            imageunit_linux 
            imf 
            intlc 
             videomanage_linux 
            svml
            
    ##组装成所需要的LDFALGS
    LDFLAGS += $(foreach lib, $(LIBS), -l$(lib))
    
    ##所需要的编译条件
    CFLAGS += -DMERGE_MCMERGE -DMCMERGE_DEBUG -fPIC
    
    ##目标文件
    TARGET := libmerge_x64.so
    
    all:$(TARGET)
    
    $(TARGET):$(FINAL_OBJS)
        $(GXX) -shared -std=c++11 -fPIC -m64 -g -D_DEBUG -DNDEBUG -o $@ $^ $(LDFLAGS)
    
    $(OUT_DIR)/%.o:$(SRC_DIR)/%.cpp
        @test -d $(OUT_DIR) || mkdir -p $(OUT_DIR)
        $(GXX) -g -c $<  -o $@ $(CFLAGS) -fpermissive
    
    $(OUT_DIR)/%.o:$(SRC_DIR)/%.c
        @test -d $(OUT_DIR) || mkdir -p $(OUT_DIR)
        $(GCC) -g -c $<  -o $@ $(CFLAGS) -fpermissive
    
    .PHONY:clean
    clean:
        rm -rf $(OUT_DIR)/*.o $(TARGET)

    模板中涉及到的一些东西都添加了注释,需要使用的时候,只需要对地址,库名称进行更改即可,以及一些编译条件的更改。

    下面对于一些这两天不太明白的地方进行注解。

    1. CFLAGS(cp http://blog.chinaunix.net/uid-31387290-id-5778675.html)

    使用gcc编译阶段,最常用的编译选项CFLAGS = -Wall -Werror -g -O0的解释:
    -Wall:编译阶段显示所有警告。
    -Werror:将所有的警告当成错误进行处理,使出现警告时就停止编译。
            常见编译报错:cc1: warnings being treated as errors 。解决方法是:把-Werror去掉,不把warnning当作error处理。
    -g:编译器在编译时,产生调试信息,最终产生供gdb调试使用的可执行文件。用了-g选项生成的a.out会比没用-g选项生成的a.out明显大点。
    -O0:编译器的优化选项的4个级别
        -O0:表示编译时没有优化。
        -O1:表示编译时使用默认优化。
        -O2:表示编译时使用二级优化。
        -O3:表示编译时使用最高级优化。
        -Os:相当于-O2.5优化,但又不所见代码尺寸。见:Optimization in GCC

    2.  .PHONY的作用(cp https://www.cnblogs.com/idorax/p/9306528.html)

    伪造的,假的。意思就是:clean是个假target,我不想生成这个target,但是我还想执行下面的语句。白嫖呗~

    .PHONY:clean
    clean:
        rm -rf $(OUT_DIR)/*.o $(TARGET)

    3. gcc和g++的区别(cp http://www.cnblogs.com/samewang/p/4774180.html)

    什么是gcc / g++

    首先说明:gcc 和 GCC 是两个不同的东西

    GCC:GNU Compiler Collection(GUN 编译器集合),它可以编译C、C++、JAV、Fortran、Pascal、Object-C、Ada等语言。

    gcc是GCC中的GUN C Compiler(C 编译器)

    g++是GCC中的GUN C++ Compiler(C++编译器)

    一个有趣的事实就是,就本质而言,gcc和g++并不是编译器,也不是编译器的集合,它们只是一种驱动器,根据参数中要编译的文件的类型,调用对应的GUN编译器而已,比如,用gcc编译一个c文件的话,会有以下几个步骤:

    Step1:Call a preprocessor, like cpp.

    Step2:Call an actual compiler, like cc or cc1.

    Step3:Call an assembler, like as.

    Step4:Call a linker, like ld

    由于编译器是可以更换的,所以gcc不仅仅可以编译C文件

    所以,更准确的说法是:gcc调用了C compiler,而g++调用了C++ compiler

    gcc和g++的主要区别

    ①. 对于 *.c和*.cpp文件,gcc分别当做c和cpp文件编译(c和cpp的语法强度是不一样的)

    ②. 对于 *.c和*.cpp文件,g++则统一当做cpp文件编译

    ③. 使用g++编译文件时,g++会自动链接标准库STL,而gcc不会自动链接STL

    ④. gcc在编译C文件时,可使用的预定义宏是比较少的

    ⑤. gcc在编译cpp文件时/g++在编译c文件和cpp文件时(这时候gcc和g++调用的都是cpp文件的编译器),会加入一些额外的宏

    ⑥. 在用gcc编译c++文件时,为了能够使用STL,需要加参数 –lstdc++ ,但这并不代表 gcc –lstdc++ 和 g++等价

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

    还有各种的编译条件,有待 后续遇到问题之后,根据相关问题进行解决。

  • 相关阅读:
    C#集合类型——Array、ArrayList、List 之浅谈
    C#反射(二)
    ASP.Net内置对象之网页之间传参(二)
    ASP.Net内置对象之网页之间传参(一)
    MyEclipse中设置智能提示
    常用Java片段
    ue中替换行
    正确的计算耗时
    JAVA之GUI编程ACTION事件
    JAVA之GUI编程窗体事件
  • 原文地址:https://www.cnblogs.com/whutao/p/10438590.html
Copyright © 2011-2022 走看看