Build 是否在后续生成中保存并重新打印成功编译文件的警告?

Build 是否在后续生成中保存并重新打印成功编译文件的警告?,build,compilation,cmake,compiler-warnings,Build,Compilation,Cmake,Compiler Warnings,重复构建项目时,如果翻译单元中存在警告但没有错误,则通常不会重新编译主源文件 这会使您很难通过错误和警告来尝试在没有警告的情况下生成项目。通常,必须不断迭代构建,直到所有错误都得到解决,然后执行完全清理和构建,以确保没有警告(以及确保先前完成的构建不是由遗留构建工件引起的“侥幸”) CMake(或其他一些实用程序,如Bash脚本)是否有办法解析生成输出中的警告,将它们保存在某个文本文件中,然后在后续生成中重新显示它们 另外,由于我正在为编译器输出着色,所以可以使用颜色控制字符保存警告并使用相同的

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

这会使您很难通过错误和警告来尝试在没有警告的情况下生成项目。通常,必须不断迭代构建,直到所有错误都得到解决,然后执行完全清理和构建,以确保没有警告(以及确保先前完成的构建不是由遗留构建工件引起的“侥幸”)

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

另外,由于我正在为编译器输出着色,所以可以使用颜色控制字符保存警告并使用相同的着色重新显示吗


(如果它很重要,目前我只编译C++,我通常使用GCC来做。我的生成生成器是NIJA,我有一些BASH脚本,我把所有的调用都封装到CGUT和NIJA。)我不是

bash
专家-因此下面的代码肯定可以改进-但下面是一个使用
CMake
/
bash
//
忍者
的工作示例,应该给出我的基本想法:

  • 检测编译器是否在
    stderr
  • 将其存储在
    中。警告
  • 在启动下一个生成之前删除具有警告的对象文件
  • 编译器本身将再次输出警告(如果尚未修复)
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)
捕获警告。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}
我认为在带有警告的
remove\u obj\u.sh中收集要删除的文件比在
.warnings
文件中搜索要快。缺点是,它可能包含已删除或尚未存在的文件(通过给出
rm-f

如果将带有警告的
remove\u obj\u.sh
调用设置为可选,则尤其如此

使用的参考资料:


  • 当所有警告都被视为错误时,为什么不使用
    -Werror
    编译,这会阻止源文件的编译?解析生成输出中的警告很容易,但当输出可能发生变化时(对于已编译的文件根本没有输出),您希望如何重新显示警告?@Tsyvarev这是个好主意,但它有一些缺陷。最基本的是警告根本没有错误重要,一般来说,如果目标
    B
    依赖于目标
    A
    ,并且目标
    A
    有警告,但目标
    B
    有实际错误,我希望尽快看到
    B
    中的错误,而不是因为非致命警告而导致构建死亡。理想情况下,我希望通过迭代重新编译过程来处理错误,而不必担心(大多数)警告,并最终得到一系列警告,然后我可以回去检查。(显然,警告有时有助于找出编译错误的根本原因,但当翻译单元中唯一的诊断是警告时,情况并非如此,我发现这种情况有问题。)另一种方法:存储每次迭代编译中的警告,然后将其与删除重复项结合起来。因此,您将收到类似于从干净构建中收集的警告。计算机科学中有10个难题:缓存失效、命名和逐个错误。你会狠狠地打第一个。
    #!/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