* Allow derivations to hint that they should not be built remotely
using the build hook mechanism, by setting the derivation attribute
  "preferLocalBuild" to true.  This has a few use cases:
  - The user environment builder.  Since it just creates a bunch of
    symlinks without much computation, there is no reason to do it
    remotely.  In fact, doing it remotely requires the entire closure
    of the user environment to be copied to the remote machine, which
    is extremely wasteful.
  - `fetchurl'.  Performing the download on a remote machine and then
    copying it to the local machine involves twice as much network
    traffic as performing the download locally, and doesn't save any
    CPU cycles on the local machine.
			
			
This commit is contained in:
		
							parent
							
								
									87ef5907e9
								
							
						
					
					
						commit
						7f893b7a43
					
				
					 2 changed files with 44 additions and 24 deletions
				
			
		| 
						 | 
					@ -11,4 +11,8 @@ derivation {
 | 
				
			||||||
  paths = derivations;
 | 
					  paths = derivations;
 | 
				
			||||||
  active = map (x: if x ? meta && x.meta ? active then x.meta.active else "true") derivations;
 | 
					  active = map (x: if x ? meta && x.meta ? active then x.meta.active else "true") derivations;
 | 
				
			||||||
  priority = map (x: if x ? meta && x.meta ? priority then x.meta.priority else "5") derivations;
 | 
					  priority = map (x: if x ? meta && x.meta ? priority then x.meta.priority else "5") derivations;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Building user environments remotely just causes huge amounts of
 | 
				
			||||||
 | 
					  # network traffic, so don't do that.
 | 
				
			||||||
 | 
					  preferLocalBuild = true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -960,6 +960,16 @@ PathSet outputPaths(const DerivationOutputs & outputs)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool canBuildLocally(const string & platform)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return platform == thisSystem 
 | 
				
			||||||
 | 
					#ifdef CAN_DO_LINUX32_BUILDS
 | 
				
			||||||
 | 
					        || (platform == "i686-linux" && thisSystem == "x86_64-linux")
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					        ;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void DerivationGoal::tryToBuild()
 | 
					void DerivationGoal::tryToBuild()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    trace("trying to build");
 | 
					    trace("trying to build");
 | 
				
			||||||
| 
						 | 
					@ -1027,28 +1037,38 @@ void DerivationGoal::tryToBuild()
 | 
				
			||||||
    foreach (DerivationOutputs::iterator, i, drv.outputs)
 | 
					    foreach (DerivationOutputs::iterator, i, drv.outputs)
 | 
				
			||||||
        if (pathFailed(i->second.path)) return;
 | 
					        if (pathFailed(i->second.path)) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Is the build hook willing to accept this job? */
 | 
					    /* Don't do a remote build if the derivation has the attribute
 | 
				
			||||||
    usingBuildHook = true;
 | 
					       `preferLocalBuild' set. */
 | 
				
			||||||
    switch (tryBuildHook()) {
 | 
					    bool preferLocalBuild =
 | 
				
			||||||
        case rpAccept:
 | 
					        drv.env["preferLocalBuild"] == "1" && canBuildLocally(drv.platform);
 | 
				
			||||||
            /* Yes, it has started doing so.  Wait until we get EOF
 | 
					 | 
				
			||||||
               from the hook. */
 | 
					 | 
				
			||||||
            state = &DerivationGoal::buildDone;
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        case rpPostpone:
 | 
					 | 
				
			||||||
            /* Not now; wait until at least one child finishes. */
 | 
					 | 
				
			||||||
            worker.waitForAWhile(shared_from_this());
 | 
					 | 
				
			||||||
            outputLocks.unlock();
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        case rpDecline:
 | 
					 | 
				
			||||||
            /* We should do it ourselves. */
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Is the build hook willing to accept this job? */
 | 
				
			||||||
 | 
					    if (!preferLocalBuild) {
 | 
				
			||||||
 | 
					        usingBuildHook = true;
 | 
				
			||||||
 | 
					        switch (tryBuildHook()) {
 | 
				
			||||||
 | 
					            case rpAccept:
 | 
				
			||||||
 | 
					                /* Yes, it has started doing so.  Wait until we get
 | 
				
			||||||
 | 
					                   EOF from the hook. */
 | 
				
			||||||
 | 
					                state = &DerivationGoal::buildDone;
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            case rpPostpone:
 | 
				
			||||||
 | 
					                /* Not now; wait until at least one child finishes. */
 | 
				
			||||||
 | 
					                worker.waitForAWhile(shared_from_this());
 | 
				
			||||||
 | 
					                outputLocks.unlock();
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            case rpDecline:
 | 
				
			||||||
 | 
					                /* We should do it ourselves. */
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    usingBuildHook = false;
 | 
					    usingBuildHook = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Make sure that we are allowed to start a build. */
 | 
					    /* Make sure that we are allowed to start a build.  If this
 | 
				
			||||||
    if (worker.getNrLocalBuilds() >= maxBuildJobs) {
 | 
					       derivation prefers to be done locally, do it even if
 | 
				
			||||||
 | 
					       maxBuildJobs is 0. */
 | 
				
			||||||
 | 
					    unsigned int curBuilds = worker.getNrLocalBuilds();
 | 
				
			||||||
 | 
					    if (curBuilds >= maxBuildJobs && !(preferLocalBuild && curBuilds == 0)) {
 | 
				
			||||||
        worker.waitForBuildSlot(shared_from_this());
 | 
					        worker.waitForBuildSlot(shared_from_this());
 | 
				
			||||||
        outputLocks.unlock();
 | 
					        outputLocks.unlock();
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
| 
						 | 
					@ -1379,11 +1399,7 @@ void DerivationGoal::startBuilder()
 | 
				
			||||||
        format("building path(s) %1%") % showPaths(outputPaths(drv.outputs)))
 | 
					        format("building path(s) %1%") % showPaths(outputPaths(drv.outputs)))
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    /* Right platform? */
 | 
					    /* Right platform? */
 | 
				
			||||||
    if (drv.platform != thisSystem 
 | 
					    if (!canBuildLocally(drv.platform))
 | 
				
			||||||
#ifdef CAN_DO_LINUX32_BUILDS
 | 
					 | 
				
			||||||
        && !(drv.platform == "i686-linux" && thisSystem == "x86_64-linux")
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        throw Error(
 | 
					        throw Error(
 | 
				
			||||||
            format("a `%1%' is required to build `%3%', but I am a `%2%'")
 | 
					            format("a `%1%' is required to build `%3%', but I am a `%2%'")
 | 
				
			||||||
            % drv.platform % thisSystem % drvPath);
 | 
					            % drv.platform % thisSystem % drvPath);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue