def get_os_version(): if conf.get_config_value('version', 'osversion') == '' or conf.get_config_value( 'version', 'osversion') == 'auto': if globalvars.OSNAME == 'FreeBSD': osversion = misc.get_cmd_output("uname", "-K") misc.verbose_output("System: Autodetecting OS version... " + osversion + "\n") return osversion elif globalvars.OSNAME == 'DragonFly': major = globalvars.OSRELEASE[:globalvars.OSRELEASE.find(".")] minor = globalvars.OSRELEASE[globalvars.OSRELEASE.find(".") + 1:] if len(major) == 1: maj = major + "00" elif len(major) == 2: maj = major + "0" else: maj = major if len(minor) == 1: mnr = minor + "00" elif len(minor) == 2: mnr = minor + "0" else: mnr = minor osversion = maj + mnr misc.verbose_output("System: Autodetecting OS version... " + osversion + "\n") return osversion else: misc.die("FATAL: INCOMPLETELY SUPPORTED OS! THIS IS A BUG.") else: osversion = conf.get_config_value('version', 'osversion') misc.verbose_output("System: OS version is \"" + osversion + "\" (override via config file)\n") return osversion
def ensure_fs_hierarchy(hier): for d in conf.get_config_value('fs', hier + '_hier').split(', '): directory = conf.get_config_value('fs', hier + '_' + d) verbose_output("Filesystem: Ensuring directory \"" + directory + "\" exists... ") if not os.path.isdir(directory): try: os.makedirs(directory) except OSError as e: die("\nFilesystem error: Could not create directory \"" + directory + "\"! Exiting.") verbose_output("ok\n")
def get_osname(): if conf.get_config_value('version', 'osname') == '' or conf.get_config_value( 'version', 'osname') == 'auto': osname = misc.get_cmd_output("uname", "-s") misc.verbose_output("System: Autodetecting OS... " + osname + "\n") return osname else: osname = conf.get_config_value('version', 'osname') misc.verbose_output("System: OS is \"" + osname + "\" (override via config file)\n") return osname
def detect_packages(): packages_present = [] packages_missing = [] value = conf.get_config_value('main', 'packages').split(', ') if isinstance(value, list): for p in conf.get_config_value('main', 'packages').split(', '): if is_package_present(p): packages_present.append(p) else: packages_missing.append(p) else: if is_package_present(value): packages_present.append(value) else: packages_missing.append(value) return(packages_present, packages_missing)
def get_os_arch(): if conf.get_config_value('version', 'osarch') == '' or conf.get_config_value( 'version', 'osarch') == 'auto': if globalvars.OSNAME == 'FreeBSD' or globalvars.OSNAME == 'DragonFly': osarch = misc.get_cmd_output("uname", "-p") misc.verbose_output("System: Autodetecting host architecture... " + osarch + "\n") return osarch else: misc.die("FATAL: INCOMPLETELY SUPPORTED OS! THIS IS A BUG.") else: osarch = conf.get_config_value('version', 'osarch') misc.verbose_output("System: Host architecture is \"" + osarch + "\" (override via config file)\n") return osarch
def ensure_clean_wrkdir(package): """Ensure that a fresh work directory is present for the package to build.""" wrkdir = misc.get_wrkdir(package) if os.path.exists(wrkdir): print("Old workdir found. Deleting... ", end='', flush=True) misc.remove_file_or_dir(wrkdir) print("ok") if package in conf.config['distfiles']: ensure_distfile("compressed", package) ensure_distfile("uncompressed", package) misc.extract_tarball(package) if package in conf.config['extrafiles']: if not os.path.exists(wrkdir): try: os.makedirs(wrkdir) except OSError as e: misc.die("\nFilesystem error: Could not create directory \"" + directory + "\"! Exiting.") if package in conf.config['extrafiles']: ensure_extrafiles_present(package) extradir = globalvars.SUBSTITUTION_MAP['rbuild_extra_dir'] + '/' + package extrafiles = conf.get_config_value('extrafiles', package).split(", ") for f in extrafiles: absolute_path = extradir + '/' + os.path.basename(f) try: shutil.copy(absolute_path, wrkdir) except IOError as e: misc.die("\nFilesystem error: Could not copy \"" + absolute_path + "\" to \"" + wrkdir + "\"! Exiting.")
def get_wrkdir(package): if package + "_name" in conf.config['distfiles']: return(globalvars.SUBSTITUTION_MAP['rbuild_const_dir'] + '/' + conf.get_config_value('distfiles', package + "_name")) elif package in conf.config['distfiles']: return(globalvars.SUBSTITUTION_MAP['rbuild_const_dir'] + '/' + os.path.basename(get_tarball_uri(package).rstrip(".tar"))) else: return(globalvars.SUBSTITUTION_MAP['rbuild_const_dir'] + '/' + package)
def get_os_major(): if conf.get_config_value('version', 'osmajor') == '' or conf.get_config_value( 'version', 'osmajor') == 'auto': if globalvars.OSNAME == 'FreeBSD' or globalvars.OSNAME == 'DragonFly': osmajor = globalvars.OSRELEASE[:globalvars.OSRELEASE.find(".")] misc.verbose_output("System: Autodetecting OS major version... " + osmajor + "\n") return osmajor else: misc.die("FATAL: INCOMPLETELY SUPPORTED OS! THIS IS A BUG.") else: osmajor = conf.get_config_value('version', 'osmajor') misc.verbose_output("System: OS major version is \"" + osmajor + "\" (override via config file)\n") return osmajor
def assert_external_binaries_available(): for b in conf.get_config_value('main', 'external_binaries').split(', '): verbose_output("Programs: Checking if \"" + b + "\" is available... ") p = subprocess.Popen('command -v ' + b, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) if p.stdout.readlines() == []: die("\nError: \"" + b + "\" is not available on this system (or not in PATH)! Exiting.") verbose_output("ok\n") print("Programs: All required external programs are available.")
def get_os_release(): if conf.get_config_value('version', 'osrelease') == '' or conf.get_config_value( 'version', 'osrelease') == 'auto': if globalvars.OSNAME == 'FreeBSD' or globalvars.OSNAME == 'DragonFly': temp = misc.get_cmd_output("uname", "-r") osrelease = temp[:temp.find("-")] misc.verbose_output("System: Autodetecting OS release... " + osrelease + "\n") return osrelease else: misc.die("FATAL: INCOMPLETELY SUPPORTED OS! THIS IS A BUG.") else: osrelease = conf.get_config_value('version', 'osrelease') misc.verbose_output("System: OS release is \"" + osrelease + "\" (override via config file)\n") return osrelease
def prepare_env(env, package): environ = os.environ.copy() env_add = [] if env in conf.config['default']: for v in conf.get_config_value('default', env).split(', '): if v.count('|') != 1: die("Error: Invalid default environment variable assignment \"" + v + "\"! Exiting.") env_add.append(v.split('|')) if package in conf.config[env + '_env']: for v in conf.get_config_value(env + '_env', package).split(', '): if v.count('|') != 1: die("Error: Invalid " + env + " environment variable assignment \"" + v + "\" for package \"" + package + "\"! Exiting.") env_add.append(v.split('|')) for e in env_add: environ[e[0]] = e[1] return(environ)
def decompress_file(srcdir, filename, tgt_dir): verbose_output("Decompressing \"" + filename + "\"... ") extension = get_archive_extension(filename) if extension.startswith("tar"): binary = conf.get_config_value("decompress", extension[4:] + "_bin") elif extension.startswith("t"): binary = conf.get_config_value("decompress", extension[2:] + "_bin") else: die("Error: Unhandled archive \"" + extension + "\"! Exiting.") assert_archiver_available(binary) generic_cmds = conf.get_config_value("decompress", "decompress_cmd").split(', ') for c in generic_cmds: cmd = c.replace('%INFILE%', srcdir + '/' + filename).replace('%TGT_DIR%', tgt_dir).replace('%BINARY%', binary).replace('%FILENAME%', filename) r = do_shell_cmd(cmd, tgt_dir, None) if r != 0: die("\nError: Could not decompress archive \"" + infile + "\"!") verbose_output("ok\n")
def ensure_distfile(mode, package): """Ensure that the compressed or uncompressed ("mode") distfile for a package is present.""" if mode == "compressed": distdir = globalvars.SUBSTITUTION_MAP['rbuild_dist_comp_dir'] filename = misc.get_filename('distfiles', package) hashtype = "md5" elif mode == "uncompressed": distdir = globalvars.SUBSTITUTION_MAP['rbuild_dist_uncomp_dir'] filename = os.path.basename(misc.get_tarball_uri(package)) hashtype = "umd5" else: misc.die("Invalid ensure_distfile mode \"" + mode + "\"! Aborting...") absolute_path = distdir + '/' + filename if not os.path.isfile(absolute_path): if mode == "compressed": misc.fetch_file(conf.get_config_value('distfiles', package), distdir, filename) else: misc.decompress_file(globalvars.SUBSTITUTION_MAP['rbuild_dist_comp_dir'], misc.get_filename('distfiles', package), distdir) checksum = misc.get_distfile_checksum(hashtype, package) misc.verbose_output("Checksum for \"" + package + "\": Comparing for " + mode + " distfile... ") if checksum == None: misc.verbose_output("skipping (not available)\n") else: if misc.get_file_hash(absolute_path) == checksum: misc.verbose_output("ok (matches)\n") else: if mode == "compressed": misc.verbose_output("Mismatch! Fetching again...\n") misc.remove_file_or_dir(absolute_path) misc.fetch_file(conf.get_config_value('distfiles', package), globalvars.SUBSTITUTION_MAP['rbuild_dist_comp_dir'], filename) misc.verbose_output("Comparing checksums once more... ") if misc.get_file_hash(absolute_path) == checksum: misc.verbose_output("ok (matches)\n") else: misc.die("Mismatch again! Bailing out...") else: misc.verbose_output("Mismatch! Extracting again...\n") misc.die("Extract again!")
def get_stdarch(): if conf.get_config_value('version', 'stdarch') == '' or conf.get_config_value( 'version', 'stdarch') == 'auto': if globalvars.OSARCH == "amd64" or globalvars.OSARCH == "x86_64": stdarch = "x86_64" elif globalvars.OSARCH == "i386": stdarch = "x86" elif globalvars.OSARCH == "aarch64" or OSARCH == "arm64": stdarch = "aarch64" else: misc.die("System: Error, unsupported architecture \"" + OSARCH + "\"!") misc.verbose_output( "System: Autodetecting host standard architecture... " + stdarch + "\n") return stdarch else: stdarch = conf.get_config_value('version', 'stdarch') misc.verbose_output("System: Host standard architecture is \"" + stdarch + "\" (override via config file)\n") return stdarch
def assemble_triple(): if conf.get_config_value('version', 'tgt_triple') == '' or conf.get_config_value( 'version', 'tgt_triple') == 'auto': if globalvars.OSNAME == 'FreeBSD': tgt_triple = globalvars.STDARCH + "-raven-" + globalvars.OSNAME.lower( ) + globalvars.OSMAJOR misc.verbose_output("System: Assembling target triple... " + tgt_triple + "\n") return tgt_triple elif globalvars.OSNAME == 'DragonFly': tgt_triple = globalvars.STDARCH + "-raven-" + globalvars.OSNAME.lower( ) + globalvars.OSRELEASE misc.verbose_output("System: Assembling target triple... " + tgt_triple + "\n") return tgt_triple else: misc.die("FATAL: INCOMPLETELY SUPPORTED OS! THIS IS A BUG.") else: tgt_triple = conf.get_config_value('version', 'tgt_triple') misc.verbose_output("System: Target triple is \"" + tgt_triple + "\" (override via config file)\n") return tgt_triple
def patch_source(package): patches = conf.get_config_value('patches', package).split(", ") patchdir = globalvars.SUBSTITUTION_MAP['rbuild_patches_dir'] + '/' + package i = 0 for uri in patches: filename = os.path.basename(uri) absolute_path = patchdir + '/' + filename verbose_output("Patching source of " + package + ": Applying patch " + str(i) + "... ") cmd = "patch -i " + absolute_path r = do_shell_cmd(cmd, get_wrkdir(package), None) if r != 0: die("\nError applying patch \"" + absolute_path + "\"! Exiting.") verbose_output("ok\n") i = i + 1
def ensure_patchfiles_present(package): """Check if patches required to build the package are present, try to fetch them otherwise.""" patches = conf.get_config_value('patches', package).split(", ") md5s = None if package + "_md5" in conf.config['patches']: md5s = conf.get_config_value('patches', package + "_md5").split(", ") patchdir = globalvars.SUBSTITUTION_MAP['rbuild_patches_dir'] + '/' + package misc.verbose_output("Patches: Ensuring directory \"" + patchdir + "\" exists... ") if not os.path.isdir(patchdir): try: os.makedirs(patchdir) except OSError as e: misc.die("\nPatches error: Could not create directory \"" + patchdir + "\"! Exiting.") misc.verbose_output("ok\n") i = 0 for uri in patches: filename = os.path.basename(uri) absolute_path = patchdir + '/' + filename if not os.path.isfile(absolute_path): misc.fetch_file(uri, patchdir, filename) misc.verbose_output("Comparing checksums for patch " + str(i) + "... ") if md5s == None: misc.verbose_output("skipping (not available)\n") else: if misc.get_file_hash(absolute_path) == md5s[i]: misc.verbose_output("ok (matches)\n") else: misc.verbose_output("Mismatch! Fetching again...\n") misc.remove_file_or_dir(absolute_path) misc.fetch_file(uri, patchdir, filename) misc.verbose_output("Comparing checksums once more... ") if misc.get_file_hash(absolute_path) == md5s[i]: misc.verbose_output("ok (matches)\n") else: misc.die("Mismatch again! Bailing out...") i = i + 1
def ensure_extrafiles_present(package): """Ensure that the extra files for a package are present.""" extradir = globalvars.SUBSTITUTION_MAP['rbuild_extra_dir'] + '/' + package extrafiles = conf.get_config_value('extrafiles', package).split(", ") md5s = None if package + "_md5" in conf.config['extrafiles']: md5s = conf.get_config_value('extrafiles', package + "_md5").split(", ") misc.verbose_output("Extra files: Ensuring directory \"" + extradir + "\" exists... ") if not os.path.isdir(extradir): try: os.makedirs(extradir) except OSError as e: misc.die("\nPatches error: Could not create directory \"" + extradir + "\"! Exiting.") misc.verbose_output("ok\n") i = 0 for f in extrafiles: filename = os.path.basename(f) absolute_path = extradir + '/' + filename if not os.path.isfile(absolute_path): misc.fetch_file(f, extradir, filename) misc.verbose_output("Comparing checksums for extra file " + str(i) + "... ") if md5s == None: misc.verbose_output("skipping (not available)\n") else: if misc.get_file_hash(absolute_path) == md5s[i]: misc.verbose_output("ok (matches)\n") else: misc.verbose_output("Mismatch! Fetching again...\n") misc.remove_file_or_dir(absolute_path) misc.fetch_file(f, extradir, filename) misc.verbose_output("Comparing checksums once more... ") if misc.get_file_hash(absolute_path) == md5s[i]: misc.verbose_output("ok (matches)\n") else: misc.die("Mismatch again! Bailing out...") i = i + 1
def build_package(phase, package): """Configure, make or install (phase) a program (package).""" if phase == "configure": activity = "Configuring" env = phase elif phase == "make": activity = "Building" env = phase elif phase == "install": activity = "Installing" env = "make" else: misc.die("\nError: Unknown build phase \"" + phase + "\"! Exiting.") env = misc.prepare_env(env, package) print(activity + " \"" + package + "\"... ", end='', flush=True) wrkdir = misc.get_wrkdir(package) for cmd in conf.get_config_value(phase + "_cmds", package).split(', '): r = misc.do_shell_cmd(cmd, wrkdir, env) if r != 0: misc.die("\nError: " + activity + " failed for package \"" + package + "\"! Exiting.") print("ok")
def assert_archiver_available(binary): if not binary in conf.get_config_value('main', 'external_binaries').split(', '): program = conf.get_config_value("fs", "tgt_prefix") + "/bin/" + binary if not os.path.isfile(program): die("Cannot decompress \"" + extenstion + "\" archives before the package is built (check package order)! Exiting.")
def is_package_present(package): for f in conf.get_config_value('mini_manifest', package).split(', '): if not os.path.isfile(f): return False return True
def get_filename(section, package): if not package in conf.config[section]: die("Error: Could not find key for \"" + package + "\" in section \"" + section + "\"! Exiting.") uri = conf.get_config_value(section, package) return(os.path.basename(uri))
def get_archive_extension(filename): for e in conf.get_config_value('decompress', 'file_types').split(', '): if filename.endswith(e) == True: return(e) die("Unsupported archive type for file \"" + filename + "\"! Exiting.")
def get_distfile_checksum(hashtype, package): if hashtype != "md5" and hashtype != "umd5": die("Unknown distfile hash type \"" + hashtype + "\"!") if package in conf.config["distfile_" + hashtype]: return(conf.get_config_value("distfile_" + hashtype, package)) return(None)