1. 程式人生 > >linux下gcc程式設計04-cmake工程管理

linux下gcc程式設計04-cmake工程管理

一。cmake簡介

 CMake是一個跨平臺的編譯、安裝、測試以及打包工具;CMake不直接編譯軟體,而是結合原生構建系統來構建軟體。
   CMake配置檔案是CMakeList.txt檔案(每個原始碼資料夾下都要有一個),CMake根據配置檔案再生成Unix的Makefile或VS的solution檔案等。
   Cmake旨在通過一個配置來解決不同平臺編寫不同編譯配置檔案的方法 cmake僅僅幫我們生成編譯工程檔案,最終編譯靠
 各自編譯器
   圖解:

  

  1》 cmake安裝 

yum -y install cmake

 檢視版本

[[email protected]
rule]# cmake --version cmake version 2.8.12.2
#include <stdio.h>
void main(){
	printf("hello\n");
}

在當前目錄下新建CMakeList.txt檔案內容

#CMake最低版本號要求
cmake_minimum_required (VERSION 2.8)
#專案資訊
project (demo)
#指定生成目標 引數1表示生成目標檔案的名稱 引數2表示原始檔
add_executable(demo hello.c)

執行 (cmake 有cmakelist.txt檔案的目錄)

cmake .

執行完成後 發現當前目錄下 生成了Makefile檔案 使用make 命令就可以編譯了

[[email protected] helloworld]# cmake .
-- Configuring done
-- Generating done
-- Build files have been written to: /root/vc/helloworld
[[email protected] helloworld]# make && ./demo
[100%] Built target demo
hello

二。cmake多目錄實戰

假設專案的目錄結構為:

inc目錄下為標頭檔案a.h:

#include <stdio.h>
#include <stdlib.h>
int add(int p1,int p2);
void syso(char* c);

math目錄下為 add方法的實現c檔案 mmath.c 因為標頭檔案不在同一個目錄 所以gcc 指定 -I

#include "a.h"
int add(int p1,int p2){
	return p1+p2;
}

utils目錄包含了syso方法的實現syso.c

#include "a.h"
void syso(char* c){
	printf(c);
}

根目錄下有個 main.c 新增應用的入口main方法
 

#include "a.h"
void main(){
	int number=add(111,333);
	char str[25];
	sprintf(str, "%d", number);
	syso(str);	
}

假設這裡分別 將 mmath.c編譯成動態庫.so syso.c程式設計靜態庫 .a 
math目錄下新增一個 CMakeLists.txt檔案

#設定輸出的連結庫的位置 PROJECT_BINARY_DIR是 cmake執行的目錄 PROJECT_SOURCE_DIR是有
# CMakeLists.txt的目錄 比如cmake .. 當前目錄就是 PROJECT_BINARY_DIR 上一級目錄就是
# PROJECT_SOURCE_DIR
set(LIBRARY_OUTPUT_PATH  ${PROJECT_BINARY_DIR})
include_directories (${PROJECT_SOURCE_DIR}/../inc)
#將某個檔案編譯成動態庫
add_library(mmath SHARED mmath.c)

utils目錄下新增一個 CMakeLists.txt檔案

#設定輸出的連結庫的位置
set(LIBRARY_OUTPUT_PATH  ${PROJECT_BINARY_DIR})
include_directories (${PROJECT_SOURCE_DIR}/../inc)
#將某個檔案編譯成靜態庫
add_library(syso STATIC syso.c)

根目錄下新增一個CMakeLists.txt檔案 要求執行根目錄自動呼叫子目錄的
 

#CMake最低版本號要求
cmake_minimum_required (VERSION 2.8)
#專案資訊
project (mydemo)
#定義編譯時 包含標頭檔案位置
include_directories (inc)
#生成時打印出訊息
MESSAGE(STATUS "開始生成子目錄math")
#cmake呼叫子目錄 執行子目錄的 CmakeLists.txt 
add_subdirectory (math) 
MESSAGE(STATUS "開始生成子目錄utils")
add_subdirectory (utils) 
#指定連結目標檔案的目錄
link_directories(${PROJECT_BINARY_DIR})
#定義一個變數 ALL_C 使用 ${變數名引用}
set(ALL_C main.c)
MESSAGE(STATUS "開始生成程式")
#指定生成目標
add_executable(mydemo ${ALL_C})
#指定 mydeo這個可執行檔案依賴 syso和mmath兩個動態連結庫
target_link_libraries(mydemo syso)
target_link_libraries(mydemo mmath)

