• GCC 64位程序的makefile条件编译心得——32位版与64位版、debug版与release版(兼容MinGW、TDMGCC)


    作者:zyl910

      为了适应现在越来越流行的64位系统,经常需要将代码分别编译为32位版和64位版。其次,除了需要生成debug版用于开发测试外,还需要生成release版用于发布。本文介绍了如何利用makefile条件编译来生成这些版本,而且不仅兼容Linux下的GCC,还支持MinGW、TDM-GCC等Windows下的GCC编译器。


    一、C程序代码

      为了测试条件编译的效果,以下面这个C语言程序为例(gcc64_make.c)——

    #include <stdio.h>
    #include <assert.h>
    
    // 获取程序位数(被编译为多少位的代码)
    int GetProgramBits()
    {
        return sizeof(int*) * 8;
    }
    
    int main(int argc, char* argv[])
    {
        printf("bits:\t%d\n", GetProgramBits());
        assert( argc>1 );
        return 0;
    }

      main函数中,前两条语句的含义为——
    第一条语句用于显示当前程序的位数。如果编译为32位版,将会显示“bits: 32”;如果编译为64位版,将会显示“bits: 64”。
    第二条语句是一条断言,需要argc变量大于1。如果编译为debug版,若运行时未加命令参数,该断言失败,于是输出错误信息并终止程序;如果编译为release版,所有断言被屏蔽,不会有错误信息。


    二、GCC命令行参数

      复习一下GCC命令行参数,看看各个版本的区别——
    32位版:加上 -m32 参数,生成32位的代码。
    64位版:加上 -m64 参数,生成64位的代码。
    debug版:加上 -g 参数,生成调试信息。
    release版:加上 -static 参数,进行静态链接,使程序不再依赖动态库。加上 -O3 参数,进行最快速度优化。加上-DNDEBUG参数,定义NDEBUG宏,屏蔽断言。

      当没有-m32或-m64参数时,一般情况下会生成跟操作系统位数一致的代码,但某些编译器存在例外,例如——
    32位Linux下的GCC,默认是编译为32位代码。
    64位Linux下的GCC,默认是编译为64位代码。
    Window系统下的MinGW,总是编译为32位代码。因为MinGW只支持32位代码。
    Window系统下的MinGW-w64(例如安装了TDM-GCC,选择MinGW-w64),默认是编译为64位代码,包括在32位的Windows系统下。


    三、makefile代码

      makefile的代码为——

    # flags
    CC = gcc
    CFLAGS = -Wall
    LFLAGS = 
    
    # args
    RELEASE =0
    BITS =
    
    # [args] 生成模式. 0代表debug模式, 1代表release模式. make RELEASE=1.
    ifeq ($(RELEASE),0)
        # debug
        CFLAGS += -g
    else
        # release
        CFLAGS += -static -O3 -DNDEBUG
        LFLAGS += -static
    endif
    
    # [args] 程序位数. 32代表32位程序, 64代表64位程序, 其他默认. make BITS=32.
    ifeq ($(BITS),32)
        CFLAGS += -m32
        LFLAGS += -m32
    else
        ifeq ($(BITS),64)
            CFLAGS += -m64
            LFLAGS += -m64
        else
        endif
    endif
    
    
    .PHONY : all clean
    
    # files
    TARGETS = gcc64_make
    OBJS = gcc64_make.o
    
    all : $(TARGETS)
    
    gcc64_make : $(OBJS)
        $(CC) $(LFLAGS) -o $@ $^
    
    
    gcc64_make.o : gcc64_make.c
        $(CC) $(CFLAGS) -c $<
    
    
    clean :
        rm -f $(OBJS) $(TARGETS) $(addsuffix .exe,$(TARGETS))

      为了控制条件编译,定义了RELEASE、BITS这两个变量,分别赋初值。然后用ifeq判断RELEASE、BITS变量的值,分别加上不同的参数。
      因赋有初值,直接执行“make”时,编译得到的是默认位数的debug版。
      若在执行make时给变量赋值,将会得到不同的版本——
    make RELEASE=0:(默认位数的)debug版。
    make RELEASE=1:(默认位数的)release版。
    make BITS=32:32位(的debug)版。
    make BITS=64:64位(的debug)版。
    make RELEASE=0 BITS=32:32位的debug版。
    make RELEASE=0 BITS=64:64位的debug版。
    make RELEASE=1 BITS=32:32位的release版。
    make RELEASE=1 BITS=64:64位的release版。


      该makefile的代码风格是精心设计的,可以很方便的扩展——
    需要增加代码文件或依赖关系时,修改“# files”之后的内容。
    需要调整编译参数时,修改前半部分的参数变量。
    需要增加新的条件编译参数时,在“# args”定义一个变量并赋初值,然后再在后面用“ifeq”判断变量来调整编译参数。

      最后的“rm -f $(OBJS) $(TARGETS) $(addsuffix .exe,$(TARGETS))”是为了兼容MinGW、TDM-GCC等Windows下的GCC编译器而设计的——
    装好MSYS,再配置一下PATH环境变量,Windows中也可以使用rm命令删除文件。
    因Windows下的可执行文件的扩展名是exe,所以使用了addsuffix函数增加“.exe”扩展名。
    因Linux下不会生成.exe可执行文件,而Windows下不会生成无扩展名的可执行文件,导致rm会因找不到文件而报错。这时可以加上-f参数忽略该错误。


    四、测试结果

    4.1 Fedora 17 64位版下的 GCC 4.7.0

      打开终端,使用cd命令进入程序所在目录,并执行以下命令——

    make clean
    make
    ./gcc64_make
    make clean
    make RELEASE=1
    ./gcc64_make
    make clean
    make BITS=32
    ./gcc64_make
    make clean
    make RELEASE=1 BITS=32
    ./gcc64_make
    gcc --version

      运行结果——


    4.2 Windows XP SP3 32位版下的 GCC 4.6.2(MinGW (20120426))

      打开命令提示符,使用cd命令进入程序所在目录,并执行以下命令——

    make clean
    make
    gcc64_make
    make clean
    make RELEASE=1
    gcc64_make
    make clean
    make BITS=64
    gcc --version

      运行结果——


    4.3 Windows 7 SP1 64位版下的 GCC 4.6.1(TDM-GCC (MinGW-w64))

      打开命令提示符,使用cd命令进入程序所在目录,并执行以下命令——

    make clean
    make
    gcc64_make
    make clean
    make RELEASE=1
    gcc64_make
    make clean
    make BITS=32
    gcc64_make
    make clean
    make RELEASE=1 BITS=32
    gcc64_make
    gcc --version

      运行结果——

    参考文献——
    《跟我一起写 Makefile》. 陈皓. http://blog.csdn.net/haoel/article/details/2886
    《Makefile条件编译debug版和release版》. 功夫Panda. http://www.cnblogs.com/caosiyang/archive/2012/06/13/2548051.html
    《assert()函数用法总结》. Glroy. http://www.cnblogs.com/ggzss/archive/2011/08/18/2145017.html
    《Windows版GCC之TDM-GCC 4.5.2》. 单鱼游弋. http://www.cnblogs.com/wxxweb/archive/2011/05/30/2063434.html


    源码下载——
    https://files.cnblogs.com/zyl910/gcc64_make.rar

    作者:zyl910
    版权声明:自由转载-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0.
  • 相关阅读:
    NHibernate之旅(14):探索NHibernate中使用视图
    NHibernate之旅(18):初探代码生成工具使用
    NHibernate之旅(15):探索NHibernate中使用存储过程(上)
    接下来5年中有用的10项开发技能
    NHibernate之旅(22):探索NHibernate一级缓存
    NHibernate之旅(24):探索NHibernate二级缓存(下)
    NHibernate之旅(17):探索NHibernate中使用存储过程(下)
    NHibernate之旅(11):探索多对多关系及其关联查询
    Python入门示例系列18 条件控制
    .NET计划之配置ASP.NET运行环境
  • 原文地址:https://www.cnblogs.com/zyl910/p/gcc64_make.html
Copyright © 2020-2023  润新知