mirror of https://github.com/natnat-mc/moonbuild
				
				
				
			
			You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							82 lines
						
					
					
						
							1.9 KiB
						
					
					
				
			
		
		
	
	
							82 lines
						
					
					
						
							1.9 KiB
						
					
					
				| SingleProcessExecutor = require 'moonbuild.core.singleprocessexecutor'
 | |
| import fork, _exit from require 'posix.unistd'
 | |
| import wait from require 'posix.sys.wait'
 | |
| import open, stderr from io
 | |
| import match from string
 | |
| 
 | |
| class Executor
 | |
| 	@getmaxparallel: =>
 | |
| 		fd = open '/proc/cpuinfo', 'r'
 | |
| 		return 1 unless fd
 | |
| 		ncpu = 0
 | |
| 		for line in fd\lines!
 | |
| 			ncpu += 1 if match line, '^processor%s*:'
 | |
| 		fd\close!
 | |
| 		ncpu == 0 and 1 or ncpu
 | |
| 
 | |
| 	new: (@dag, @nparallel) =>
 | |
| 		@processes = {}
 | |
| 		@nprocesses = 0
 | |
| 		@building = {}
 | |
| 		@nbuilt = 0
 | |
| 
 | |
| 	execute: (opts) =>
 | |
| 		if @nparallel == 1
 | |
| 			return (SingleProcessExecutor @dag, 1)\execute opts
 | |
| 
 | |
| 		block = @dag\buildablenodes!
 | |
| 		while #block != 0
 | |
| 			for node in *block
 | |
| 				@addprocess node, opts
 | |
| 				if @nprocesses == @nparallel
 | |
| 					@waitprocess!
 | |
| 			block = [node for node in *@dag\buildablenodes! when not @building[node]]
 | |
| 			while #block == 0 and @nprocesses != 0
 | |
| 				@waitprocess!
 | |
| 				block = [node for node in *@dag\buildablenodes! when not @building[node]]
 | |
| 
 | |
| 		while @nprocesses !=0
 | |
| 			@waitprocess!
 | |
| 
 | |
| 		for name, node in pairs @dag.nodes
 | |
| 			error "Node #{name} wasn't built" unless node.built
 | |
| 
 | |
| 		unless opts.quiet
 | |
| 			if @nbuilt == 0
 | |
| 				print "Nothing to be done"
 | |
| 			else
 | |
| 				print "Built #{@nbuilt} targets"
 | |
| 
 | |
| 	addprocess: (node, opts) =>
 | |
| 		if node.sync
 | |
| 			while @nprocesses != 0
 | |
| 				@waitprocess!
 | |
| 			node\build opts
 | |
| 			node.built = true
 | |
| 			node\updatecache!
 | |
| 			return
 | |
| 
 | |
| 		pid = fork!
 | |
| 		error "Failed to fork" unless pid
 | |
| 		if pid!=0
 | |
| 			@processes[pid] = node
 | |
| 			@nprocesses += 1
 | |
| 			@building[node] = true
 | |
| 		else
 | |
| 			ok, status = pcall -> node\build opts
 | |
| 			if ok
 | |
| 				_exit status and 0 or 2
 | |
| 				_exit 0
 | |
| 			else
 | |
| 				stderr\write status
 | |
| 				_exit 1
 | |
| 
 | |
| 	waitprocess: =>
 | |
| 		pid, ty, status = wait!
 | |
| 		error "Failed to wait" unless pid
 | |
| 		error "Failed to build #{@processes[pid].name}" if ty != 'exited' or status != 0 and status != 2
 | |
| 		@processes[pid].built = true
 | |
| 		@processes[pid]\updatecache!
 | |
| 		@processes[pid] = nil
 | |
| 		@nprocesses -= 1
 | |
| 		@nbuilt += 1 if status == 0
 | |
| 
 |