@@ -55,81 +55,118 @@ while [[ $# -gt 0 ]]; do
5555 shift
5656done
5757
58- FAILED=0
58+ # Skip slow rendering tests (matplotlib/imageio) during local precheck.
59+ # CI runs the full suite via ./mfc.sh lint without this variable.
60+ export MFC_SKIP_RENDER_TESTS=1
5961
6062log " Running$MAGENTA precheck$COLOR_RESET (same checks as CI lint-gate)..."
6163echo " "
6264
63- # 1. Check formatting
64- log " [$CYAN 1/5$COLOR_RESET ] Checking$MAGENTA formatting$COLOR_RESET ..."
65- # Capture state before formatting
65+ # Temp files for collecting results from parallel jobs
66+ TMPDIR_PC=$( mktemp -d)
67+ trap " rm -rf $TMPDIR_PC " EXIT
68+
69+ # --- Phase 1: Format (modifies files, must run alone) ---
6670BEFORE_HASH=$( git diff -- ' *.f90' ' *.fpp' ' *.py' 2> /dev/null | compute_hash)
6771if ! ./mfc.sh format -j " $JOBS " > /dev/null 2>&1 ; then
68- error " Formatting check failed to run."
69- FAILED=1
72+ FORMAT_OK=1
7073else
71- # Check if formatting changed any Fortran/Python files
7274 AFTER_HASH=$( git diff -- ' *.f90' ' *.fpp' ' *.py' 2> /dev/null | compute_hash)
7375 if [ " $BEFORE_HASH " != " $AFTER_HASH " ]; then
74- error " Code was not formatted. Files have been auto-formatted; review and stage the changes."
75- echo " "
76- git diff --stat -- ' *.f90' ' *.fpp' ' *.py' 2> /dev/null || true
77- echo " "
78- FAILED=1
76+ FORMAT_OK=2
77+ else
78+ FORMAT_OK=0
79+ fi
80+ fi
81+
82+ # --- Phase 2: All remaining checks in parallel (read-only) ---
83+
84+ # Spell check
85+ (
86+ if ./mfc.sh spelling > /dev/null 2>&1 ; then
87+ echo " 0" > " $TMPDIR_PC /spell_exit"
88+ else
89+ echo " 1" > " $TMPDIR_PC /spell_exit"
90+ fi
91+ ) &
92+ PID_SPELL=$!
93+
94+ # Lint (ruff + unit tests) — safe after format since files are stable
95+ (
96+ if ./mfc.sh lint > /dev/null 2>&1 ; then
97+ echo " 0" > " $TMPDIR_PC /lint_exit"
7998 else
80- ok " Formatting check passed. "
99+ echo " 1 " > " $TMPDIR_PC /lint_exit "
81100 fi
101+ ) &
102+ PID_LINT=$!
103+
104+ # Source lint (fast grep checks — run inline)
105+ SOURCE_FAILED=0
106+ if grep -qiR ' !\$acc\|!\$omp' --exclude=" parallel_macros.fpp" --exclude=" acc_macros.fpp" --exclude=" omp_macros.fpp" --exclude=" shared_parallel_macros.fpp" --exclude=" syscheck.fpp" ./src/* 2> /dev/null; then
107+ SOURCE_FAILED=1
108+ fi
109+ if grep -qiR ' double_precision\|dsqrt\|dexp\|dlog\|dble\|dabs\|double\ precision\|real(8)\|real(4)\|dprod\|dmin\|dmax\|dfloat\|dreal\|dcos\|dsin\|dtan\|dsign\|dtanh\|dsinh\|dcosh\|d0' --exclude-dir=syscheck --exclude=" *nvtx*" --exclude=" *precision_select*" ./src/* 2> /dev/null; then
110+ SOURCE_FAILED=1
111+ fi
112+ if grep -qiR -e ' \.\.\.' -e ' \-\-\-' -e ' ===' ./src/* 2> /dev/null; then
113+ SOURCE_FAILED=1
114+ fi
115+
116+ # Doc reference check
117+ DOC_FAILED=0
118+ if ! python3 toolchain/mfc/lint_docs.py > /dev/null 2>&1 ; then
119+ DOC_FAILED=1
82120fi
83121
84- # 2. Spell check
122+ # --- Collect results ---
123+
124+ FAILED=0
125+
126+ log " [$CYAN 1/5$COLOR_RESET ] Checking$MAGENTA formatting$COLOR_RESET ..."
127+ if [ " $FORMAT_OK " = " 1" ]; then
128+ error " Formatting check failed to run."
129+ FAILED=1
130+ elif [ " $FORMAT_OK " = " 2" ]; then
131+ error " Code was not formatted. Files have been auto-formatted; review and stage the changes."
132+ echo " "
133+ git diff --stat -- ' *.f90' ' *.fpp' ' *.py' 2> /dev/null || true
134+ echo " "
135+ FAILED=1
136+ else
137+ ok " Formatting check passed."
138+ fi
139+
140+ wait $PID_SPELL
85141log " [$CYAN 2/5$COLOR_RESET ] Running$MAGENTA spell check$COLOR_RESET ..."
86- if ./mfc.sh spelling > /dev/null 2>&1 ; then
142+ SPELL_RC=$( cat " $TMPDIR_PC /spell_exit" 2> /dev/null || echo " 1" )
143+ if [ " $SPELL_RC " = " 0" ]; then
87144 ok " Spell check passed."
88145else
89146 error " Spell check failed. Run$MAGENTA ./mfc.sh spelling$COLOR_RESET for details."
90147 FAILED=1
91148fi
92149
93- # 3. Lint toolchain (Python)
150+ wait $PID_LINT
94151log " [$CYAN 3/5$COLOR_RESET ] Running$MAGENTA toolchain lint$COLOR_RESET ..."
95- if ./mfc.sh lint > /dev/null 2>&1 ; then
152+ LINT_RC=$( cat " $TMPDIR_PC /lint_exit" 2> /dev/null || echo " 1" )
153+ if [ " $LINT_RC " = " 0" ]; then
96154 ok " Toolchain lint passed."
97155else
98156 error " Toolchain lint failed. Run$MAGENTA ./mfc.sh lint$COLOR_RESET for details."
99157 FAILED=1
100158fi
101159
102- # 4. Source code lint checks
103160log " [$CYAN 4/5$COLOR_RESET ] Running$MAGENTA source lint$COLOR_RESET checks..."
104- SOURCE_FAILED=0
105-
106- # Check for raw OpenACC/OpenMP directives
107- if grep -qiR ' !\$acc\|!\$omp' --exclude=" parallel_macros.fpp" --exclude=" acc_macros.fpp" --exclude=" omp_macros.fpp" --exclude=" shared_parallel_macros.fpp" --exclude=" syscheck.fpp" ./src/* 2> /dev/null; then
108- error " Found raw OpenACC/OpenMP directives. Use macros instead."
109- SOURCE_FAILED=1
110- fi
111-
112- # Check for double precision intrinsics
113- if grep -qiR ' double_precision\|dsqrt\|dexp\|dlog\|dble\|dabs\|double\ precision\|real(8)\|real(4)\|dprod\|dmin\|dmax\|dfloat\|dreal\|dcos\|dsin\|dtan\|dsign\|dtanh\|dsinh\|dcosh\|d0' --exclude-dir=syscheck --exclude=" *nvtx*" --exclude=" *precision_select*" ./src/* 2> /dev/null; then
114- error " Found double precision intrinsics. Use generic intrinsics."
115- SOURCE_FAILED=1
116- fi
117-
118- # Check for junk code patterns
119- if grep -qiR -e ' \.\.\.' -e ' \-\-\-' -e ' ===' ./src/* 2> /dev/null; then
120- error " Found junk code patterns (..., ---, ===) in source."
121- SOURCE_FAILED=1
122- fi
123-
124161if [ $SOURCE_FAILED -eq 0 ]; then
125162 ok " Source lint passed."
126163else
164+ error " Source lint failed."
127165 FAILED=1
128166fi
129167
130- # 5. Doc reference check
131168log " [$CYAN 5/5$COLOR_RESET ] Checking$MAGENTA doc references$COLOR_RESET ..."
132- if python3 toolchain/mfc/lint_docs.py 2>&1 ; then
169+ if [ $DOC_FAILED -eq 0 ] ; then
133170 ok " Doc references are valid."
134171else
135172 error " Doc reference check failed. Run$MAGENTA python3 toolchain/mfc/lint_docs.py$COLOR_RESET for details."
0 commit comments