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

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # 7.3 編寫函數來測試和設置編譯器標志 **NOTE**:*此示例代碼可以在 https://github.com/dev-cafe/cmake-cookbook/tree/v1.0/chapter-7/recipe-03 中找到,其中包含一個C/C++示例。該示例在CMake 3.5版(或更高版本)中是有效的,并且已經在GNU/Linux、macOS和Windows上進行過測試。* 前兩個示例中,我們使用了宏。本示例中,將使用一個函數來抽象細節并避免代碼重復。我們將實現一個接受編譯器標志列表的函數。該函數將嘗試用這些標志逐個編譯測試代碼,并返回編譯器理解的第一個標志。這樣,我們將了解幾個新特性:函數、列表操作、字符串操作,以及檢查編譯器是否支持相應的標志。 ## 準備工作 按照上一個示例的推薦,我們將在(`set_compiler_flag.cmake`)模塊中定義函數,然后調用函數。該模塊包含以下代碼,我們將在后面詳細討論: ``` cmake include(CheckCCompilerFlag) include(CheckCXXCompilerFlag) include(CheckFortranCompilerFlag) function(set_compiler_flag _result _lang) # build a list of flags from the arguments set(_list_of_flags) # also figure out whether the function # is required to find a flag set(_flag_is_required FALSE) foreach(_arg IN ITEMS ${ARGN}) string(TOUPPER "${_arg}" _arg_uppercase) if(_arg_uppercase STREQUAL "REQUIRED") set(_flag_is_required TRUE) else() list(APPEND _list_of_flags "${_arg}") endif() endforeach() set(_flag_found FALSE) # loop over all flags, try to find the first which works foreach(flag IN ITEMS ${_list_of_flags}) unset(_flag_works CACHE) if(_lang STREQUAL "C") check_c_compiler_flag("${flag}" _flag_works) elseif(_lang STREQUAL "CXX") check_cxx_compiler_flag("${flag}" _flag_works) elseif(_lang STREQUAL "Fortran") check_Fortran_compiler_flag("${flag}" _flag_works) else() message(FATAL_ERROR "Unknown language in set_compiler_flag: ${_lang}") endif() # if the flag works, use it, and exit # otherwise try next flag if(_flag_works) set(${_result} "${flag}" PARENT_SCOPE) set(_flag_found TRUE) break() endif() endforeach() # raise an error if no flag was found if(_flag_is_required AND NOT _flag_found) message(FATAL_ERROR "None of the required flags were supported") endif() endfunction() ``` ## 具體實施 展示如何在CMakeLists.txt中使用`set_compiler_flag`函數: 1. 定義最低CMake版本、項目名稱和支持的語言(本例中是C和C++): ```cmake cmake_minimum_required(VERSION 3.5 FATAL_ERROR) project(recipe-03 LANGUAGES C CXX) ``` 2. 顯示包含`set_compiler_flag.cmake`: ```cmake include(set_compiler_flag.cmake) ``` 3. 測試C標志列表: ```cmake set_compiler_flag( working_compile_flag C REQUIRED "-foo" # this should fail "-wrong" # this should fail "-wrong" # this should fail "-Wall" # this should work with GNU "-warn all" # this should work with Intel "-Minform=inform" # this should work with PGI "-nope" # this should fail ) message(STATUS "working C compile flag: ${working_compile_flag}") ``` 4. 測試C++標志列表: ```cmake set_compiler_flag( working_compile_flag CXX REQUIRED "-foo" # this should fail "-g" # this should work with GNU, Intel, PGI "/RTCcsu" # this should work with MSVC ) message(STATUS "working CXX compile flag: ${working_compile_flag}") ``` 5. 現在,我們可以配置項目并驗證輸出。只顯示相關的輸出,相應的輸出可能會因編譯器的不同而有所不同: ```shell $ mkdir -p build $ cd build $ cmake .. -- ... -- Performing Test _flag_works -- Performing Test _flag_works - Failed -- Performing Test _flag_works -- Performing Test _flag_works - Failed -- Performing Test _flag_works -- Performing Test _flag_works - Failed -- Performing Test _flag_works -- Performing Test _flag_works - Success -- working C compile flag: -Wall -- Performing Test _flag_works -- Performing Test _flag_works - Failed -- Performing Test _flag_works -- Performing Test _flag_works - Success -- working CXX compile flag: -g -- ... ``` ## 工作原理 這里使用的模式是: 1. 定義一個函數或宏,并將其放入模塊中 2. 包含模塊 3. 調用函數或宏 從輸出中,可以看到代碼檢查列表中的每個標志。一旦檢查成功,它就打印成功的編譯標志。看看`set_compiler_flag.cmake`模塊的內部,這個模塊又包含三個模塊: ```cmake include(CheckCCompilerFlag) include(CheckCXXCompilerFlag) include(CheckFortranCompilerFlag) ``` 這都是標準的CMake模塊,CMake將在`${CMAKE_MODULE_PATH}`中找到它們。這些模塊分別提供`check_c_compiler_flag`、`check_cxx_compiler_flag`和`check_fortran_compiler_flag`宏。然后定義函數: ```cmake function(set_compiler_flag _result _lang) ... endfunction() ``` `set_compiler_flag`函數需要兩個參數,`_result`(保存成功編譯標志或為空字符串)和`_lang`(指定語言:C、C++或Fortran)。 我們也能這樣調用函數: ```cmake set_compiler_flag(working_compile_flag C REQUIRED "-Wall" "-warn all") ``` 這里有五個調用參數,但是函數頭只需要兩個參數。這意味著`REQUIRED`、`-Wall`和`-warn all`將放在`${ARGN}`中。從`${ARGN}`開始,我們首先使用`foreach`構建一個標志列表。同時,從標志列表中過濾出`REQUIRED`,并使用它來設置`_flag_is_required`: ```cmake # build a list of flags from the arguments set(_list_of_flags) # also figure out whether the function # is required to find a flag set(_flag_is_required FALSE) foreach(_arg IN ITEMS ${ARGN}) string(TOUPPER "${_arg}" _arg_uppercase) if(_arg_uppercase STREQUAL "REQUIRED") set(_flag_is_required TRUE) else() list(APPEND _list_of_flags "${_arg}") endif() endforeach() ``` 現在,我們將循環`${_list_of_flags}`,嘗試每個標志,如果`_flag_works`被設置為`TRUE`,我們將`_flag_found`設置為`TRUE`,并中止進一步的搜索: ```cmake set(_flag_found FALSE) # loop over all flags, try to find the first which works foreach(flag IN ITEMS ${_list_of_flags}) unset(_flag_works CACHE) if(_lang STREQUAL "C") check_c_compiler_flag("${flag}" _flag_works) elseif(_lang STREQUAL "CXX") check_cxx_compiler_flag("${flag}" _flag_works) elseif(_lang STREQUAL "Fortran") check_Fortran_compiler_flag("${flag}" _flag_works) else() message(FATAL_ERROR "Unknown language in set_compiler_flag: ${_lang}") endif() # if the flag works, use it, and exit # otherwise try next flag if(_flag_works) set(${_result} "${flag}" PARENT_SCOPE) set(_flag_found TRUE) break() endif() endforeach() ``` `unset(_flag_works CACHE)`確保`check_*_compiler_flag`的結果,不會在使用`_flag_works result`變量時,使用的是緩存結果。 如果找到了標志,并且`_flag_works`設置為`TRUE`,我們就將`_result`映射到的變量: ```cmake set(${_result} "${flag}" PARENT_SCOPE) ``` 這需要使用`PARENT_SCOPE`來完成,因為我們正在修改一個變量,希望打印并在函數體外部使用該變量。請注意,如何使用`${_result}`語法解引用,從父范圍傳遞的變量`_result`的值。不管函數的名稱是什么,這對于確保工作標志被設置非常有必要。如果沒有找到任何標志,并且該標志設置了`REQUIRED`,那我們將使用一條錯誤消息停止配置: ```cmake # raise an error if no flag was found if(_flag_is_required AND NOT _flag_found) message(FATAL_ERROR "None of the required flags were supported") endif() ``` ## 更多信息 我們也可以使用宏來完成這個任務,而使用函數可以對范圍有更多的控制。我們知道函數只能可以修改結果變量。 另外,需要在編譯和鏈接時設置一些標志,方法是為`check_<lang>_compiler_flag`函數設置`CMAKE_REQUIRED_FLAGS`。如第5章,第7節中討論的那樣,Sanitizer就是這種情況。
                  <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>

                              哎呀哎呀视频在线观看