<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                #三、初試cmake [TOC] cmake 的helloworld 本節選擇了一個最簡單的例子Helloworld來演練一下cmake的完整構建過程,本節并不會深入的探討cmake,僅僅展示一個簡單的例子,并加以粗略的解釋。我們選擇了EverestLinux作為基本開發平臺,因為這個只有一張CD的發行版本,包含了gcc-4.2/gtk/qt3/qt4等完整的開發環境,同時,系統默認集成了cmake 最新版本2.4.6 。 ###1,準備工作 首先,在/backup 目錄建立一個cmake 目錄,用來放置我們學習過程中的所有練習。mkdir -p /backup/cmake以后我們所有的cmake 練習都會放在/backup/cmake 的子目錄下(你也可以自行安排目錄, 這個并不是限制,僅僅是為了敘述的方便) 然后在cmake 建立第一個練習目錄t1cd /backup/cmakemkdir t1cd t1在t1目錄建立main.c 和CMakeLists.txt( 注意文件名大小寫): main.c 文件內容://main.c ``` #include <stdio.h> int main(){ printf(“Hello World from t1 Main!\n”); return 0;} ``` CmakeLists.txt 文件內容: ``` PROJECT (HELLO)SET(SRC_LIST main.c) MESSAGE(STATUS "This is BINARY dir " ${HELLO_BINARY_DIR}) MESSAGE(STATUS "This is SOURCE dir "${HELLO_SOURCE_DIR}) ADD_EXECUTABLE(hello SRC_LIST) ``` ###2,開始構建所有的文件 創建完成后,t1目錄中應該存在main.c和CMakeLists.txt兩個文件。接下來我們來構建這個工程,在這個目錄運行: ``` cmake . ( 注意命令后面的點號,代表本目錄)。 ``` 輸出大概是這個樣子: >-- Check for working C compiler: /usr/bin/gcc -- Check for working C compiler: /usr/bin/gcc -- works-- Check size of void* -- Check size of void* - done -- Check for working CXX compiler: /usr/bin/c++ -- Check for working CXX compiler: /usr/bin/c++ -- works-- This is BINARY dir /backup/cmake/t1 -- This is SOURCE dir /backup/cmake/t1-- Configuring done -- Generating done -- Build files have been written to: /backup/cmake/t1 再讓我們看一下目錄中的內容:你會發現,系統自動生成了:CMakeFiles, CMakeCache.txt, cmake_install.cmake 等文件,并且生成了Makefile. 現在不需要理會這些文件的作用,以后你也可以不去理會。最關鍵的是,它自動生成了 Makefile. 然后進行工程的實際構建,在這個目錄輸入make 命令,大概會得到如下的彩色輸出: >Scanning dependencies of target hello [100%] Building C object CMakeFiles/hello.dir/main.o Linking C executable hello [100%] Built target hello 如果你需要看到make 構建的詳細過程,可以使用make VERBOSE=1 或者VERBOSE=1 make 命令來進行構建。 這時候,我們需要的目標文件hello 已經構建完成,位于當前目錄,嘗試運行一下:./hello 得到輸出: Hello World from Main 恭喜您,到這里為止您已經完全掌握了cmake 的使用方法。 ###3,簡單的解釋: 我們來重新看一下CMakeLists.txt ,這個文件是cmake 的構建定義文件,文件名是大小寫相關的,如果工程存在多個目錄,需要確保每個要管理的目錄都存在一個CMakeLists.txt。(關于多目錄構建,后面我們會提到,這里不作過多解釋)。上面例子中的CMakeLists.txt 文件內容如下: ``` PROJECT (HELLO)SET(SRC_LIST main.c) MESSAGE(STATUS "This is BINARY dir " ${HELLO_BINARY_DIR}) MESSAGE(STATUS "This is SOURCE dir "${HELLO_SOURCE_DIR}) ADD_EXECUTABLE(hello ${SRC_LIST}) ``` - PROJECT 指令的語法是: PROJECT(projectname [CXX] [C] [Java]) 你可以用這個指令定義工程名稱,并可指定工程支持的語言,支持的語言列表是可以忽略的,默認情況表示支持所有語言。 這個指令隱式的定義了兩個cmake 變量: <projectname>_BINARY_DIR 以及<projectname>_SOURCE_DIR ,這里就是HELLO_BINARY_DIR 和HELLO_SOURCE_DIR( 所以CMakeLists.txt 中兩個MESSAGE 指令可以直接使用了這兩個變量),因為采用的是內部編譯,兩個變量目前指的都是工程所在路徑/backup/cmake/t1 ,后面我們會講到外部編譯,兩者所指代的內容會有所不同。 同時cmake 系統也幫助我們預定義了PROJECT_BINARY_DIR 和PROJECT_SOURCE_DIR 變量,他們的值分別跟HELLO_BINARY_DIR 與HELLO_SOURCE_DIR 一致。 為了統一起見,建議以后直接使用PROJECT_BINARY_DIR,PROJECT_SOURCE_DIR,即使修改了工程名稱,也不會影響這兩個變量。如果使用了<projectname>_SOURCE_DIR ,修改工程名稱后,需要同時修改這些變量。 - SET 指令的語法是: SET(VAR [VALUE] [CACHE TYPE DOCSTRING[FORCE]]) 現階段,你只需要了解SET指令可以用來顯式的定義變量即可。比如我們用到的是SET(SRC_LIST main.c),如果有多個源文件,也可以定義成:SET(SRC_LIST main.c t1.c t2.c) 。 - MESSAGE 指令的語法是: MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] "message to display" ...) 這個指令用于向終端輸出用戶定義的信息,包含了三種類型: SEND_ERROR,產生錯誤,生成過程被跳過。 SATUS,輸出前綴為—的信息。 FATAL_ERROR,立即終止所有 cmake 過程。 我們在這里使用的是 STATUS 信息輸出,演示了由 PROJECT 指令定義的兩個隱式變量 HELLO_BINARY_DIR 和 HELLO_SOURCE_DIR。 FATAL_ERROR,立即終止所有cmake 過程. - ADD_EXECUTABLE(hello ${SRC_LIST}) 定義了這個工程會生成一個文件名為hello的可執行文件,相關的源文件是SRC_LIST 中定義的源文件列表,本例中你也可以直接寫成ADD_EXECUTABLE(hello main.c) 。 在本例我們使用了${}來引用變量,這是cmake的變量應用方式,但是,有一些例外,比如在IF控制語句,變量是直接使用變量名引用,而不需要${}。如果使用了${}去應用變量,其實IF會去判斷名為${}所代表的值的變量,那當然是不存在的了。 將本例改寫成一個最簡化的CMakeLists.txt: ``` PROJECT(HELLO) ADD_EXECUTABLE(hello main.c) ``` ###4,基本語法規則 前面提到過,cmake 其實仍然要使用“cmake語言和語法”去構建,上面的內容就是所謂的“cmake語言和語法”,最簡單的語法規則是: * 1,變量使用${}方式取值,但是在IF控制語句中是直接使用變量名 * 2,指令(參數1 參數2...) 參數使用括弧括起,參數之間使用空格或分號分開。以上面的ADD_EXECUTABLE 指令為例,如果存在另外一個func.c 源文件,就要寫成: `ADD_EXECUTABLE(hello main.c func.c) `或者`ADD_EXECUTABLE(hello main.c;func.c) ` * 3,指令是大小寫無關的,參數和變量是大小寫相關的。但,推薦你全部使用大寫指令。 上面的MESSAGE 指令我們已經用到了這條規則:`MESSAGE(STATUS “This is BINARY dir” ${HELLO_BINARY_DIR})` 也可以寫成: ``` MESSAGE(STATUS “This is BINARY dir ${HELLO_BINARY_DIR}”) ``` 這里需要特別解釋的是作為工程名的HELLO 和生成的可執行文件hello 是沒有任何關系的。hello定義了可執行文件的文件名,你完全可以寫成:ADD_EXECUTABLE(t1 main.c) 編譯后會生成一個t1可執行文件。 ###5,關于語法的疑惑 cmake 的語法還是比較靈活而且考慮到各種情況,比如SET(SRC_LIST main.c) 也可以寫成SET(SRC_LIST “main.c”) 是沒有區別的,但是假設一個源文件的文件名是`fu nc.c`( 文件名中間包含了空格)。這時候就必須使用雙引號,如果寫成了SET(SRC_LIST fu nc.c) ,就會出現錯誤,提示 你找不到fu文件和nc.c文件。這種情況,就必須寫成: SET(SRC_LIST “fu nc.c”) 此外,你可以可以忽略掉source 列表中的源文件后綴,比如可以寫成 ADD_EXECUTABLE(t1 main),cmake會自動的在本目錄查找main.c或者main.cpp等,當然,最好不要偷這個懶,以免這個目錄確實存在一個main.c 一個main. 同時參數也可以使用分號來進行分割。下面的例子也是合法的:`ADD_EXECUTABLE(t1 main.c t1.c) `可以寫成ADD_EXECUTABLE(t1 main.c;t1.c).我們只需要在編寫CMakeLists.txt 時注意形成統一的風格即可。 ###6,清理工程: 跟經典的autotools 系列工具一樣,運行:make clean 即可對構建結果進行清理。 ###7,問題?問題! “我嘗試運行了make distclean ,這個指令一般用來清理構建過程中產生的中間文件的,如果要發布代碼,必然要清理掉所有的中間文件,但是為什么在cmake工程中這個命令是無效的?” 是的,cmake 并不支持make distclean,關于這一點,官方是有明確解釋的: 因為CMakeLists.txt可以執行腳本并通過腳本生成一些臨時文件,但是卻沒有辦法來跟蹤這些臨時文件到底是哪些。因此,沒有辦法提供一個可靠的make distclean 方案。 >Some build trees created with GNU autotools have a "makedistclean" target that cleans the build and also removes Makefilesand other parts of the generated build system. CMake does notgenerate a "make distclean" target because CMakeLists.txt filescan run scripts and arbitrary commands; CMake has no way oftracking exactly which files are generated as part of running CMake. Providing a distclean target would give users the falseimpression that it would work as expected. (CMake does generate a"make clean" target to remove files generated by the compiler andlinker.) >A "make distclean" target is only necessary if the user performsan in-source build. CMake supports in-source builds, but westrongly encourage users to adopt the notion of an out-of-sourcebuild. Using a build tree that is separate from the source treewill prevent CMake from generating any files in the source tree.Because CMake does not change the source tree, there is no needfor a distclean target. One can start a fresh build by deletingthe build tree or creating a separate build tree. 同時,還有另外一個非常重要的提示,就是:我們剛才進行的是內部構建(in-source build) ,而cmake 強烈推薦的是外部構建(out-of-source build) 。 ###8,內部構建與外部構建 上面的例子展示的是“內部構建”,相信看到生成的臨時文件比您的代碼文件還要多的時候,估計這輩子你都不希望再使用內部構建:-D 舉個簡單的例子來說明外部構建,以編譯wxGTK動態庫和靜態庫為例,在Everest 中打包方式是這樣的: 解開wxGTK 后。 在其中建立static 和shared 目錄。 進入static 目錄,運行../configure –enable-static;make 會在static 目錄生成wxGTK 的靜態庫。 進入shared 目錄,運行../configure –enable-shared;make 就會在shared 目錄生成動態庫。 這就是外部編譯的一個簡單例子。 對于cmake,內部編譯上面已經演示過了,它生成了一些無法自動刪除的中間文件,所以,引出了我們對外部編譯的探討,外部編譯的過程如下: * 1,首先,請清除t1目錄中除main.c CmakeLists.txt 之外的所有中間文件,最關鍵的是CMakeCache.txt 。 * 2,在t1目錄中建立build 目錄,當然你也可以在任何地方建立build 目錄,不一定必須在工程目錄中。 * 3,進入build 目錄,運行cmake ..( 注意,..代表父目錄,因為父目錄存在我們需要的CMakeLists.txt ,如果你在其他地方建立了build 目錄,需要運行cmake < 工程的全路徑>),查看一下build 目錄,就會發現了生成了編譯需要的Makefile 以及其他的中間文件. * 4,運行make構建工程,就會在當前目錄(build 目錄)中獲得目標文件hello 。 上述過程就是所謂的out-of-source 外部編譯,一個最大的好處是,對于原有的工程沒有任何影響,所有動作全部發生在編譯目錄。通過這一點,也足以說服我們全部采用外部編譯方式構建工程。這里需要特別注意的是: 通過外部編譯進行工程構建,HELLO_SOURCE_DIR 仍然指代工程路徑,即/backup/cmake/t1 而HELLO_BINARY_DIR 則指代編譯路徑,即/backup/cmake/t1/build ###9,小結 本小節描述了使用cmake 構建Hello World程序的全部過程,并介紹了三個簡單的指令: `PROJECT/``MESSAGE`/`ADD_EXECUTABLE` 以及變量調用的方法,同時提及了兩個隱式變量<projectname>_SOURCE_DIR 及<projectname>_BINARY_DIR,演示了變量調用的方法,從這個過程來看,有些開發者可能會想,這實在比我直接寫Makefile 要復雜多了,甚至我都可以不編寫Makefile ,直接使用`gcc main.c`即可生成需要的目標文件。是的,正如第一節提到的,如果工程只有幾個文件,還是直接編寫Makefile 最簡單。但是,kdelibs 壓縮包達到了50多M,您認為使用什么方案會更容易一點呢? 下一節,我們的任務是讓HelloWorld看起來更像一個工程。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看