Raw File
app.def
{#- Required jinja arguments                                                                  -#}
{#- APPTAINER_BOOTSTRAP: The BootStrap to use (typically localimage or oras)                  -#}
{#- APPTAINER_FROM: The From to use (path to an image or an oras URI)                         -#}
{#- APPLICATION_DIR: Path on the host to the application repository                           -#}
{#- MOOSE_DIR: Path on the host to the MOOSE repository                                       -#}
{#- BINARY_NAME: Name of the application binary                                               -#}

{#- Optional jinja arguments                                                                  -#}
{#- MOOSE_JOBS: Number of jobs to pass to the build                                           -#}
{#- MOOSE_OPTIONS: Options to pass to the MOOSE configure                                     -#}
{#- MOOSE_SKIP_DOCS: Set to anything to skip the docs build                                   -#}
{#- MOOSE_DOCS_FLAGS: Doc options to pass during the make install                             -#}
{#- METHOD: The method to build; defaults to "opt"                                            -#}
{#- TEST_DIRS: Directories to test in the %test section; defaults to just "tests"             -#}
{#- EXTRA_MAMBA_PACKAGES: Extra mamba packages to install                                     -#}

{#- Civet Specific jinja arguments                                                            -#}
{#- CIVET_STEP_ALLOWED_TO_FAIL: BOOL, specific to Civet. Available in %post, %test section    -#}

{#- Optional Application specific jinja arguments                                             -#}
{#- SECTION_ENVIRONMENT: Adds additional environment variables set upon entering container    -#}
{#- SECTION_POST: Partially replaces %post (make, make install, section)                      -#}
{#- SECTION_TEST: Partially replaces %test (for loop section)                                 -#}

{#- The within-container build directory to use                                               -#}
{%- set ROOT_BUILD_DIR = '/root/build' -%}

BootStrap: {{ APPTAINER_BOOTSTRAP }}
From: {{ APPTAINER_FROM }}

%setup
    # Load jinja vars
    ROOT_BUILD_DIR={{ ROOT_BUILD_DIR }}
    APPLICATION_DIR={{ APPLICATION_DIR }}
    MOOSE_DIR={{ MOOSE_DIR }}

    # Build directory in the container
    BUILD_DIR=${APPTAINER_ROOTFS}${ROOT_BUILD_DIR}
    mkdir ${BUILD_DIR}

    # Copy application into the container
    cp -r ${APPLICATION_DIR} ${BUILD_DIR}

    # Where the application ends up; needed for MOOSE logic below
    APPLICATION_NAME=$(basename ${APPLICATION_DIR})
    APPLICATION_BUILD_DIR=${BUILD_DIR}/${APPLICATION_NAME}

    # Figure out where moose is; regardless %post will expect
    # it to be in {{ ROOT_BUILD_DIR }}/moose
    MOOSE_BUILD_DIR=${BUILD_DIR}/moose
    MOOSE_RELATIVE_PATH=$(realpath --relative-to ${APPLICATION_DIR} ${MOOSE_DIR})
    # MOOSE_DIR is not in the application; we need to copy it
    if [[ $MOOSE_RELATIVE_PATH = ..* ]]; then
        mkdir ${MOOSE_BUILD_DIR}
        cp -r ${MOOSE_DIR}/. ${MOOSE_BUILD_DIR}
    # MOOSE_DIR is the application (combined-opt)
    elif [[ '{{ BINARY_NAME }}' == 'moose' ]]; then
        # do nothing
        :
    # MOOSE_DIR is in the application, setup a symlink
    else
        ln -s ./${APPLICATION_NAME}/${MOOSE_RELATIVE_PATH} ${MOOSE_BUILD_DIR}
    fi

{%- if MOOSE_SKIP_DOCS is not defined %}
    # Need large_media for documentation
    cd ${MOOSE_BUILD_DIR}
    git submodule update --init large_media
{%- endif %}

%environment
{%- if BINARY_NAME == 'moose' %}
    export PATH=/opt/moose/bin:$PATH
{%- else %}
    export PATH=/opt/{{ BINARY_NAME }}/bin:$PATH
{%- endif %}
{%- if SECTION_ENVIRONMENT is defined %}
    {{ SECTION_ENVIRONMENT }}
{%- endif %}

%post
{%- if SECTION_POST_BEGIN is defined %}
    {{ SECTION_POST_BEGIN }}
{%- endif %}
    # Load jinja vars
    APPLICATION_NAME=$(basename {{ APPLICATION_DIR }})
    BINARY_NAME={{ BINARY_NAME }}
    export METHOD={{ METHOD or "opt" }}
    MOOSE_DOCS_FLAGS="{{ MOOSE_DOCS_FLAGS }}"
    export MOOSE_JOBS={{ MOOSE_JOBS or "1" }}
    MOOSE_OPTIONS="{{ MOOSE_OPTIONS }}"
    MOOSE_SKIP_DOCS={{ MOOSE_SKIP_DOCS }}
    TEMP_LOC={{ ROOT_BUILD_DIR }}
    APPLICATION_DIR=${TEMP_LOC}/${APPLICATION_NAME}
    export MOOSE_DIR=${TEMP_LOC}/moose

    # If MOOSE_DIR is a symlink, we're using MOOSE within
    # the app, so use that instead
    if test -h $MOOSE_DIR; then
        MOOSE_DIR_REAL=$(realpath $MOOSE_DIR)
        rm ${MOOSE_DIR}
        export MOOSE_DIR=${MOOSE_DIR_REAL}
    fi

    # Remove the libmesh methods from moose-dev that we do not need
    for method in opt oprof devel dbg; do
        if [ "$method" != "$METHOD" ]; then
            find ${LIBMESH_DIR}/lib -name "*_$method.so*" -delete -print
            find ${LIBMESH_DIR}/lib -name "*_$method.la" -delete -print
            find ${LIBMESH_DIR}/bin -name "*-$method" -delete -print
            find ${LIBMESH_DIR} -name "*-$method.pc" -delete -print
        fi
    done

    # Setup install
{%- if BINARY_NAME == 'moose' %}
    MOOSE_PREFIX=/opt/moose
{%- else %}
    MOOSE_PREFIX=/opt/${BINARY_NAME}
{%- endif %}
    cd ${MOOSE_DIR}
    ./configure --prefix=$MOOSE_PREFIX ${MOOSE_OPTIONS}
    # Build and install
{%- if BINARY_NAME == 'moose' %}
    cd ${APPLICATION_DIR}/modules
{%- else %}
    cd ${APPLICATION_DIR}
{%- endif %}
{%- if SECTION_POST_PRE_MAKE is defined %}
    {{ SECTION_POST_PRE_MAKE }}
{%- endif %}
    make -j ${MOOSE_JOBS}
{%- if SECTION_POST_PRE_INSTALL is defined %}
    {{ SECTION_POST_PRE_INSTALL }}
{%- endif %}
    make install -j ${MOOSE_JOBS} MOOSE_SKIP_DOCS=${MOOSE_SKIP_DOCS} MOOSE_DOCS_FLAGS="${MOOSE_DOCS_FLAGS}"
{%- if SECTION_POST_POST_INSTALL is defined %}
    {{ SECTION_POST_POST_INSTALL }}
{%- endif %}

{%- if BINARY_NAME == 'moose' %}
    # Also build and install moose_test-opt
    cd ${APPLICATION_DIR}/test
    make -j ${MOOSE_JOBS}
    make install -j ${MOOSE_JOBS} MOOSE_SKIP_DOCS=1
    # Create moose-opt symlink to combined-opt
    cd /opt/moose/bin
    ln -s combined-opt moose-opt
{%- endif %}

    # Fix permissions for installed application
    chmod -R o=u-w,g=u-w ${MOOSE_PREFIX}

{%- if SECTION_POST_END is defined %}
    {{ SECTION_POST_END }}
{%- endif %}
    # Cleanup
    rm -rf $TEMP_LOC

%test
    set -x

    # Load jinja vars
    export BINARY_NAME={{ BINARY_NAME }}
    export METHOD={{ METHOD or "opt" }}
    TEST_DIRS="{{ TEST_DIRS or "tests" }}"
    # Temp location for copying and running in
    export TEMP_LOC=$(mktemp -d /tmp/${BINARY_NAME}test.XXXXXX)
    # Really make sure that we nuke the temp location in all circumstances
    trap "/usr/bin/rm -rf $TEMP_LOC" EXIT HUP INT TERM
{%- if SECTION_TEST_BEGIN is defined %}
    {{ SECTION_TEST_BEGIN }}
{%- endif %}

    function run_tests()
    {
        local BINARY_NAME=$1
        local TEST_DIR=$2
        local TEMP_TEST_LOC=${TEMP_LOC}/${TEST_DIR}
        mkdir $TEMP_TEST_LOC &&                                 \
          cd $TEMP_TEST_LOC &&                                  \
          ${BINARY_NAME}-${METHOD} --copy-inputs $TEST_DIR &&   \
          cd ${BINARY_NAME}/${TEST_DIR} &&                      \
          ${BINARY_NAME}-${METHOD} --run -j ${MOOSE_JOBS:-1} -t
        return_code=$?
        rm -rf $TEMP_TEST_LOC
        return $return_code
    }

    return_flag=0

{%- if BINARY_NAME == 'moose' %}
    run_tests moose_test tests || return_flag=$?
{%- endif %}

    # Copy and run each subset of tests
    for TEST_DIR in ${TEST_DIRS}; do
        run_tests ${BINARY_NAME} ${TEST_DIR} || return_flag=$?
    done

    rm -rf $TEMP_LOC

    if [ $return_flag != 0 ]; then
        exit $return_flag
    fi

{%- if SECTION_TEST_END is defined %}
    {{ SECTION_TEST_END }}
{%- endif %}
back to top