1. 程式人生 > 其它 >C++_動態連結庫和搜尋共享庫

C++_動態連結庫和搜尋共享庫

標準

1998	C++98
2011	C++11  ISO/IEC 14882:2011	
2014	C++14
2017	C++17
2020	ISO C++ 委員會正式釋出了C++20 標準,命名為 ISO/IEC 14882:2020		

實現

01.命令檢視自己的g++編譯器預設的c++版本
   g++ -dM -E -x c++  /dev/null | grep -F __cplusplus
02.g++命令編譯cpp檔案的時候其實也可以指定c++標準,例如直接指定C++17的標準  相比於正常的命令只是多了一個命令列引數-std=c++17  
	g++ -std=c++17 test.cpp -o test.o
03.系統的g++有哪些
    ls /usr/bin/ |grep g++	
	
04切換版本--gcc和g++同時切換
   檢視當前的gcc/g++是否是通過update-alternatives管理的,檢視其連結方式
       ll /usr/bin/gcc*
       ll /usr/bin/g++*
	直接連結的
  # 切換gcc的版本
  sudo update-alternatives --config gcc
  
  # 切換g++的版本
  sudo update-alternatives --config g++	

動態庫

製作-生成連結庫	  
使用連結庫
搜尋連結庫
   "Linux下的庫有動態與靜態兩種,
   動態通常用.so為字尾,靜態用.a為字尾
   Windows 下.DLL是動態連結庫, .LIB是靜態連結庫
   動態庫與靜態庫的區別動態庫個編譯好的程式,程式執行時可以直接呼叫其中的函式, 不參加工程的編譯.
   而靜態庫應該說是一個程式集, 只是把一些相應的函式總結在一起, 如果呼叫靜態庫中的函式,
   在編譯時,這些呼叫的函式都將參加編譯靜態庫必要的目的碼的是在對程式編譯的時候被加入到程式中,
   而執行時不再需要.a的庫了而動態庫,則是在執行時轉載從記憶體管理的角度來看。">	

共享搜尋庫

  01.預設情況下, /etc/ld.so.conf  檔案中包含有預設的共享庫搜尋路徑
       /etc/ld.so.conf.d/
  02.第二種,通過LD_LIBRARY_PATH環境變數
   可以通過在.bashrc或者.cshrc中配置該環境變數,
     LD_LIBRARY_PATH的意思是告訴loader在哪些目錄中可以找到共享庫. 可以設定多個搜尋目錄, 這些目錄之間用冒號分隔
  03.,通過編譯選項-Wl, -rpath指定動態搜尋的路徑 -Wl選項告訴編譯器將後面的引數傳遞給連結器。
  
 具體解釋:
  01. ldd  list-dynamic-dependencies 命令檢視可執行程式的連結庫
     ldd 不會列出依賴樹,如果想要依賴樹,用 lddtree(apt install pax-utils)
	    ldd 未必會顯示所有依賴的庫(不包含用 ldopen() 函式直接從程式碼中載入的,因為很有可能會根據使用者輸入來載入,無法預判)
     ldd可以列出一個程式所需要得動態連結庫(so)
	 “=>” 左邊 表示該程式需要連線的共享庫之 so 名稱,
	 “=>” 右邊 表示由 Linux 的共享庫系統找到的對應的共享庫在檔案系統中的具體位置
	可執行模組的dependency的工作原理,其實質是通過ld-linux.so(elf動態庫的裝載器)來實現
	ld-linux.so.2是glibc的庫檔案,一般連結到相應版本的ld-xxx.so上,是和動態庫載入有關的函式
	通過動態編譯連結的,當一個 需要動態連結 的應用被作業系統載入時,系統必須要 定位 然後 載入它所需要的所有動態庫檔案。 
	在Linux環境下,這項工作是由ld-linux.so.2來負責完成的,
   
   ld-linux.so.2 man page給我們更高一層的全域性介紹, 它是在 連結器(通常是ld)在執行狀態下的部件,
   用來定位和載入動態庫到應用的執行地址(或者是執行記憶體)當中去。
   
   ldconfig 命令的用途, 主要是在預設搜尋目錄(/lib和/usr/lib)以及動態庫配置檔案/etc/ld.so.conf內所列的目錄下
   :ldconfig,配置檔案目錄:/etc/ld.so.conf.d,配置檔案在/etc/ld.so.conf內容由使用者編輯,緩衝檔案/etc/ld.so.cache
   
 02.-Wl pass comma-separated to the linker  
   
   執行時動態庫 not found。即使在使用-L和-l引數使得成功編譯,在執行時仍然可能會找不到庫,因為執行時庫的搜尋路徑可能並沒有包含-L的目錄。
   第一種方法:找到缺少的動態庫(由於編譯和連結時候的使用到了這個動態庫,所以很容易找得到),將其加到/lib,/usr/lib中的一個資料夾下,這幾個資料夾是系統預設的搜尋路徑。將庫檔案放置在其中,執行時就可以搜尋到了( /lib  /usr/lib )。
   第二種方法:設定臨時增加連結動態庫的路徑;export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:[your lib]
   第三種方法:/etc/ld.so.cache中快取了動態庫路徑,可以通過修改配置檔案/etc/ld.so.conf中指定的動態庫搜尋路徑,然後執行ldconfig命令來改變。
   第四種方法:在連結時語句後面新增如下命令:-Wl,-rpath=[your lib] 。其中-WI是gcc引數,-rpath是ld引數
       (從 GCC5.4 左右開始)-Wl,-rpath 設定的變為 runpath 而不是 rpath.二者唯一區別在於動態庫搜尋路徑順序.一般並不推薦使用 rpath.

