C++ project
centos7環境下使用
靜態庫和動態庫:當我們需要把一些通用的功能封裝起來,供以后調用的時候。在之前我們是將公用的部分提煉出來寫在一個xxx.h和xxx.cpp文件中,然后在我們的主程序中引入xxx.h的頭文件,然后再在編譯的時候將主程序和xxx.cpp文件一起編譯實現的。
在編譯的時候其實有兩個過程,首先會將主程序main.cpp和公用的xxx.cpp分別編譯為兩個二進制的文件,然后在鏈接在一起形成一個可執行文件。
上面的這種依賴其他的公用代碼的方式在C++中可以通過將依賴編譯為庫的方式來引用。
編譯出來的庫又分為兩種:靜態庫和動態庫。
靜態庫:當我們將上面的公用的部分編譯為一個靜態庫的時候,在使用這個靜態庫的時候編譯器會將靜態庫和主程序代碼一起鏈接打包到生成的可執行文件中去。這樣生成的可執行文件可能就會比較臃腫,但是執行的時候比較快,而且由于將需要的東西都全部打包在一起了,這個執行文件的移植性就比較好。還有就是如果我們的庫文件更新了,那么這個主程序就需要引入更新后的庫文件重新打包。
靜態庫的生成和使用:
代碼文件_public.h
#include <stdio.h>
void sayhello();
代碼文件_public.cpp
#include "./_public.h"
void sayhello()
{
printf("hello~
");
}
主程序文件:test.cpp
#include "./_public.h"
sayhello();
首先將_public.c編譯成二進制的.o文件:g++ -c _public.cpp。完成后當前目錄會生成一個_public.o的文件
通過ar工具將目標文件打包成.a靜態庫文件:ar -crv lib_public.a _public.o。完成后當前目錄下會生成一個lib_public.a文件,這個文件就是靜態庫文件
將主程序文件和靜態庫文件一起打包生成可執行文件:g++ -o test test.cpp -L./ -l_public。-L用來指定靜態庫所在的目錄,我們的靜態庫就在當前目錄下所以直接用./。-l后面跟的是引用的靜態庫的名稱(去除掉前面的lib和后綴.o)
然后./test執行生成的可執行文件test
動態庫:動態庫在程序編譯時并不會被連接到目標代碼中,而是在程序運行是才被載入。不同的應用程序如果調用相同的庫,那么在內存里只需要有一份該共享庫的實例,規避了空間浪費問題。動態庫在程序運行是才被載入,也解決了靜態庫對程序的更新、部署和發布頁會帶來麻煩。用戶只需要更新動態庫即可,增量更新。
同樣上上面的代碼將其編譯為共享庫并調用的流程如下:
首先將_public.c編譯成二進制的.o文件:g++ -fPIC -c _public.cpp。完成后當前目錄會生成一個_public.o的文件,-fPIC創建與地址無關的編譯程序(pic,position independent code),是為了能夠在多個應用程序間共享。
生成動態鏈接庫.so文件:g++ -shared -o lib_public.so_public.o。完成后當前目錄會生成一個lib_public.so文件,該文件就是生成的動態鏈接庫。
生成可執行文件:g++ -o test1 test.cpp -L./ -l_public
將生成的lib_public.so文件拷貝到/usr/lib中,因為這個g++默認去尋找動態庫的地址:cp lib_public.so /usr/lib/lib_public.so。
執行命令:ldconfig。這個命令用于更新動態庫的列表以便能將我們新拷貝進去的庫文件能被g++找到。
運行程序:./test1
參考地址:https://blog.csdn.net/kai_zone/article/details/93907101
使用cmake構建項目:
cmake安裝:刪除自帶版本本yum remove cmake -y && rm -f /usr/bin/cmake,下載wget -c https://github.com/Kitware/CMake/releases/download/v3.14.2/cmake-3.14.2.tar.gz,解壓tar xvf cmake-3.14.2.tar.gz && cd cmake-3.14.2/,安裝(1)./bootstrap(2)gmake(3)gamek install,軟鏈ln -s /usr/local/bin/cmake /usr/bin/,查看安裝后的版本cmake --version。參考自:
https://blog.csdn.net/MaxWoods/article/details/89383362
用cmake編譯一個簡單的c++文件:
test1.cpp文件如下
#include "stdio.h"
int main()
{
printf("this is a test
");
return 0;
}
當前目錄下創建一個CMakeLists.txt內容如下:
# CMake 最低版本要求
cmake_minimum_required(VERSION 3.10.2)
# 項目信息
project(test)
# 指定生成目標,這里表示用當前目錄下的test1.cpp編譯生成的可執行文件為test。如果要一起編譯多個.cpp文件直接空格后加在后面即可。
add_executable(test test1.cpp)
執行cmake .來生成makefile,然后用make執行生成的makefile,成功后就生成了可執行文件test,然后./test 運行生成的文件即可。
如果當前目錄下面又很多的.cpp文件,都需要進行編譯,如果將它們的名字全部一個個加到CMakeLists.txt文件中比較麻煩,可以使用下面的方式對當前目錄下的全部文件進行編譯:
# CMake 最低版本要求
cmake_minimum_required(VERSION 3.10.2)
# 項目信息
project(test)
# 查找當前目錄下的所有源文件
# 并將名稱保存到 DIR_SRCS 變量
aux_source_directory(. DIR_SRCS)
# 指定生成目標
add_executable(test ${DIR_SRCS})
用cmake生成靜態庫:
將上面靜態庫的時候使用的test.cpp、_public.h和_public.cpp拷貝到當前目錄下,生成CMakeLists.txt文件:
# 生成鏈接庫
add_library (_public STATUC _public.cpp)
執行后就可以再當前目錄下生成lib_public.a這個靜態庫文件
在test.cpp中引入這個靜態庫文件,CMakeLists.txt文件:
# CMake 最低版本要求
cmake_minimum_required(VERSION 3.10.2)
# 項目信息
project(test)
# 指定生成目標
add_executable(test test.cpp)
# 添加靜態鏈接庫,將當前目錄下的_public鏈接到生成的可執行文件test中
target_link_libraries(test _public)
使用包含子目錄的方式,將靜態庫放在子目錄中,一次性用CMakeLists.txt生成可執行文件。在當前文件夾中新建一個subFile文件夾,將上個例子中的_public.h和_public.cpp和生成靜態庫的CMakeLists.txt移到這個子目錄中,當前目錄下是test.cpp、_public.h文件,在當前目錄下生成一個CMakeLists.txt文件,內容如下:
# CMake 最低版本號要求
cmake_minimum_required (VERSION 3.10.2)
# 項目信息
project (test)
# 查找當前目錄下的所有源文件
# 并將名稱保存到 DIR_SRCS 變量
aux_source_directory(. DIR_SRCS)
# 添加 subFile子目錄,這個子目錄中需要包含CMakeLists.txt文件,并會自動去執行那個CMakeLists.txt文件進行編譯生成靜態庫。
add_subdirectory(subFile)
# 指定生成目標
add_executable(test test.cpp)
# 添加鏈接庫
target_link_libraries(test _public)
在實際項目中,頭文件可能不是和代碼文件放在同一目錄下面,這種情況可以用include_directories()的方式包含頭文件的目錄到cmake里面。測試文件如下:./_public.c,./CMakeLists.txt,./include/_public.h,./lib,
目的是_public.c包含include文件夾下的頭文件,編譯的靜態庫和動態庫輸出到lib文件夾下。
CMakeLists.txt文件內容如下:
# CMake 最低版本要求
cmake_minimum_required(VERSION 3.10.2)
# 項目信息
project(test)
#設置庫文件的輸出目錄
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
#包含頭文件目錄進去
include_directories(include)
add_library (_publiclib STATIC _public.cpp)
add_library (_publicdll SHARED _public.cpp)
在上面的示例中生成庫的操作都是和生成主程序的操作分開進行的,其實是可以將其放在同一個CMakeLists.txt種完成的。
測試文件如下:./src/_public.cpp,./src/test.cpp,./include/_public.h,./lib,./CMakeLists.txt
CMakeLists.txt文件內容如下:
# CMake 最低版本要求
cmake_minimum_required(VERSION 3.10.2)
# 項目信息
project(test)
#設置庫文件的輸出目錄,${PROJECT_SOURCE_DIR}表示當前目錄
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
#包含頭文件目錄進去
include_directories(include)
add_library (_publiclib SHARED src/_public.cpp)
#${PROJECT_NAME}等同于上面的project()中設置的值
add_executable(${PROJECT_NAME} src/test.cpp)
target_link_libraries(${PROJECT_NAME} _publiclib)
在CMakeLists.txt主程序調用外部的庫的時候一般有一下幾種方式:
(1)指定引用庫的絕對路徑
# CMake 最低版本要求
cmake_minimum_required(VERSION 3.10.2)
# 項目信息
project(test)
#${PROJECT_NAME}等同于上面的project()中設置的值
add_executable(${PROJECT_NAME} src/test.cpp)
target_link_libraries(${PROJECT_NAME} _publiclib)
//設置包的根路徑為test_lib變量的值
set(test_lib /root/cmake-project/make5Dir)
#包含頭文件目錄進去
include_directories(${test_lib}/include)
add_executable(${PROJECT_NAME} src/test.cpp)
target_link_libraries(${PROJECT_NAME} ${test_lib}/lib/lib_publiclib.a)
(2)在生成庫的時候就將庫文件和頭文件使用installl的方式安裝到/usr中,使用庫的時候就直接從其中進行引用。
將_public.h和_public.cpp文件放在當前目錄下,使用cmake的方式將頭文件和編譯的靜態庫安裝到/usr/include和/usr/lib下面,CMakeLists.txt文件內容如下:
# CMake 最低版本要求
cmake_minimum_required(VERSION 3.10.2)
# 項目信息
project(test1)
#生成靜態庫
add_library(_public1 STATIC _public1.cpp)
#設置CMAKE_INSTALL_PREFIX變量,該變量會作為安裝的目錄的前綴
set(CMAKE_INSTALL_PREFIX /usr)
#打印CMAKE_INSTALL_PREFIX變量的值
#message(${CMAKE_INSTALL_PREFIX})
#將當前目錄下的_public.h文件安裝到usr/include中
install(FILES ./_public1.h DESTINATION include)
#將生成的靜態庫安裝到usr/lib下面
install(TARGETS _public1 ARCHIVE DESTINATION lib)
執行命令:cmake , make install。后_public.h和lib_public.a文件會安裝到指定的目錄中。
然后test.cpp中引用上面安裝的庫,CMakeLists.txt文件如下:
cmake_minimum_required(VERSION 3.10.1)
project(test2)
#包含的頭文件目錄
include_directories(/usr/include)
add_executable(${PROJECT_NAME} test.cpp)
//添加鏈接庫的目錄
target_link_libraries(${PROJECT_NAME} /usr/lib/lib_public1.a)
(3)使用find_package()的方式導入庫
生成自己的find_package可用模塊:
文件結構:./_public2.h,./_public2.cpp,./CMakeLists.txt,./Find_public2.cmake
Find_public2.cmake內容:
#從/usr/include/下找到_public2.h文件,路徑賦值給_public2_INCLUDE_DIR
find_path(_public2_INCLUDE_DIR NAMES _public2.h PATHS "/usr/include/")
#從/usr/lib/下找到_public2.cpp文件,路徑賦值給_public2_LIBRARY
find_library(_public2_LIBRARY NAMES _public2 PATHS "/usr/lib/")
#如果兩個都找了就給變量_public2_FOUND賦值為True
IF (_public2_INCLUDE_DIR AND _public2_LIBRARY)
SET(_public2_FOUND TRUE)
ENDIF (_public2_INCLUDE_DIR AND _public2_LIBRARY)
#如果_public2_FOUND為真
IF (_publi2_FOUND)
#如果是QUIETLY,模式,沒有找到包就出現提示信息并不中斷程序
IF (NOT public2_FIND_QUIETLY)
MESSAGE(STATUS "Found _public2:${_public2_LIBRARY}")
ENDIF (NOT public2_FIND_QUIETLY)
ELSE (_publi2_FOUND)
#如果是REQUIRED,模式,沒有找到包則中斷程序并提示信息
IF (public2_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "could not find _public2 library")
ENDIF (public2_FIND_REQUIRED)
ENDIF (_publi2_FOUND)
CMakeLists.txt文件內容:
cmake_minimum_required(VERSION 3.10.2)
project(test3)
#生成靜態庫
add_library(_public2 STATIC _public2.cpp)
#set(CMAKE_MODULE_PATH /usr/local/share/cmake-3.14/Modules)
#設置install的默認目錄
set(CMAKE_INSTALL_PREFIX /usr)
#將cmake文件,.h文件,.cpp文件安裝到設置的目錄下
install(FILES Find_public2.cmake DESTINATION /usr/local/share/cmake-3.14/Modules/)
install(FILES _public2.h DESTINATION include)
install(TARGETS _public2 ARCHIVE DESTINATION lib)
在源程序中引用上面自己的模塊:
文件結構:./test.cpp ./CMakeLists.txt
CMakeLists.txt內容:
cmake_minimum_required(VERSION 3.10.2)
project(test)
#set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/lib/cmake/)
#使用REQUIRED的方式加載_public2包,相當于去找上面的Find_public2.cmake文件
find_package(_public2 REQUIRED)
#判斷_public2_FOUND的值來確定是否找到頭文件和庫文件是否找到
if(_public2_FOUND)
#包含_public_INCLUDE_DIR變量指代的頭文件
include_directories(${_public_INCLUDE_DIR})
add_executable(${PROJECT_NAME} test.cpp)
#包含_public2_LIBRARY變量指代的庫文件
target_link_libraries(${PROJECT_NAME} ${_public2_LIBRARY})
else(_public2_FOUND)
message(FATAL_ERROR "_public2 library not found")
endif(_public2_FOUND)
總結
以上是生活随笔為你收集整理的C++ project的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 为何把2点半比作是神奇的2点半? 为什么
- 下一篇: AspNetForum 论坛整改:添加