#-----------------------------
# 下面的程式碼僅用於學習命令
#-----------------------------
#-----執行命令 拿到系統版本 指定uname -r 將結果寫入MY_HOST_SYSTEM_NAME變數
EXEC_PROGRAM(uname ARGS -s OUTPUT_VARIABLE MY_HOST_SYSTEM_NAME)
if(MY_HOST_SYSTEM_NAME STREQUAL "Linux")
	message(STATUS "系統是:${MY_HOST_SYSTEM_NAME}")
endif()
#-----給INSTALL_STATIC_LIBRARIES定義個預設值 如果cmake ../ -DINSTALL_STATIC_LIBRARIES=OFF 沒有帶這個引數預設值就是ON 帶了就是帶了的值
OPTION(INSTALL_STATIC_LIBRARIES "Install static libraries",ON)
message(STATUS "輸出是:${INSTALL_STATIC_LIBRARIES}")
#-----迴圈輸出 0-5 步數是1	
foreach(loop_var RANGE 0 5 1)
	message(STATUS "迴圈輸出是:${loop_var}")
endforeach(loop_var)	

foreach(loop_var "zs" "ls")
	message(STATUS "迴圈輸出是:${loop_var}")
endforeach(loop_var)
#包含一個包含cmake語法的txt檔案 
include(a.txt)
#-----獲取環境變數
set(MPATH $ENV{PATH})
message(STATUS "包含獲取變數:${a} 環境變數 ${MPATH}")			

#-----定義巨集
MACRO(testMacro age)  
  set(age 11) #巨集修改引數是無效的
  message(STATUS "這是一個巨集定義 引數是 ${age}")
endmacro(testMacro)
#呼叫巨集
set(age 10)
testMacro(${age})					  
					  
#-----定義函式
function(myage age])
   set(age 11 PARENT_SCOPE) #函式內修改引數是無效的 呼叫方的值還是之前的值 必須加上PARENT_SCOPE才能修改
  message(STATUS "這是一個函式定義 引數是 ${age}")
endfunction(myage)	
set(age 10)
myage(${age})		
#注意函式內部修改的值對外部無效 除非使用了引用修改值 PARENT_SCOPE	  
message(STATUS "age值: ${age}")					  
					  
#-----get_filename_component 得到一個完整檔名中的特定部分。					  
GET_FILENAME_COMPONENT(MYDIR "c:/a/a.txt" DIRECTORY) #獲取目錄 結果 c:/a
message(${MYDIR})
GET_FILENAME_COMPONENT(MYDIR "c:/a/a.txt" EXT)		#EXT獲取字尾 	txt路徑(PATH),檔名(NAME),副檔名(EXT),去掉副檔名的檔名(NAME_WE),完整路徑(ABSOLUTE),或者所有符號連結被解析出的完整路徑(REALPATH)		  
message(${MYDIR})					  		  

因為執行cmake 會生成很多的臨時檔案為了 怕汙染原始碼  我們進入bin目錄執行 
 

[[email protected] bin]# cmake ../
CMake Warning (dev) in CMakeLists.txt:
  Syntax Warning in cmake code at

    /root/vc/cmake/CMakeLists.txt:33:59

  Argument not separated from preceding token by whitespace.
This warning is for project developers.  Use -Wno-dev to suppress it.

-- 開始生成子目錄math
-- 開始生成子目錄utils
-- 開始生成程式
-- 系統是:Linux
-- 輸出是:OFF
-- 迴圈輸出是:0
-- 迴圈輸出是:1
-- 迴圈輸出是:2
-- 迴圈輸出是:3
-- 迴圈輸出是:4
-- 迴圈輸出是:5
-- 迴圈輸出是:zs
-- 迴圈輸出是:ls
-- 包含獲取變數:1 環境變數 /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
-- 這是一個巨集定義 引數是 10
-- 這是一個函式定義 引數是 10
-- age值: 11
c:/a
.txt
-- Configuring done
-- Generating done
-- Build files have been written to: /root/vc/cmake/bin
[[email protected] bin]# make
Scanning dependencies of target mmath
[ 33%] Building C object math/CMakeFiles/mmath.dir/mmath.c.o
Linking C shared library ../libmmath.so
[ 33%] Built target mmath
Scanning dependencies of target syso
[ 66%] Building C object utils/CMakeFiles/syso.dir/syso.c.o
Linking C static library ../libsyso.a
[ 66%] Built target syso
Scanning dependencies of target mydemo
[100%] Building C object CMakeFiles/mydemo.dir/main.c.o
Linking C executable mydemo
[100%] Built target mydemo
[[email protected] bin]# ./mydemo