GCC 64位程序的makefile條件編譯心得——32位版與64位版、debug版與release版(兼容MinGW、TDM-GCC)


作者: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


源碼下載——
http://files.cnblogs.com/zyl910/gcc64_make.rar


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM