小型C/C++項目的makefile編寫


【前言】在我所接觸到的Linux嵌入式開發中,大多使用的是C語言,采用makefile文件對源文件進行編譯后生成可執行文件。本文即從個人經歷上介紹小型的C項目如何編寫makefile文檔。

一、gcc命令

從目的上看,gcc命令和makefile的功能是一樣,即是把源文件編譯后生成可執行文件或.o二進制文件。gcc命令中有許多的額外的參數,本文僅介紹以下幾種最簡單和常用的方法:

有helloworld.c文件如下:

#include <stdio.h>
int main()
{
        printf("helloworld!\n");
        return 0;
}

使用如下gcc命令,將在同一文件目錄下生成a.out可執行文件,在terminal中運行該文件即可在屏幕中打印出helloworld!:

$  gcc helloworld.c

使用如下gcc命令,將在同一文件目錄下生成helloworld.o二進制文件,它可以被用來連接文件:

$    gcc -c helloworld.c

如果要生成特定名稱的可執行文件,可以使用如下gcc命令,它將生成helloworld可執行文件,區別於a.out可執行文件,在termianl執行它可以打印出helloworld!:

$    gcc helloworld.c -o helloworld

以上三種gcc命令,主要區別是參數不同,-c和-o的區別在於,-c只編譯不連接,故只生成.o的二進制文件,-o即指定名稱輸出可執行文件。對於單個或者幾個的源文件,使用gcc命令即可,但是一旦文件具有依賴關系,gcc命令的執行順序是需要規定的,否則無法順序編譯項目,這是gcc命令的缺點,而makefile區別於gcc命令的地方正在於它能規定好文件間的依賴關系,以及加入依賴的庫文件和頭文件。

如果要引用其它目錄下的頭文件,其gcc命令如下,采用-I的參數:

$    gcc -I /ycl/include/ helloworld.c -o helloworld

如果要引用其它的目錄下的庫文件,如libmlib.so,其gcc命令如下,采用-L的參數:

$    gcc -L /ycl/lib –lmlib helloworld.c -o helloworld

 

二、makefile簡要語法

makefile的用處是告訴編輯器,本項目以怎樣的規則進行編譯和鏈接,運行make命令需要makfile文件作為支撐。

要弄明白makefile,其關鍵是理解它的核心語法(源自博文http://blog.csdn.net/liang13664759/article/details/1771246 ):

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

target也就是一個目標文件,可以是Object File,也可以是執行文件。還可以是一個標簽(Label),對於標簽這種特性,在后續的“偽目標”章節中會有敘述。

prerequisites就是,要生成那個target所需要的文件或是目標。

command也就是make需要執行的命令。(任意的Shell命令)

這是一個文件的依賴關系,也就是說,target這一個或多個的目標文件依賴於prerequisites中的文件,其生成規則定義在command中。說白一點就是說,prerequisites中如果有一個以上的文件比target文件要新的話,command所定義的命令就會被執行。這就是Makefile的規則。也就是Makefile中最核心的內容。

示例代碼如下:

CXX = g++

CXXFLAGS =    -O2 -g -Wall -fmessage-length=0
CFLAGS = `pkg-config --cflags lcm`
LDFLAGS=`pkg-config --libs lcm`\
        -lpthread

OBJS =        DSRC_module.o    \
            LCMHandler.o    \
            UDPHandler.o

TARGET =    DSRC_module
$(TARGET):    $(OBJS)
    $(CXX) -o $@ $^ $(LDFLAGS)

 DSRC_module.o: DSRC_module.cpp
    $(CXX) $(CFLAGS) -I. -o $@ -c $<

  LCMHandler.o: LCMHandler.cpp
    $(CXX) $(CFLAGS) -I. -o $@ -c $<

  UDPHandler.o: UDPHandler.cpp
    $(CXX) $(CFLAGS) -I. -o $@ -c $<

  all: $(TARGET)

  clean:
    rm -f $(OBJS) $(TARGET)

示例代碼中出現了變量,makefile中變量采用$(變量)的方法使用,如$(TARGET)即表示DSRC_module。該makefile的目的是生成名為DSRC_ module的可執行文件,即$(TARGET),它的依賴文件是$(OBJS)所代表的DSRC_module.o、LCMHandler.o、UDPHandler.o三個文件。由於這三個文件都未生成,故針對每一個文件都需要進行編譯生成,所以有三個.o文件為目標的makefile語句。

文中特殊字符說明如下:$@--目標文件,$^--所有的依賴文件,$<--第一個依賴文件。比如在如下的代碼中,$@代表DSRC_module.cpp,$<代表第一個依賴文件,也就是DSRC_module.cpp。

DSRC_module.o: DSRC_module.cpp 
    $(CXX) $(CFLAGS) -I. -o $@ -c $<

三、makefile編寫

使用裝用CDT插件的eclipse可以直接生成helloworld項目的makefile項目,makefile內容如下:

CXXFLAGS =    -O2 -g -Wall -fmessage-length=0

OBJS =        example.o

LIBS =

TARGET =    example

$(TARGET):    $(OBJS)
    $(CXX) -o $(TARGET) $(OBJS) $(LIBS)

all:    $(TARGET)

clean:
    rm -f $(OBJS) $(TARGET)

其中CXXFLAGS是編譯參數變量,CXX是makefile內置變量,CXX默認表示g++(C++編譯器)。這個makefile的有兩個功能:①編譯代碼,將example.c編譯成example.o並鏈接成example可執行文件;②清除項目,當項目需要重新編譯或整理時,使用make clean命令即可清除生的OBJS和TARGET變量中的名稱。

在上述代碼中,之所以依賴文件沒有.c文件,這是因為此處使用了makefile的自動推導功能,只要依賴關系中有.o文件,它會自動添加同名稱的.c文件作為依賴文件,並由$(CXX) -o example.o可以自動推導出$(CXX) -o example.c。

$(TARGET):    $(OBJS)
    $(CXX) -o $(TARGET) $(OBJS) $(LIBS)

基於上述的makefile文件,如果此時需要添加新的.c和.h文件,則改變OBJS的內容即可,比如填加test.c文件,則代碼如下(注意test.o前的不能加空格,需用tab鍵):

CXXFLAGS =    -O2 -g -Wall -fmessage-length=0

OBJS =        example.o\
                   test.o

LIBS =

TARGET =    example

$(TARGET):    $(OBJS)
    $(CXX) -o $(TARGET) $(OBJS) $(LIBS)

all:    $(TARGET)

clean:
    rm -f $(OBJS) $(TARGET)    

如果需要添加頭文件,那么注意盡量不要使用makefile的自動推導功能,否則可能找不到頭文件,則只需添加和修改如下代碼:

CXXFLAGS =    -O2 -g -Wall -fmessage-length=0

OBJS = example.cpp\ test.cpp 
HEADER_DIR = -I/home/duser/dot3 

LIBS = TARGET = example $(TARGET): $(OBJS) $(CXX) -o $(TARGET) $(OBJS) $(LIBS) all: $(TARGET) clean: rm -f $(TARGET)
$(TARGET):    $(OBJS)
    $(CXX) $(HEADER_DIR) $(OBJS) -o $(TARGET)  $(LIBS)

如果需要添加庫文件,需要兩個變量,LDFLAGS---相當於庫所在路徑,LIBS---要鏈接的庫文件。則只需添加和修改如下代碼:

LDFLAGS += -L/lib
LIB += -ltest
$(TARGET):    $(OBJS)
$(CXX) $(HEADER_DIR) $(OBJS) -o $(TARGET)  $(LIBS) $(LDFLGS)$(LIBS)

     


免責聲明!

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



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