100100 myChunk=$2
101101 system=$3
102102 outputDir=$4
103+ preEvalFile=$5
103104
104105 # Default is 5, higher values effectively disable the warning.
105106 # This randomly breaks Eval.
@@ -121,12 +122,12 @@ let
121122 --show-trace \
122123 --arg chunkSize "$chunkSize" \
123124 --arg myChunk "$myChunk" \
124- --arg preEvalFile "${ preEvalFile } " \
125+ --arg preEvalFile "$preEvalFile" \
125126 --arg systems "[ \"$system\" ]" \
126127 --arg includeBroken ${ lib . boolToString includeBroken } \
127128 --argstr extraNixpkgsConfigJson ${ lib . escapeShellArg ( builtins . toJSON extraNixpkgsConfig ) } \
128129 -I ${ nixpkgs } \
129- -I ${ preEvalFile } \
130+ -I "$ preEvalFile" \
130131 > "$outputDir/result/$myChunk" \
131132 2> "$outputDir/stderr/$myChunk"
132133 exitCode=$?
164165 echo "System: $evalSystem"
165166 cores=$NIX_BUILD_CORES
166167 echo "Cores: $cores"
167- attrCount=$(jq '.paths | length' "${ preEvalFile } ")
168- echo "Attribute count: $attrCount"
169- echo "Chunk size: $chunkSize"
170- # Same as `attrCount / chunkSize` but rounded up
171- chunkCount=$(( (attrCount - 1) / chunkSize + 1 ))
172- echo "Chunk count: $chunkCount"
173168
174169 mkdir -p $out/${ evalSystem }
175170
@@ -190,29 +185,61 @@ let
190185 done
191186 ) &
192187
193- seq_end=$(( chunkCount - 1 ))
188+ chunkedEval() {
189+ local chunkOutputDir=$1
190+ local preEvalFile=$2
194191
195- ${ lib . optionalString quickTest ''
196- seq_end=0
197- '' }
192+ local attrCount=$(jq '.paths | length' "$preEvalFile")
193+ echo "Attribute count: $attrCount"
194+ echo "Chunk size: $chunkSize"
195+ # Same as `attrCount / chunkSize` but rounded up
196+ local chunkCount=$(( (attrCount - 1) / chunkSize + 1 ))
197+ echo "Chunk count: $chunkCount"
198198
199- chunkOutputDir=$(mktemp -d)
200- mkdir "$chunkOutputDir"/{result,stats,timestats,stderr}
199+ local seq_end=$(( chunkCount - 1 ))
200+ ${ lib . optionalString quickTest ''
201+ seq_end=0
202+ '' }
201203
202- seq -w 0 "$seq_end" |
203- command time -f "%e" -o "$out/${ evalSystem } /total-time" \
204- xargs -I{} -P"$cores" \
205- ${ singleChunk } "$chunkSize" {} "$evalSystem" "$chunkOutputDir"
204+ mkdir -p "$chunkOutputDir"/{result,stats,timestats,stderr}
206205
207- cp -r "$chunkOutputDir"/stats $out/${ evalSystem } /stats-by-chunk
206+ seq -w 0 "$seq_end" |
207+ xargs -I{} -P"$cores" \
208+ ${ singleChunk } "$chunkSize" {} "$evalSystem" "$chunkOutputDir" "$preEvalFile"
208209
209- if (( chunkSize * chunkCount != attrCount )); then
210- # A final incomplete chunk would mess up the stats, don't include it
211- rm "$chunkOutputDir"/stats/"$seq_end"
212- fi
210+ if (( chunkSize * chunkCount != attrCount )); then
211+ # A final incomplete chunk would mess up the stats, don't include it
212+ rm "$chunkOutputDir"/stats/"$seq_end"
213+ fi
214+ }
215+
216+ chunkOutputDirs=$(mktemp -d)
217+
218+ # Preparation for the second eval
219+ disallowedAttributesPreEvalFile=$(mktemp)
220+ jq '{
221+ paths: (.attrPathsDisallowedForInternalUse | map(.attrPath)),
222+ attrPathsDisallowedForInternalUse: []
223+ }' ${ preEvalFile } > "$disallowedAttributesPreEvalFile"
224+
225+ startEpoch=$(date +%s)
226+
227+ # The first eval evaluates only attributes that are not disallowed for internal Nixpkgs use, ensuring that they don't depend on disallowed attributes
228+ # Because the first eval doesn't evaluate the disallowed attributes themselves, but we still want to check that they don't fail evaluation, we evaluate them separately in a second eval
229+ # The reason we need two evals is because we want disallowed attributes to be able to depend on other disallowed attributes, which inherently needs a separate Nixpkgs instantiation
230+ # And while we could interleave that instantiation into a single eval, that would ~double memory usage for all chunks, while doing it separately doesn't
231+ echo "Evaluating the internally allowed attributes"
232+ chunkedEval "$chunkOutputDirs"/allowed ${ preEvalFile }
233+ echo "Evaluating the internally disallowed attributes"
234+ chunkedEval "$chunkOutputDirs"/disallowed "$disallowedAttributesPreEvalFile"
235+
236+ echo $(( $(date +%s) - startEpoch )) > "$out/${ evalSystem } /total-time"
237+
238+ # We only use the stats from the allowed attrs eval, because the disallowed attrs are generally not even a full chunk
239+ cp -r "$chunkOutputDirs"/allowed/stats $out/${ evalSystem } /stats-by-chunk
213240
214- cat "$chunkOutputDir" /result/* | jq -s 'add | map_values(.outputs)' > $out/${ evalSystem } /paths.json
215- cat "$chunkOutputDir" /result/* | jq -s 'add | map_values(.meta)' > $out/${ evalSystem } /meta.json
241+ cat "$chunkOutputDirs"/* /result/* | jq -s 'add | map_values(.outputs)' > $out/${ evalSystem } /paths.json
242+ cat "$chunkOutputDirs"/* /result/* | jq -s 'add | map_values(.meta)' > $out/${ evalSystem } /meta.json
216243 '' ;
217244
218245 diff = callPackage ./diff.nix { } ;
0 commit comments