在后续版本中保存并重新打印成功编译文件的警告?

Kyl*_*and 4 compilation build cmake compiler-warnings

重复构建项目时,如果翻译单元中存在警告但没有错误,则通常不会重新编译主源文件.

这可能使得难以通过错误警告来尝试在没有警告的情况下构建项目.通常,必须保持迭代构建直到所有错误都得到处理,然后进行全面清理并构建以确保没有警告(以及确保先前完成的构建不是由剩余引起的"侥幸"构建工件).

是否有任何方法使用CMake(或其他一些实用程序,如Bash脚本)来解析警告的构建输出,将它们保存在某个文本文件中,然后在后续构建中重新显示它们?

对于奖励积分,因为我正在为我的编译器输出着色,是否可以使用颜色控制字符保存警告并使用相同的颜色重新显示?

(如果重要的是,目前我只编译C++,而且我通常使用GCC这样做.我选择的构建生成器是Ninja,我有一些我编写的Bash脚本将我的所有调用都包含在内CMake和Ninja.)

Flo*_*ian 5

我不是bash专家 - 所以下面的代码肯定可以改进 - 但这是一个带CMake/ bash/ gcc/ 的工作示例ninja,应该给出我的基本想法:

  • 检测编译器是否发出警告/错误 stderr
  • 存放在 <object file name>.warnings
  • 在下一个构建开始之前删除具有警告的目标文件
  • 编译器本身将再次输出警告(如果尚未修复)

的CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
project(CaptureWarnings CXX)

add_compile_options(-fdiagnostics-color=always -Wconversion)
configure_file(capture_warnings.sh.in ${CMAKE_BINARY_DIR}/capture_warnings.sh @ONLY)

file(WRITE foo.cc "int main() {\nreturn 0.5;\n}")
file(WRITE bar.cc "")

set_directory_properties(PROPERTIES 
    RULE_LAUNCH_COMPILE "bash ${CMAKE_BINARY_DIR}/capture_warnings.sh")

add_executable(MyExe foo.cc bar.cc)
Run Code Online (Sandbox Code Playgroud)

capture_warnings.sh.in

#!/bin/bash

# shell script invoked with the following arguments
# $(CXX) $(CXX_DEFINES) $(CXX_FLAGS) -MMD -MT OBJ_FILE -MF DEP_FILE -o OBJ_FILE -c SRC_FILE

# extract parameters
OBJECT_FILE="${@: -3:1}"

# invoke compiler
set -o pipefail
$@ 2> ${OBJECT_FILE}.warnings
ERROR=${PIPESTATUS}

OUT=$(<${OBJECT_FILE}.warnings)

if ! [[ -z "$OUT" ]]; then
    # reprint the warning/error
    >&2 echo "${OUT}"
    echo "rm -f ${PWD}/${OBJECT_FILE}" >> @CMAKE_BINARY_DIR@/remove_obj_with_warnings.sh
else
    rm -f ${OBJECT_FILE}.warnings
fi

exit ${ERROR}
Run Code Online (Sandbox Code Playgroud)

build.sh

#!/bin/bash

if ! [ -d build ]; then
    mkdir build
    cmake -H. -Bbuild -G "Ninja"
fi

if [ -f build/remove_obj_with_warnings.sh ]; then 
    sh ./build/remove_obj_with_warnings.sh
    rm build/remove_obj_with_warnings.sh
fi

cmake --build build
Run Code Online (Sandbox Code Playgroud)

我认为收集要删除remove_obj_with_warnings.sh.warnings文件比对文件的grepping更快.缺点是它可能包含已删除或尚未存在的文件(由给予覆盖rm -f).

如果您将remove_obj_with_warnings.sh呼叫设为可选,则尤其如此.

使用的参考文献:

  1. 使CMake使用gccfilter
  2. 让gcc在调试信息中放置相对文件名
  3. bash:将stdout和stderr重定向(并追加)到文件和终端,并获得正确的退出状态
  4. 在Bash脚本中处理gcc警告和输出