<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>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 5.6 探究編譯和鏈接命令 **NOTE**:*此示例代碼可以在 https://github.com/dev-cafe/cmake-cookbook/tree/v1.0/chapter-5/recipe-06 中找到,其中包含一個C++例子。該示例在CMake 3.9版(或更高版本)中是有效的,并且已經在GNU/Linux、macOS和Windows上進行過測試。代碼庫還有一個與CMake 3.5兼容的示例。* 生成構建系統期間最常見的操作,是試圖評估在哪種系統上構建項目。這意味著要找出哪些功能工作,哪些不工作,并相應地調整項目的編譯。使用的方法是查詢依賴項是否被滿足的信號,或者在代碼庫中是否啟用工作區。接下來的幾個示例,將展示如何使用CMake執行這些操作。我們將特別討論以下事宜: 1. 如何確保代碼能成功編譯為可執行文件。 2. 如何確保編譯器理解相應的標志。 3. 如何確保特定代碼能成功編譯為運行可執行程序。 ## 準備工作 示例將展示如何使用來自對應的` Check<LANG>SourceCompiles.cmake`標準模塊的`check_<lang>_source_compiles`函數,以評估給定編譯器是否可以將預定義的代碼編譯成可執行文件。該命令可幫助你確定: * 編譯器支持所需的特性。 * 鏈接器工作正常,并理解特定的標志。 * 可以使用`find_package`找到的包含目錄和庫。 本示例中,我們將展示如何檢測OpenMP 4.5標準的循環特性,以便在C++可執行文件中使用。使用一個C++源文件,來探測編譯器是否支持這樣的特性。CMake提供了一個附加命令`try_compile`來探究編譯。本示例將展示,如何使用這兩種方法。 **TIPS**:*可以使用CMake命令行界面來獲取關于特定模塊(` cmake --help-module <module-name>`)和命令(`cmake --help-command <command-name>`)的文檔。示例中,` cmake --help-module CheckCXXSourceCompiles`將把`check_cxx_source_compiles`函數的文檔輸出到屏幕上,而` cmake --help-command try_compile`將對`try_compile`命令執行相同的操作。* ## 具體實施 我們將同時使用`try_compile`和`check_cxx_source_compiles`,并比較這兩個命令的工作方式: 1. 創建一個C++11工程: ```cmake cmake_minimum_required(VERSION 3.9 FATAL_ERROR) project(recipe-06 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_STANDARD_REQUIRED ON) ``` 2. 查找編譯器支持的OpenMP: ```cmake find_package(OpenMP) if(OpenMP_FOUND) # ... <- the steps below will be placed here else() message(STATUS "OpenMP not found: no test for taskloop is run") endif() ``` 3. 如果找到OpenMP,再檢查所需的特性是否可用。為此,設置了一個臨時目錄,`try_compile`將在這個目錄下來生成中間文件。我們把它放在前面步驟中引入的`if`語句中: ```cmake set(_scratch_dir ${CMAKE_CURRENT_BINARY_DIR}/omp_try_compile) ``` 4. 調用`try_compile`生成一個小項目,以嘗試編譯源文件`taskloop.cpp`。編譯成功或失敗的狀態,將保存到`omp_taskloop_test_1`變量中。需要為這個示例編譯設置適當的編譯器標志、包括目錄和鏈接庫。因為使用導入的目標`OpenMP::OpenMP_CXX`,所以只需將`LINK_LIBRARIES`選項設置為`try_compile`即可。如果編譯成功,則任務循環特性可用,我們為用戶打印一條消息: ```cmake try_compile( omp_taskloop_test_1 ${_scratch_dir} SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/taskloop.cpp LINK_LIBRARIES OpenMP::OpenMP_CXX ) message(STATUS "Result of try_compile: ${omp_taskloop_test_1}") ``` 5. 要使用`check_cxx_source_compiles`函數,需要包含`CheckCXXSourceCompiles.cmake`模塊文件。其他語言也有類似的模塊文件,C(`CheckCSourceCompiles.cmake`)和Fortran(`CheckFortranSourceCompiles.cmake`): ```cmake include(CheckCXXSourceCompiles) ``` 6. 我們復制源文件的內容,通過` file(READ ...)`命令讀取內容到一個變量中,試圖編譯和連接這個變量: ```cmake file(READ ${CMAKE_CURRENT_SOURCE_DIR}/taskloop.cpp _snippet) ``` 7. 我們設置了`CMAKE_REQUIRED_LIBRARIES`。這對于下一步正確調用編譯器是必需的。注意使用導入的`OpenMP::OpenMP_CXX`目標,它還將設置正確的編譯器標志和包含目錄: ```cmake set(CMAKE_REQUIRED_LIBRARIES OpenMP::OpenMP_CXX) ``` 8. 使用代碼片段作為參數,調用`check_cxx_source_compiles`函數。檢查結果將保存到`omp_taskloop_test_2`變量中: ```cmake check_cxx_source_compiles("${_snippet}" omp_taskloop_test_2) ``` 9. 調用`check_cxx_source_compiles`并向用戶打印消息之前,我們取消了變量的設置: ```cmake unset(CMAKE_REQUIRED_LIBRARIES) message(STATUS "Result of check_cxx_source_compiles: ${omp_taskloop_test_2}" ``` 10. 最后,進行測試: ```shell $ mkdir -p build $ cd build $ cmake .. -- ... -- Found OpenMP_CXX: -fopenmp (found version "4.5") -- Found OpenMP: TRUE (found version "4.5") -- Result of try_compile: TRUE -- Performing Test omp_taskloop_test_2 -- Performing Test omp_taskloop_test_2 - Success -- Result of check_cxx_source_compiles: 1 ``` ## 工作原理 `try_compile`和`check_cxx_source_compiles`都將編譯源文件,并將其鏈接到可執行文件中。如果這些操作成功,那么輸出變量`omp_task_loop_test_1`(前者)和`omp_task_loop_test_2`(后者)將被設置為`TRUE`。然而,這兩個命令實現的方式略有不同。`check_<lang>_source_compiles`命令是`try_compile`命令的簡化包裝。因此,它提供了一個接口: 1. 要編譯的代碼片段必須作為CMake變量傳入。大多數情況下,這意味著必須使用`file(READ ...)`來讀取文件。然后,代碼片段被保存到構建目錄的`CMakeFiles/CMakeTmp`子目錄中。 2. 微調編譯和鏈接,必須通過設置以下CMake變量進行: * CMAKE_REQUIRED_FLAGS:設置編譯器標志。 * CMAKE_REQUIRED_DEFINITIONS:設置預編譯宏。 * CMAKE_REQUIRED_INCLUDES:設置包含目錄列表。 * CMAKE_REQUIRED_LIBRARIES:設置可執行目標能夠連接的庫列表。 3. 調用`check_<lang>_compiles_function`之后,必須手動取消對這些變量的設置,以確保后續使用中,不會保留當前內容。 **NOTE**:*使用CMake 3.9中可以對于OpenMP目標進行導入,但是目前的配置也可以使用CMake的早期版本,通過手動為`check_cxx_source_compiles`設置所需的標志和庫:`set(CMAKE_REQUIRED_FLAGS ${OpenMP_CXX_FLAGS})`和`set(CMAKE_REQUIRED_LIBRARIES ${OpenMP_CXX_LIBRARIES})`。* **TIPS**:*Fortran下,CMake代碼的格式通常是固定的,但也有意外情況。為了處理這些意外,需要為`check_fortran_source_compiles`設置`-ffree-form`編譯標志。可以通過`set(CMAKE_REQUIRED_FLAGS “-ffree-form")`實現。* 這個接口反映了:測試編譯是通過,在CMake調用中直接生成和執行構建和連接命令來執行的。 命令`try_compile`提供了更完整的接口和兩種不同的操作模式: 1. 以一個完整的CMake項目作為輸入,并基于它的`CMakeLists.txt`配置、構建和鏈接。這種操作模式提供了更好的靈活性,因為要編譯項目的復雜度是可以選擇的。 2. 提供了源文件,和用于包含目錄、鏈接庫和編譯器標志的配置選項。 因此,`try_compile`基于在項目上調用CMake,其中`CMakeLists.txt`已經存在(在第一種操作模式中),或者基于傳遞給`try_compile`的參數動態生成文件。 ## 更多信息 本示例中概述的類型檢查并不總是萬無一失的,并且可能產生假陽性和假陰性。作為一個例子,可以嘗試注釋掉包含`CMAKE_REQUIRED_LIBRARIES`的行。運行這個例子仍然會報告“成功”,這是因為編譯器將忽略OpenMP的`pragma`字段。 當返回了錯誤的結果時,應該怎么做?構建目錄的`CMakeFiles`子目錄中的`CMakeOutput.log`和`CMakeError.log`文件會提供一些線索。它們記錄了CMake運行的操作的標準輸出和標準錯誤。如果懷疑結果有誤,應該通過搜索保存編譯檢查結果的變量集來檢查前者。如果你懷疑有誤報,你應該檢查后者。 調試`try_compile`需要一些注意事項。即使檢查不成功,CMake也會刪除由該命令生成的所有文件。幸運的是,`debug-trycompile`將阻止CMake進行刪除。如果你的代碼中有多個`try_compile`調用,一次只能調試一個: 1. 運行CMake,不使用`--debug-trycompile`,將運行所有`try_compile`命令,并清理它們的執行目錄和文件。 2. 從CMake緩存中刪除保存檢查結果的變量。緩存保存到`CMakeCache.txt`文件中。要清除變量的內容,可以使用`-U `的CLI開關,后面跟著變量的名稱,它將被解釋為一個全局表達式,因此可以使用`*`和`?`: ```shell $ cmake -U <variable-name> ``` 3. 再次運行CMake,使用`--debug-trycompile`。只有清除緩存的檢查才會重新運行。這次不會清理執行目錄和文件。 **TIPS**:*`try_compile`提供了靈活和干凈的接口,特別是當編譯的代碼不是一個簡短的代碼時。我們建議在測試編譯時,小代碼片段時使用`check_<lang>_source_compile`。其他情況下,選擇`try_compile`。*
                  <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>

                              哎呀哎呀视频在线观看