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

http://github.com/nddrylliog/ooc · Java · 214 lines · 163 code · 41 blank · 10 comment · 38 complexity · 2ac840b805899b65d508e29a2c6edfe9 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.List;
  8. import java.util.Set;
  9. import org.ooc.frontend.BuildParams;
  10. import org.ooc.frontend.model.Import;
  11. import org.ooc.frontend.model.Include;
  12. import org.ooc.frontend.model.Module;
  13. import org.ooc.frontend.model.Use;
  14. import org.ooc.frontend.model.Include.Mode;
  15. import org.ooc.frontend.pkgconfig.PkgConfigFrontend;
  16. import org.ooc.frontend.pkgconfig.PkgInfo;
  17. import org.ooc.middle.UseDef;
  18. import org.ooc.middle.UseDef.Requirement;
  19. import org.ooc.utils.FileUtils;
  20. import org.ooc.utils.ProcessUtils;
  21. import org.ooc.utils.ShellUtils;
  22. /**
  23. * Drives the compilation process, e.g. chooses in which order
  24. * files are compiled, optionally checks for timestamps and stuff.
  25. * Great fun.
  26. *
  27. * @author Amos Wenger
  28. */
  29. public abstract class Driver {
  30. public BuildParams params;
  31. public Driver(BuildParams params) {
  32. super();
  33. this.params = params;
  34. }
  35. public abstract int compile(Module module, String outName) throws Error,
  36. IOException, InterruptedException;
  37. protected void copyLocalHeaders(Module module, BuildParams params, HashSet<Module> done) {
  38. if(done.contains(module)) return;
  39. done.add(module);
  40. for(Include inc: module.getIncludes()) {
  41. if(inc.getMode() == Mode.LOCAL) {
  42. try {
  43. File file = params.sourcePath.getFile(module.getPrefixLessPath()).getParentFile();
  44. File target = new File(params.outPath, inc.getPath() + ".h");
  45. target.getParentFile().mkdirs();
  46. FileUtils.copy(new File(file, inc.getPath() + ".h"),
  47. target);
  48. } catch(Exception e) { e.printStackTrace(); }
  49. }
  50. }
  51. for(Import imp: module.getAllImports()) {
  52. copyLocalHeaders(imp.getModule(), params, done);
  53. }
  54. }
  55. protected void addDeps(Module module, Set<Module> toCompile, Set<String> done) {
  56. toCompile.add(module);
  57. done.add(module.getPath());
  58. params.compiler.addObjectFile(new File(params.outPath, module.getPath(".c")).getPath());
  59. for(Import imp: module.getAllImports()) {
  60. if(!done.contains(imp.getModule().getPath())) {
  61. addDeps(imp.getModule(), toCompile, done);
  62. }
  63. }
  64. }
  65. protected Collection<String> getFlagsFromUse(Module module, boolean doLinking) throws IOException, InterruptedException {
  66. Set<String> list = new HashSet<String>();
  67. Set<Module> done = new HashSet<Module>();
  68. getFlagsFromUse(module, list, done, new HashSet<UseDef>(), doLinking);
  69. return list;
  70. }
  71. protected void getFlagsFromUse(Module module, Set<String> flagsDone,
  72. Set<Module> modulesDone, Set<UseDef> usesDone, boolean doLinking) throws IOException, InterruptedException {
  73. if(modulesDone.contains(module)) return;
  74. modulesDone.add(module);
  75. for(Use use: module.getUses()) {
  76. UseDef useDef = use.getUseDef();
  77. getFlagsFromUse(useDef, flagsDone, usesDone, doLinking);
  78. }
  79. for(Import imp: module.getAllImports()) {
  80. getFlagsFromUse(imp.getModule(), flagsDone, modulesDone, usesDone, doLinking);
  81. }
  82. }
  83. private void getFlagsFromUse(UseDef useDef, Set<String> flagsDone,
  84. Set<UseDef> usesDone, boolean doLinking) throws IOException, InterruptedException {
  85. if(usesDone.contains(useDef)) return;
  86. usesDone.add(useDef);
  87. if(doLinking) {
  88. compileNasms(useDef.getLibs(), flagsDone);
  89. }
  90. for(String pkg: useDef.getPkgs()) {
  91. PkgInfo info = PkgConfigFrontend.getInfo(pkg);
  92. for(String cflag: info.cflags) {
  93. if(!flagsDone.contains(cflag)) {
  94. flagsDone.add(cflag);
  95. }
  96. }
  97. if(doLinking) {
  98. for(String library: info.libraries) {
  99. // FIXME lazy
  100. String lpath = "-l"+library;
  101. if(!flagsDone.contains(lpath)) {
  102. flagsDone.add(lpath);
  103. }
  104. }
  105. }
  106. }
  107. for(String includePath: useDef.getIncludePaths()) {
  108. // FIXME lazy too.
  109. String ipath = "-I"+includePath;
  110. if(!flagsDone.contains(ipath)) {
  111. flagsDone.add(ipath);
  112. }
  113. }
  114. for(String libPath: useDef.getLibPaths()) {
  115. // FIXME lazy too.
  116. String lpath = "-L"+libPath;
  117. if(!flagsDone.contains(lpath)) {
  118. flagsDone.add(lpath);
  119. }
  120. }
  121. for(Requirement req: useDef.getRequirements()) {
  122. getFlagsFromUse(req.getUseDef(), flagsDone, usesDone, doLinking);
  123. }
  124. }
  125. public void compileNasms(List<String> nasms, Collection<String> list) throws IOException, InterruptedException {
  126. boolean has = false;
  127. if(nasms.isEmpty()) return;
  128. List<String> reallyNasms = new ArrayList<String>();
  129. for(String nasm: nasms) {
  130. if(nasm.endsWith(".s")) {
  131. reallyNasms.add(nasm);
  132. has = true;
  133. }
  134. }
  135. if(has) {
  136. if(params.verbose) {
  137. System.out.println("Should compile nasms "+reallyNasms);
  138. }
  139. List<String> command = new ArrayList<String>();
  140. command.add(findExec("nasm").getPath());
  141. command.add("-f");
  142. command.add("elf");
  143. command.addAll(reallyNasms);
  144. ProcessBuilder builder = new ProcessBuilder(command);
  145. Process process = builder.start();
  146. ProcessUtils.redirectIO(process);
  147. int code = process.waitFor();
  148. if(code != 0) {
  149. System.err.println("nasm failed, aborting compilation process");
  150. System.exit(code);
  151. }
  152. for(String nasm: nasms) {
  153. if(nasm.endsWith(".s")) {
  154. list.add(nasm.substring(0, nasm.length() - 1) + "o");
  155. } else {
  156. list.add(nasm);
  157. }
  158. }
  159. } else {
  160. list.addAll(nasms);
  161. }
  162. }
  163. protected File findExec(String name) throws Error {
  164. File execFile = ShellUtils.findExecutable(name);
  165. if(execFile == null) {
  166. execFile = ShellUtils.findExecutable(name+".exe");
  167. }
  168. if(execFile == null) {
  169. throw new Error(name+" not found :/");
  170. }
  171. return execFile;
  172. }
  173. }