上一篇我們直接設定庫的導出目錄(LIBRARY_OUTPUT_PATH)到上一層的 lib 資料夾中讓主程式使用,但是實際使用上通常會使用 "install()" 指令來設定安裝規則,將庫和標頭檔安裝到指定路徑或系統目錄上,而且有了安裝規則就可以依此來解除安裝,不用手動去安裝路徑刪除檔案。
定義:生成安裝規則
install(FILES <files_name> DESTINATION )
files_name : 標頭檔或檔案名稱
dir : 將要安裝的路徑
install(TARGETS <targets_name> DESTINATION )
targets_name : 庫名稱
dir : 將要安裝的路徑
定義:GNU 的標準安裝路徑
定義出的變量
${CMAKE_INSTALL_PREFIX} : /usr/local
${CMAKE_INSTALL_BINDIR} : /bin
${CMAKE_INSTALL_INCLUDEDIR} : /include
$ git clone https://github.com/m11112089/2023_iT_CMake.git
$ cd ~/2023_iT_CMake/Day14/範例1在內部安裝
1. 編輯 MathFunctions/CMakeLists.txt
在 MathFunctions/CMakeLists.txt 中設定庫和標頭檔的安裝路徑
install(TARGETS mysqrt DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/../Main/lib)
# 安裝庫到 ~/2023_iT_CMake/Day14/範例1在內部安裝/Main/lib
install(FILES include/mysqrt.h DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/../Main/include)
# 安裝頭文件到 ~/2023_iT_CMake/Day14/範例1在內部安裝/Main/include
2. 進入/MathFunctions/build 資料夾編譯出動態庫文件
$ cd /MathFunctions/build
$ cmake ..
$ make
3. 安裝
因為make只能產生目標文件與安裝規則,所以需要再使用make install將目標文件依照安裝規則安裝至指定位置。
$ make install
執行完指令後可以看到確切的安裝位置訊息。
kai@esoc:~/2023_iT_CMake/Day14/範例1在內部安裝/MathFunctions/build$ make install
[100%] Built target mysqrt
Install the project...
-- Install configuration: ""
-- Up-to-date: /home/kai/2023_iT_CMake/Day14/範例1在內部安裝/MathFunctions/../Main/lib/libmysqrt.so.1.0.0
-- Up-to-date: /home/kai/2023_iT_CMake/Day14/範例1在內部安裝/MathFunctions/../Main/lib/libmysqrt.so.1
-- Up-to-date: /home/kai/2023_iT_CMake/Day14/範例1在內部安裝/MathFunctions/../Main/lib/libmysqrt.so
-- Up-to-date: /home/kai/2023_iT_CMake/Day14/範例1在內部安裝/MathFunctions/../Main/include/mysqrt.h
4. 查看生成出來的檔案
kai@esoc:~/2023_iT_CMake/Day14/範例1在內部安裝/Main$ tree
.
├── build
├── CMakeLists.txt
├── include
│ └── mysqrt.h
├── lib
│ ├── libmysqrt.so -> libmysqrt.so.1
│ ├── libmysqrt.so.1 -> libmysqrt.so.1.0.0
│ └── libmysqrt.so.1.0.0
└── src
└── main.cpp
5. 編譯與執行主專案
$ cd ~/2023_iT_CMake/Day14/範例1在內部安裝/Main/build
$ cmake ..
$ make
$ ./main 100
$ cd ~/2023_iT_CMake/Day14/範例2安裝至系統路徑
根據GNU Coding Standards的規則,使用者通常將標頭檔安裝在/usr/local/include,庫會安裝在/usr/local/bin。
1. 編輯 MathFunctions/CMakeLists.txt
在CMakeLists.txt中設定安裝庫和頭文件的系統路徑,先將GNUInstallDirs引入,再設定安裝路徑。
include(GNUInstallDirs)
# 引入 GNUInstallDirs 變數
install(FILES include/mysqrt.h DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR})
# 安裝庫到 /usr/local/include
install(TARGETS mysqrt DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR})
# 安裝頭文件到 /usr/local/bin
2. 進入/MathFunctions/build 資料夾編譯出動態庫文件
$ cd /MathFunctions/build
$ cmake ..
$ make
3. 安裝
因為是系統路徑,所以需要超級使用者(superuser)權限
$ sudo make install
kai@esoc:~/2023_iT_CMake/Day14/範例2安裝至系統路徑/MathFunctions/build$ sudo make install
[sudo] password for kai:
[100%] Built target mysqrt
Install the project...
-- Install configuration: ""
-- Installing: /usr/local/include/mysqrt.h
-- Installing: /usr/local/bin/libmysqrt.so.1.0.0
-- Up-to-date: /usr/local/bin/libmysqrt.so.1
-- Up-to-date: /usr/local/bin/libmysqrt.so
4. 查看生成出來的檔案
在完成編譯與安裝指令後,可以看到在/usr/local/bin和/usr/local/include會出現主程式所需要的標頭檔與動態庫
kai@esoc:/usr/local/bin$ tree
.
├── docker-compose -> /usr/lib/docker/cli-plugins/docker-compose
├── libmysqrt.so -> libmysqrt.so.1
├── libmysqrt.so.1 -> libmysqrt.so.1.0.0
├── libmysqrt.so.1.0.0
kai@esoc:/usr/local/include$ tree -L 1
.
├── librealsense2
├── librealsense2-gl
└── mysqrt.h
5. 編輯 CMakeLists.txt
include(GNUInstallDirs)
# 引入 GNUInstallDirs 變數
include_directories(${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR})
# 設定include路徑
target_link_directories(main PUBLIC ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR})
# 設定執行檔main搜尋lib的路徑
target_link_libraries(main mysqrt)
# 將mysqrt連結到執行檔main
6. 編譯與執行主專案
$ cd build
$ cmake ..
$ make
$ ./main 100
7. 再使用ldd指令查看庫鍊結情況
$ ldd main
kai@esoc:~/2023_iT_CMake/Day14/範例2安裝至系統路徑/Main/build$ ldd main
linux-vdso.so.1 (0x00007ffd713f8000)
libmysqrt.so.1 => /usr/local/bin/libmysqrt.so.1 (0x00007f951d281000)
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f951d000000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f951d23b000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f951cc00000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f951cf19000)
/lib64/ld-linux-x86-64.so.2 (0x00007f951d28e000)
可以發現主程式順利鍊結到系統路徑中的mysqrt動態庫
Program Library HOWTO
ld.so(8) — Linux manual page
GNU Coding Standards