<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國際加速解決方案。 廣告
                # 1.8 設置編譯器選項 **NOTE**:*此示例代碼可以在 https://github.com/dev-cafe/cmake-cookbook/tree/v1.0/chapter-01/recipe-08 中找到,有一個C++示例。該示例在CMake 3.5版(或更高版本)中是有效的,并且已經在GNU/Linux、macOS和Windows上進行過測試。* 前面的示例展示了如何探測CMake,從而獲得關于編譯器的信息,以及如何切換項目中的編譯器。后一個任務是控制項目的編譯器標志。CMake為調整或擴展編譯器標志提供了很大的靈活性,您可以選擇下面兩種方法: * CMake將編譯選項視為目標屬性。因此,可以根據每個目標設置編譯選項,而不需要覆蓋CMake默認值。 * 可以使用`-D`CLI標志直接修改`CMAKE_<LANG>_FLAGS_<CONFIG>`變量。這將影響項目中的所有目標,并覆蓋或擴展CMake默認值。 本示例中,我們將展示這兩種方法。 ## 準備工作 編寫一個示例程序,計算不同幾何形狀的面積,`computer_area.cpp`: ```c++ #include "geometry_circle.hpp" #include "geometry_polygon.hpp" #include "geometry_rhombus.hpp" #include "geometry_square.hpp" #include <cstdlib> #include <iostream> int main() { using namespace geometry; double radius = 2.5293; double A_circle = area::circle(radius); std::cout << "A circle of radius " << radius << " has an area of " << A_circle << std::endl; int nSides = 19; double side = 1.29312; double A_polygon = area::polygon(nSides, side); std::cout << "A regular polygon of " << nSides << " sides of length " << side << " has an area of " << A_polygon << std::endl; double d1 = 5.0; double d2 = 7.8912; double A_rhombus = area::rhombus(d1, d2); std::cout << "A rhombus of major diagonal " << d1 << " and minor diagonal " << d2 << " has an area of " << A_rhombus << std::endl; double l = 10.0; double A_square = area::square(l); std::cout << "A square of side " << l << " has an area of " << A_square << std::endl; return EXIT_SUCCESS; } ``` 函數的各種實現分布在不同的文件中,每個幾何形狀都有一個頭文件和源文件。總共有4個頭文件和5個源文件要編譯: ```shell . ├─ CMakeLists.txt ├─ compute-areas.cpp ├─ geometry_circle.cpp ├─ geometry_circle.hpp ├─ geometry_polygon.cpp ├─ geometry_polygon.hpp ├─ geometry_rhombus.cpp ├─ geometry_rhombus.hpp ├─ geometry_square.cpp └─ geometry_square.hpp ``` 我們不會為所有文件提供清單,讀者可以參考 https://github.com/dev-cafe/cmake-cookbook/tree/v1.0/chapter-01/recipe-08 。 ## 具體實施 現在已經有了源代碼,我們的目標是配置項目,并使用編譯器標示進行實驗: 1. 設置CMake的最低版本: ```cmake cmake_minimum_required(VERSION 3.5 FATAL_ERROR) ``` 2. 聲明項目名稱和語言: ```cmake project(recipe-08 LANGUAGES CXX) ``` 3. 然后,打印當前編譯器標志。CMake將對所有C++目標使用這些: ```cmake message("C++ compiler flags: ${CMAKE_CXX_FLAGS}") ``` 4. 為目標準備了標志列表,其中一些將無法在Windows上使用: ```cmake list(APPEND flags "-fPIC" "-Wall") if(NOT WIN32) list(APPEND flags "-Wextra" "-Wpedantic") endif() ``` 5. 添加了一個新的目標——`geometry`庫,并列出它的源依賴關系: ```cmake add_library(geometry STATIC geometry_circle.cpp geometry_circle.hpp geometry_polygon.cpp geometry_polygon.hpp geometry_rhombus.cpp geometry_rhombus.hpp geometry_square.cpp geometry_square.hpp ) ``` 6. 為這個庫目標設置了編譯選項: ```cmake target_compile_options(geometry PRIVATE ${flags} ) ``` 7. 然后,將生成`compute-areas`可執行文件作為一個目標: ```cmkae add_executable(compute-areas compute-areas.cpp) ``` 8. 還為可執行目標設置了編譯選項: ```cmake target_compile_options(compute-areas PRIVATE "-fPIC" ) ``` 9. 最后,將可執行文件鏈接到geometry庫: ```cmake target_link_libraries(compute-areas geometry) ``` ## 如何工作 本例中,警告標志有`-Wall`、`-Wextra`和`-Wpedantic`,將這些標示添加到`geometry`目標的編譯選項中; `compute-areas`和 `geometry`目標都將使用`-fPIC`標志。編譯選項可以添加三個級別的可見性:`INTERFACE`、`PUBLIC`和`PRIVATE`。 可見性的含義如下: * **PRIVATE**,編譯選項會應用于給定的目標,不會傳遞給與目標相關的目標。我們的示例中, 即使`compute-areas`將鏈接到`geometry`庫,`compute-areas`也不會繼承`geometry`目標上設置的編譯器選項。 * **INTERFACE**,給定的編譯選項將只應用于指定目標,并傳遞給與目標相關的目標。 * **PUBLIC**,編譯選項將應用于指定目標和使用它的目標。 目標屬性的可見性CMake的核心,我們將在本書中經常討論這個話題。以這種方式添加編譯選項,不會影響全局CMake變量`CMAKE_<LANG>_FLAGS_<CONFIG>`,并能更細粒度控制在哪些目標上使用哪些選項。 我們如何驗證,這些標志是否按照我們的意圖正確使用呢?或者換句話說,如何確定項目在CMake構建時,實際使用了哪些編譯標志?一種方法是,使用CMake將額外的參數傳遞給本地構建工具。本例中會設置環境變量`VERBOSE=1`: ```shell $ mkdir -p build $ cd build $ cmake .. $ cmake --build . -- VERBOSE=1 ... lots of output ... [ 14%] Building CXX object CMakeFiles/geometry.dir/geometry_circle.cpp.o /usr/bin/c++ -fPIC -Wall -Wextra -Wpedantic -o CMakeFiles/geometry.dir/geometry_circle.cpp.o -c /home/bast/tmp/cmake-cookbook/chapter-01/recipe-08/cxx-example/geometry_circle.cpp [ 28%] Building CXX object CMakeFiles/geometry.dir/geometry_polygon.cpp.o /usr/bin/c++ -fPIC -Wall -Wextra -Wpedantic -o CMakeFiles/geometry.dir/geometry_polygon.cpp.o -c /home/bast/tmp/cmake-cookbook/chapter-01/recipe-08/cxx-example/geometry_polygon.cpp [ 42%] Building CXX object CMakeFiles/geometry.dir/geometry_rhombus.cpp.o /usr/bin/c++ -fPIC -Wall -Wextra -Wpedantic -o CMakeFiles/geometry.dir/geometry_rhombus.cpp.o -c /home/bast/tmp/cmake-cookbook/chapter-01/recipe-08/cxx-example/geometry_rhombus.cpp [ 57%] Building CXX object CMakeFiles/geometry.dir/geometry_square.cpp.o /usr/bin/c++ -fPIC -Wall -Wextra -Wpedantic -o CMakeFiles/geometry.dir/geometry_square.cpp.o -c /home/bast/tmp/cmake-cookbook/chapter-01/recipe-08/cxx-example/geometry_square.cpp ... more output ... [ 85%] Building CXX object CMakeFiles/compute-areas.dir/compute-areas.cpp.o /usr/bin/c++ -fPIC -o CMakeFiles/compute-areas.dir/compute-areas.cpp.o -c /home/bast/tmp/cmake-cookbook/chapter-01/recipe-08/cxx-example/compute-areas.cpp ... more output ... ``` 輸出確認編譯標志,確認指令設置正確。 控制編譯器標志的第二種方法,不用對`CMakeLists.txt`進行修改。如果想在這個項目中修改`geometry`和`compute-areas`目標的編譯器選項,可以使用CMake參數進行配置: ```shell $ cmake -D CMAKE_CXX_FLAGS="-fno-exceptions -fno-rtti" .. ``` 這個命令將編譯項目,禁用異常和運行時類型標識(RTTI)。 也可以使用全局標志,可以使用`CMakeLists.txt`運行以下命令: ```shell $ cmake -D CMAKE_CXX_FLAGS="-fno-exceptions -fno-rtti" .. ``` 這將使用`-fno-rtti - fpic - wall - Wextra - wpedantic`配置`geometry`目標,同時使用`-fno exception -fno-rtti - fpic`配置`compute-areas`。 **NOTE**:*本書中,我們推薦為每個目標設置編譯器標志。使用`target_compile_options()`不僅允許對編譯選項進行細粒度控制,而且還可以更好地與CMake的更高級特性進行集成。* ## 更多信息 大多數時候,編譯器有特性標示。當前的例子只適用于`GCC`和`Clang`;其他供應商的編譯器不確定是否會理解(如果不是全部)這些標志。如果項目是真正跨平臺,那么這個問題就必須得到解決,有三種方法可以解決這個問題。 最典型的方法是將所需編譯器標志列表附加到每個配置類型CMake變量`CMAKE_<LANG>_FLAGS_<CONFIG> `。標志確定設置為給定編譯器有效的標志,因此將包含在`if-endif`子句中,用于檢查`CMAKE_<LANG>_COMPILER_ID`變量,例如: ```cmake if(CMAKE_CXX_COMPILER_ID MATCHES GNU) list(APPEND CMAKE_CXX_FLAGS "-fno-rtti" "-fno-exceptions") list(APPEND CMAKE_CXX_FLAGS_DEBUG "-Wsuggest-final-types" "-Wsuggest-final-methods" "-Wsuggest-override") list(APPEND CMAKE_CXX_FLAGS_RELEASE "-O3" "-Wno-unused") endif() if(CMAKE_CXX_COMPILER_ID MATCHES Clang) list(APPEND CMAKE_CXX_FLAGS "-fno-rtti" "-fno-exceptions" "-Qunused-arguments" "-fcolor-diagnostics") list(APPEND CMAKE_CXX_FLAGS_DEBUG "-Wdocumentation") list(APPEND CMAKE_CXX_FLAGS_RELEASE "-O3" "-Wno-unused") endif() ``` 更細粒度的方法是,不修改` CMAKE_<LANG>_FLAGS_<CONFIG>`變量,而是定義特定的標志列表: ```cmake set(COMPILER_FLAGS) set(COMPILER_FLAGS_DEBUG) set(COMPILER_FLAGS_RELEASE) if(CMAKE_CXX_COMPILER_ID MATCHES GNU) list(APPEND CXX_FLAGS "-fno-rtti" "-fno-exceptions") list(APPEND CXX_FLAGS_DEBUG "-Wsuggest-final-types" "-Wsuggest-final-methods" "-Wsuggest-override") list(APPEND CXX_FLAGS_RELEASE "-O3" "-Wno-unused") endif() if(CMAKE_CXX_COMPILER_ID MATCHES Clang) list(APPEND CXX_FLAGS "-fno-rtti" "-fno-exceptions" "-Qunused-arguments" "-fcolor-diagnostics") list(APPEND CXX_FLAGS_DEBUG "-Wdocumentation") list(APPEND CXX_FLAGS_RELEASE "-O3" "-Wno-unused") endif() ``` 稍后,使用生成器表達式來設置編譯器標志的基礎上,為每個配置和每個目標生成構建系統: ```cmake target_compile_option(compute-areas PRIVATE ${CXX_FLAGS} "$<$<CONFIG:Debug>:${CXX_FLAGS_DEBUG}>" "$<$<CONFIG:Release>:${CXX_FLAGS_RELEASE}>" ) ``` 當前示例中展示了這兩種方法,我們推薦后者(特定于項目的變量和`target_compile_options`)。 兩種方法都有效,并在許多項目中得到廣泛應用。不過,每種方式都有缺點。`CMAKE_<LANG>_COMPILER_ID `不能保證為所有編譯器都定義。此外,一些標志可能會被棄用,或者在編譯器的較晚版本中引入。與`CMAKE_<LANG>_COMPILER_ID `類似,`CMAKE_<LANG>_COMPILER_VERSION`變量不能保證為所有語言和供應商都提供定義。盡管檢查這些變量的方式非常流行,但我們認為更健壯的替代方法是檢查所需的標志集是否與給定的編譯器一起工作,這樣項目中實際上只使用有效的標志。結合特定于項目的變量、`target_compile_options`和生成器表達式,會讓解決方案變得非常強大。我們將在第7章的第3節中展示,如何使用`check-and-set`模式。
                  <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>

                              哎呀哎呀视频在线观看