From 8d88572b03a3095f8ff9d604850f5553339deae8 Mon Sep 17 00:00:00 2001 From: dehnert Date: Tue, 16 Aug 2016 15:50:37 +0200 Subject: [PATCH] packager and script Former-commit-id: 4db9b3616e8549a9b1a436f62e9b9f1a14d3728c --- util/osx-package/packager.py | 94 ++++++++++++++++++++++++++++-------- util/osx-package/run.sh | 10 ++++ 2 files changed, 85 insertions(+), 19 deletions(-) create mode 100644 util/osx-package/run.sh diff --git a/util/osx-package/packager.py b/util/osx-package/packager.py index 39d06a667..60b26a8b8 100644 --- a/util/osx-package/packager.py +++ b/util/osx-package/packager.py @@ -1,6 +1,7 @@ import argparse import subprocess import os +from shutil import copyfile def get_dependencies(file): # Call otool -L file to obtain the dependencies. @@ -16,32 +17,87 @@ def get_dependencies(file): return result +def create_package(args): + create_package_dirs(args.dir) + copy_binary_to_package_dir(args.bin, args.binary_basename, args.dir) + run_dylibbundler(args.bundler_binary, args.dir, args.binary_basename) + pass + def parse_arguments(): parser = argparse.ArgumentParser(description='Package the storm binary on Mac OS.') - parser.add_argument('binary', help='the binary to package') + parser.add_argument('--bin', dest='bin', help='the binary to package', default='storm') + parser.add_argument('--dir', dest='dir', help='the root directory of the package (will be created if it does not exist)', default='.') + parser.add_argument('--dylibbundler', dest='bundler_binary', help='the binary of the dylibbundler', default='dylibbundler') args = parser.parse_args() + args.binary_dir = os.path.split(args.bin)[0] + args.binary_basename = os.path.split(args.bin)[1] return args -dep_exeptions = set() -dep_exeptions.add("libSystem.B.dylib") -dep_exeptions.add("libc++.1.dylib") +def create_package_dirs(root_dir): + if not os.path.exists(root_dir): + os.makedirs(root_dir) + if not os.path.exists(root_dir + "/bin"): + os.makedirs(root_dir + "/bin") + if not os.path.exists(root_dir + "/lib"): + os.makedirs(root_dir + "/bin") + pass -def rec_gather_all_dependencies(file, deps = set()): - current_deps = get_dependencies(file) - new_deps = current_deps.keys() - dep_exeptions - deps - deps = deps | current_deps.keys() - - for d in new_deps: - rec_gather_all_dependencies(file, deps) - - return deps +def copy_binary_to_package_dir(binary, binary_basename, root_dir): + copyfile(binary, root_dir + "/bin/storm") + pass + +def run_dylibbundler(bundler_binary, root_dir, binary_basename): + command = [bundler_binary, "-cd", "-od", "-b", "-p", "@executable_path/../lib", "-x", root_dir + "/bin/" + binary_basename, "-d", root_dir + "/lib"] + print("executing " + str(command)) + #proc = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE) + pass + +def fix_paths(root_dir, binary_basename): + fix_paths_file(root_dir + "/bin/" + binary_basename) + for file in os.listdir(root_dir + "/lib"): + fix_paths_file(root_dir + "/lib/" + file) + pass + pass + +def fix_paths_file(file): + print("fixing paths for " + file) + fixable_deps = get_fixable_deps(file) + for (path, lib) in fixable_deps: + change_fixable_dep(file, path, lib) + +native_libs = ["libc++.1.dylib", "libSystem.B.dylib"] + +def get_fixable_deps(file): + # Call otool -L file to obtain the dependencies. + proc = subprocess.Popen(["otool", "-L", file], stdin=subprocess.PIPE, stdout=subprocess.PIPE) + result = [] + for line_bytes in proc.stdout: + line = line_bytes.decode("utf-8").strip() + lib = line.split()[0] + if lib.startswith("@rpath/"): + result.append(("@rpath", lib.split("/", 1)[1])) + elif lib.startswith("/"): + path_file = os.path.split(lib) + if path_file[1] not in native_libs: + result.append((path_file[0], path_file[1])) + return result -def print_deps(deps): - print("Found the following dependencies:") - for d in deps: - print(d) +def change_fixable_dep(file, path, lib): + # Call install_name_tool to change the fixable dependencies + command = ["install_name_tool", "-change", path + "/" + lib, "@executable_path/../lib/" + lib, file] + print("executing " + str(command)) + proc = subprocess.Popen(command, stdout=subprocess.PIPE) + #print ("after call to install_name_tool") + #proc = subprocess.Popen(["otool", "-L", file], stdout=subprocess.PIPE) + #for line_bytes in proc.stdout: + # line = line_bytes.decode("utf-8").strip() + # print(line) + pass if __name__ == "__main__": args = parse_arguments() - deps = rec_gather_all_dependencies(args.binary) - print_deps(deps) + + #create_package(args) + fix_paths(args.dir, args.binary_basename) + + diff --git a/util/osx-package/run.sh b/util/osx-package/run.sh new file mode 100644 index 000000000..0db5b2b5d --- /dev/null +++ b/util/osx-package/run.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +DYLIBBUNDLER_DIR=/Users/chris/work/macdylibbundler/ + +mkdir -p $1 +mkdir -p $1/bin +mkdir -p $1/lib +cp $2 $1/bin +$DYLIBBUNDLER_DIR/dylibbundler -cd -od -b -p @executable_path/../lib -x $1/bin/storm -d $1/lib +python packager.py --bin storm --dir $1