【发布时间】: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_RELEASE 和CMAKE_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_options和COMPILE_OPTIONS没有在任何地方的项目中使用。