利用makefile構建c++項目的思路介紹


入門介紹

  起因是我在工作中,遇到了一個多個執行文件打包成的組件,而每個執行文件都需要將pb編進二進制中,導致release包非常大。所以想到,是否應該將pb編程動態鏈接庫,再供可執行文件使用呢?達成這個目的需要做兩件事。1、將pb編成.so文件。2、將原本的鏈接方式改為動態鏈接。

  makefile是make構建項目所需要的規則文件。通產在其中指定了編譯目標、編譯指令、編譯依賴。通常的makefile被命名為“Makefile”“makefile”,但也可以通過make -f filename去指定非標准命名的makefile,以適應不同的項目需求。

生成目標文件

通常我們想要的目標文件分為三種,可執行文件(a.out),.a文件(靜態鏈接庫),.so(動態鏈接庫)。

許多人都清楚怎樣處理一個單純的main.cpp,g++ main.cpp即可。執行完畢后同級目錄下會出現a.out。a.out代表着g++編譯並鏈接得到的可執行文件。如果不喜歡a.out這個默認名稱,通常使用g++ -o hello hello.cpp這樣的命令。可能有人會不清楚,g++ -o hello hello.cpp 和 g++ hello.cpp -o hello有什么區別呢?畢竟很多人百度g++,無非也只是想得到一個確切能用的命令而已,不了解也不奇怪。-o的意思是 指定了了g++的輸出目標,所以寫在哪里都可以。

g++的常用選項:https://www.cnblogs.com/lidan/archive/2011/05/25/2239517.html

初學者需了解-o -g -static -fPIC -D等常用參數。

makefile說到底還是像腳本一樣執行了g++命令,想要利用makefile構建c++項目,會使用g++命令就是第一步。

 

makefile基礎語法:https://www.cnblogs.com/wang_yb/p/3990952.html

一個常見簡單的makefile文件通常長這樣:
$(target):*.o
        $(CXX) $(CXXFLAGS) -o $@ $^
 
    %.o:%.cpp
        $(CXX) $(CXXFLAGS) -o $@ $<

             
make會從上至下尋找第一個編譯目標。如果將target:*.o挪到文件的最下方,那執行make后,也只能得到一堆.o文件,而無法得到target。
有時候目標文件不止一個,這個時候就要使用all來指定多個target。
在文件上方添加: all:$(target) $(target2)
 
all:$(target) $(target2)
    $(target):*.o
        $(CXX) $(CXXFLAGS) -o $@ $^
    $(target2):*.o
        $(CXX) $(CXXFLAGS) -o $@ $^
    %.o:%.cpp
        $(CXX) $(CXXFLAGS) -o $@ $<    
 
target和target2是最終的目標文件,但我們為make指定的目的文件是"all",target和target2其實是"all"的依賴。
 
如果目標是一個/多個普通的可執行文件,CXXFLAGS="-g",如果目標需要鏈接動態鏈接庫,CXXFLAGS="-g -fPIC"
如果目標是一個動態鏈接庫,CXXFLAGS="-g -shared"
如果目標是一個靜態鏈接庫,生成target的指令就不是cxx而是ar
all:$(target) $(target2)
    $(target):*.o
        ar -cvr $@ $^
    $(target2):*.o
        $(CXX) $(CXXFLAGS) -o $@ $^
    %.o:%.cpp
        $(CXX) $(CXXFLAGS) -o $@ $<    

鏈接動態鏈接庫

如果目標僅僅是生成可執行文件,那么上一步已經完成了。但是我的目標是生成動態鏈接庫並用可執行文件去鏈接它,已達到節省空間的目的。

g++的-l與-L分別指定了動態鏈接庫和鏈接庫所在的地址。如 g++ -o hello hello.cpp -luuid -L/usr/lib

除此之外,也可以在代碼中指定要使用的動態鏈接庫。dlopen了解一下。

編譯成功后,接下來就是運行的問題了。ldconfig命令可以幫助我們知道,這台機器上動態鏈接庫的地址有哪些。想要成功運行連接了動態鏈接庫的可執行文件,方法有四種。

1、將動態鏈接庫直接丟進ldconfig包含的路徑中。

2、將動態鏈接庫丟到自定義的目錄中,與系統自帶的庫分開,並將自定義目錄加入到/etc/ld.so.conf文件中

3、如果是daemon進程,在start腳本中export LD_LIBARY_PATH也是個辦法

4、使用g++的rpath指令指定庫的路徑。
3、4是簡單易用的辦法,推薦新手使用。
 

結語

本文只介紹了構建項目的大體思路,並未給出具體的命令與說明。如果需要更詳細的說明,不妨百度/google我給出的關鍵詞or看看我貼出的兩篇文章。

 


免責聲明!

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



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