前言
上一篇文章講解了如何構(gòu)建靜態(tài)庫或者動態(tài)庫协饲,本文目標為:
1扫腺、引入外部靜態(tài)庫
2砌创、引入外部動態(tài)庫
準備工作
創(chuàng)建sample7,在里面創(chuàng)建3rdlilb姆打,將上一篇文章構(gòu)建的Math.h頭文件件余、以及將lib文件夾下內(nèi)容全部拷貝進來讥脐,創(chuàng)建src源碼目錄,將sample2的main.cpp拷貝進來啼器,最終目錄如下:
./sample7
|
+--- CMakeLists.txt
|
+--- build/
+--- src/
+--- CMakeLists.txt
+--- main.cpp
+--- lib/
+--- libMath.a
+--- libmath.1.2.dylib
+--- libmath.1.dylib
+--- libmath.dylib
+--- Math.h
這里要再main.cpp中應用外部math庫旬渠,其內(nèi)容為:
#include <stdio.h>
#include <stdlib.h>
#include "Math.h"
int main(int argc, char *argv[])
{
if (argc < 3){
printf("Usage: %s base exponent \n", argv[0]);
return 1;
}
double base = atof(argv[1]);
int exponent = atoi(argv[2]);
double result = power(base, exponent);
printf("%g ^ %d is %g\n", base, exponent, result);
return 0;
}
工程根目錄下CMakeLists.txt內(nèi)容為:
# CMake 最低版本號要求
cmake_minimum_required (VERSION 2.8)
if(POLICY CMP0042)
cmake_policy(SET CMP0042 NEW) # CMake 3.0+ (2.8.12): MacOS "@rpath" in target's install name
endif()
# 項目工程名
project (sample7)
message(STATUS "root This is BINARY dir " ${PROJECT_BINARY_DIR})
message(STATUS "root This is SOURCE dir " ${PROJECT_SOURCE_DIR})
# 添加子目錄
ADD_SUBDIRECTORY(src)
1、引入外部靜態(tài)庫
src目錄下的CMakeLists.txt文件內(nèi)容為:
# 打印信息
message(STATUS "src This is BINARY dir " ${PROJECT_BINARY_DIR})
message(STATUS "src This is SOURCE dir " ${PROJECT_SOURCE_DIR})
# 定義工程根目錄; CMAKE_SOURCE_DIR為內(nèi)建變量端壳,表示工程根目錄的CMakeLists.txt文件路徑
SET(ROOT_DIR ${CMAKE_SOURCE_DIR})
# 指定頭文件搜索路徑
INCLUDE_DIRECTORIES(${ROOT_DIR}/3rdlib)
# 指定引用的外部庫的搜索路徑
LINK_DIRECTORIES(${ROOT_DIR}/3rdlib)
# 指定可執(zhí)行文件存放目錄
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
# 構(gòu)建可執(zhí)行程序
ADD_EXECUTABLE(sample7 main.cpp)
TARGET_LINK_LIBRARIES(sample7 libmath.a)
- INCLUDE_DIRECTORIES(${ROOT_DIR}/3rdlib)
用于指定頭文件的搜索路徑告丢,因為Math.h與main.cpp不在同一目錄,所以如果不配置這個搜索路徑损谦,肯定會報錯 - LINK_DIRECTORIES(${ROOT_DIR}/3rdlib)
指定靜態(tài)庫或者動態(tài)庫的搜索路徑 - TARGET_LINK_LIBRARIES(sample7 libmath.a)
指定要連接的靜態(tài)庫岖免,必須要有岳颇,第二個參數(shù)也可以換成math,那么將自動去搜索libmath.a或者libmath.so或者libmath.dyld動態(tài)庫
還有另外一種寫法颅湘,如下:
# 打印信息
message(STATUS "src This is BINARY dir " ${PROJECT_BINARY_DIR})
message(STATUS "src This is SOURCE dir " ${PROJECT_SOURCE_DIR})
# 定義工程根目錄; CMAKE_SOURCE_DIR為內(nèi)建變量话侧,表示工程根目錄的CMakeLists.txt文件路徑
SET(ROOT_DIR ${CMAKE_SOURCE_DIR})
# 指定頭文件搜索路徑
INCLUDE_DIRECTORIES(${ROOT_DIR}/3rdlib)
# 以導入外部庫的方式(不會重新編譯)重新構(gòu)建一個靜態(tài)庫libMath
add_library(libMath STATIC IMPORTED)
# 設置要導入的外部靜態(tài)庫的路徑
set_target_properties(libMath PROPERTIES IMPORTED_LOCATION ${ROOT_DIR}/3rdlib/libmath.a)
# 指定可執(zhí)行文件存放目錄
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
# 構(gòu)建可執(zhí)行程序
ADD_EXECUTABLE(sample7 main.cpp)
# 注意這里連接的庫名為新構(gòu)建的庫名libMath而外部庫libmath
TARGET_LINK_LIBRARIES(sample7 libMath)
這里解釋下,這里是先根據(jù)外部靜態(tài)庫重新構(gòu)建一個libMath靜態(tài)庫闯参,然后可執(zhí)行程序連接到該庫
- add_library(libMath STATIC IMPORTED)
以導入外部庫的方式重新構(gòu)建一個靜態(tài)庫libMath,不會重新編譯 - set_target_properties(libMath PROPERTIES IMPORTED_LOCATION ${ROOT_DIR}/3rdlib/libmath.a)
設置要導入的外部靜態(tài)庫的路徑
tips:
建議用方式一導入外部庫
2瞻鹏、引入外部動態(tài)庫
修改src下CMakeLists.txt文件內(nèi)容:
# 打印信息
message(STATUS "src This is BINARY dir " ${PROJECT_BINARY_DIR})
message(STATUS "src This is SOURCE dir " ${PROJECT_SOURCE_DIR})
# 定義工程根目錄; CMAKE_SOURCE_DIR為內(nèi)建變量,表示工程根目錄的CMakeLists.txt文件路徑
SET(ROOT_DIR ${CMAKE_SOURCE_DIR})
# 指定頭文件搜索路徑
INCLUDE_DIRECTORIES(${ROOT_DIR}/3rdlib)
# 指定引用的外部庫的搜索路徑
LINK_DIRECTORIES(${ROOT_DIR}/3rdlib)
# 指定可執(zhí)行文件存放目錄
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
# 構(gòu)建可執(zhí)行程序
ADD_EXECUTABLE(sample7 main.cpp)
TARGET_LINK_LIBRARIES(sample7 libmath.dylib)
tips:
因為sample7 在構(gòu)建的時候引入了動態(tài)庫赢赊,所以當./sample7 在執(zhí)行的時候?qū)⑷ブ付ǖ哪夸浖虞d這個動態(tài)庫(這個路徑非編譯時指定的動態(tài)庫路徑乙漓,發(fā)現(xiàn)會報錯"dyld: Library not loaded: @rpath/libmath.1.dylib") ,如果將他們拷貝到/usr/local/lib/目錄下释移,發(fā)現(xiàn)就不報錯了叭披。對于mac 系統(tǒng),它默認按照如下順序搜索動態(tài)庫:
1.編譯目標代碼時指定的動態(tài)庫搜索路徑(通過 -Wl,-rpath參數(shù)指定的)
2.環(huán)境變量LD_LIBRARY_PATH指定的動態(tài)庫搜索路徑玩讳;
3.配置文件/etc/ld.so.conf中指定的動態(tài)庫搜索路徑涩蜘;
4.默認的動態(tài)庫搜索路徑/usr/lib
5.默認的動態(tài)庫搜索路徑/usr/local/lib
其它系統(tǒng)可能有些區(qū)別,但大體都差不多
引入靜態(tài)庫和動態(tài)庫的區(qū)別
1熏纯、引入靜態(tài)庫時同诫,靜態(tài)庫在連接階段會被連接到最終目標中(比如可執(zhí)行執(zhí)行程序中),缺點就是同一份靜態(tài)庫如果被不同的程序引用樟澜,那么內(nèi)存中會存在這個靜態(tài)庫函數(shù)的多份拷貝
2误窖、引入動態(tài)庫時,連接階段不會被拷貝最終目標中秩贰,程序運行時將按照指定的規(guī)則(上一步提到的規(guī)則霹俺,并非編譯時的動態(tài)庫路徑)去搜索這個動態(tài)庫,搜索到了之后才加載到內(nèi)存中毒费。所以多個程序就算引用了同一個動態(tài)庫丙唧,內(nèi)存中也只是存在一份動態(tài)庫函數(shù)的拷貝
CMake 環(huán)境變量關鍵字
1、CMAKE_INCLUDE_PATH
2觅玻、CMAKE_LIBRARY_PATH
這兩個變量在cmake語法中顯示調(diào)用并沒有效果想际,它的作用給CMake的FIND__XXX()系列函數(shù)提供查找路徑,比如如下代碼
# 在環(huán)境變量CMAKE_LIBRARY_PATH指定的目錄中查找libmath.dylib
# 的路徑溪厘,并賦值給mypath變量
message(STATUS "ddd This is SOURCE dir " ${CMAKE_INCLUDE_PATH})
FIND_PATH(myHeader hello.h)
FIND_LIBRARY(mypath libmath.dylib)
message(STATUS "ee This is SOURCE dir " ${myHeader})
message(STATUS "ttt This is SOURCE dir " ${mypath})
將libmath.dyld,Math.h分別拷貝到/usr/local/lib胡本,/usr/local/include目錄中,執(zhí)行
export PATH=$PATH:/usr/local/lib:/usr/local/include
cmake ..
發(fā)現(xiàn)${myHeader}和${mypath}都是有值的