diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 1ebeb7dd17..a3bd0489d1 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -12,8 +12,9 @@ concurrency: cancel-in-progress: ${{ github.ref != 'refs/heads/develop' }} env: - CLANG_DOCKER_IMAGE: axom/tpls:clang-19_02-17-26_21h-05m - GCC_DOCKER_IMAGE: axom/tpls:gcc-13_02-17-26_21h-05m + CLANG_DOCKER_IMAGE: axom/tpls:clang-19_03-19-26_22h-14m + GCC_DOCKER_IMAGE: axom/tpls:gcc-13_03-19-26_22h-15m + LLD_CMAKE_FLAGS: "-DAXOM_CXX_EXE_LINKER_FLAGS=--ld-path=/usr/bin/ld.lld" jobs: # Hacky solution to reference env variables outside of `run` steps https://stackoverflow.com/a/74217028 @@ -29,6 +30,8 @@ jobs: runs-on: ubuntu-24.04 needs: - set_image_vars + env: + USE_NINJA: "yes" strategy: fail-fast: true matrix: @@ -38,18 +41,21 @@ jobs: host_config: gcc@13.3.1.cmake compiler_image: ${{ needs.set_image_vars.outputs.gcc_docker_image }} cmake_opts: '-DBUILD_SHARED_LIBS=ON -DBLT_CXX_STD=c++20 -DENABLE_BENCHMARKS:BOOL=ON' + use_lld: 'no' do_build: 'yes' do_benchmarks: 'yes' - job_name: gcc@13.3.1, shared, 32bit host_config: gcc@13.3.1.cmake compiler_image: ${{ needs.set_image_vars.outputs.gcc_docker_image }} cmake_opts: '-DBUILD_SHARED_LIBS=ON -DAXOM_USE_64BIT_INDEXTYPE:BOOL=OFF' + use_lld: 'no' do_build: 'yes' do_benchmarks: 'no' - job_name: llvm@19.0.0, shared, benchmarks, quest regression host_config: llvm@19.0.0.cmake compiler_image: ${{ needs.set_image_vars.outputs.clang_docker_image }} cmake_opts: '-DBUILD_SHARED_LIBS=ON -DAXOM_QUEST_ENABLE_EXTRA_REGRESSION_TESTS:BOOL=ON -DENABLE_BENCHMARKS:BOOL=ON' + use_lld: 'no' do_build: 'yes' do_benchmarks: 'yes' include: @@ -59,6 +65,7 @@ jobs: host_config: llvm@19.0.0.cmake compiler_image: ${{ needs.set_image_vars.outputs.clang_docker_image }} cmake_opts: '-DBUILD_SHARED_LIBS=ON -DAXOM_QUEST_ENABLE_EXTRA_REGRESSION_TESTS:BOOL=ON -DAXOM_ENABLE_MIR:BOOL=OFF -DAXOM_ENABLE_BUMP:BOOL=OFF -U RAJA_DIR' + use_lld: 'no' do_build: 'yes' do_benchmarks: 'no' - build_type: Debug @@ -67,6 +74,7 @@ jobs: host_config: llvm@19.0.0.cmake compiler_image: ${{ needs.set_image_vars.outputs.clang_docker_image }} cmake_opts: '-DBUILD_SHARED_LIBS=ON -DAXOM_QUEST_ENABLE_EXTRA_REGRESSION_TESTS:BOOL=ON -U UMPIRE_DIR' + use_lld: 'no' do_build: 'yes' do_benchmarks: 'no' - build_type: Debug @@ -75,6 +83,7 @@ jobs: host_config: llvm@19.0.0.cmake compiler_image: ${{ needs.set_image_vars.outputs.clang_docker_image }} cmake_opts: '-DBUILD_SHARED_LIBS=ON -DAXOM_QUEST_ENABLE_EXTRA_REGRESSION_TESTS:BOOL=ON -DAXOM_ENABLE_MIR:BOOL=OFF -DAXOM_ENABLE_BUMP:BOOL=OFF -U RAJA_DIR -U UMPIRE_DIR' + use_lld: 'no' do_build: 'yes' do_benchmarks: 'no' - build_type: Debug @@ -83,6 +92,7 @@ jobs: host_config: llvm@19.0.0.cmake compiler_image: ${{ needs.set_image_vars.outputs.clang_docker_image }} cmake_opts: '-DBUILD_SHARED_LIBS=ON -DAXOM_QUEST_ENABLE_EXTRA_REGRESSION_TESTS:BOOL=ON -U CALIPER_DIR -U ADIAK_DIR' + use_lld: 'no' do_build: 'yes' do_benchmarks: 'no' name: ${{ matrix.build_type }} - ${{ matrix.config.job_name }} @@ -111,6 +121,9 @@ jobs: HOST_CONFIG=${{ matrix.config.host_config }} \ CMAKE_EXTRA_FLAGS=" ${{ matrix.config.cmake_opts }} " \ BUILD_TYPE=${{ matrix.build_type }} \ + USE_NINJA=${{ env.USE_NINJA }} \ + USE_LLD=${{ matrix.config.use_lld }} \ + LLD_CMAKE_FLAGS="${{ env.LLD_CMAKE_FLAGS }}" \ ./scripts/github-actions/linux-build_and_test.sh - name: Upload Test Results uses: actions/upload-artifact@v4 @@ -192,4 +205,3 @@ jobs: submodules: recursive - name: Check ${{ matrix.check_type }} run: ./scripts/github-actions/linux-check.sh - diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4556c48b92..e5cb171afb 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -10,6 +10,8 @@ variables: BUILD_ROOT: ${CI_PROJECT_DIR} FULL_BUILD_ROOT: ${CI_BUILDS_DIR}/axom/${CI_JOB_NAME} SLURM_OVERLAP: 1 + USE_LLD: "OFF" + LLD_EXTRA_CMAKE_OPTIONS: "-DAXOM_CXX_EXE_LINKER_FLAGS=--ld-path=/usr/bin/ld.lld" .src_workflow: rules: @@ -25,7 +27,10 @@ variables: script: - echo -e "\e[0Ksection_start:$(date +%s):src_build_and_test\r\e[0KSource Build and Test ${CI_PROJECT_NAME}" - export LSAN_OPTIONS=${LSAN_OPTIONS} - - ${ALLOC_COMMAND} python3 scripts/llnl_scripts/build_src.py -v --host-config ${HOST_CONFIG} --extra-cmake-options '-DENABLE_DOCS=OFF ${EXTRA_CMAKE_OPTIONS}' --build-type ${BUILD_TYPE:-Debug} ${EXTRA_OPTIONS} + - export SELECTED_EXTRA_CMAKE_OPTIONS="-DENABLE_DOCS=OFF ${EXTRA_CMAKE_OPTIONS}" + - if [ "${USE_LLD}" = "ON" ]; then export SELECTED_EXTRA_CMAKE_OPTIONS="${SELECTED_EXTRA_CMAKE_OPTIONS} ${LLD_EXTRA_CMAKE_OPTIONS}"; fi + - 'echo "[INFO: Extra CMake options: ${SELECTED_EXTRA_CMAKE_OPTIONS}]"' + - ${ALLOC_COMMAND} python3 scripts/llnl_scripts/build_src.py -v --host-config ${HOST_CONFIG} --extra-cmake-options "${SELECTED_EXTRA_CMAKE_OPTIONS}" --build-type ${BUILD_TYPE:-Debug} ${EXTRA_OPTIONS} - echo -e "\e[0Ksection_end:$(date +%s):src_build_and_test\r\e[0K" artifacts: expire_in: 2 weeks diff --git a/.gitlab/build_dane.yml b/.gitlab/build_dane.yml index e5a6f7b4d4..1939388363 100644 --- a/.gitlab/build_dane.yml +++ b/.gitlab/build_dane.yml @@ -20,12 +20,14 @@ - when: on_success before_script: - module load cmake/3.19.2 + - module load ninja #### # Template .src_build_on_dane: variables: ALLOC_TIME: "40" + EXTRA_OPTIONS: "--ninja" extends: [.src_build_script, .on_dane, .src_workflow] needs: [] @@ -41,6 +43,7 @@ dane-llvm_19_1_3-debug-src: variables: COMPILER: "llvm@19.1.3" HOST_CONFIG: "dane-toss_4_x86_64_ib-${COMPILER}.cmake" + USE_LLD: "ON" extends: .src_build_on_dane dane-llvm_19_1_3-release-src: @@ -48,6 +51,7 @@ dane-llvm_19_1_3-release-src: COMPILER: "llvm@19.1.3" HOST_CONFIG: "dane-toss_4_x86_64_ib-${COMPILER}.cmake" BUILD_TYPE: "Release" + USE_LLD: "ON" EXTRA_CMAKE_OPTIONS: "-DAXOM_QUEST_ENABLE_EXTRA_REGRESSION_TESTS:BOOL=ON" extends: .src_build_on_dane diff --git a/.gitlab/build_matrix.yml b/.gitlab/build_matrix.yml index d21af3dbdf..9df9d5da19 100644 --- a/.gitlab/build_matrix.yml +++ b/.gitlab/build_matrix.yml @@ -20,12 +20,14 @@ - when: on_success before_script: - module load cmake/3.26 + - module load ninja #### # Template .src_build_on_matrix: variables: ALLOC_TIME: "40" + EXTRA_OPTIONS: "--ninja" extends: [.src_build_script, .on_matrix, .src_workflow] needs: [] diff --git a/.gitlab/build_tioga.yml b/.gitlab/build_tioga.yml index 2f7d720d7a..9ee62b513f 100644 --- a/.gitlab/build_tioga.yml +++ b/.gitlab/build_tioga.yml @@ -18,12 +18,14 @@ - when: on_success before_script: - module load cmake/3.29.2 + - module load ninja #### # Template .src_build_on_tioga: variables: ALLOC_TIME: "60" + EXTRA_OPTIONS: "--ninja" extends: [.src_build_script, .on_tioga, .src_workflow] needs: [] diff --git a/.gitlab/build_tuolumne.yml b/.gitlab/build_tuolumne.yml index fbededfef3..050b49548a 100644 --- a/.gitlab/build_tuolumne.yml +++ b/.gitlab/build_tuolumne.yml @@ -18,6 +18,7 @@ - when: on_success before_script: - module load cmake/3.29 + - module load ninja #### # Template @@ -25,6 +26,7 @@ variables: ALLOC_TIME: "60" NUM_NODES: "1" + EXTRA_OPTIONS: "--ninja" extends: [.src_build_script, .on_tuolumne, .src_workflow] needs: [] diff --git a/host-configs/docker/gcc@13.3.1.cmake b/host-configs/docker/gcc@13.3.1.cmake index e1e9346de2..50dc18f634 100644 --- a/host-configs/docker/gcc@13.3.1.cmake +++ b/host-configs/docker/gcc@13.3.1.cmake @@ -8,9 +8,9 @@ set(CMAKE_PREFIX_PATH "/home/axom/axom_tpls/gcc-13.3.1/blt-0.7.1-tp6erawewp4l2ew set(CMAKE_INSTALL_RPATH_USE_LINK_PATH "ON" CACHE STRING "") -set(CMAKE_BUILD_RPATH "/home/axom/axom_tpls/gcc-13.3.1/axom-develop-ofy2ds6xm3ggsfnnn2bzwtfoyqooykov/lib;/home/axom/axom_tpls/gcc-13.3.1/axom-develop-ofy2ds6xm3ggsfnnn2bzwtfoyqooykov/lib64;;" CACHE STRING "") +set(CMAKE_BUILD_RPATH "/home/axom/axom_tpls/gcc-13.3.1/axom-develop-vj2h6qhht3szk7mhxrqfp7ffs7ljhcbp/lib;/home/axom/axom_tpls/gcc-13.3.1/axom-develop-vj2h6qhht3szk7mhxrqfp7ffs7ljhcbp/lib64;;" CACHE STRING "") -set(CMAKE_INSTALL_RPATH "/home/axom/axom_tpls/gcc-13.3.1/axom-develop-ofy2ds6xm3ggsfnnn2bzwtfoyqooykov/lib;/home/axom/axom_tpls/gcc-13.3.1/axom-develop-ofy2ds6xm3ggsfnnn2bzwtfoyqooykov/lib64;;" CACHE STRING "") +set(CMAKE_INSTALL_RPATH "/home/axom/axom_tpls/gcc-13.3.1/axom-develop-vj2h6qhht3szk7mhxrqfp7ffs7ljhcbp/lib;/home/axom/axom_tpls/gcc-13.3.1/axom-develop-vj2h6qhht3szk7mhxrqfp7ffs7ljhcbp/lib64;;" CACHE STRING "") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") @@ -102,7 +102,7 @@ set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main # scr not built #------------------------------------------------------------------------------ -# Devtools +# Devtools & Python #------------------------------------------------------------------------------ # ClangFormat disabled since llvm@19 and devtools not in spec diff --git a/host-configs/docker/llvm@19.0.0.cmake b/host-configs/docker/llvm@19.0.0.cmake index 515d46d6db..49a86fc3b0 100644 --- a/host-configs/docker/llvm@19.0.0.cmake +++ b/host-configs/docker/llvm@19.0.0.cmake @@ -8,9 +8,9 @@ set(CMAKE_PREFIX_PATH "/home/axom/axom_tpls/llvm-19.0.0/blt-0.7.1-p7mm766jfnjcbc set(CMAKE_INSTALL_RPATH_USE_LINK_PATH "ON" CACHE STRING "") -set(CMAKE_BUILD_RPATH "/home/axom/axom_tpls/llvm-19.0.0/axom-develop-pue4pbqffz5ostcywjjmbqrpva3p7c2o/lib;/home/axom/axom_tpls/llvm-19.0.0/axom-develop-pue4pbqffz5ostcywjjmbqrpva3p7c2o/lib64;;" CACHE STRING "") +set(CMAKE_BUILD_RPATH "/home/axom/axom_tpls/llvm-19.0.0/axom-develop-aftfr3lcr7ucuo4hgbetvfxg4ent3afe/lib;/home/axom/axom_tpls/llvm-19.0.0/axom-develop-aftfr3lcr7ucuo4hgbetvfxg4ent3afe/lib64;;" CACHE STRING "") -set(CMAKE_INSTALL_RPATH "/home/axom/axom_tpls/llvm-19.0.0/axom-develop-pue4pbqffz5ostcywjjmbqrpva3p7c2o/lib;/home/axom/axom_tpls/llvm-19.0.0/axom-develop-pue4pbqffz5ostcywjjmbqrpva3p7c2o/lib64;;" CACHE STRING "") +set(CMAKE_INSTALL_RPATH "/home/axom/axom_tpls/llvm-19.0.0/axom-develop-aftfr3lcr7ucuo4hgbetvfxg4ent3afe/lib;/home/axom/axom_tpls/llvm-19.0.0/axom-develop-aftfr3lcr7ucuo4hgbetvfxg4ent3afe/lib64;;" CACHE STRING "") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") @@ -104,7 +104,7 @@ set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main # scr not built #------------------------------------------------------------------------------ -# Devtools +# Devtools & Python #------------------------------------------------------------------------------ # ClangFormat disabled since llvm@19 and devtools not in spec diff --git a/scripts/docker/dockerfile_clang-19 b/scripts/docker/dockerfile_clang-19 index f9a2ae2f1f..bd7c128f69 100644 --- a/scripts/docker/dockerfile_clang-19 +++ b/scripts/docker/dockerfile_clang-19 @@ -6,7 +6,7 @@ ARG branch=develop SHELL ["/bin/bash", "-c"] RUN sudo apt-get update -y -RUN sudo apt-get install gettext gfortran-$(gcc -dumpversion) graphviz libomp-19-dev libopenblas-dev \ +RUN sudo apt-get install gettext gfortran-$(gcc -dumpversion) graphviz libomp-19-dev libopenblas-dev lld ninja-build \ lsb-release lua5.2 lua5.2-dev python3-sphinx locales ssh -fy RUN sudo locale-gen en_US.utf8 RUN sudo useradd -m -s /bin/bash -G sudo axom @@ -37,4 +37,4 @@ RUN cp ./axom_repo/*.cmake /home/axom/export_hostconfig # Make sure the new hostconfig worked # Note: having high job slots causes build log to disappear and job to fail -RUN cd axom_repo && python3 config-build.py -hc *.cmake -bp build && cd build && make -j4 VERBOSE=1 && make -j4 test && cd /home/axom && rm -rf axom_repo \ No newline at end of file +RUN cd axom_repo && python3 config-build.py --ninja -hc *.cmake -bp build && cd build && (ninja || (echo && echo "==================================================================" && echo " Non-verbose build failed. Re-running with verbose output." && echo "==================================================================" && echo && ninja -v)) && ctest --output-on-failure -T Test -VV -j4 && cd /home/axom && rm -rf axom_repo diff --git a/scripts/docker/dockerfile_gcc-12_cuda-12 b/scripts/docker/dockerfile_gcc-12_cuda-12 index 16286a0dba..65bae51abf 100644 --- a/scripts/docker/dockerfile_gcc-12_cuda-12 +++ b/scripts/docker/dockerfile_gcc-12_cuda-12 @@ -19,7 +19,7 @@ SHELL ["/bin/bash", "-c"] RUN sudo apt-get update -y RUN sudo apt-get install -y supervisor RUN sudo useradd --create-home --shell /bin/bash ${USER} -RUN sudo apt-get install doxygen elfutils gfortran graphviz language-pack-en-base less libopenblas-dev libomp-dev mpich python3-sphinx ssh tree unzip cpio libxcursor1 libxkbcommon0 -fy +RUN sudo apt-get install doxygen elfutils gfortran graphviz language-pack-en-base less libopenblas-dev libomp-dev lld mpich ninja-build python3-sphinx ssh tree unzip cpio libxcursor1 libxkbcommon0 -fy WORKDIR /opt/archives RUN sudo curl -L https://github.com/gitpod-io/openvscode-server/releases/download/openvscode-server-v1.69.1/openvscode-server-v1.69.1-linux-x64.tar.gz > \ @@ -44,13 +44,13 @@ RUN cd ${HOME}/axom_repo && python3 ./scripts/uberenv/uberenv.py --spack-env-fil # Note: having high job slots causes build log to disappear and job to fail # Omit testing step, hangs at slam_lulesh unit test (same behavior for azure pipeline images, as well) # Disable link-time optimization from MPI wrapper causing linkage failures -RUN cd ${HOME}/axom_repo && python3 config-build.py -hc *cuda.cmake \ +RUN cd ${HOME}/axom_repo && python3 config-build.py --ninja -hc *cuda.cmake \ -bp ${HOME}/axom_repo/build-release \ -ip ${HOME}/axom_repo/install-release \ -DCMAKE_EXE_LINKER_FLAGS=-fno-lto \ -bt Release \ && cd ${HOME}/axom_repo/build-release \ - && make -j4 install + && (ninja install || (echo && echo "==================================================================" && echo " Non-verbose install failed. Re-running with verbose output." && echo "==================================================================" && echo && ninja -v install)) # Install VisIt binary # Download tarball, installer, test script, perform installation and cleanup @@ -80,4 +80,3 @@ RUN sed -i "s/XXX/${USER}/g" /etc/supervisord.conf RUN touch /var/log/openvscode-server.log && chown -R ${USER}:${USER} /var/log/openvscode-server.log CMD ["/usr/bin/supervisord"] - diff --git a/scripts/docker/dockerfile_gcc-13 b/scripts/docker/dockerfile_gcc-13 index 1a825951c9..7d9b81a4bc 100644 --- a/scripts/docker/dockerfile_gcc-13 +++ b/scripts/docker/dockerfile_gcc-13 @@ -6,7 +6,7 @@ ARG branch=develop SHELL ["/bin/bash", "-c"] RUN sudo apt-get update -y -RUN sudo apt-get install gettext gfortran-$(gcc -dumpversion) graphviz libopenblas-dev \ +RUN sudo apt-get install gettext gfortran-$(gcc -dumpversion) graphviz libopenblas-dev lld ninja-build \ lsb-release lua5.2 lua5.2-dev python3-sphinx locales ssh -fy RUN sudo locale-gen en_US.utf8 RUN sudo useradd -m -s /bin/bash -G sudo axom @@ -37,4 +37,4 @@ RUN cp ./axom_repo/*.cmake /home/axom/export_hostconfig # Make sure the new hostconfig worked # Note: having high job slots causes build log to disappear and job to fail -RUN cd axom_repo && python3 config-build.py -hc *.cmake -bp build && cd build && make -j4 VERBOSE=1 && make -j4 test && cd /home/axom && rm -rf axom_repo \ No newline at end of file +RUN cd axom_repo && python3 config-build.py --ninja -hc *.cmake -bp build && cd build && (ninja || (echo && echo "==================================================================" && echo " Non-verbose build failed. Re-running with verbose output." && echo "==================================================================" && echo && ninja -v)) && ctest --output-on-failure -T Test -VV -j4 && cd /home/axom && rm -rf axom_repo diff --git a/scripts/github-actions/linux-build_and_test.sh b/scripts/github-actions/linux-build_and_test.sh index b0c472e16b..71631483c3 100755 --- a/scripts/github-actions/linux-build_and_test.sh +++ b/scripts/github-actions/linux-build_and_test.sh @@ -18,43 +18,152 @@ function or_die () { fi } +function format_duration () { + local total_seconds="$1" + local hours=$(( total_seconds / 3600 )) + local minutes=$(( (total_seconds % 3600) / 60 )) + local seconds=$(( total_seconds % 60 )) + printf "%d:%02d:%02d" "$hours" "$minutes" "$seconds" +} + +function print_timing_line () { + local label="$1" + local seconds="$2" + if [[ -n "$seconds" ]] ; then + printf " %-22s %s\n" "$label" "$(format_duration "$seconds")" + fi +} + +function print_timing_summary () { + local status="$1" + local total_seconds=$(( $(date +%s) - TOTAL_START_SECONDS )) + + # Disable shell tracing so the summary is readable in CI logs. + set +x + + echo + echo "==================================================================" + echo " Stage Timing Summary" + echo "==================================================================" + print_timing_line "configure" "$CONFIGURE_SECONDS" + print_timing_line "build" "$BUILD_SECONDS" + print_timing_line "test" "$TEST_SECONDS" + print_timing_line "benchmarks" "$BENCHMARKS_SECONDS" + print_timing_line "memcheck" "$MEMCHECK_SECONDS" + print_timing_line "total" "$total_seconds" + echo " result exit code ${status}" + echo "==================================================================" +} + +function retry_build_verbose () { + local build_cmd="$1" + local verbose_build_cmd="$2" + + if eval "$build_cmd" ; then + return 0 + fi + + echo + echo "==================================================================" + echo " Non-verbose build failed. Re-running with verbose output." + echo "==================================================================" + echo + + eval "$verbose_build_cmd" +} + echo "~~~~ helpful info ~~~~" echo "USER="`id -u -n` echo "PWD="`pwd` echo "HOST_CONFIG=$HOST_CONFIG" echo "CMAKE_EXTRA_FLAGS=$CMAKE_EXTRA_FLAGS" +echo "USE_NINJA=$USE_NINJA" +echo "USE_LLD=$USE_LLD" +echo "LLD_CMAKE_FLAGS=$LLD_CMAKE_FLAGS" echo "~~~~~~~~~~~~~~~~~~~~~~" export BUILD_TYPE=${BUILD_TYPE:-Debug} +export USE_NINJA=${USE_NINJA:-no} +export USE_LLD=${USE_LLD:-no} +TOTAL_START_SECONDS=$(date +%s) +CONFIGURE_SECONDS="" +BUILD_SECONDS="" +TEST_SECONDS="" +BENCHMARKS_SECONDS="" +MEMCHECK_SECONDS="" +trap 'status=$?; set +x; print_timing_summary "$status"' EXIT if [[ "$DO_BUILD" == "yes" ]] ; then echo "~~~~~~ FIND NUMPROCS ~~~~~~~~" NUMPROCS=`python3 -c "import os; print(f'{os.cpu_count()}')"` NUM_BUILD_PROCS=`python3 -c "import os; print(f'{max(2, os.cpu_count() * 8 // 10)}')"` + BUILD_GENERATOR_FLAG="" + BUILD_TOOL="make" + BUILD_CMD="make -j $NUM_BUILD_PROCS" + VERBOSE_BUILD_CMD="make -j $NUM_BUILD_PROCS VERBOSE=1" + if [[ "$USE_NINJA" == "yes" ]] ; then + BUILD_GENERATOR_FLAG="--ninja" + BUILD_TOOL="ninja" + BUILD_CMD="ninja" + VERBOSE_BUILD_CMD="ninja -v" + fi + if [[ "$USE_LLD" == "yes" ]] ; then + CMAKE_EXTRA_FLAGS="${CMAKE_EXTRA_FLAGS} ${LLD_CMAKE_FLAGS}" + fi echo "~~~~~~ RUNNING CMAKE ~~~~~~~~" - or_die python3 ./config-build.py -bp builddir -hc ./host-configs/docker/${HOST_CONFIG} -bt ${BUILD_TYPE} -DENABLE_GTEST_DEATH_TESTS=ON ${CMAKE_EXTRA_FLAGS} + STAGE_START_SECONDS=$(date +%s) + python3 ./config-build.py -bp builddir -hc ./host-configs/docker/${HOST_CONFIG} -bt ${BUILD_TYPE} ${BUILD_GENERATOR_FLAG} -DENABLE_GTEST_DEATH_TESTS=ON ${CMAKE_EXTRA_FLAGS} + STATUS=$? + CONFIGURE_SECONDS=$(( $(date +%s) - STAGE_START_SECONDS )) + if [[ $STATUS != 0 ]] ; then + echo ERROR $STATUS command: python3 ./config-build.py + exit $STATUS + fi or_die cd builddir echo "~~~~~~ BUILDING ~~~~~~~~" - if [[ ${CMAKE_EXTRA_FLAGS} == *COVERAGE* ]] ; then - or_die make -j $NUM_BUILD_PROCS - else - or_die make -j $NUM_BUILD_PROCS VERBOSE=1 + STAGE_START_SECONDS=$(date +%s) + retry_build_verbose "${BUILD_CMD}" "${VERBOSE_BUILD_CMD}" + STATUS=$? + BUILD_SECONDS=$(( $(date +%s) - STAGE_START_SECONDS )) + if [[ $STATUS != 0 ]] ; then + echo ERROR $STATUS command: ${BUILD_CMD} + exit $STATUS fi echo "~~~~~~ RUNNING TESTS ~~~~~~~~" - make CTEST_OUTPUT_ON_FAILURE=1 test ARGS='-T Test -VV -j$NUM_BUILD_PROCS' + STAGE_START_SECONDS=$(date +%s) + ctest --output-on-failure -T Test -VV -j $NUM_BUILD_PROCS + STATUS=$? + TEST_SECONDS=$(( $(date +%s) - STAGE_START_SECONDS )) + if [[ $STATUS != 0 ]] ; then + echo ERROR $STATUS command: ctest --output-on-failure -T Test -VV -j $NUM_BUILD_PROCS + exit $STATUS + fi if [[ "${DO_BENCHMARKS}" == "yes" ]] ; then echo "~~~~~~ RUNNING BENCHMARKS ~~~~~~~~" - make CTEST_OUTPUT_ON_FAILURE=1 run_benchmarks + STAGE_START_SECONDS=$(date +%s) + ${BUILD_TOOL} -j $NUM_BUILD_PROCS run_benchmarks + STATUS=$? + BENCHMARKS_SECONDS=$(( $(date +%s) - STAGE_START_SECONDS )) + if [[ $STATUS != 0 ]] ; then + echo ERROR $STATUS command: ${BUILD_TOOL} -j $NUM_BUILD_PROCS run_benchmarks + exit $STATUS + fi fi if [[ "${DO_MEMCHECK}" == "yes" ]] ; then echo "~~~~~~ RUNNING MEMCHECK ~~~~~~~~" - or_die ctest -T memcheck + STAGE_START_SECONDS=$(date +%s) + ctest -T memcheck + STATUS=$? + MEMCHECK_SECONDS=$(( $(date +%s) - STAGE_START_SECONDS )) + if [[ $STATUS != 0 ]] ; then + echo ERROR $STATUS command: ctest -T memcheck + exit $STATUS + fi fi fi - diff --git a/scripts/github-actions/linux-check.sh b/scripts/github-actions/linux-check.sh index 1b1f9cbdee..ebad6912f9 100755 --- a/scripts/github-actions/linux-check.sh +++ b/scripts/github-actions/linux-check.sh @@ -25,6 +25,24 @@ echo "HOST_CONFIG=$HOST_CONFIG" echo "CMAKE_EXTRA_FLAGS=$CMAKE_EXTRA_FLAGS" echo "~~~~~~~~~~~~~~~~~~~~~~" +echo "~~~~ linker info ~~~~" +lld_path="$(command -v lld || true)" +ld_lld_path="$(command -v ld.lld || true)" +echo "lld path=${lld_path:-not found}" +if [[ -n "$lld_path" ]] ; then + readlink -f "$lld_path" || true +fi +echo "ld.lld path=${ld_lld_path:-not found}" +if [[ -n "$ld_lld_path" ]] ; then + readlink -f "$ld_lld_path" || true +fi +if [[ -e /usr/bin/ld.lld ]] ; then + ls -l /usr/bin/ld.lld +else + echo "/usr/bin/ld.lld not found" +fi +echo "~~~~~~~~~~~~~~~~~~~~~" + echo "~~~~~~ RUNNING CMAKE ~~~~~~~~" cmake_args="-DCMAKE_BUILD_TYPE=Debug -DBUILD_SHARED_LIBS=ON -DENABLE_CLANGTIDY=OFF" diff --git a/scripts/llnl_scripts/build_src.py b/scripts/llnl_scripts/build_src.py index 4992dc4371..4374de90c1 100755 --- a/scripts/llnl_scripts/build_src.py +++ b/scripts/llnl_scripts/build_src.py @@ -45,6 +45,11 @@ def parse_args(): dest="testserial", default=False, help="Run unit tests serially") + parser.add_argument("--ninja", + action="store_true", + dest="ninja", + default=False, + help="Use the Ninja generator and build tool") # Extra cmake options to pass to config build parser.add_argument("--extra-cmake-options", dest="extra_cmake_options", @@ -107,7 +112,8 @@ def main(): report_to_stdout = opts["verbose"], extra_cmake_options = opts["extra_cmake_options"], build_type = opts["buildtype"], - test_serial = opts["testserial"]) + test_serial = opts["testserial"], + use_ninja = opts["ninja"]) # Otherwise try to build a specific host-config else: # Command-line arg has highest priority @@ -164,7 +170,8 @@ def main(): report_to_stdout = opts["verbose"], extra_cmake_options = opts["extra_cmake_options"], build_type = opts["buildtype"], - test_serial = opts["testserial"]) + test_serial = opts["testserial"], + use_ninja = opts["ninja"]) finally: os.chdir(original_wd) diff --git a/scripts/llnl_scripts/llnl_lc_build_tools.py b/scripts/llnl_scripts/llnl_lc_build_tools.py index c691e3ea8d..2c0692cab5 100755 --- a/scripts/llnl_scripts/llnl_lc_build_tools.py +++ b/scripts/llnl_scripts/llnl_lc_build_tools.py @@ -203,8 +203,32 @@ def build_and_test_host_config(test_root, host_config, report_to_stdout = False, extra_cmake_options = "", build_type = "Debug", - test_serial = False): + test_serial = False, + use_ninja = False): + total_start_time = time.perf_counter() + stage_timings = [] + + def record_stage(stage_name, start_time): + stage_timings.append((stage_name, int(time.perf_counter() - start_time))) + + def print_stage_summary(): + total_seconds = int(time.perf_counter() - total_start_time) + print("[==================================================================]") + print("[ Stage Timing Summary ]") + print("[==================================================================]") + for stage_name, seconds in stage_timings: + print("[ {0:<28} {1} ]".format(stage_name, convertSecondsToReadableTime(seconds))) + print("[ {0:<28} {1} ]".format("total", convertSecondsToReadableTime(total_seconds))) + print("[==================================================================]") + host_config_root = get_host_config_root(host_config) + build_tool = "ninja" if use_ninja else "make" + build_tool_flags = "-j16" + build_log_id = build_tool + configure_generator_flag = "--ninja" if use_ninja else "" + downstream_generator_flag = '-G "Ninja"' if use_ninja else "" + build_cmd = build_tool if use_ninja else f"{build_tool} {build_tool_flags}" + verbose_build_cmd = f"{build_cmd} -v" if use_ninja else f"{build_cmd} VERBOSE=1" # setup build and install dirs build_dir = pjoin(test_root, f"build-{host_config_root}") install_dir = pjoin(test_root, f"install-{host_config_root}") @@ -216,9 +240,11 @@ def build_and_test_host_config(test_root, host_config, cfg_output_file = pjoin(test_root, f"output.log.{host_config_root}.configure.txt") print(f"[starting configure of {host_config}]") print(f"[log file: {cfg_output_file}]") - res = sexe(f"{sys.executable} config-build.py -bp {build_dir} -ip {install_dir} -bt {build_type} -hc {host_config} {extra_cmake_options}", + stage_start_time = time.perf_counter() + res = sexe(f"{sys.executable} config-build.py -bp {build_dir} -ip {install_dir} -bt {build_type} -hc {host_config} {configure_generator_flag} {extra_cmake_options}", output_file = cfg_output_file, echo=True) + record_stage("configure", stage_start_time) if report_to_stdout: with open(cfg_output_file, 'r', encoding='utf8') as build_out: @@ -226,6 +252,7 @@ def build_and_test_host_config(test_root, host_config, if res != 0: print(f"[ERROR: Configure for host-config: {host_config} failed]\n") + print_stage_summary() return res #### @@ -233,10 +260,11 @@ def build_and_test_host_config(test_root, host_config, #### # build the code - bld_output_file = pjoin(build_dir,"output.log.make.txt") + bld_output_file = pjoin(build_dir, f"output.log.{build_log_id}.txt") print("[starting build]") print(f"[log file: {bld_output_file}]") - res = sexe(f"cd {build_dir} && make -j 16 VERBOSE=1 ", + stage_start_time = time.perf_counter() + res = sexe(f"cd {build_dir} && {build_cmd}", output_file = bld_output_file, echo=True) @@ -244,21 +272,32 @@ def build_and_test_host_config(test_root, host_config, with open(bld_output_file, 'r', encoding='utf8') as build_out: print(build_out.read()) + if res != 0: + print("[==================================================================]") + print("[ Non-verbose build failed. Re-running with verbose output. ]") + print("[==================================================================]") + res = sexe(f"cd {build_dir} && {verbose_build_cmd}", + echo=True) + record_stage("build", stage_start_time) + if res != 0: print(f"[ERROR: Build for host-config: {host_config} failed]\n") + print_stage_summary() return res # test the code - tst_output_file = pjoin(build_dir,"output.log.make.test.txt") + tst_output_file = pjoin(build_dir, f"output.log.{build_log_id}.test.txt") print("[starting unit tests]") print(f"[log file: {tst_output_file}]") parallel_test = "" if test_serial else "-j16" - tst_cmd = f"cd {build_dir} && make CTEST_OUTPUT_ON_FAILURE=1 test ARGS=\"--no-compress-output -T Test -VV {parallel_test}\"" + tst_cmd = f"cd {build_dir} && CTEST_OUTPUT_ON_FAILURE=1 ctest --no-compress-output -T Test -VV {parallel_test}" + stage_start_time = time.perf_counter() res = sexe(tst_cmd, output_file = tst_output_file, echo=True) + record_stage("unit tests", stage_start_time) if report_to_stdout: with open(tst_output_file, 'r', encoding='utf8') as test_out: @@ -282,16 +321,19 @@ def build_and_test_host_config(test_root, host_config, if res != 0: print(f"[ERROR: Tests for host-config: {host_config} failed]\n") + print_stage_summary() return res # build the docs - docs_output_file = pjoin(build_dir,"output.log.make.docs.txt") + docs_output_file = pjoin(build_dir, f"output.log.{build_log_id}.docs.txt") print("[starting docs generation]") print(f"[log file: {docs_output_file}]") - res = sexe(f"cd {build_dir} && make -j16 docs ", + stage_start_time = time.perf_counter() + res = sexe(f"cd {build_dir} && {build_cmd} docs", output_file = docs_output_file, echo=True) + record_stage("docs", stage_start_time) if report_to_stdout: with open(docs_output_file, 'r', encoding='utf8') as docs_out: @@ -299,19 +341,23 @@ def build_and_test_host_config(test_root, host_config, if res != 0: print(f"[ERROR: Docs generation for host-config: {host_config} failed]\n\n") + print_stage_summary() return res # install the code - inst_output_file = pjoin(build_dir,"output.log.make.install.txt") + inst_output_file = pjoin(build_dir, f"output.log.{build_log_id}.install.txt") print("[starting install]") print(f"[log file: {inst_output_file}]") - res = sexe(f"cd {build_dir} && make -j16 install ", + stage_start_time = time.perf_counter() + res = sexe(f"cd {build_dir} && {build_cmd} install", output_file = inst_output_file, echo=True) + record_stage("install", stage_start_time) if res != 0: print(f"[ERROR: Install for host-config: {host_config} failed]\n\n") + print_stage_summary() return res # simple sanity check for make install @@ -339,20 +385,23 @@ def build_and_test_host_config(test_root, host_config, "mkdir build", "cd build", """echo "[Configuring '{0}' example]" """.format("using-with-cmake"), - "cmake -C ../host-config.cmake ..", + f"cmake {downstream_generator_flag} -C ../host-config.cmake ..".strip(), """echo "[Building '{0}' example]" """.format("using-with-cmake"), - "make ", + build_cmd, """echo "[Running '{0}' example]" """.format("using-with-cmake"), "./example", """echo "[Done]" """ ] + stage_start_time = time.perf_counter() res = sexe(" && ".join(example_commands), output_file = install_example_output_file, echo=True) + record_stage("installed cmake example", stage_start_time) if res != 0: print(f"[ERROR: Installed 'using-with-cmake' example for host-config: {host_config} failed]\n\n") + print_stage_summary() return res @@ -368,23 +417,27 @@ def build_and_test_host_config(test_root, host_config, "mkdir build", "cd build", """echo "[Configuring '{0}' example]" """.format("using-with-blt"), - "cmake -C ../host-config.cmake ..", + f"cmake {downstream_generator_flag} -C ../host-config.cmake ..".strip(), """echo "[Building '{0}' example]" """.format("using-with-blt"), - "make ", + build_cmd, """echo "[Running '{0}' example]" """.format("using-with-blt"), "./bin/example", """echo "[Done]" """ ] + stage_start_time = time.perf_counter() res = sexe(" && ".join(example_commands), output_file = install_example_output_file, echo=True) + record_stage("installed blt example", stage_start_time) if res != 0: print(f"[ERROR: Installed 'using-with-blt' example for host-config: {host_config} failed]\n\n") + print_stage_summary() return res if should_test_installed_tutorials: + stage_start_time = time.perf_counter() for _tut in ["radiuss_tutorial", "shaping_tutorial"]: # Notes: Might require loading module for more recent cmake than the system default for some platforms install_example_dir = pjoin(install_dir, "examples", "axom", _tut) @@ -398,9 +451,9 @@ def build_and_test_host_config(test_root, host_config, "mkdir build", "cd build", f"""echo "[Configuring '{_tut}']" """, - f"cmake -C ../host-config.cmake -DCMAKE_BUILD_TYPE={build_type} ..", + f"cmake {downstream_generator_flag} -C ../host-config.cmake -DCMAKE_BUILD_TYPE={build_type} ..".strip(), f"""echo "[Building '{_tut}']" """, - "make -j16", + build_cmd, f"""echo "[Running lessons for {_tut}]" """, "ctest -j16", """echo "[Done]" """ @@ -411,12 +464,17 @@ def build_and_test_host_config(test_root, host_config, echo=True) if local_res != 0: print(f"[ERROR: Installed '{_tut}' for host-config: {host_config} failed]\n\n") + record_stage("installed tutorials", stage_start_time) + print_stage_summary() return local_res + record_stage("installed tutorials", stage_start_time) + print_stage_summary() return 0 print(f"[SUCCESS: Build, test, and install for host-config: {host_config} complete]\n") + print_stage_summary() set_group_and_perms(build_dir) set_group_and_perms(install_dir) @@ -430,7 +488,8 @@ def build_and_test_host_configs(prefix, report_to_stdout = False, extra_cmake_options = "", build_type = "Debug", - test_serial = False): + test_serial = False, + use_ninja = False): host_configs = get_host_configs_for_current_machine(prefix, use_generated_host_configs) if len(host_configs) == 0: log_failure(prefix,"[ERROR: No host configs found at %s]" % prefix) @@ -453,7 +512,8 @@ def build_and_test_host_configs(prefix, report_to_stdout = report_to_stdout, extra_cmake_options=extra_cmake_options, build_type = build_type, - test_serial = test_serial) == 0: + test_serial = test_serial, + use_ninja = use_ninja) == 0: ok.append(host_config) log_success(build_dir, "[Success: Built host-config: {0}]".format(host_config), timestamp) else: diff --git a/src/cmake/AxomMacros.cmake b/src/cmake/AxomMacros.cmake index 192277fed0..ac5b5e4ea1 100644 --- a/src/cmake/AxomMacros.cmake +++ b/src/cmake/AxomMacros.cmake @@ -159,6 +159,14 @@ macro(axom_add_executable) OUTPUT_NAME ${arg_OUTPUT_NAME} FOLDER ${arg_FOLDER}) + if(AXOM_C_EXE_LINKER_FLAGS) + target_link_options(${arg_NAME} PRIVATE + $<$:${AXOM_C_EXE_LINKER_FLAGS}>) + endif() + if(AXOM_CXX_EXE_LINKER_FLAGS) + target_link_options(${arg_NAME} PRIVATE + $<$:${AXOM_CXX_EXE_LINKER_FLAGS}>) + endif() endmacro(axom_add_executable)