PageRenderTime 38ms CodeModel.GetById 9ms app.highlight 25ms RepoModel.GetById 1ms app.codeStats 0ms

/src/org/ooc/frontend/drivers/SequenceDriver.java

http://github.com/nddrylliog/ooc
Java | 267 lines | 198 code | 66 blank | 3 comment | 49 complexity | 5723d68e28dfa8110afb8b5aaf1fe331 MD5 | raw file
  1package org.ooc.frontend.drivers;
  2
  3import java.io.File;
  4import java.io.IOException;
  5import java.util.ArrayList;
  6import java.util.Collection;
  7import java.util.HashSet;
  8import java.util.Iterator;
  9import java.util.List;
 10import java.util.NoSuchElementException;
 11import java.util.concurrent.atomic.AtomicInteger;
 12
 13import org.ooc.frontend.BuildParams;
 14import org.ooc.frontend.Target;
 15import org.ooc.frontend.compilers.AbstractCompiler;
 16import org.ooc.frontend.model.Import;
 17import org.ooc.frontend.model.Module;
 18import org.ooc.utils.ProcessUtils;
 19
 20public class SequenceDriver extends Driver {
 21
 22	int finalCode;
 23	
 24	public SequenceDriver(BuildParams params) {
 25		super(params);
 26	}
 27
 28	@Override
 29	public int compile(Module module, String outName) throws Error, IOException, InterruptedException {
 30		
 31		copyLocalHeaders(module, params, new HashSet<Module>());
 32		
 33		if(params.verbose) {
 34			System.out.println("Sequence driver, using " + params.sequenceThreads + " threads.");
 35		}
 36		
 37		HashSet<Module> toCompile = collectDeps(module, new HashSet<Module>(), new HashSet<String>());
 38		
 39		final ArrayList<String> oPaths = new ArrayList<String> ();
 40		final long tt0 = System.nanoTime(); 
 41		final Iterator<Module> iterator = toCompile.iterator();
 42		// since we have several worker threads, we have to use an AtomicInteger
 43		final AtomicInteger count = new AtomicInteger(toCompile.size());		
 44		
 45		finalCode = 0;
 46	
 47		Runnable runnable = new Runnable() {
 48			
 49			public void run() {
 50				
 51				AbstractCompiler compiler = params.compiler.clone();
 52				
 53				while(iterator.hasNext()) {
 54					
 55					Module currentModule = null;
 56					
 57					synchronized(iterator) {
 58						try {
 59							currentModule = iterator.next();
 60							iterator.remove();
 61						} catch(NoSuchElementException e) {
 62							// oh, we reached the end early? good.
 63							break;
 64						}
 65					}
 66				
 67					initCompiler(compiler);
 68					compiler.setCompileOnly();
 69					
 70					String path = new File(params.outPath, currentModule.getPath("")).getPath();
 71					String oPath = path + ".o";
 72					String cPath = path + ".c";
 73					synchronized(oPaths) {
 74						oPaths.add(oPath);
 75					}
 76					
 77					if(new File(cPath).lastModified() > new File(oPath).lastModified()) {
 78					
 79						compiler.addObjectFile(cPath);
 80						compiler.setOutputPath(oPath);
 81		
 82						for(String define: params.defines) {
 83							compiler.defineSymbol(define);
 84						}
 85						
 86						for(String compilerArg: params.compilerArgs) {
 87							compiler.addObjectFile(compilerArg);
 88						}
 89						
 90						for (File incPath: params.incPath.getPaths()) {
 91							compiler.addIncludePath(incPath.getAbsolutePath());
 92						}
 93						
 94						if (params.fatArchitectures != null) {
 95							compiler.setFatArchitectures(params.fatArchitectures);
 96						}
 97						if (params.osxSDKAndDeploymentTarget != null) {
 98							compiler.setOSXSDKAndDeploymentTarget(params.osxSDKAndDeploymentTarget);
 99						}
100
101						try {
102							Collection<String> libs = getFlagsFromUse(currentModule, false);
103							for(String lib: libs) compiler.addObjectFile(lib);
104						} catch (Exception e) {
105							e.printStackTrace();
106						}
107						
108						if(params.verbose) System.out.println(compiler.getCommandLine());
109						
110						long tt1 = System.nanoTime();
111						int code = -1;
112						try {
113							code = compiler.launch();
114						} catch (Exception e) {
115							e.printStackTrace();
116						}
117						long tt2 = System.nanoTime();
118						if(params.timing) System.out.println("  (" + ((tt2 - tt1) / 1000000)+")");
119							
120						if(code != 0) {
121							System.err.println("C compiler failed, aborting compilation process");
122							finalCode = code;
123						}
124						
125					} else {
126						
127						if(params.veryVerbose) {
128							System.out.println("Skipping "+cPath+", just the same.");
129						}
130						
131					}
132					
133					synchronized(iterator) {
134						count.decrementAndGet();
135					}
136
137				}		
138			}
139		};
140		
141		for(int i = 0; i < params.sequenceThreads; i++) {
142			new Thread(runnable).start();
143		}
144		
145		while(count.get() > 0) {
146			Thread.sleep(100L);
147		}
148		
149		if(finalCode != 0) return finalCode;
150		
151		if(params.link) {
152			
153			initCompiler(params.compiler);
154			if(params.linker != null) params.compiler.setExecutable(params.linker);
155			
156			for(String oPath: oPaths) {
157				params.compiler.addObjectFile(oPath);
158			}
159			
160			for(String define: params.defines) {
161				params.compiler.defineSymbol(define);
162			}
163			for(String dynamicLib: params.dynamicLibs) {
164				params.compiler.addDynamicLibrary(dynamicLib);
165			}
166			for(String additional: params.additionals) {
167				params.compiler.addObjectFile(additional);
168			}
169		
170			for (File libPath: params.libPath.getPaths()) {
171				params.compiler.addLibraryPath(libPath.getAbsolutePath());
172			}
173			
174			if (params.fatArchitectures != null) {
175				params.compiler.setFatArchitectures(params.fatArchitectures);
176			}
177			if (params.osxSDKAndDeploymentTarget != null) {
178				params.compiler.setOSXSDKAndDeploymentTarget(params.osxSDKAndDeploymentTarget);
179			}
180
181			params.compiler.setOutputPath(outName);
182			Collection<String> libs = getFlagsFromUse(module, true);
183			for(String lib: libs) params.compiler.addObjectFile(lib);
184			
185			if(params.enableGC) {
186				params.compiler.addDynamicLibrary("pthread");
187				if(params.dynGC) {
188					params.compiler.addDynamicLibrary("gc");
189				} else {
190					params.compiler.addObjectFile(new File(params.distLocation, "libs/"
191							+ Target.guessHost().toString(params.arch.equals("") ? Target.getArch() : params.arch) + "/libgc.a").getPath());
192				}
193			}
194			if(params.verbose) System.out.println(params.compiler.getCommandLine());
195	
196			long tt1 = System.nanoTime();
197			int code = params.compiler.launch();
198			long tt2 = System.nanoTime();
199			if(params.timing) System.out.println("  (linking " + ((tt2 - tt1) / 1000000)+"ms)");
200			if(params.timing) System.out.println("(total " + ((System.nanoTime() - tt0) / 1000000)+"ms)");
201			
202			if(code != 0) {
203				System.err.println("C compiler failed, aborting compilation process");
204				return code;
205			}
206		
207		}
208		
209		if(params.outlib != null) {
210			
211			// TODO: make this platform-independant (for now it's a linux-friendly hack)
212			List<String> args = new ArrayList<String>();
213			args.add("ar"); // ar = archive tool
214			args.add("rcs"); // r = insert files, c = create archive, s = create/update .o file index
215			args.add(params.outlib);
216			
217			HashSet<Module> allModules = collectDeps(module, new HashSet<Module>(), new HashSet<String>());
218			for(Module dep: allModules) {
219				args.add(new File(params.outPath, dep.getPath("")).getPath() + ".o");
220			}
221			
222			if(params.verbose) {
223				StringBuilder command = new StringBuilder();
224				for(String arg: args) {
225					command.append(arg).append(" ");
226				}
227				System.out.println(command);
228			}
229			
230			ProcessBuilder builder = new ProcessBuilder(args);
231			Process process = builder.start();
232			ProcessUtils.redirectIO(process);
233			
234		}
235		
236		
237		return 0;
238		
239	}
240
241	void initCompiler(AbstractCompiler compiler) {
242		compiler.reset();
243		
244		if(params.debug) compiler.setDebugEnabled();
245		compiler.addIncludePath(new File(params.distLocation, "libs/headers/").getPath());
246		compiler.addIncludePath(params.outPath.getPath());
247		
248		for(String compilerArg: params.compilerArgs) {
249			compiler.addObjectFile(compilerArg);
250		}
251	}
252
253	private HashSet<Module> collectDeps(Module module, HashSet<Module> toCompile, HashSet<String> done) {
254		
255		toCompile.add(module);
256		done.add(module.getPath());
257		
258		for(Import import1: module.getAllImports()) {
259			if(done.contains(import1.getModule().getPath())) continue;
260			collectDeps(import1.getModule(), toCompile, done);
261		}
262		
263		return toCompile;
264		
265	}
266	
267}