#!/usr/bin/python # # Copyright Colin Sherratt 2014 import subprocess import os.path import platform class Module: def set_source_dir(self, source_dir): self.source_dir = source_dir def set_output_dir(self, output_dir): self.output_dir = output_dir def get_base_dir(self): return self.source_dir def get_output_dir(self): return os.path.join(self.output_dir, self.dir) def get_source_dir(self): return os.path.join(self.get_base_dir(), "src") def get_source_crate(self): return os.path.join(self.get_source_dir(), self.name, self.ext) def get_test_dir(self): return os.path.join(self.get_source_dir(), self.name, "test.rs") def has_tests(self): return os.path.isfile(self.get_test_dir()) def get_dep(self): args = ["rustc", self.get_source_crate(), "--dep-info", ".tmp.txt", "--no-analysis", "--no-trans", "--out-dir=%s" % self.get_output_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", self.get_source_crate()] 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].get_ename() for m in self.dep_modules) setup = "" if self.setup: setup = "\tsh -c \"%s\"\n" % self.setup how = "%s\n%s\trustc --out-dir=%s %s %s\n" % ( dep, setup, self.get_output_dir(), self.get_flags(mods), self.get_source_crate() ) return how def make_test_rules(self, mods): dep = self.get_dep() + " " dep += " ".join(mods[m].get_ename() for m in self.dep_modules) dep = ": ".join(["test/%s" % self.name, " ".join( [self.get_ename(), os.path.join(self.get_source_dir()), self.get_test_dir(), dep.split(": ", 2)[1]])] ) how = "%s\n\trustc --test -o test/%s %s %s\n" % ( dep, self.name, self.get_flags(mods), self.get_test_dir() ) 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 def pre_setup(self): if self.presetup: p = subprocess.Popen(["sh", "-c", self.presetup]) p.wait() def write_cleanup(self, f): pass def get_ename(self): if self.ename == None: self.ename = os.path.join(self.dir, self.get_name()) return self.ename 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="", setup=None, presetup=None, ext=None): self.source_dir = "" self.name = name self.ename = None self.other_flags = other_flags self.setup = setup self.presetup = presetup if dep_modules: self.dep_modules = dep_modules else: self.dep_modules = [] if ext is None: self.ext = Lib.ext else: self.ext = ext def get_flags(self, mods): flags = ["$(RUST_LIB_FLAGS)", self.flags] + self.collect_flags(mods) return " ".join(flags) class Bin(Module): ext = "main.rs" dir = "bin" flags = "" def __init__(self, name, dep_modules=None, other_flags="", setup=None, presetup=None): self.source_dir = "" self.name = name self.ename = None self.other_flags = other_flags self.setup = setup self.presetup = presetup if dep_modules: self.dep_modules = dep_modules else: self.dep_modules = [] def get_flags(self, mods): flags = ["$(RUST_BIN_FLAGS)", self.flags] + self.collect_flags(mods) return " ".join(flags) class LibXcodebuild(Module): ext = "" dir = "lib" flags = "" def get_name(self): return self.name def get_path_to_xcode_project(self): return os.path.join(self.get_base_dir(), self.path_to_xcode_project) def get_path_to_output_dir(self): return " ".join(os.path.join(self.get_base_dir(), p) for p in self.path_to_output) def __init__(self, name, path_to_xcode_project, path_to_output, dep_modules=None, other_flags=""): self.source_dir = "" self.name = name self.ename = None self.other_flags = other_flags self.path_to_xcode_project = path_to_xcode_project self.path_to_output = path_to_output self.setup = None self.presetup = None if dep_modules: self.dep_modules = dep_modules else: self.dep_modules = [] def make_rule(self, mods): out = "%s: lib %s\n" % (self.get_ename(), " ".join(mods[m].get_ename() for m in self.dep_modules)) out += "\txcodebuild -project %s build\n\tcp %s lib\n" % ( self.get_path_to_xcode_project(), self.get_path_to_output_dir() ) return out def write_cleanup(self, f): f.write("\t-xcodebuild -project %s clean\n" % self.get_path_to_xcode_project()) class LibMakefile(Module): ext = "" dir = "lib" flags = "" def get_name(self): return self.name def get_path_to_makefile_dir(self): return os.path.join(self.get_base_dir(), self.path_to_makefile_dir) def get_path_to_output_dir(self): return " ".join(os.path.join(self.get_base_dir(), p) for p in self.path_to_output) def __init__(self, name, path_to_makefile_dir, path_to_output, dep_modules=None, other_flags=""): self.source_dir = "" self.name = name self.ename = None self.other_flags = other_flags self.path_to_makefile_dir = path_to_makefile_dir self.path_to_output = path_to_output self.setup = None self.presetup = None if dep_modules: self.dep_modules = dep_modules else: self.dep_modules = [] def make_rule(self, mods): out = "%s: lib %s %s\n" % (self.get_ename(), self.get_path_to_makefile_dir() + "Makefile", " ".join(mods[m].get_ename() for m in self.dep_modules)) out += "\tmake -j 16 -C %s\n\tcp %s lib\n" % ( self.get_path_to_makefile_dir(), self.get_path_to_output_dir() ) return out def write_cleanup(self, f): f.write("\t-make -C %s clean\n" % self.path_to_makefile_dir) class LibConfigureMakefile(LibMakefile): def make_rule(self, mods): out = "%s:\n" % (os.path.join(self.get_path_to_makefile_dir(), "Makefile")) out += "\tcd %s && ./configure\n\n" % ( os.path.join(self.get_path_to_makefile_dir()) ) out += "%s: lib %s\n" % (self.get_ename(), os.path.join(self.get_path_to_makefile_dir(), "Makefile")) out += "\tmake -j 16 -C %s\n\tcp %s lib\n" % ( self.get_path_to_makefile_dir(), self.get_path_to_output_dir() ) return out class LibCMake(Module): ext = "" dir = "lib" flags = "" def get_name(self): return self.name def get_path_to_makefile_dir(self): return os.path.join(self.get_base_dir(), self.path_to_makefile_dir) def get_path_to_output_dir(self): return " ".join(os.path.join(self.get_base_dir(), p) for p in self.path_to_output) def __init__(self, name, path_to_makefile_dir, path_to_output, dep_modules=None, other_flags="", cmake_flags=""): self.source_dir = "" self.name = name self.ename = None 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 self.setup = None self.presetup = None if dep_modules: self.dep_modules = dep_modules else: self.dep_modules = [] def make_rule(self, mods): out = "%s:\n" % (self.get_path_to_makefile_dir() + "Makefile") out += "\tcd %s && cmake %s .\n\n" % (self.get_path_to_makefile_dir(), self.cmake_flags) out += "%s: lib %s %s\n" % (self.get_ename(), self.get_path_to_makefile_dir() + "Makefile", " ".join(mods[m].get_ename() for m in self.dep_modules)) out += "\tmake -j 16 -C %s && cp %s lib\n" % ( self.get_path_to_makefile_dir(), self.get_path_to_output_dir() ) return out def write_cleanup(self, f): f.write("\t-make -C %s clean\n" % self.path_to_makefile_dir) f.write("\t-rm %s\n" % (os.path.join(self.path_to_makefile_dir, "Makefile"))) def write_makefile(modules): modules = {m.name: m for m in modules} for m in modules.values(): m.pre_setup() 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.get_ename() for m in modules.values()) with open("Makefile", "w+") as f: f.write("RUST_FLAGS=-L lib --opt-level=3\n") f.write("RUST_LIB_FLAGS=$(RUST_FLAGS)\n") f.write("RUST_BIN_FLAGS=$(RUST_FLAGS) -Zlto\n") f.write("RUST_TEST_FLAGS=$(RUST_FLAGS)\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\t-rm -r lib bin test\n") for m in modules.values(): m.write_cleanup(f) f.write("\n") f.write(rules) def set_output_dir(modules, output_dir): for m in modules: m.set_output_dir(output_dir) def set_source_dir(modules, source_dir): for m in modules: m.set_source_dir(source_dir) _base = os.path.abspath(os.path.dirname(__file__)) modules = [Lib("oculus-vr", ["libovr.a", "cgmath"])] if platform.system() == "Linux": modules += [LibMakefile("libovr.a", "modules/oculus_sdk_linux/", ["modules/oculus_sdk_linux/LibOVR/Lib/Linux/Release/x86_64/libovr.a"])] elif platform.system() == "Darwin": modules += [LibXcodebuild("libovr.a", "modules/oculus_sdk_mac/LibOVR/Projects/Mac/Xcode/LibOVR.xcodeproj", ["modules/oculus_sdk_mac/LibOVR/Lib/MacOS/Release/libovr.a"])] modules_all = modules + \ [Bin("oculus-info", ["oculus-vr"]), Lib("cgmath", ext="cgmath.rs")] set_output_dir(modules, ".") set_source_dir(modules, _base) set_output_dir(modules_all, ".") set_source_dir(modules_all, _base) if __name__ == "__main__": write_makefile(modules_all)