首页 > 解决方案 > cmake Xcode 生成器在发布模式下使用 -O0 代替 -O3 或 -O2

问题描述

背景

我有一些大型多平台 C++ 项目,它在 Windows/MacOS/Linux (msvc/clang/clang) 上运行。由于项目很大,我无法提供 [mcve]。-O3我正在尝试,这样的示例使用标志构建。

对于 MacOS 项目以这种方式构建:

mkdir build_release
cd build_release
cmake -G Xcode -DCMAKE_BUILD_TYPE=Release ..
cmake --build . --config Release -j 8

制作

$ cmake --version
cmake version 3.19.6

CMake suite maintained and supported by Kitware (kitware.com/cmake).

$ clang++ --version
Apple clang version 12.0.0 (clang-1200.0.32.29)
Target: x86_64-apple-darwin19.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

Xcode 12.4 (12D4e)

问题

在构建日志中,我注意到它-O0被用来代替-O3-O2!!!

所以我检查了我的 CMakeLists.txt 文件以找到解释:

$ git grep -E "CMAKE_C(XX)?_FLAGS"
CMake/build_flags_override.cmake:    init_and_replace_flags(CMAKE_CXX_FLAGS_DEBUG "/MDd" "/MTd")
CMake/build_flags_override.cmake:    init_and_replace_flags(CMAKE_CXX_FLAGS_RELEASE "/MD" "/MT")
CMake/build_flags_override.cmake:    init_and_replace_flags(CMAKE_CXX_FLAGS "/MD" "/MT")
CMake/build_flags_override.cmake:    init_and_replace_flags(CMAKE_C_FLAGS_DEBUG "/MDd" "/MTd")
CMake/build_flags_override.cmake:    init_and_replace_flags(CMAKE_C_FLAGS_RELEASE "/MD" "/MT")
CMake/build_flags_override.cmake:    init_and_replace_flags(CMAKE_C_FLAGS "/MD" "/MT")
CMake/macostools.cmake:        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fobjc-arc" PARENT_SCOPE)
CMake/macostools.cmake:        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fobjc-arc" PARENT_SCOPE)
CMakeLists.txt:    set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -g -DNDEBUG")
CMakeLists.txt:    set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -g -DNDEBUG")
CMakeLists.txt:        set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /bigobj")

所以优化级别没有调整。

所有目标(除了一个)都是常规的 cmake 目标(不使用空间配置默认设置)。唯一不同的配置如下:

add_executable(MyTarget)

set_target_properties(MyTarget PROPERTIES
    OUTPUT_NAME "Product name"
    MACOSX_BUNDLE TRUE
    MACOSX_BUNDLE_BUNDLE_NAME "Product name"
    MACOSX_BUNDLE_INFO_PLIST ${PRODUCT_CONFIGURATION_DIR}/Info.plist
    MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}.0"
    MACOSX_BUNDLE_LONG_VERSION_STRING "Product name v${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}.0"
    MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}.0"
    MACOSX_BUNDLE_GUI_IDENTIFIER "com.product.identifier"
    MACOSX_BUNDLE_COPYRIGHT "(C) ${EI_CURRENT_YEAR} Company name"
    MACOSX_RPATH TRUE
    MACOSX_FRAMEWORK_IDENTIFIER com.product.identifier
    XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@loader_path/Libraries"
    RESOURCE "${RESOURCE_FILES}"
    XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME TRUE
    XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ""
    XCODE_ATTRIBUTE_EXECUTABLE_NAME "exe_name"
    XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT[variant=Release] dwarf-with-dsym
)

更烦人的是明确添加-O3并且CMAKE_C_FLAGS_RELEASE不会CMAKE_CXX_FLAGS_RELEASE改变情况。

我不知道发生了什么。我敢肯定几个月前它很好,现在优化被禁用了。我不知道问题是由软件更新或CMakeList.txt.

我想避免 git 二进制搜索,因为配置过程非常耗时(涉及 git 子模块)。

问题

有谁知道这个问题的根源和/或如何克服它?

线索

在 Windows 和 Linux 上都很好。

当我在 MacOS ( make)上使用默认生成器时,使用了-G Xcode适当的优化标志 ( -O3)。我会很高兴,但在这种情况下cmake,无法利用XCODE_ATTRIBUTE_*在最终目标上设置的属性,这不符合我的要求。

标签: c++xcodecmake

解决方案


问题原来是订单。

我刚刚移动了这部分:

set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -g -DNDEBUG")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -g -DNDEBUG")

归根结底,CMakeLists.txt一切都按预期进行。

我注意到在它最初(更改之前)的位置$CMAKE_CXX_FLAGS_RELEASE是空的。当我将语句移动到(更改之前)的底部原始值时,$CMAKE_CXX_FLAGS_RELEASE包含-O3.

我不知道这两个位置之间可能会产生这种影响。这两个地方之间没有任何东西显式地改变了这个变量。


推荐阅读