77#include " ssLogger/ssLog.hpp"
88
99#include < unordered_set>
10+ #include < future>
11+ #include < chrono>
1012
1113namespace
1214{
@@ -489,7 +491,8 @@ bool runcpp2::SetupDependenciesIfNeeded(const runcpp2::Data::Profile& profile,
489491 const Data::ScriptInfo& scriptInfo,
490492 std::vector<Data::DependencyInfo*>& availableDependencies,
491493 const std::vector<std::string>& dependenciesLocalCopiesPaths,
492- const std::vector<std::string>& dependenciesSourcePaths)
494+ const std::vector<std::string>& dependenciesSourcePaths,
495+ const int maxThreads)
493496{
494497 ssLOG_FUNC_INFO ();
495498
@@ -510,9 +513,13 @@ bool runcpp2::SetupDependenciesIfNeeded(const runcpp2::Data::Profile& profile,
510513 }
511514
512515 if (!PopulateAbsoluteIncludePaths (availableDependencies, dependenciesLocalCopiesPaths))
513- {
514516 return false ;
515- }
517+
518+ std::vector<std::future<bool >> actions;
519+
520+ // Cache logs for worker threads
521+ ssLOG_ENABLE_CACHE_OUTPUT_FOR_NEW_THREADS ();
522+ int logLevel = ssLOG_GET_CURRENT_THREAD_TARGET_LEVEL ();
516523
517524 // Run setup steps
518525 for (int i = 0 ; i < availableDependencies.size (); ++i)
@@ -524,46 +531,150 @@ bool runcpp2::SetupDependenciesIfNeeded(const runcpp2::Data::Profile& profile,
524531 continue ;
525532 }
526533
527- ssLOG_INFO (" Running setup commands for " << availableDependencies.at (i)->Name );
528- if (!RunDependenciesSteps ( profile,
529- availableDependencies.at (i)->Setup ,
530- dependenciesLocalCopiesPaths.at (i),
531- true ))
534+ actions.emplace_back
535+ (
536+ std::async
537+ (
538+ std::launch::async,
539+ [i, &profile, &availableDependencies, &dependenciesLocalCopiesPaths, logLevel]()
540+ {
541+ ssLOG_SET_CURRENT_THREAD_TARGET_LEVEL (logLevel);
542+
543+ ssLOG_INFO (" Running setup commands for " << availableDependencies.at (i)->Name );
544+ if (!RunDependenciesSteps ( profile,
545+ availableDependencies.at (i)->Setup ,
546+ dependenciesLocalCopiesPaths.at (i),
547+ true ))
548+ {
549+ ssLOG_ERROR (" Failed to setup dependency " <<
550+ availableDependencies.at (i)->Name );
551+ return false ;
552+ }
553+ return true ;
554+ }
555+ )
556+ );
557+
558+ // Evaluate the setup results for each batch
559+ if (actions.size () >= maxThreads || i == availableDependencies.size () - 1 )
532560 {
533- ssLOG_ERROR (" Failed to setup dependency " << availableDependencies.at (i)->Name );
534- return false ;
561+ std::chrono::system_clock::time_point deadline =
562+ std::chrono::system_clock::now () + std::chrono::seconds (60 );
563+ for (int j = 0 ; j < actions.size (); ++j)
564+ {
565+ if (!actions.at (j).valid ())
566+ {
567+ ssLOG_ERROR (" Failed to construct actions for setup" );
568+ ssLOG_OUTPUT_ALL_CACHE_GROUPED ();
569+ return false ;
570+ }
571+
572+ std::future_status actionStatus = actions.at (j).wait_until (deadline);
573+ if (actionStatus == std::future_status::ready)
574+ {
575+ if (!actions.at (j).get ())
576+ {
577+ ssLOG_ERROR (" Setup failed for dependencies" );
578+ ssLOG_OUTPUT_ALL_CACHE_GROUPED ();
579+ return false ;
580+ }
581+ }
582+ else
583+ {
584+ ssLOG_ERROR (" Dependencies setup timeout" );
585+ ssLOG_OUTPUT_ALL_CACHE_GROUPED ();
586+ return false ;
587+ }
588+ }
589+ actions.clear ();
535590 }
536591 }
537-
592+
593+ ssLOG_OUTPUT_ALL_CACHE_GROUPED ();
538594 return true ;
539595}
540596
541597bool runcpp2::BuildDependencies (const runcpp2::Data::Profile& profile,
542598 const Data::ScriptInfo& scriptInfo,
543599 const std::vector<Data::DependencyInfo*>& availableDependencies,
544- const std::vector<std::string>& dependenciesLocalCopiesPaths)
600+ const std::vector<std::string>& dependenciesLocalCopiesPaths,
601+ const int maxThreads)
545602{
546603 ssLOG_FUNC_INFO ();
547604
548605 // If the script info is not populated (i.e. empty script info), don't do anything
549606 if (!scriptInfo.Populated )
550607 return true ;
551-
608+
609+ std::vector<std::future<bool >> actions;
610+
611+ // Cache logs for worker threads
612+ ssLOG_ENABLE_CACHE_OUTPUT_FOR_NEW_THREADS ();
613+ int logLevel = ssLOG_GET_CURRENT_THREAD_TARGET_LEVEL ();
614+
552615 // Run build steps
553616 for (int i = 0 ; i < availableDependencies.size (); ++i)
554617 {
555618 ssLOG_INFO (" Running build commands for " << availableDependencies.at (i)->Name );
556619
557- if (!RunDependenciesSteps ( profile,
558- availableDependencies.at (i)->Build ,
559- dependenciesLocalCopiesPaths.at (i),
560- true ))
620+ actions.emplace_back
621+ (
622+ std::async
623+ (
624+ std::launch::async,
625+ [i, &profile, &availableDependencies, &dependenciesLocalCopiesPaths, logLevel]()
626+ {
627+ ssLOG_SET_CURRENT_THREAD_TARGET_LEVEL (logLevel);
628+
629+ if (!RunDependenciesSteps ( profile,
630+ availableDependencies.at (i)->Build ,
631+ dependenciesLocalCopiesPaths.at (i),
632+ true ))
633+ {
634+ ssLOG_ERROR (" Failed to build dependency " << availableDependencies.at (i)->Name );
635+ return false ;
636+ }
637+ return true ;
638+ }
639+ )
640+ );
641+
642+ // Evaluate the setup results for each batch
643+ if (actions.size () >= maxThreads || i == availableDependencies.size () - 1 )
561644 {
562- ssLOG_ERROR (" Failed to build dependency " << availableDependencies.at (i)->Name );
563- return false ;
645+ std::chrono::system_clock::time_point deadline =
646+ std::chrono::system_clock::now () + std::chrono::seconds (60 );
647+ for (int j = 0 ; j < actions.size (); ++j)
648+ {
649+ if (!actions.at (j).valid ())
650+ {
651+ ssLOG_ERROR (" Failed to construct actions for building dependencies" );
652+ ssLOG_OUTPUT_ALL_CACHE_GROUPED ();
653+ return false ;
654+ }
655+
656+ std::future_status actionStatus = actions.at (j).wait_until (deadline);
657+ if (actionStatus == std::future_status::ready)
658+ {
659+ if (!actions.at (j).get ())
660+ {
661+ ssLOG_ERROR (" Build failed for dependencies" );
662+ ssLOG_OUTPUT_ALL_CACHE_GROUPED ();
663+ return false ;
664+ }
665+ }
666+ else
667+ {
668+ ssLOG_ERROR (" Dependencies build timeout" );
669+ ssLOG_OUTPUT_ALL_CACHE_GROUPED ();
670+ return false ;
671+ }
672+ }
673+ actions.clear ();
564674 }
565675 }
566676
677+ ssLOG_OUTPUT_ALL_CACHE_GROUPED ();
567678 return true ;
568679}
569680
@@ -875,7 +986,6 @@ bool runcpp2::ResolveImports( Data::ScriptInfo& scriptInfo,
875986 INTERNAL_RUNCPP2_SAFE_START ();
876987
877988 // For each dependency, check if import path exists
878- // for(Data::DependencyInfo& dependency : scriptInfo.Dependencies)
879989 for (int i = 0 ; i < scriptInfo.Dependencies .size (); ++i)
880990 {
881991 Data::DependencyInfo& dependency = scriptInfo.Dependencies .at (i);
@@ -884,7 +994,7 @@ bool runcpp2::ResolveImports( Data::ScriptInfo& scriptInfo,
884994 Data::DependencySource& source = dependency.Source ;
885995 if (source.ImportPath .empty ())
886996 continue ;
887-
997+
888998 if (!source.ImportPath .is_relative ())
889999 {
8901000 ssLOG_ERROR (" Import path is not relative: " << source.ImportPath .string ());
0 commit comments