Keep multi-word values intact when loading toolchain/modules - #1702
Keep multi-word values intact when loading toolchain/modules#1702Mohit-Ak wants to merge 1 commit into
Conversation
A `KEY=value` line in toolchain/modules was exported with `eval "export $_entry"`, which word-splits the value. Everything after the first word was treated as a further name to export; that failed, and the failure went to stderr, which `./mfc.sh load` output is routinely redirected away from. The variable ended up set but holding only its first word, with nothing to say so. The consequences are not cosmetic: on Frontier, CRAY_CCE_LLD_ARGS needs two -plugin-opt flags for CCE 21, one of which works around a code-generation bug that silently discards stores. Written unquoted, only the first was applied -- the build succeeded and the numerical workaround was simply absent. Splitting on the first '=' instead, as the issue suggests, fixes multi-word values but breaks the multi-assignment lines that are already in the file (CC=nvc CXX=nvc++ FC=nvfortran would collapse into CC). So the loader now walks the line word by word and starts a new assignment only at a word shaped like an identifier followed by '=', treating anything else as a continuation of the current value. Values are still expanded once so "$VAR" references to earlier exports keep working, but the expanded result is exported directly rather than re-evaluated, which is what dropped the extra words before. Fixes MFlowCode#1690
Code reviewThe core fix looks correct. I diffed old-vs-new behavior across all 23 Found 1 issue worth addressing, plus three minor notes.
Before the export loop ever runs, MFC/toolchain/bootstrap/modules.sh Lines 153 to 162 in 38c24b2 Any word of a multi-word value that does not itself contain The originally reported #1690 case works only incidentally, because every one of its words happens to contain MFC/toolchain/mfc/bootstrap_tests/test_modules_env.py Lines 104 to 127 in 38c24b2
Minor notes, take or leave:
MFC/toolchain/bootstrap/modules.sh Lines 105 to 118 in 38c24b2
MFC/toolchain/bootstrap/modules.sh Lines 128 to 130 in 38c24b2
Lines 39 to 46 in 38c24b2 Generated with Claude Code - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
A
KEY=valueline intoolchain/moduleswas exported by the loader like this:The entry isn't quoted, so
evalword-splits the value. Everything after the first word is treated as a further name to export, that fails, and the failure goes to stderr — which./mfc.sh loadoutput is routinely redirected away from. The result is a variable that looks set but holds only its first word, with nothing anywhere to say so:As #1690 notes, that's not cosmetic: on Frontier
CRAY_CCE_LLD_ARGSneeds two-plugin-optflags for CCE 21, one of which works around a code-generation bug that silently discards stores. Written unquoted, only the first is applied — the build succeeds, the tests run, and the numerical workaround is simply absent.Why not the split-on-first-
=fixThe issue suggests splitting on the first
=and exporting without re-evaluating. That does fix multi-word values, but it breaks the multi-assignment lines already in the file, because those carry several assignments per line. I swept both approaches over every assignment line currently intoolchain/modules:Eight lines in the file have this shape (
b-gpu,a-gpu,w-gpu,e-gpu,p-gpu,pifx-cpu×3,c-cpu,i-all, …), so split-on-=would quietly stop setting the compilers on most clusters.What this does instead
The loader now walks the line word by word and starts a new assignment only at a word shaped like an identifier followed by
=; anything else is a continuation of the current value. Both shapes then survive, including a multi-word value followed by another assignment.Values still go through one round of expansion so
"$VAR"references to previously-exported variables keep working (NVHPC_CUDA_HOME=$CUDA_HOME), but the expanded result is exported directly rather than re-evaluated — re-evaluating is what dropped the extra words. Word-splitting runs underset -fso a value like-Wl,*can't pick up filenames from the working directory, and the previous globbing state is restored afterward.Testing
toolchain/mfc/bootstrap_tests/test_modules_env.pydrives the real__export_assignmentsfunction out ofmodules.sh(rather than a copy), so it fails if the implementation regresses. It covers every assignment shape currently intoolchain/modules, the multi-word cases from the issue,$VARexpansion inside a multi-word value, glob safety, and a sweep asserting that every assignment line shipped intoolchain/modulesexports each of its names.Against the unpatched loader, 4 of the 12 fail, with the 8 existing-shape tests still passing:
With the fix:
(382 vs. 370 on master — the 12 new tests, and ruff clean.)
./mfc.sh precheckpasses all seven gates (formatting, spelling, toolchain lint, source lint, doc references, parameter docs, example cases).I also ran the real loader loop end-to-end for several cluster slugs to confirm nothing changed for existing configurations:
One judgement call worth flagging: I put the new tests under
toolchain/mfc/bootstrap_tests/since there was no existing home for shell-level tests. Happy to move them if you'd rather they lived elsewhere.Fixes #1690