@@ -180,7 +180,7 @@ class ProjectBuilder {
180180 }
181181 }
182182
183- const projectBuildContexts = await this . _createRequiredBuildContexts ( requestedProjects ) ;
183+ const projectBuildContexts = await this . _buildContext . createRequiredProjectContexts ( requestedProjects ) ;
184184 let fsTarget ;
185185 if ( destPath ) {
186186 fsTarget = resourceFactory . createAdapter ( {
@@ -236,7 +236,16 @@ class ProjectBuilder {
236236 } ) ) ;
237237
238238 const alreadyBuilt = [ ] ;
239+ const changedDependencyResources = [ ] ;
239240 for ( const projectBuildContext of queue ) {
241+ if ( changedDependencyResources . length ) {
242+ // Notify build cache of changed resources from dependencies
243+ projectBuildContext . dependencyResourcesChanged ( changedDependencyResources ) ;
244+ }
245+ const changedResources = await projectBuildContext . determineChangedResources ( ) ;
246+ for ( const resourcePath of changedResources ) {
247+ changedDependencyResources . push ( resourcePath ) ;
248+ }
240249 if ( ! await projectBuildContext . requiresBuild ( ) ) {
241250 const projectName = projectBuildContext . getProject ( ) . getName ( ) ;
242251 alreadyBuilt . push ( projectName ) ;
@@ -275,19 +284,24 @@ class ProjectBuilder {
275284 try {
276285 const startTime = process . hrtime ( ) ;
277286 const pWrites = [ ] ;
278- for ( const projectBuildContext of queue ) {
287+ while ( queue . length ) {
288+ const projectBuildContext = queue . shift ( ) ;
279289 const project = projectBuildContext . getProject ( ) ;
280290 const projectName = project . getName ( ) ;
281291 const projectType = project . getType ( ) ;
282292 this . #log. verbose ( `Processing project ${ projectName } ...` ) ;
283293
284294 // Only build projects that are not already build (i.e. provide a matching build manifest)
285- if ( alreadyBuilt . includes ( projectName ) ) {
295+ if ( alreadyBuilt . includes ( projectName ) || ! ( await projectBuildContext . requiresBuild ( ) ) ) {
286296 this . #log. skipProjectBuild ( projectName , projectType ) ;
287297 } else {
288298 this . #log. startProjectBuild ( projectName , projectType ) ;
289- await projectBuildContext . getTaskRunner ( ) . runTasks ( ) ;
299+ const changedResources = await projectBuildContext . runTasks ( ) ;
290300 this . #log. endProjectBuild ( projectName , projectType ) ;
301+ for ( const pbc of queue ) {
302+ // Propagate resource changes to following projects
303+ pbc . getBuildCache ( ) . dependencyResourcesChanged ( changedResources ) ;
304+ }
291305 }
292306 if ( ! requestedProjects . includes ( projectName ) ) {
293307 // Project has not been requested
@@ -306,7 +320,7 @@ class ProjectBuilder {
306320 project ,
307321 this . _graph , this . _buildContext . getBuildConfig ( ) , this . _buildContext . getTaskRepository ( ) ,
308322 projectBuildContext . getBuildSignature ( ) ) ;
309- pWrites . push ( projectBuildContext . getBuildCache ( ) . storeCache ( buildManifest ) ) ;
323+ pWrites . push ( projectBuildContext . getBuildCache ( ) . writeCache ( buildManifest ) ) ;
310324 }
311325 }
312326 await Promise . all ( pWrites ) ;
@@ -337,6 +351,7 @@ class ProjectBuilder {
337351
338352 async #update( projectBuildContexts , requestedProjects , fsTarget ) {
339353 const queue = [ ] ;
354+ const changedDependencyResources = [ ] ;
340355 await this . _graph . traverseDepthFirst ( async ( { project} ) => {
341356 const projectName = project . getName ( ) ;
342357 const projectBuildContext = projectBuildContexts . get ( projectName ) ;
@@ -345,6 +360,15 @@ class ProjectBuilder {
345360 // => This project needs to be built or, in case it has already
346361 // been built, it's build result needs to be written out (if requested)
347362 queue . push ( projectBuildContext ) ;
363+
364+ if ( changedDependencyResources . length ) {
365+ // Notify build cache of changed resources from dependencies
366+ await projectBuildContext . dependencyResourcesChanged ( changedDependencyResources ) ;
367+ }
368+ const changedResources = await projectBuildContext . determineChangedResources ( ) ;
369+ for ( const resourcePath of changedResources ) {
370+ changedDependencyResources . push ( resourcePath ) ;
371+ }
348372 }
349373 } ) ;
350374
@@ -353,7 +377,8 @@ class ProjectBuilder {
353377 } ) ) ;
354378
355379 const pWrites = [ ] ;
356- for ( const projectBuildContext of queue ) {
380+ while ( queue . length ) {
381+ const projectBuildContext = queue . shift ( ) ;
357382 const project = projectBuildContext . getProject ( ) ;
358383 const projectName = project . getName ( ) ;
359384 const projectType = project . getType ( ) ;
@@ -365,8 +390,12 @@ class ProjectBuilder {
365390 }
366391
367392 this . #log. startProjectBuild ( projectName , projectType ) ;
368- await projectBuildContext . runTasks ( ) ;
393+ const changedResources = await projectBuildContext . runTasks ( ) ;
369394 this . #log. endProjectBuild ( projectName , projectType ) ;
395+ for ( const pbc of queue ) {
396+ // Propagate resource changes to following projects
397+ pbc . getBuildCache ( ) . dependencyResourcesChanged ( changedResources ) ;
398+ }
370399 if ( ! requestedProjects . includes ( projectName ) ) {
371400 // Project has not been requested
372401 // => Its resources shall not be part of the build result
@@ -386,52 +415,11 @@ class ProjectBuilder {
386415 project ,
387416 this . _graph , this . _buildContext . getBuildConfig ( ) , this . _buildContext . getTaskRepository ( ) ,
388417 projectBuildContext . getBuildSignature ( ) ) ;
389- pWrites . push ( projectBuildContext . getBuildCache ( ) . storeCache ( buildManifest ) ) ;
418+ pWrites . push ( projectBuildContext . getBuildCache ( ) . writeCache ( buildManifest ) ) ;
390419 }
391420 await Promise . all ( pWrites ) ;
392421 }
393422
394- async _createRequiredBuildContexts ( requestedProjects ) {
395- const requiredProjects = new Set ( this . _graph . getProjectNames ( ) . filter ( ( projectName ) => {
396- return requestedProjects . includes ( projectName ) ;
397- } ) ) ;
398-
399- const projectBuildContexts = new Map ( ) ;
400-
401- for ( const projectName of requiredProjects ) {
402- this . #log. verbose ( `Creating build context for project ${ projectName } ...` ) ;
403- const projectBuildContext = await this . _buildContext . createProjectContext ( {
404- project : this . _graph . getProject ( projectName )
405- } ) ;
406-
407- projectBuildContexts . set ( projectName , projectBuildContext ) ;
408-
409- if ( await projectBuildContext . requiresBuild ( ) ) {
410- const taskRunner = projectBuildContext . getTaskRunner ( ) ;
411- const requiredDependencies = await taskRunner . getRequiredDependencies ( ) ;
412-
413- if ( requiredDependencies . size === 0 ) {
414- continue ;
415- }
416- // This project needs to be built and required dependencies to be built as well
417- this . _graph . getDependencies ( projectName ) . forEach ( ( depName ) => {
418- if ( projectBuildContexts . has ( depName ) ) {
419- // Build context already exists
420- // => Dependency will be built
421- return ;
422- }
423- if ( ! requiredDependencies . has ( depName ) ) {
424- return ;
425- }
426- // Add dependency to list of projects to build
427- requiredProjects . add ( depName ) ;
428- } ) ;
429- }
430- }
431-
432- return projectBuildContexts ;
433- }
434-
435423 async _getProjectFilter ( {
436424 dependencyIncludes,
437425 explicitIncludes,
0 commit comments