製作-生成動態連結庫

g++ 生成動態連結庫
 
CMake如何生成動態連結庫檔案
  CMakeLists.txt
    SET(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/lib)
    ADD_LIBRARY(filename SHARED ${CURRENT_SOURCES} ${CURRENT_INCLUDE})
    執行完成之後可以在庫檔案的輸出目錄看到libfilename.so檔案。
配置階段解析所有的輸入變數,並存儲在CMakeCache.txt這個檔案。這個階段解決了使用者構建一個專案需要依賴的各種輸入引數
解析器使用了lex/yacc 語法解析器-antlr4 ,執行構建動作-解析器Parser生成。解析器的匹配器找到各種token
    CMake找到標頭檔案, include_directories(/home/include
	     找到庫檔案   link_directories
		 連結庫檔案   target_link_libraries
		生成
           add_library	  指定的原始檔生成連結檔案
		       SHARED庫會被動態連結(動態連結庫),在執行時會被載入。MODULE庫是一種不會被連結到其它目標中的外掛,但是可能會在執行時使用dlopen-系列的函式
           add_executable			   

使用動態連結庫

 .a 檔案是 static library, 在編譯的時候一起編入可執行檔案
   -o 的作用是給生成的可執行檔案命名, -L 的作用是宣告 .a 所在的目錄, -l 是指明所用的 .a 檔案,
  
gcc/g++來連結的時候一樣,要使用 -L 來指定第三方庫所在路徑。
     cmake可以使用  LINK_DIRECTORIES 命令來指定第三方庫所在路徑	


find_package 和 find_library 指令可以得到庫檔案的絕對路徑

動態庫的新增:
  link_directories(${PROJECT_SOURCE_DIR}/lib) #新增動態連線庫的路徑
  target_link_libraries(project_name -lmxnet ) #新增libmxnet.so
  
  
  靜態庫的新增:
  add_library(mxnet STATIC IMPORTED)
  set_property(TARGET mxnet PROPERTY IMPORTED_LOCATION /path/to/libmxnet.a)
  target_link_libraries(project_name mxnet ) #新增libmxnet.a

其他

ln 命令用於給檔案建立連結,根據 Linux 系統儲存檔案的特點,連結的方式分為以下 2 種:軟連線和硬連結	
   s:建立軟連結檔案。如果不加 "-s" 選項,則建立硬連結檔案;
   許可權位中"l"表示這是一個軟連結檔案;其次,在檔案的後面通過 "->" 顯示出原始檔的完整名字。所以軟連結比硬連結的標誌要明顯得多
 ll

python的搜尋路徑和pip

 Python  where python
 PYTHONPATH 是Python中一個重要的環境變數,用於在匯入模組的時候搜尋路徑,通過訪問Pythonpath可以看到,
  路徑列表的第一個元素為空字串,代表的是相對路徑下的當前目錄
  搜尋路徑
  PYTHONPATH 是 python查詢模組和包的路徑,每匯入一個模組,python直譯器將依次在PYTHONPATH 下尋找
  可以通過 sys.path 來檢視 PYTHONPATH 的具體內容
     1、新增環境變數 PYTHONPATH,python會新增此路徑下的模組,在.bash_profile檔案中新增如下類似行:
      export PYTHONPATH=$PYTHONPATH:/usr/local/lib/python3.7/site-packages
     2、在site-packages路徑下新增一個路徑配置檔案,檔案的副檔名為.pth,內容為要新增的路徑即可
         如果本來python就沒有新增上site-packages目錄,那第二個方法其實也是用不了的。
     3、sys.path.append()函式新增搜尋路徑,引數值即為要新增的路徑。
       import sys
       sys.path.append('/Users/username/Documents/')	 
 pip 安裝路徑
     apt-get install -y pip-python3       (python3.x就去安裝pip3)
       pip list   (2) pip freeze 第二種還會顯示出庫的版本號和路徑
	 
   升級pip--已有pip的前提下
    線上的方式

    離線的方式
      01.下載wheel  https://pypi.org/project/pip/#files
	  02.上傳到離線的jiqi
	  03.執行 pip install
	  
安裝open3d遇到的問題
   pip 安裝open3d,不要安裝open3d-python  python版本與open3d匹配問題
   pip版本問題-升級pip版本 pip版本和python匹配問題
      open官網查詢得知, 3.6 3.7 3.8 3.9版本的python支援open3d
	  
環境變數	說明
  PYTHONSTARTUP	在互動式啟動時執行的檔案(無預設值)
  PYTHONPATH	‘:’ - 以預設模組搜尋路徑為字首的分隔目錄列表。結果是sys.path。
  PYTHONHOME	交替的 <prefix> 目錄 (或者 <prefix>:<exec_prefix>). 預設的模組搜尋路徑為 <prefix>/pythonX.X.
  PYTHONCASEOK	忽略import語句中的大小寫(Windows)。
  PYTHONIOENCODING	用於 stdin/stdout/stderr 中的編碼
  PYTHONHASHSEED	如果此變數設定為random,則效果與-R選項相同:使用一個隨機值為str,bytes和datetime物件的雜湊值設定種子。它也可以設定為 [0, 4294967295] 範圍內的整數,以獲得具有可預測種子的雜湊值。

參考

https://github.com/cplusplus/draft/tree/c++20