【问题标题】:cmake Xcode generator uses -O0 in release mode instead -O3 or -O2cmake Xcode 生成器在发布模式下使用 -O0 代替 -O3 或 -O2
【发布时间】:2021-03-11 16:17:58
【问题描述】:

背景

我有一些大型多平台 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

$ 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_RELEASECMAKE_CXX_FLAGS_RELEASE 不会改变情况。

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

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

问题

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

线索

在 Windows 和 Linux 上都可以。

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

【问题讨论】:

  • “由于项目很大,我无法提供minimal reproducible example。” - 拥有一个大项目绝对不妨碍提供minimal reproducible example。在标题中,您声称使用 -O0 的是 XCode:这可以通过简单的项目轻松检查,该项目只有 add_executable 调用而无需额外设置。
  • 我试图提供minimal reproducible example,这样的示例构建带有-O3 标志。我一直在尝试在小型项目中重现它,但很难发现可能在大型项目中导致这种情况的细节。如果我可以重现它,那么我很可能可以修复它。
  • 我已经展示了什么是相关的 cmake 变量以及它们是如何被修改的。我已经指出,使用不同的发电机它就可以工作。所以我希望其他人能知道还有什么可能导致这种奇怪的行为,或者希望有人会提出正确的问题。
  • 除了CMAKE_CXX_FLAGS,还有其他指定编译器标志的方法(例如target_compile_options 命令或COMPILE_OPTIONS 属性)。此外,变量CMAKE_CXX_FLAGS 可能会间接被另一个变量中包含的名称更改。至于调试,我建议在命令行中找到-O0 的位置并检查 nearest 选项。您可以了解这些最近的选项来自哪里,因此您可以检查这些位置是否有 -O0
  • 这是一些线索。遗憾的是,target_compile_optionsCOMPILE_OPTIONS 没有在任何地方的项目中使用。

标签: c++ xcode cmake


【解决方案1】:

问题原来是命令。

我只是移动了这部分:

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

我不知道这两个位置之间有什么可能会产生这种效果。这两个地方之间没有显式更改此变量的任何内容。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-06
    • 2023-04-07
    • 1970-01-01
    • 2022-01-19
    • 1970-01-01
    • 1970-01-01
    • 2018-04-08
    相关资源
    最近更新 更多