1. 程式人生 > >cmake教程5-macro巨集定義以及傳遞引數給原始檔

cmake教程5-macro巨集定義以及傳遞引數給原始檔

引入在C++程式中我們經常見到如下,兩個問題:
1. 輸出當前程式的版本號
2. 通過cmake新增macro巨集定義 出入到原始檔,例如在編譯opencv/caffe的時候,我們通過cmake -DUSE_CUDA=ON/OFF來確定,是否使用cuda.
問題cmake中如何實現上述兩個功能的呢?

至於問題1:

我們可能想到直接在標頭檔案中定義,這樣也可以,但是如果直接在cmake中定義,然後傳遞給程式讀取生成更加靈活。

至於問題2:

可以在cmake中通過option函式以及add_definitions函式來實現。

cmake 傳遞版本號給原始檔

首先定義demo11Config.h.in標頭檔案接受CMakeLists.txt傳遞來的版本號引數,檔案內容如下:

// the configured options and settings for demo11
#define demo11_VERSION_MAJOR @[email protected]
#define demo11_VERSION_MINOR @[email protected]

demo11.cpp程式碼如下:


#include <stdio.h>
// demoConfig.h檔案是cmake生成的
#include "demoConfig.h"
int main(int argc, char* argv[]){ printf("%s version: %d.%d \n", argv[0], demo11_VERSION_MAJOR, demo11_VERSION_MINOR); }

注意的是demoConfig.h是生成的在專案結構中並不存在,專案目錄如下:

這裡寫圖片描述

CMakeLists.txt如下:

cmake_minimum_required(VERSION 3.5)

project(demo11)

# The version number
set(demo11_VERSION_MAJOR 1)
set(demo11_VERSION_MINOR 0
) # configure a header file to pass some of the CMake settings to # source code(demo11Config.h.in), the file demoConfig.h does't exists configure_file( "${PROJECT_SOURCE_DIR}/demo11Config.h.in" "${PROJECT_BINARY_DIR}/demoConfig.h" ) # add the binary tree to the search path for include files # so that we will find demoConfig.h include_directories("${PROJECT_BINARY_DIR}") # add the exectuable add_executable(demo11 demo11.cpp)

cmake 編譯如下:

root@xy:~/cmake_practice/cmake_build/build_demo11# cmake ../../cmake_tuorial/demo11/
-- The C compiler identification is GNU 5.4.0

可以看到生產了demoConfig.h:

drwxr-xr-x  3 root root  4096 Jun 29 08:42 ./
........
-rw-r--r--  1 root root   112 Jun 29 08:42 demoConfig.h
-rw-r--r--  1 root root  4865 Jun 29 08:42 Makefile

demoConfig.h內容如下:


// the configured options and settings for demo11
#define demo11_VERSION_MAJOR 1
#define demo11_VERSION_MINOR 0

make & run,輸出如下:

root@xy:~/cmake_practice/cmake_build/build_demo11# ./demo11
./demo11 version: 1.0

新增macro到src檔案中(add_definitions/option)

本例項在cmake中新增macro定義到原始檔中,從而選擇使用不同的lib 模組函式.

專案目錄如下:demo12.cpp根據cmake定義的macro USE_SPECIFIED決定使用模組SpecifiedFun(特定的函式),還是模組CommonFun(一般的函式).

這裡寫圖片描述

兩個模組都只有一個函式showSelectedFun,主要是輸出呼叫了哪個函式.
模組CommonFun,內容如下:

void showSelectedFun(){
    std::cout<<"Select to use common function"<<std::endl;
}

對應的cmake如下:

add_library(common_fun CommonFun.cpp)

模組SpecifiedFun,內容如下:

void showSelectedFun(){
    std::cout<<"Select to use specified function"<<std::endl;
}

對應的cmake如下:

add_library(specified_fun SpecifiedFun.cpp)

主CMakeLists.txt內容如下, 主要是通過option USE_SPECIFIED ON/OFF來決定使用新增macro add_definitions(-DUSE_SPECIFIED)

cmake_minimum_required(VERSION 3.5)

# should we use specified function
# if not set, then will use common function
option(USE_SPECIFIED "select to use specified function" ON)

# select to use specified function, or common function
message("USE_SPECIFIED is ${USE_SPECIFIED}")

if(USE_SPECIFIED)
    add_definitions(-DUSE_SPECIFIED)
    include_directories("${PROJECT_SOURCE_DIR}/SpecifiedFun")
    add_subdirectory(SpecifiedFun)
    set(EXTRA_LIBS ${EXTRA_LIBS} specified_fun)
    message("select to use specified function, lib is: ${EXTRA_LIBS}")
else()
    include_directories("${PROJECT_SOURCE_DIR}/CommonFun")
    add_subdirectory(CommonFun)
    set(EXTRA_LIBS ${EXTRA_LIBS} common_fun)
    message("select to use common function, lib is: ${EXTRA_LIBS}")
endif(USE_SPECIFIED)

add_executable(demo12 demo12.cpp)
target_link_libraries(demo12 ${EXTRA_LIBS})

首先編譯不使用USE_SPECIFIEDUSE_SPECIFIED=OFF

root@xy:~/tmp/demo12/build# cmake -DUSE_SPECIFIED=OFF ..
..........
USE_SPECIFIED is OFF
select to use common function, lib is: common_fun
-- Configuring done
-- Generating done
-- Build files have been written to: /home/xy/tmp/demo12/build

編譯make:

root@xy:~/tmp/demo12/build# make 
Scanning dependencies of target common_fun
[ 25%] Building CXX object CommonFun/CMakeFiles/common_fun.dir/CommonFun.cpp.o
[ 50%] Linking CXX static library libcommon_fun.a
[ 50%] Built target common_fun
Scanning dependencies of target demo12
[ 75%] Building CXX object CMakeFiles/demo12.dir/demo12.cpp.o
[100%] Linking CXX executable demo12
[100%] Built target demo12

執行:

root@xy:~/tmp/demo12/build# ./demo12 
Select to use common function

使用macro USE_SPECIFIED直接使用cmake .. 即可
接下來的步驟一樣就不重複了

相關推薦

cmake教程5-macro巨集定義以及傳遞引數原始檔

引入在C++程式中我們經常見到如下,兩個問題: 1. 輸出當前程式的版本號 2. 通過cmake新增macro巨集定義 出入到原始檔,例如在編譯opencv/caffe的時候,我們通過cmake -DUSE_CUDA=ON/OFF來確定,是否使用c

unity自定義巨集定義以及常用自帶的巨集定義

如下是系統有的巨集, //如果你的平臺已經被你switch platform 你的那個平臺過後,對應的輸出列印是彩色的,否則是灰色的 #if UNITY_IPHONE         Debug.Log("UNITY_IPHONE"); #elif UNITY_ANDROI

JSP 關於的使用以及傳遞引數

首先說明一下,<jsp:forward>是動作指令。 我覺得有必要對jsp中的幾個指令總結一下了 jsp中的指令分為兩大類,編譯指令和動作指令。 編制指令 <%@ i

Unity3D和IOS的互動教程——通過URL啟動APP並傳遞引數

最近專案(麻將手遊)中遇到這樣一個需求:在建立一個私人房後通過ShareSDK分享一個連線到微信,點選這個連線後設備將跳轉至下載頁面或是啟動APP並直接進入到指定房間。由於目前沒有原生IOS的開發經驗,在發揮面向百度程式設計師的特長之後,寫出來下面的方案並用於專案中,實測可

Makefile(或者shell)的變數通過gcc的-D巨集定義選項傳遞給C原始檔

當make巢狀呼叫時,上層Makefile中定義的變數會以系統環境變數的方式傳遞到下層的Makefile中。這裡的系統環境變數與本makefile中定義的變數的關係有點類似於全域性變數與區域性變數的關係。預設情況下,只有通過命令列設定的變數會被傳遞。而定義在檔案中的變數,如果要向下層Makefile傳遞,則

struts2在action中傳遞引數頁面的方法

由於在Action中並不能直接誒訪問Servlet API,但它提供了相關類ActionContext來訪問HttpServletRequest、HttpSession和ServletContext,所以在向前端頁面傳值的方法就出現了多樣化。一般我們經常使用的就是通過request、session來

