簡體   English   中英

Makefile建立共享庫

[英]Makefile to build shared library

我一直在構建C++11庫,並且頭文件/源文件的數量已經增長到編譯調用它的程序的程度,這需要將20多個.cpp文件傳遞給g++ 我一直在閱讀共享庫,這似乎是最好的解決方案。

但是,由於頭文件/源文件經常更改,因此我希望創建一個makefile ,該makefile將自動從頭文件和源文件生成所有.so文件。

為了更好地演示我要執行的操作,我將使用我的一個子庫Chrono並演示如何手動執行此操作。

我首先像這樣創建目標文件,

$ g++ -std=c++11 -fPIC -g -c -Wall ../src/Chrono/cpp/DateTime.cpp
$ g++ -std=c++11 -fPIC -g -c -Wall ../src/Chrono/cpp/Schedule.cpp
$ g++ -std=c++11 -fPIC -g -c -Wall ../src/Chrono/cpp/Duration.cpp
$ g++ -std=c++11 -fPIC -g -c -Wall ../src/Chrono/cpp/DayCount.cpp

這樣,我現在在當前目錄中就有DateTime.oSchedule.oDuration.oDayCount.o 然后,我創建.so文件,

$ g++ -shared -Wl,-soname,libChrono.so.1 -o libChrono.so.1.0.1 DateTime.o Schedule.o Duration.o DayCount.o -lc

然后我去

$ rm ./*.o && ldconfig -n ./

現在,我的工作目錄包含libChrono.so.1.0.1和符號鏈接libChrono.so.1

我需要為此執行很多子目錄,因此您可以看到,只要對標頭/源進行了更改,它就會迅速變得效率低下。 如果有人可以幫助我設計一個只需通過調用make即可完成所有這些工作的makefile,我將不勝感激。

謝謝!

更新:

根據goldilock的建議和一些挖掘,我設法做到了:

CXX=g++
CFLAGS=-std=c++11 
TARGET=./lib/libChrono.so.1.0.1
CHRONODIR=./src/Chrono
CHRONOSRC=$(wildcard $(CHRONODIR)/cpp/*.cpp)
CHRONOOBJ=$(join $(addsuffix ../obj/,  $(dir $(CHRONOSRC))), $(notdir (CHRONOSRC:.cpp=.o)))

all: $(TARGET)
    @true

clean:
    @-rm -f $(TARGET) $(CHRONOOBJ)

./lib/libChrono.so.1.0.1: $(CHRONOOBJ)
    @echo "======================="
    @echo "Creating library file $@"
    @echo "======================="
    @$(CXX) -shared -Wl,-soname,$(join $(basename $@), .1) -o $@ $^ -l
    @echo "-- $@ file created --"

$(CHRONODIR)/cpp/../obj/%.o : $(CHRONOSRC)
    @mkdir -p $(dir $@)
    @echo "============="
    @echo "Compiling $<"
    @$(CXX) $(CFLAGS) -fPIC -g -Wall -c $< -o $@

4 .o文件在lib/中生成,但是我從ld收到多個定義投訴。 在我分別編譯目標文件之前,但這將CHRONOOBJ展開為一行。 有任何想法嗎?

幸運的是,您包括了問題的根源:

我一直在構建C ++ 11庫,並且頭文件/源文件的數量已經增長到編譯調用它的程序的程度,這需要將20多個.cpp文件傳遞給g ++。

因為這揭示了潛在的XY問題 對此的直接解決方案是將目標文件放入歸檔文件(也稱為靜態庫)中並使用它。

GNU make具有創建C ++ .o文件的隱式規則 它等於:

%.o: %.cpp
    $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $<

也就是說,如果你make DateTime.o與生成文件的目錄中未重新定義這一點,就會使DateTime.o 您可能想將內容添加到$(CXXFLAGS)中,例如:

CXXFLAGS += -Wall -Wextra --std=c++11

如果您打算使用共享庫路由,則-fPIC也可以到那里。 那一行可能是您的整個makefile。

但是,您還希望將它們放在一起,因此必須首先聲明所有對象和組合它們的規則:

OBJS = DateTime.o Schedule.o Duration.o

libChrono.a: $(OBJS)
    ar crvs $@ $^

最后一行(請參閱man ar )創建包含$(OBJS)中所有對象的檔案$(OBJS) 然后,可以通過將其放在相同目錄(或庫路徑中的目錄)中並鏈接-lChrono ,將其與任何程序一起使用。 僅提取和編譯必要的部分。這省去了在系統目錄中維護共享庫的麻煩。

如果仍然認為需要共享庫,則$@$^自動變量 您可以使用類似的方法來創建.so ,類似於以下內容:

SO_FLAGS = -shared

libChrono.so.1.0.1: $(OBJS)
    $(CXX) $(SO_FLAGS) -Wl,-soname,libChrono.so.1 -o $@ $^ -lc

如果這是您的第一條規則, make會處理所有事情:首先構建對象,然后構建庫。 請注意,這一行已排除了您正常的$(CXXFLAGS)來從問題中完全復制編譯器行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM