linux 編譯 c或cpp 文件爲動態庫 so 文件(最簡單直觀的模板)

把源碼編譯打包爲動態庫so文件,做平臺的可能對這些不熟悉。

對我們這些算是經常用到的。

總結個模板,一看就懂的那種,提供給有需要的人。

前提條件,機器上有 gcc工具鏈。

如果文件個數少,可以直接單個編譯,如下:

Building shared lib...
g++ -c -fPIC  Quote.cpp -o  Quote.o
g++ -c -fPIC  QuoteExport.cpp -o  QuoteExport.o
g++ -c -fPIC  Start.cpp -o  Start.o
Generating shared lib...
g++ -shared -fPIC -o  libQuoteLib.so  ./Quote.o  ./QuoteExport.o  ./Start.o  
cp libQuoteLib.so ../
OK!
 

如果文件個數較多,或者誇文件夾了,層層嵌套。

那麼就整個makefile模板文件,放到代碼的根目錄下,直接執行一個make即可。

模板文件如下:

############################################################################
#makefile,created by yangyongzhen qq:534117529
############################################################################

#****************************************************************************
# Cross complie path
#****************************************************************************
#GCC_PATH=D:\msysgit\mingw

CROSS_COMPILE=


CC     := $(CROSS_COMPILE)gcc
CXX    := $(CROSS_COMPILE)g++
AS	   := $(CROSS_COMPILE)as
AR     := $(CROSS_COMPILE)ar 
LD     := $(CROSS_COMPILE)ld
RANLIB := $(CROSS_COMPILE)ranlib
OBJDUMP:= $(CROSS_COMPILE)objdump
OBJCOPY:= $(CROSS_COMPILE)objcopy
STRIP  := $(CROSS_COMPILE)strip

#****************************************************************************
# Flags
#****************************************************************************

CFLAGS= 
LDSCRIPT= 
LDFLAGS= 


#****************************************************************************
# Source files
#****************************************************************************
SRC_C=$(shell find . -name "*.cpp")

OBJ_C=$(patsubst %.cpp, %.o, $(SRC_C))

SRCS := $(SRC_C) $(SRC_C)

OBJS := $(OBJ_C) 


#****************************************************************************
# Targets of the build
#****************************************************************************
TARGET   	:= libQuoteLib

.PHONY: clean
all:  prebuild  $(TARGET).so

#****************************************************************************
# TARGET
#****************************************************************************
prebuild:
	@echo Building shared lib...

$(TARGET).so : $(OBJS)
	@echo Generating shared lib...
	$(CXX) -shared -fPIC -o  $(TARGET).so $(OBJS) 
	cp $(TARGET).so ../
	@echo OK!

%.o : %.cpp
	$(CXX) -c -fPIC $(CFLAGS) $< -o  $@
	
clean:
	@echo The following files:
	rm  -f  $(TARGET) *.so
	find . -name "*.[od]" |xargs rm
	@echo Removed!

注:在linux上,源文件的函數或方法前,不需要聲明 __declspec(dllexport)
在WIn32上才需要。

所以在頭文件中一般會看到:

#ifdef _WIN32
#define TAP_CDECL  __cdecl
#define TAP_DLLEXPORT __declspec(dllexport)
#else
#define TAP_CDECL
#define TAP_DLLEXPORT
#endif

__cdecl 是C Declaration的縮寫(declaration,聲明),表示C語言默認的函數調用方法:所有參數從右到左依次入棧,這些參數由調用者清除,稱爲手動清棧。

被調用函數不會要求調用者傳遞多少參數,調用者傳遞過多或者過少的參數,甚至完全不同的參數都不會產生編譯階段的錯誤。

_stdcall 是StandardCall的縮寫,是C++的標準調用方式:所有參數從右到左依次入棧,如果是調用類成員的話,最後一個入棧的是this指針。這些堆棧中的參數由被調用的函數在返回後清除,使用的指令是 retnX,X表示參數佔用的字節數,CPU在ret之後自動彈出X個字節的堆棧空間。稱爲自動清棧。函數在編譯的時候就必須確定參數個數,並且調用者必須嚴格的控制參數的生成,不能多,不能少,否則返回後會出錯。

C中不加說明默認函數爲_cdecl方式(C中也只能用這種方式),C++也一樣,但是默認的調用方式可以在IDE環境中設置。

帶有可變參數的函數必須且只能使用_cdecl方式

__cdecl __fastcall與__stdcall,三者都是調用約定(Calling convention),它決定以下內容:1)函數參數的壓棧順序,2)由調用者還是被調用者把參數彈出棧,3)以及產生函數修飾名的方法。

1、__stdcall調用約定:函數的參數自右向左通過棧傳遞,被調用的函數在返回前清理傳送參數的內存棧。

2、__cdecl是C和C++程序的缺省調用方式。每一個調用它的函數都包含清空堆棧的代碼,所以產生的可執行文件大小會比調用_stdcall函數的大。函數採用從右到左的壓棧方式。注意:對於可變參數的成員函數,始終使用__cdecl的轉換方式。

3、__fastcall調用約定:它是通過寄存器來傳送參數的(實際上,它用ECX和EDX傳送前兩個雙字(DWORD)或更小的參數,剩下的參數仍舊自右向左壓棧傳送,被調用的函數在返回前清理傳送參數的內存棧)。

4、thiscall僅僅應用於"C++"成員函數。this指針存放於CX寄存器,參數從右到左壓。thiscall不是關鍵詞,因此不能被程序員指定。

5、nakedcall採用1-4的調用約定時,如果必要的話,進入函數時編譯器會產生代碼來保存ESI,EDI,EBX,EBP寄存器,退出函數時則產生代碼恢復這些寄存器的內容。naked call不產生這樣的代碼。naked call不是類型修飾符,故必須和_declspec共同使用。

關於__declspec的解釋,轉自:CSDN博主「fengbingchun」

原文鏈接:https://blog.csdn.net/fengbingchun/article/details/78825004

__declspec是Microsoft VC中專用的關鍵字,它配合着一些屬性可以對標準C/C++進行擴充。__declspec關鍵字應該出現在聲明的前面。

__declspec(dllexport)用於Windows中的動態庫中,聲明導出函數、類、對象等供外面調用,省略給出.def文件。即將函數、類等聲明爲導出函數,供其它程序調用,作爲動態庫的對外接口函數、類等。

.def文件(模塊定義文件)是包含一個或多個描述各種DLL屬性的Module語句的文本文件。.def文件或__declspec(dllexport)都是將公共符號導入到應用程序或從DLL導出函數。如果不提供__declspec(dllexport)導出DLL函數,則DLL需要提供.def文件。

__declspec(dllimport)用於Windows中,從別的動態庫中聲明導入函數、類、對象等供本動態庫或exe文件使用。當你需要使用DLL中的函數時,往往不需要顯示地導入函數,編譯器可自動完成。

不使用__declspec(dllimport)也能正確編譯代碼,但使用__declspec(dllimport)使編譯器可以生成更好的代碼。編譯器之所以能夠生成更好的代碼,是因爲它可以確定函數是否存在於DLL中,這使得編譯器可以生成跳過間接尋址級別的代碼,而這些代碼通常會出現在跨DLL邊界的函數調用中。聲明一個導入函數,是說這個函數是從別的DLL導入。一般用於使用某個DLL的exe中。
--------------------- 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章