後端接受前端的引數型別(前端傳遞引數後端)

引數傳遞形式:  Get請求  引數放到url後面,用&隔開即可 Post請求  傳遞的引數的形式就比較多了。。。。 一、普通的鍵值對引數: get請求實質也是鍵值對的形式 二、list傳值 也可以把list物件放到物件裡面

layui使用button按鈕 點擊出現子彈層 彈層中載入表單,並傳遞引數父彈出層

在父層中增加button按鈕和隱藏域接收子彈出層傳遞的值 <button id="btnMenuTree" type="button" class="layui-btn layui-btn-radius layui-btn-normal layui-btn-xs">選擇</bu

內部類怎麼傳遞引數外部類???

參考連結:http://wendal.net/404.html傳入: //匿名內部類,只能訪問final的本地變數及方法引數 public void addUser(final String name, String passwd, final String userTyp

以form表單的形式傳遞引數rest介面

/** * 以傳統form表單的方式提交引數(並不是以json格式提交) * * @param url 提交的rest url * @param paramMap body引數 * @param r

(三)在TestNG中傳遞引數方法使用

TestNG允許我們在Test Method 以及 @Before/After類註解 、 @Factory類註解註解的方法中傳入引數引數傳遞的方式有兩種,一種是藉助xml檔案配置,一種是以編碼的方式傳遞引數。一、藉助xml檔案配置:1.在方法上使用@Parameters({"

android原生webview中呼叫JS方法並傳遞引數JS遇到的問題

在使用webview時,需要給JS傳遞一個引數,之前前端同事把JS方法內容和html內容分離了,所以在使用下面的方法的時候一直顯示方法未定義[INFO:CONSOLE(1)] "Uncaught ReferenceError: load is not defined", s

JSP傳遞引數servlet的三種方法

Jsp與Servlet之間的傳值有兩種,一種是Jsp傳值給Sevlet,另一種是Servlet傳值給Jsp;使用request、response物件完成傳值,具體實現如下:1.JSP傳值給ServletJSP傳值給Servlet有幾種形式:Form表單傳值,url傳值,其他方式傳值a、form表單傳值:JSP

[JNI]開發之旅(8)傳遞引數JNI函式

本節將介紹在JNI程式設計中如何傳遞引數和返回值。 首先要強調的是,native方法不但可以傳遞Java的基本型別做引數,還可以傳遞更復雜的型別,比如String,陣列,甚至自定義的類。jni.h中定義了很多介面供我們操作。 其實在前面章節的例子中,我們已經

typedef詳解以及巨集定義#define的區別

typedef是在計算機程式語言中用來為複雜的宣告定義簡單的別名,它與巨集定義有些差異。它本身是一種儲存類的關鍵字,與auto、extern、mutable、static、register等關鍵字不能出現在同一個表示式中; typedef 中文解釋:宣告型別; typedef為C語言

flask框架模板巨集macro定義及使用

示例1 (index.html) <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title&g

Python 函式定義以及引數傳遞

Python 函式定義以及引數傳遞1.函式定義#形如def func(args...): doSomething123以關鍵字def 開頭,後面是函式名和引數下面是函式處理過程。 舉例: def add( a, b ): return a+b12引數可以設定預設值,如: def add( a, b=10

強大的巨集定義(macro)

事件分發:(global.h) #pragma once #include <map> #include <functional> #include <Windows.h> #include <tchar.h> #include <v

生產環境的開源容器管理平臺--Rancher入門教程 5定義Catalog工具

Rancher是一個用於部署和管理生產環境的容器的開源平臺,它與Kubernetes/Mesos/Docker Swarm進行整合。使得在任何硬體環境上容器化應用變得觸手可及。在這個系列的教程中我們將會學習如何使用rancher, 上篇文章介紹瞭如何在rancher中新增自定義的catal

Alex 的 Hadoop 菜鳥教程: 第5課 YARN 安裝以及helloworld (基於centos的CDH)

原帖地址:http://blog.csdn.net/nsrainbow/article/details/36627675 新老MapReduce的比較 說到YARN肯定要先說下老的MapReduce MRv1 (MapReduce v1)的架構圖 從上圖中可以清楚的看出