#!/usr/bin/python -u from distutils import sysconfig import glob import json import os import multiprocessing import shutil import sys import subprocess import sysinfo system_version = sysinfo.get_system_version() module_files = ["system-%s.json" % system_version, "sugar.json", "activities.json"] scripts_dir = os.path.abspath(os.path.dirname(__file__)) base_dir = os.path.dirname(scripts_dir) install_dir = os.path.join(base_dir, "install") dnbuild_dir = os.path.join(install_dir, "dnbuild") share_dir = os.path.join(install_dir, "share") include_dir = os.path.join(install_dir, "include") bin_dir = os.path.join(install_dir, "bin") etc_dir = os.path.join(install_dir, "etc") build_dir = os.path.join(base_dir, "build") source_dir = os.path.join(base_dir, "source") modules_dir = os.path.join(scripts_dir, "modules") build_state_path = os.path.join(dnbuild_dir, "state.json") if os.uname()[4] == "x86_64": lib_dir = os.path.join(install_dir, "lib64") system_lib_dir = "/usr/lib64" else: lib_dir = os.path.join(install_dir, "lib") system_lib_dir = "/usr/lib" state = { "built_modules": {} } def load_state(): global state if os.path.exists(build_state_path): state = json.load(open(build_state_path)) def save_state(): json.dump(state, open(build_state_path, "w+")) def add_path(name, path): if name not in os.environ: os.environ[name] = path return splitted = os.environ[name].split(":") splitted.append(path) os.environ[name] = ":".join(splitted) def get_module_source_dir(module): return os.path.join(source_dir, module["name"]) def get_module_build_dir(module): return os.path.join(build_dir, module["name"]) def get_module_commit_id(module): orig_cwd = os.getcwd() os.chdir(get_module_source_dir(module)) commit_id = subprocess.check_output(["git", "rev-parse", "HEAD"]) os.chdir(orig_cwd) return commit_id.strip() def run_command(args): print " ".join(args) subprocess.check_call(args) def unlink_libtool_files(): orig_cwd = os.getcwd() os.chdir(lib_dir) for filename in glob.glob("*.la"): os.unlink(filename) os.chdir(orig_cwd) def pull_source(module): module_dir = get_module_source_dir(module) if os.path.exists(module_dir): os.chdir(module_dir) run_command(["git", "remote", "set-url", "origin", module["repo"]]) run_command(["git", "remote", "update", "origin"]) else: os.chdir(source_dir) run_command(["git", "clone", "--progress", module["repo"], module["name"]]) os.chdir(module_dir) branch = module.get("branch", "master") run_command(["git", "checkout", branch]) def build_autotools(module): autogen = os.path.join(get_module_source_dir(module), "autogen.sh") jobs = multiprocessing.cpu_count() * 2 run_command([autogen, "--prefix", install_dir, "--libdir", lib_dir]) run_command(["make", "-j", "%d" % jobs]) run_command(["make", "install"]) unlink_libtool_files() def build_activity(module): run_command(["./setup.py", "install", "--prefix", install_dir]) def build(module): module_source_dir = get_module_source_dir(module) if module.get("out-of-source", True): module_build_dir = get_module_build_dir(module) if not os.path.exists(module_build_dir): os.mkdir(module_build_dir) os.chdir(module_build_dir) else: os.chdir(module_source_dir) if os.path.exists(os.path.join(module_source_dir, "setup.py")): build_activity(module) elif os.path.exists(os.path.join(module_source_dir, "autogen.sh")): build_autotools(module) else: print "Unknown build system" sys.exit(1) state["built_modules"][module["name"]] = get_module_commit_id(module) save_state() def load_modules(): modules = [] for module_file in module_files: path = os.path.join(modules_dir, module_file) modules.extend(json.load(open(path))) return modules def clear_built_modules(modules, index): if index < len(modules) - 1: for module in modules[index + 1:]: name = module["name"] if name in state["built_modules"]: del state["built_modules"][name] def rmtree(dir): print "Deleting %s" % dir shutil.rmtree(dir, ignore_errors=True) def cmd_build(): modules = load_modules() for i, module in enumerate(modules): print "\n=== Building %s ===\n" % module["name"] try: pull_source(module) old_commit_id = state["built_modules"].get(module["name"], None) new_commit_id = get_module_commit_id(module) if old_commit_id is None or old_commit_id != new_commit_id: clear_built_modules(modules, i) build(module) else: print "\n* Already built, skipping *" except subprocess.CalledProcessError: sys.exit(1) def cmd_shell(): user_shell = os.environ.get('SHELL', '/bin/sh') os.execlp(user_shell, user_shell) def cmd_run(): os.execlp(sys.argv[2], *sys.argv[2:]) def cmd_clean(): rmtree(install_dir) rmtree(build_dir) for module in load_modules(): if not module.get("out-of-source", True): rmtree(get_module_source_dir(module)) def setup_environ(): add_path("LD_LIBRARY_PATH", lib_dir) add_path("PATH", bin_dir) add_path("GIO_EXTRA_MODULES", os.path.join(system_lib_dir, "gio", "modules")) add_path("GI_TYPELIB_PATH", os.path.join(lib_dir, "girepository-1.0")) add_path("GI_TYPELIB_PATH", os.path.join(system_lib_dir, "girepository-1.0")) add_path("PKG_CONFIG_PATH", os.path.join(lib_dir, "pkgconfig")) add_path("GST_PLUGIN_PATH", os.path.join(lib_dir , "gstreamer-1.0")) add_path("GST_REGISTRY", os.path.join(dnbuild_dir, "gstreamer.registry")) add_path("PYTHONPATH", sysconfig.get_python_lib(prefix=install_dir)) add_path("PYTHONPATH", sysconfig.get_python_lib(prefix=install_dir, plat_specific=True)) add_path("XDG_DATA_DIRS", "/usr/share") add_path("XDG_DATA_DIRS", share_dir) add_path("XDG_CONFIG_DIRS", "/etc") add_path("XDG_CONFIG_DIRS", etc_dir) os.environ["GTK_DATA_PREFIX"] = install_dir os.environ["GTK_PATH"] = os.path.join(lib_dir, "gtk-2.0") def setup_gconf(): gconf_dir = os.path.join(etc_dir, "gconf") gconf_pathdir = os.path.join(gconf_dir, "2") if not os.path.exists(gconf_pathdir): os.makedirs(gconf_pathdir) gconf_path = os.path.join(gconf_pathdir, "path.jhbuild") if not os.path.exists(gconf_path): input = open("/etc/gconf/2/path") output = open(gconf_path, "w") for line in input.readlines(): if "/etc/gconf" in line: output.write(line.replace("/etc/gconf", gconf_dir)) output.write(line) output.close() input.close() os.environ["GCONF_DEFAULT_SOURCE_PATH"] = gconf_path os.environ["GCONF_SCHEMA_INSTALL_SOURCE"] = \ "xml:merged:" + os.path.join(gconf_dir, "gconf.xml.defaults") def setup_dirs(): for dir in [source_dir, install_dir, build_dir, share_dir, dnbuild_dir, os.path.join(share_dir, "aclocal")]: if not os.path.exists(dir): os.mkdir(dir) def main(): load_state() setup_dirs() setup_gconf() setup_environ() commands = {"build": cmd_build, "shell": cmd_shell, "run": cmd_run, "clean": cmd_clean} if sys.argv[1]: commands[sys.argv[1]]() main()