make 失败无法停止 shell 脚本

Failure in make fails to halt shell script

我正在对 personal project using bash scripts (parts of the unit testing have been reviewed on Code Review)、cmake 和最新版本的 Fedora Linux 进行自动化构建和单元测试。积极测试在构建系统上通过,但是,当我在其中一个单元测试中强制 LD 失败时,构建仍然在更高级别通过。它需要在所有级别上都失败。

这是由 cmake 命令生成的 make 的错误消息:

/home/pacman/Documents/projects/VMWithEditor/VMWithEditor/human_readable_program_format.c:179: multiple definition of `HRF_delete_linked_list_of_program_steps'; CMakeFiles/Run_All_Unit_Tests.exe.dir/home/pacman/Documents/projects/VMWithEditor/VMWithEditor/UnitTests/HRF_UnitTest/HRF_UnitTest/unit_test_human_readable_program_format.c.o:/home/pacman/Documents/projects/VMWithEditor/VMWithEditor/UnitTests/RunAllUnitTests/RunAllUnitTests/../../../human_readable_program_format.c:179: first defined here  
collect2: error: ld returned 1 exit status  
make[2]: *** [CMakeFiles/Run_All_Unit_Tests.exe.dir/build.make:433: Run_All_Unit_Tests.exe] Error 1  
make[2]: Leaving directory '/home/pacman/Documents/projects/VMWithEditor/VMWithEditor/UnitTests/RunAllUnitTests/RunAllUnitTests/Debug'  
make[1]: *** [CMakeFiles/Makefile2:95: CMakeFiles/Run_All_Unit_Tests.exe.dir/all] Error 2  
make[1]: Leaving directory '/home/pacman/Documents/projects/VMWithEditor/VMWithEditor/UnitTests/RunAllUnitTests/RunAllUnitTests/Debug'  
make: *** [Makefile:103: all] Error 2  

这是顶级shell脚本的输出,最后2个构建不应该执行:

Building CommandLine_UnitTest/CommandLine_UnitTest  
Building ControlConsole_UnitTest/ControlConsole_UnitTest  
Building Editor_UnitTest/Editor_UnitTest  
Building HRF_UnitTest/HRF_UnitTest  
Building Parser_Unit_Test/Parser_Unit_Test  
Building RunAllUnitTests/RunAllUnitTests  
Building State_Machine_Unit_Test/State_Machine_Unit_Test  
Building VirtualMachine_UnitTest/VirtualMachine_UnitTest  

这是 shell 脚本,它应该不会失败:

buildDebug.sh

#! /bin/sh

# Create a Debug build directory and then build the target within the Debug directory
# Stop on any build errors and stop the parent process.

mkdir Debug
cd Debug
cmake -DCMAKE_BUILD_TYPE=Debug ..
retVal=$?
if [ $retVal -ne 0 ]; then
    echo "\n\ncmake failed $retval!\n\n"
    exit $retVal
fi
make VERBOSE=1
if [ $retVal -ne 0 ]; then
    echo "\n\nmake failed! $retval\n\n"
    exit $retVal
fi

前一个shell脚本被这个shell脚本调用,子目录中有8个前shell脚本的实例。

buildAllDebug.sh

#! /bin/sh

# Build the debug version of all the unit tests
# Stop on any build errors.

for i in *
do
    if [ -d $i ] ; then
        TESTDIRECTORY="$i/$i"
        SHELLFILE="$TESTDIRECTORY/buildDebug.sh";
        if [ -f $SHELLFILE ] ; then
            echo "Building $TESTDIRECTORY";
            cd "$TESTDIRECTORY"
            ./buildDebug.sh >& buildDebuglog.txt
            retVal=$?
            if [ $retVal -ne 0 ]; then
                exit $retVal
            fi
            cd ../..
        fi
    fi
done;

这会生成报告错误的 make 文件:

CMakeLists.txt

cmake_minimum_required(VERSION 3.18.4)

set(EXECUTABLE_NAME "Run_All_Unit_Tests.exe")

project(${EXECUTABLE_NAME} LANGUAGES C VERSION 1.0)

if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
    set(GCC_WARN_COMPILE_FLAGS  " -Wall ")
    set(CMAKE_C_FLAGS  "${CMAKE_CXX_FLAGS} ${GCC_WARN_COMPILE_FLAGS}")
endif()

set(VM_SRC_DIR "../../..")
set(COMMON_TEST_DIR "../../Common_UnitTest_Code")
set(LEXICAL_TEST_DIR "../../State_Machine_Unit_Test/State_Machine_Unit_Test")
set(PARSER_TEST_DIR "../../Parser_Unit_Test/Parser_Unit_Test")
set(CMD_LINE_TEST_DIR "../../CommandLine_UnitTest/CommandLine_UnitTest")
set(HRF_TEST_DIR "../../HRF_UnitTest/HRF_UnitTest")


add_executable(${EXECUTABLE_NAME}
run_all_unit_tests_main.c
${HRF_TEST_DIR}/hrf_unit_test_main.c
${HRF_TEST_DIR}/unit_test_human_readable_program_format.c
${LEXICAL_TEST_DIR}/lexical_analyzer_unit_test_main.c 
${LEXICAL_TEST_DIR}/internal_character_transition_unit_tests.c
${LEXICAL_TEST_DIR}/internal_sytax_state_tests.c
${LEXICAL_TEST_DIR}/lexical_analyzer_test_data.c
${LEXICAL_TEST_DIR}/lexical_analyzer_unit_test_utilities.c
${VM_SRC_DIR}/error_reporting.c  
${VM_SRC_DIR}/safe_string_functions.c
${VM_SRC_DIR}/arg_flags.c
${VM_SRC_DIR}/file_io_vm.c
${VM_SRC_DIR}/opcode.c
${VM_SRC_DIR}/parser.c 
${VM_SRC_DIR}/default_program.c
${VM_SRC_DIR}/human_readable_program_format.c
${VM_SRC_DIR}/lexical_analyzer.c 
${VM_SRC_DIR}/virtual_machine.c 
${PARSER_TEST_DIR}/parser_unit_test_main.c
${PARSER_TEST_DIR}/internal_parser_tests.c
${PARSER_TEST_DIR}/parser_unit_test.c
${CMD_LINE_TEST_DIR}/command_line_unit_test_main.c
${VM_SRC_DIR}/error_reporting.c
${VM_SRC_DIR}/arg_flags.c
${VM_SRC_DIR}/safe_string_functions.c
${COMMON_TEST_DIR}/unit_test_logging.c
)

set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED True)

configure_file(VMWithEditorConfig.h.in VMWithEditorConfig.h)

target_compile_definitions(${EXECUTABLE_NAME} PUBLIC UNIT_TESTING)
target_compile_definitions(${EXECUTABLE_NAME} PUBLIC ALL_UNIT_TESTING)
target_include_directories(${EXECUTABLE_NAME} PUBLIC "${PROJECT_BINARY_DIR}")
target_include_directories(${EXECUTABLE_NAME} PRIVATE "${VM_SRC_DIR}")
target_include_directories(${EXECUTABLE_NAME} PRIVATE "${COMMON_TEST_DIR}")
target_include_directories(${EXECUTABLE_NAME} PRIVATE "${LEXICAL_TEST_DIR}")
target_include_directories(${EXECUTABLE_NAME} PRIVATE "${CMD_LINE_TEST_DIR}")
target_include_directories(${EXECUTABLE_NAME} PRIVATE "${PARSER_TEST_DIR}")
target_include_directories(${EXECUTABLE_NAME} PRIVATE "${HRF_TEST_DIR}")

构建的目录结构:

这是由 ls -R 生成的,然后经过编辑删除了这个问题不需要的内容。

/UnitTests/:
    buildAllDebug.sh  
    buildAll.log  
    buildDebug.sh  
    buildRelease.sh  
    CommandLine_UnitTest  
    Common_UnitTest_Code  
    ControlConsole_UnitTest
    DirStructure.txt
    Editor_UnitTest
    HRF_UnitTest
    Parser_Unit_Test
    RunAllUnitTests
    State_Machine_Unit_Test
    UnitTests
    VirtualMachine_UnitTest

    /UnitTests/CommandLine_UnitTest:
    /UnitTests/CommandLine_UnitTest/CommandLine_UnitTest:
    buildDebuglog.txt
    buildDebug.sh
    buildRelease.sh
    CMakeLists.txt

    /UnitTests/Common_UnitTest_Code:

    /UnitTests/ControlConsole_UnitTest:
    /UnitTests/ControlConsole_UnitTest/ControlConsole_UnitTest:
        buildDebug.sh
        buildRelease.sh
        CMakeLists.txt

    /UnitTests/Editor_UnitTest:
    /UnitTests/Editor_UnitTest/Editor_UnitTest:
        buildDebug.sh
        buildRelease.sh
        CMakeLists.txt

    /UnitTests/HRF_UnitTest:
    /UnitTests/HRF_UnitTest/HRF_UnitTest:
        buildDebug.sh
        buildRelease.sh
        CMakeLists.txt

    /UnitTests/Parser_Unit_Test:
    /UnitTests/Parser_Unit_Test/Parser_Unit_Test:
        buildDebug.sh
        buildRelease.sh
        CMakeLists.txt

    /UnitTests/RunAllUnitTests:
    /UnitTests/RunAllUnitTests/RunAllUnitTests:
        buildDebug.sh
        buildRelease.sh
        CMakeLists.txt

    /UnitTests/State_Machine_Unit_Test:
    /UnitTests/State_Machine_Unit_Test/State_Machine_Unit_Test:
        buildDebug.sh
        buildRelease.sh
        CMakeLists.txt

    /UnitTests/UnitTests:

    /UnitTests/VirtualMachine_UnitTest:
    /UnitTests/VirtualMachine_UnitTest/VirtualMachine_UnitTest:
        buildDebug.sh
        buildRelease.sh
        CMakeLists.txt

你有:

make VERBOSE=1
if [ $retVal -ne 0 ]; then

但是retVal仍然是cmake命令的return代码。要么重置它,要么直接测试 $?