/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

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