#!/usr/bin/python # # Copyright Colin Sherratt 2014 import subprocess import os.path import platform class Module: def has_tests(self): return os.path.isfile("src/%s/test.rs" % self.name) def get_dep(self): args = ["rustc", "src/%s/%s" % (self.name, self.ext), "--dep-info", ".tmp.txt", "--no-analysis", "--no-trans", "--out-dir=%s" % self.dir] subprocess.call(args) with open(".tmp.txt", "r") as f: return f.read().split("\n")[0] def get_name(self): args = ["rustc", "--crate-file-name", "src/%s/%s" % (self.name, self.ext)] with open(".tmp.txt", "w+") as f: subprocess.call(args, stdout=f) f.seek(0) return f.read().split("\n")[0] def collect_flags(self, mods): flags = [self.other_flags] for m in [mods[name] for name in self.dep_modules]: flags += m.collect_flags(mods) return flags def get_flags(self, mods): flags = [self.flags] + self.collect_flags(mods) return " ".join(flags) def make_rule(self, mods): dep = self.get_dep() + " " dep += " ".join(mods[m].ename for m in self.dep_modules) how = "%s\n\trustc $(RUST_FLAGS) --out-dir=%s %s src/%s/%s\n" % (dep, self.dir, self.get_flags(mods), self.name, self.ext) return how def make_test_rules(self, mods): dep = self.get_dep() + " " dep += " ".join(mods[m].ename for m in self.dep_modules) dep = ": ".join(["test/%s" % self.name, " ".join([self.ename, "src/%s/test.rs" % self.name, dep.split(": ", 2)[1]])]) how = "%s\n\trustc $(RUST_FLAGS) --test -o test/%s %s src/%s/test.rs\n" % (dep, self.name, self.get_flags(mods), self.name) how += "\ntest/.%s.check: test/%s\n" % (self.name, self.name) how += "\t./test/%s && touch test/.%s.check\n" % (self.name, self.name) return how class cd: """Context manager for changing the current working directory, creating if necessary""" def __init__(self, newPath): newPath = os.path.abspath(os.path.expandvars(os.path.expanduser(newPath))) self.newPath = newPath if not os.path.exists(newPath): os.makedirs(newPath) def __enter__(self): self.savedPath = os.getcwd() os.chdir(self.newPath) def __exit__(self, etype, value, traceback): os.chdir(self.savedPath) class Lib(Module): ext = "lib.rs" dir = "lib" flags = "" def __init__(self, name, dep_modules=None, other_flags=""): self.name = name self.ename = "lib/%s" % self.get_name() self.other_flags = other_flags if dep_modules: self.dep_modules = dep_modules else: self.dep_modules = [] class Bin(Module): ext = "main.rs" dir = "bin" flags = "-Zlto" def __init__(self, name, dep_modules=None, other_flags=""): self.name = name self.ename = "bin/%s" % self.get_name() self.other_flags = other_flags if dep_modules: self.dep_modules = dep_modules else: self.dep_modules = [] class LibMakefile(Module): ext = "" dir = "" flags = "" def get_name(self): return self.name def __init__(self, name, path_to_makefile_dir, path_to_output, dep_modules=None, other_flags=""): self.name = name self.ename = "lib/%s" % self.get_name() self.other_flags = other_flags self.path_to_makefile_dir = path_to_makefile_dir self.path_to_output = path_to_output if dep_modules: self.dep_modules = dep_modules else: self.dep_modules = [] def make_rule(self, mods): out = "%s: %s\n" % (self.ename, self.path_to_makefile_dir + "Makefile") out += "\tmake -C %s && cp %s %s\n" % (self.path_to_makefile_dir, self.path_to_output, self.ename) return out class LibCMake(Module): ext = "" dir = "" flags = "" def get_name(self): return self.name def __init__(self, name, path_to_makefile_dir, path_to_output, dep_modules=None, other_flags="", cmake_flags=""): self.name = name self.ename = "lib/%s" % self.get_name() self.other_flags = other_flags self.path_to_makefile_dir = path_to_makefile_dir self.path_to_output = path_to_output self.cmake_flags = cmake_flags if dep_modules: self.dep_modules = dep_modules else: self.dep_modules = [] def make_rule(self, mods): out = "%s:\n" % (self.path_to_makefile_dir + "Makefile") out += "\tcd %s && cmake %s .\n\n" % (self.path_to_makefile_dir, self.cmake_flags) out += "%s: %s\n" % (self.ename, self.path_to_makefile_dir + "Makefile") out += "\tmake -C %s && cp %s %s\n" % (self.path_to_makefile_dir, self.path_to_output, self.ename) return out def write_makefile(modules): modules = {m.name: m for m in modules} rules = "\n".join(m.make_rule(modules) for m in modules.values()) + "\n" rules += "\n".join(m.make_test_rules(modules) for m in modules.values() if m.has_tests()) all = " ".join(m.ename for m in modules.values()) with open("Makefile", "w+") as f: f.write("RUST_FLAGS=--opt-level=3 -L lib\n") f.write("\n") f.write("all: lib bin test %s\n" % all) f.write("\n") f.write("lib:\n\tmkdir lib\n") f.write("\n") f.write("bin:\n\tmkdir bin\n") f.write("\n") f.write("test:\n\tmkdir test\n") f.write("\n") f.write("check: test test/.check\n") f.write("\n") f.write("test/.check: lib test %s\n" % " ".join("test/.%s.check" % m.name for m in modules.values() if m.has_tests())) f.write("\n") f.write("clean:\n\trm -r lib bin test\n") f.write("\n") f.write(rules) modules = [Bin("oculus-info", ["oculus-vr"]), LibMakefile("libovr_wrapper.a", "src/oculus-vr/", "src/oculus-vr/libovr_wrapper.a", ["cgmath", "libOculusVR.a"]), LibCMake("libOculusVR.a", "modules/OculusSDK/LibOVR/", "modules/OculusSDK/LibOVR/libOculusVR.a"), Lib("cgmath")] if platform.system() == "Linux": modules += [Lib("oculus-vr", ["libOculusVR.a", "libedid.a", "cgmath", "libovr_wrapper.a"]), LibCMake("libedid.a", "modules/OculusSDK/3rdParty/EDID/", "modules/OculusSDK/3rdParty/EDID/libedid.a")] elif platform.system() == "Darwin": modules += [Lib("oculus-vr", ["libOculusVR.a", "cgmath", "libovr_wrapper.a"])] write_makefile(modules)