<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    cmake 學習筆記(一)

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接
    • 最大的Qt4程序群(KDE4)采用cmake作為構建系統
    • Qt4的python綁定(pyside)采用了cmake作為構建系統
    • 開源的圖像處理庫 opencv 采用cmake 作為構建系統
    • ...

    看來不學習一下cmake是不行了,一點一點來吧,找個最簡單的C程序,慢慢復雜化,試試看:

    例子一

    單個源文件 main.c

    例子二

    ==>分解成多個 main.c hello.h hello.c

    例子三

    ==>先生成一個靜態庫,鏈接該庫

    例子四

    ==>將源文件放置到不同的目錄

    例子五

    ==>控制生成的程序和庫所在的目錄

    例子六

    ==>使用動態庫而不是靜態庫

    例子一

    一個經典的C程序,如何用cmake來進行構建程序呢?

    //main.c
    #include <stdio.h>
    int main()
    {
        printf("Hello World!/n");
        return 0;
    }

    編寫一個 CMakeList.txt 文件(可看做cmake的工程文件):

    project(HELLO)
    set(SRC_LIST main.c)
    add_executable(hello ${SRC_LIST})

    然后,建立一個任意目錄(比如本目錄下創建一個build子目錄),在該build目錄下調用cmake

    • 注意:為了簡單起見,我們從一開始就采用cmake的 out-of-source 方式來構建(即生成中間產物與源代碼分離),并始終堅持這種方法,這也就是此處為什么單獨創建一個目錄,然后在該目錄下執行 cmake 的原因
    cmake .. -G"NMake Makefiles"
    nmake

    或者

    cmake .. -G"MinGW Makefiles"
    make

    即可生成可執行程序 hello(.exe)

    目錄結構

    +
    | 
    +--- main.c
    +--- CMakeList.txt
    |
    /--+ build/
       |
       +--- hello.exe

    cmake 真的不太好用哈,使用cmake的過程,本身也就是一個編程的過程,只有多練才行。

    我們先看看:前面提到的這些都是什么呢?

    CMakeList.txt

    第一行 project 不是強制性的,但最好始終都加上。這一行會引入兩個變量

    • HELLO_BINARY_DIR 和 HELLO_SOURCE_DIR

    同時,cmake自動定義了兩個等價的變量

    • PROJECT_BINARY_DIR 和 PROJECT_SOURCE_DIR

    因為是out-of-source方式構建,所以我們要時刻區分這兩個變量對應的目錄

    可以通過message來輸出變量的值

    message(${PROJECT_SOURCE_DIR})

    set 命令用來設置變量

    add_exectuable 告訴工程生成一個可執行文件。

    add_library 則告訴生成一個庫文件。

    • 注意:CMakeList.txt 文件中,命令名字是不區分大小寫的,而參數和變量是大小寫相關的。

    cmake命令

    cmake 命令后跟一個路徑(..),用來指出 CMakeList.txt 所在的位置。

    由于系統中可能有多套構建環境,我們可以通過-G來制定生成哪種工程文件,通過 cmake -h 可得到詳細信息。

    要顯示執行構建過程中詳細的信息(比如為了得到更詳細的出錯信息),可以在CMakeList.txt內加入:

    • SET( CMAKE_VERBOSE_MAKEFILE on )

    或者執行make時

    • $ make VERBOSE=1

    或者

    • $ export VERBOSE=1
    • $ make

    例子二

    一個源文件的例子一似乎沒什么意思,拆成3個文件再試試看:

    • hello.h 頭文件
    #ifndef DBZHANG_HELLO_
    #define DBZHANG_HELLO_
    void hello(const char* name);
    #endif //DBZHANG_HELLO_
    • hello.c
    #include <stdio.h>
    #include "hello.h"
    
    void hello(const char * name)
    {
        printf ("Hello %s!/n", name);
    }
    • main.c
    #include "hello.h"
    int main()
    {
        hello("World");
        return 0;
    }
    • 然后準備好CMakeList.txt 文件

     

    project(HELLO)
    set(SRC_LIST main.c hello.c)
    add_executable(hello ${SRC_LIST})

    執行cmake的過程同上,目錄結構

     

    +
    | 
    +--- main.c
    +--- hello.h
    +--- hello.c
    +--- CMakeList.txt
    |
    /--+ build/
       |
       +--- hello.exe

    例子很簡單,沒什么可說的。

    例子三

    接前面的例子,我們將 hello.c 生成一個庫,然后再使用會怎么樣?

    改寫一下前面的CMakeList.txt文件試試:

    project(HELLO)
    set(LIB_SRC hello.c)
    set(APP_SRC main.c)
    add_library(libhello ${LIB_SRC})
    add_executable(hello ${APP_SRC})
    target_link_libraries(hello libhello)

    和前面相比,我們添加了一個新的目標 libhello,并將其鏈接進hello程序

    然后想前面一樣,運行cmake,得到

    +
    | 
    +--- main.c
    +--- hello.h
    +--- hello.c
    +--- CMakeList.txt
    |
    /--+ build/
       |
       +--- hello.exe
       +--- libhello.lib

    里面有一點不爽,對不?

    • 因為我的可執行程序(add_executable)占據了 hello 這個名字,所以 add_library 就不能使用這個名字了
    • 然后,我們去了個libhello 的名字,這將導致生成的庫為 libhello.lib(或 liblibhello.a),很不爽
    • 想生成 hello.lib(或libhello.a) 怎么辦?

    添加一行

    set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")

    就可以了

    例子四

    在前面,我們成功地使用了庫,可是源代碼放在同一個路徑下,還是不太正規,怎么辦呢?分開放唄

    我們期待是這樣一種結構

    +
    |
    +--- CMakeList.txt
    +--+ src/
    |  |
    |  +--- main.c
    |  /--- CMakeList.txt
    |
    +--+ libhello/
    |  |
    |  +--- hello.h
    |  +--- hello.c
    |  /--- CMakeList.txt
    |
    /--+ build/

    哇,現在需要3個CMakeList.txt 文件了,每個源文件目錄都需要一個,還好,每一個都不是太復雜

    • 頂層的CMakeList.txt 文件
    project(HELLO)
    add_subdirectory(src)
    add_subdirectory(libhello)
    • src 中的 CMakeList.txt 文件
    include_directories(${PROJECT_SOURCE_DIR}/libhello)
    set(APP_SRC main.c)
    add_executable(hello ${APP_SRC})
    target_link_libraries(hello libhello)
    • libhello 中的 CMakeList.txt 文件
    set(LIB_SRC hello.c)
    add_library(libhello ${LIB_SRC})
    set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")

    恩,和前面一樣,建立一個build目錄,在其內運行cmake,然后可以得到

    • build/src/hello.exe
    • build/libhello/hello.lib

    回頭看看,這次多了點什么,頂層的 CMakeList.txt 文件中使用 add_subdirectory 告訴cmake去子目錄尋找新的CMakeList.txt 子文件

    在 src 的 CMakeList.txt 文件中,新增加了include_directories,用來指明頭文件所在的路徑。

    例子五

    前面還是有一點不爽:如果想讓可執行文件在 bin 目錄,庫文件在 lib 目錄怎么辦?

    就像下面顯示的一樣:

       + build/
       |
       +--+ bin/
       |  |
       |  /--- hello.exe
       |
       /--+ lib/
          |
          /--- hello.lib
    • 一種辦法:修改頂級的 CMakeList.txt 文件
    project(HELLO)
    add_subdirectory(src bin)
    add_subdirectory(libhello lib)

    不是build中的目錄默認和源代碼中結構一樣么,我們可以指定其對應的目錄在build中的名字。

    這樣一來:build/src 就成了 build/bin 了,可是除了 hello.exe,中間產物也進來了。還不是我們最想要的。

    • 另一種方法:不修改頂級的文件,修改其他兩個文件

    src/CMakeList.txt 文件

    include_directories(${PROJECT_SOURCE_DIR}/libhello)
    #link_directories(${PROJECT_BINARY_DIR}/lib)
    set(APP_SRC main.c)
    set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
    add_executable(hello ${APP_SRC})
    target_link_libraries(hello libhello)

    libhello/CMakeList.txt 文件

    set(LIB_SRC hello.c)
    add_library(libhello ${LIB_SRC})
    set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
    set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")

    例子六

    在例子三至五中,我們始終用的靜態庫,那么用動態庫應該更酷一點吧。 試著寫一下

    如果不考慮windows下,這個例子應該是很簡單的,只需要在上個例子的 libhello/CMakeList.txt 文件中的add_library命令中加入一個SHARED參數:

    add_library(libhello SHARED ${LIB_SRC})

    可是,我們既然用cmake了,還是兼顧不同的平臺吧,于是,事情有點復雜:

    • 修改 hello.h 文件
    #ifndef DBZHANG_HELLO_
    #define DBZHANG_HELLO_
    #if defined _WIN32
        #if LIBHELLO_BUILD
            #define LIBHELLO_API __declspec(dllexport)
        #else
            #define LIBHELLO_API __declspec(dllimport)
        #endif
    #else
        #define LIBHELLO_API
    #endif
    LIBHELLO_API void hello(const char* name);
    #endif //DBZHANG_HELLO_
    • 修改 libhello/CMakeList.txt 文件
    set(LIB_SRC hello.c)
    add_definitions("-DLIBHELLO_BUILD")
    add_library(libhello SHARED ${LIB_SRC})
    set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
    set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")

    恩,剩下來的工作就和原來一樣了。

    轉自:http://blog.csdn.net/dbzhang800/article/details/6314073

    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全