[英]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.o
, Schedule.o
, Duration.o
和DayCount.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.