GNU make使用(一)


[時間:2017-01] [狀態:Self]
[關鍵詞:makefile,gcc,編譯,動態庫,靜態庫,可執行文件,shell命令]

引言

前段時間在Linux下編寫一個可測試的程序發現,我對makefile實踐太少各種別扭吧。因此參考網上的一篇文章,自己嘗試下常用的可執行文件、靜態庫、動態庫的自動編譯,以及調用,作為后續開發的參考。
本文主要包括三部分:

  • 可執行文件的Makefile
  • 靜態庫*.a的Makefile
  • 動態庫*.b的Makefile

這是我對Makefile學習總結的第二篇文章,其他的可參考GNU make簡介

本文主要參考,感謝@竹林聽雨的分享。
在Linux下編譯時常用的命令有:

  • make : 編譯整個工程
  • make install : 輸出編譯之后的結果,可能是系統目錄,也可能是自定義目錄
  • make clean : 清除編譯過程中的中間文件,比如.o,.s等
  • make distclean : 恢復編譯前的環境,注意本文中使用make veryclean

1. 可執行文件的Makefile

代碼如下:

#源文件,自動找所有.c和.cpp文件,並將目標定義為同名.o文件
SOURCE  := $(wildcard *.c) $(wildcard *.cpp)
OBJS    := $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCE)))

#目標文件名,輸入任意你想要的執行文件名
TARGET  := exe_check

#編譯參數
CC      := g++
LIBS    :=
LDFLAGS :=
DEFINES :=
INCLUDE := -I.
CFLAGS  := -g -Wall -O3 $(DEFINES) $(INCLUDE)
CXXFLAGS:= $(CFLAGS) -DHAVE_CONFIG_H

#下面的基本上不需要做任何改動了
.PHONY : everything objs clean veryclean rebuild

everything : $(TARGET)

all : $(TARGET)

objs : $(OBJS)

rebuild: veryclean everything

clean :
	rm -fr *.so
	rm -fr *.o

veryclean : clean
	rm -fr $(TARGET)
#這里是實際完成編譯的命令
$(TARGET) : $(OBJS)
	$(CC) $(CXXFLAGS) -o $@ $(OBJS) $(LDFLAGS) $(LIBS)

如果你是直接拷貝這個makefile的話,麻煩檢查下上面的shell命令前空白必須是Tab鍵,不能是空格。

2. 靜態庫的Makefile和調用示例

Makefile文件如下,主要使用ar/ranlib打包命令:

#共享庫文件名,lib*.a
TARGET  := libtest.a

#編譯參數
CC      := g++
AR      = ar
RANLIB  = ranlib
LIBS    :=
LDFLAGS :=
DEFINES :=
INCLUDE := -I.
CFLAGS  := -g -Wall -O3 $(DEFINES) $(INCLUDE)
CXXFLAGS:= $(CFLAGS) -DHAVE_CONFIG_H

#下面的基本上不需要做任何改動了

#源文件,自動找所有.c和.cpp文件,並將目標定義為同名.o文件
SOURCE  := $(wildcard *.c) $(wildcard *.cpp)
OBJS    := $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCE)))
#頭文件,自動查找.h文件
HEADER := $(wildcard *.h)

.PHONY : everything objs clean veryclean rebuild install

everything : $(TARGET)

all : $(TARGET)

objs : $(OBJS)

rebuild: veryclean everything
             
clean :
	rm -fr *.o

veryclean : clean
	rm -fr $(TARGET)

install :
	test -f ./sample/lib && echo ' ' || mkdir ./sample/lib
	cp $(TARGET) ./sample/lib/
	test -f ./sample/include/ && echo ' ' || mkdir ./sample/include
	cp $(HEADER) ./sample/include/

$(TARGET) : $(OBJS)
	$(AR) cru $(TARGET) $(OBJS)
	$(RANLIB) $(TARGET)

由於一般動態庫或者靜態庫需要安裝,這里添見了install標簽。

調用靜態庫的話,需要使用下面makefile,這里僅給出相對可執行文件的makefile差別,如下:

#compile and lib parameter
#編譯參數
CC      := g++
LIBS    := -ltest
LDFLAGS := -L./lib/
DEFINES :=
INCLUDE := -I. -I./include
CFLAGS  := -g -Wall -O3 $(DEFINES) $(INCLUDE)
CXXFLAGS:= $(CFLAGS) -DHAVE_CONFIG_H

主要加入了靜態庫所在的目錄及-l命令。

3. 動態庫的Makefile及調用示例

Makefile如下,直接調用g++編譯成動態庫:

#共享庫文件名,lib*.so
TARGET  := libtest.so

#編譯參數
CC      := g++
LIBS    :=
LDFLAGS :=
DEFINES :=
INCLUDE := -I.
CFLAGS  := -g -Wall -O3 $(DEFINES) $(INCLUDE)
CXXFLAGS:= $(CFLAGS) -DHAVE_CONFIG_H
SHARE   := -fpic -shared -o
  

#下面的基本上不需要做任何改動了

#源文件,自動找所有.c和.cpp文件,並將目標定義為同名.o文件
SOURCE  := $(wildcard *.c) $(wildcard *.cpp)
OBJS    := $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCE)))
#頭文件,自動查找.h文件
HEADER := $(wildcard *.h)

.PHONY : everything objs clean veryclean rebuild install

everything : $(TARGET)

all : $(TARGET)

objs : $(OBJS)
	$(CC) -c -fPIC $(SOURCE)

rebuild: veryclean everything
         
clean :
	rm -fr *.o
    
veryclean : clean
	rm -fr $(TARGET)

install :
	test -d ./sample/lib && echo ' ' || mkdir ./sample/lib
	cp $(TARGET) ./sample/lib/
	test -d ./sample/include/ && echo ' ' || mkdir ./sample/include
	cp $(HEADER) ./sample/include/

$(TARGET) : objs
	$(CC) $(CXXFLAGS) $(SHARE) $@ $(OBJS) $(LDFLAGS) $(LIBS)

這里就是需要關注下-fPIC-fpic的不同使用位置,否則可能會出現編譯錯誤。
調用動態庫的示例代碼的Makefile跟可執行文件的主要區別如下:

#目標文件名,輸入任意你想要的執行文件名
TARGET  := shared_check

#編譯參數
CC      := g++
LIBS    := -ltest
LDFLAGS := -L./lib/
DEFINES :=
INCLUDE := -I. -I./include
CFLAGS  := -g -Wall -O3 $(DEFINES) $(INCLUDE)
CXXFLAGS:= $(CFLAGS) -DHAVE_CONFIG_H

4. 小結

簡單整理完了,直接看Makefile確實不是很難,但是其中涉及比較多的shell命令,比如wild、test、patsubst以及gcc編譯指令,這方面有待加強。
不做實際驗證才不會明白其中有各種坑的。簡單過一遍GNU Makefile還是很有幫助的。

本文所有涉及的Makefile及源碼可以從我的git下載,url:https://git.oschina.net/Tocy/SampleCode.git。相關文件位於makefile-template文件夾下。


免責聲明!

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



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