以后沒啥好圖蒸辆,封面就上小姐姐圖了
這次書接上回耻卡,前段時間寫了一篇《使用cmake構(gòu)建C/C++項目和動態(tài)庫》的文章,傳送門。但是直接通過cmake編譯鏈接后穆碎,會有一個問題瑟啃,那就是需要的.so文件不能更改目錄论泛,一旦.so文件目錄變了,整個程序就沒法運行了,這肯定是不行的蛹屿。
原因
后來我查一下一下屁奏,linux系統(tǒng)中,程序加載運行需要的.so文件是有順序的
- 環(huán)境變量LD_LIBRARY_PATH指定的路徑
- gcc 編譯時指定的運行時庫路徑-rpath
- ldconfig 配置文件ld.so.conf指定的路徑
- 系統(tǒng)默認庫位置 /lib, /usr/lib
如果沒有指定so的位置错负,gcc會自動把當前so所在的目錄作為so的連接目錄坟瓢。知道原因了,問題就好解決了
解決辦法
先看一下現(xiàn)在的 CMakeLists.txt文件
cmake_minimum_required(VERSION 3.13.3)
project(project1 C)
set(CMAKE_C_STANDARD 99)
add_library(shared SHARED library.h library.c)
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
add_executable(project1 main.c)
target_link_libraries(project1 shared)
我實驗了兩種辦法犹撒,一是把.so 文件放到/lib
或者 /usr/lib
中折联,這也是在安裝很多軟件時的做法,當使用包管理器安裝軟件時识颊,需要的.so文件大多是安裝到這兩個目錄下诚镰。在一種就是在編譯時指定 rpath
的目錄,使用相對目錄,這樣在復(fù)制文件的時候怕享,把.so一起復(fù)制就可以了执赡。
先用最簡單的辦法,把so目錄放到系統(tǒng)目錄下
現(xiàn)在的目錄結(jié)構(gòu)如下函筋,程序依賴的libshared.so 在 lib 目錄下沙合,現(xiàn)在把 libshared.so 復(fù)制到 /lib 目錄下。這里有個要注意的地方跌帐,復(fù)制完后要執(zhí)行 ldconfig
命令首懈,重新生成緩存,要不然程序依然找不到對應(yīng)的.so文件
命令如下
sudo mv lib/libshared.so /lib
sudo ldconfig
這時候在運行 project1 不會報錯
編譯時指定 rpath目錄
設(shè)置 rpaht 有兩種方式
方式1
set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_INSTALL_RPATH $ORIGIN)
通過修改編譯后的 install 路徑, 讓程序在運行時通過程序的相對目錄加載.so文件谨敛,其中 $ORIGIN 變量是程序的當前目錄
方式2
set_target_properties(project1 PROPERTIES LINK_FLAGS "-Wl,-rpath,./")
方式2更粗暴究履,直接設(shè)置gcc的編譯參數(shù),指定rpaht 是當前目錄
修改 CMakeLists.txt文件
cmake_minimum_required(VERSION 3.13.3)
project(project1 C)
set(CMAKE_C_STANDARD 99)
add_library(shared SHARED library.h library.c)
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
#方式1
set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_INSTALL_RPATH $ORIGIN)
add_executable(project1 main.c)
#方式2
#set_target_properties(project1 PROPERTIES LINK_FLAGS "-Wl,-rpath,./")
target_link_libraries(project1 shared)
重新生成 MakeFile 文件, 然后編譯
編譯生成的 libshared.so 還是在 lib目錄下脸狸,先移動到可執(zhí)行文件的同級目錄下
最終目錄如圖最仑,現(xiàn)在無論怎么復(fù)制文件,只要可執(zhí)行文件和動態(tài)庫在一個目錄下炊甲,都以運行了
總結(jié)
解決linux下 動態(tài)編譯的程序找不到動態(tài)庫的問題泥彤,有多種解決辦法,這次用了兩種
- 把需要的.so文件放到 /lib 或者 /usr/lib 下卿啡, 然后執(zhí)行
ldconfig
命令 - 通過指定 rpath 來決定加載 .so的目錄