From 291567361967c977a01286896e234679ca7ec78f Mon Sep 17 00:00:00 2001 From: Marco Biasini <marco.biasini@unibas.ch> Date: Thu, 31 May 2012 17:36:28 +0200 Subject: [PATCH] fix deployment on MacOS X --- cmake_support/OST.cmake | 4 +- deployment/macos/deploy.py | 3 +- deployment/macos/deps.py | 133 +++++++++++----------------- modules/bindings/src/CMakeLists.txt | 4 +- 4 files changed, 57 insertions(+), 87 deletions(-) diff --git a/cmake_support/OST.cmake b/cmake_support/OST.cmake index 06457ad71..ce0ee563e 100644 --- a/cmake_support/OST.cmake +++ b/cmake_support/OST.cmake @@ -215,7 +215,7 @@ macro(module) RUNTIME_OUTPUT_DIRECTORY ${LIB_STAGE_PATH}) if (APPLE) set_target_properties(${_LIB_NAME} PROPERTIES - LINK_FLAGS "-Wl,-rpath,@@loader_path" + LINK_FLAGS "-Wl,-rpath,@loader_path" INSTALL_NAME_DIR "@rpath") endif() if (WIN32) @@ -350,7 +350,7 @@ macro(executable_libexec) "${LIBEXEC_STAGE_PATH}") if (APPLE AND NOT _ARG_NO_RPATH AND NOT _ARG_STATIC) set_target_properties(${_ARG_NAME} PROPERTIES - LINK_FLAGS "-Wl,-rpath,@loader_path/../lib") + LINK_FLAGS "-Wl,-rpath,@loader_path/../../lib") endif() if (_ARG_LINK) target_link_libraries(${_ARG_NAME} ${_ARG_LINK}) diff --git a/deployment/macos/deploy.py b/deployment/macos/deploy.py index dea9207ab..51246c532 100644 --- a/deployment/macos/deploy.py +++ b/deployment/macos/deploy.py @@ -20,8 +20,7 @@ bundle.create_bundle('DNG', opts.bundle) if opts.bundle: shutil.copytree('../../examples', 'DNG.app/Contents/examples') os.system('rm `find DNG.app/Contents/examples/ -name "*.pyc"` 2> /dev/null') - os.system('rm -rf DNG.app/Contents/examples/demos/harmony') - os.system('rm -rf DNG.app/Contents/examples/demos/dokk') + os.system('rm -rf DNG.app/Contents/examples/code_fragments/') if opts.dmg: os.system('rm -rf openstructure.dmg') os.system('hdiutil create -srcFolder DNG.app openstructure.dmg') \ No newline at end of file diff --git a/deployment/macos/deps.py b/deployment/macos/deps.py index 627d73ef7..e8bcc7978 100644 --- a/deployment/macos/deps.py +++ b/deployment/macos/deps.py @@ -26,8 +26,8 @@ def _deps_for_lib(lib, pool, recursive=True): pool.add(d) return -def collect_deps(stage_dir, components, binaries, site_packages, - site_packages_dir): +def collect_deps(stage_dir, components, binaries, libexec_binaries, + site_packages, site_packages_dir): """ Collect the dependencies for the given components and returns a list of frameworks/libraries that the component depends on. @@ -49,6 +49,14 @@ def collect_deps(stage_dir, components, binaries, site_packages, continue if bin_name not in pool: _deps_for_lib(bin_name, pool) + for bin in libexec_binaries: + bin_name=os.path.abspath(os.path.join(stage_dir, 'libexec/openstructure', + bin)) + if not os.path.exists(bin_name): + print 'WARNING:', bin_name, 'does not exist' + continue + if bin_name not in pool: + _deps_for_lib(bin_name, pool) for site_package in site_packages: full_path=get_python_module_path(site_package) print full_path @@ -60,12 +68,15 @@ def collect_deps(stage_dir, components, binaries, site_packages, _deps_for_lib(so_file, pool) return pool -BINARIES=['gosty', 'chemdict_tool'] +BINARIES=['chemdict_tool', 'tmalign', 'tmscore'] +LIBEXEC_BINARIES=['gosty'] COMPONENTS=['mol', 'geom', 'conop', 'gfx', 'gui', 'seq_alg', 'seq', 'img', 'img_alg', 'info', 'io', 'db', 'base'] SCRIPTS=['dng', 'ost'] +LIBEXEC_SCRIPTS=['ost_config'] + CHANGE_ID_RPATH='install_name_tool -id @rpath/%s %s' -CHANGE_ID='install_name_tool -id @executable_path/%s %s' +CHANGE_ID='install_name_tool -id @rpath/%s %s' CHANGE_LOAD_CMD_RPATH='install_name_tool -change %s @rpath/%s %s' CHANGE_LOAD_CMD='install_name_tool -change %s @executable_path/%s %s' ADD_RPATH='install_name_tool -add_rpath %s %s 2> /dev/null' @@ -74,25 +85,24 @@ REMOVE_HEADERS='rm -rf `find %s/lib -type d -name Headers`' REMOVE_CURRENT='rm -rf `find %s/lib -type d -name Current`' # collect libs of non-standard libraries/frameworks we depend on -def copy_binaries(stage_dir, outdir, binary_names, scripts, use_rpath, +def copy_binaries(stage_dir, outdir, binary_names, scripts, bin_dir, append_bin=True): - exe_path=os.path.abspath(os.path.join(outdir, 'bin')) + exe_path=os.path.abspath(os.path.join(outdir, bin_dir)) for binary_name in binary_names: if append_bin: - bin_name=os.path.join(stage_dir, 'bin', binary_name) + bin_name=os.path.join(stage_dir, bin_dir, binary_name) else: bin_name=os.path.join(stage_dir, binary_name) if not os.path.exists(bin_name): print 'WARNING:', binary_name, 'does not exist' continue - dst_name=os.path.join(outdir, 'bin', os.path.basename(bin_name)) + dst_name=os.path.join(outdir, bin_dir, os.path.basename(bin_name)) shutil.copy(bin_name, dst_name) - update_load_commands(dst_name, True, use_rpath, exe_path) - os.system(ADD_RPATH % ('../lib', dst_name)) + update_load_commands(dst_name, True, exe_path) for script in scripts: - shutil.copy(os.path.join(stage_dir, 'bin', script), - os.path.join(outdir,'bin', script)) + shutil.copy(os.path.join(stage_dir, bin_dir, script), + os.path.join(outdir,bin_dir, script)) def split_framework_components(abs_path): """ @@ -108,46 +118,31 @@ def split_framework_components(abs_path): trail=os.path.join(*parts[i+1:]) return lead, trail -def change_id(id, lib, use_rpath): +def change_id(id, lib): os.chmod(lib, 0666) - if use_rpath: - os.system(CHANGE_ID_RPATH % (id,lib)) - else: - os.system(CHANGE_ID % (id,lib)) + os.system(CHANGE_ID_RPATH % (id,lib)) os.chmod(lib, 0444) -def update_load_commands(lib, exe, use_rpath, exe_path): +def update_load_commands(lib, exe, exe_path): direct_deps=set() _deps_for_lib(lib, direct_deps, recursive=False) os.chmod(lib, 0666) for direct_dep in direct_deps: if direct_dep.endswith('.dylib'): - if use_rpath: - new_name=os.path.basename(direct_dep) - os.system(CHANGE_LOAD_CMD_RPATH % (direct_dep, new_name, lib)) - else: - new_name=os.path.join('../lib', os.path.basename(direct_dep)) - os.system(CHANGE_LOAD_CMD % (direct_dep, new_name, lib)) + new_name=os.path.basename(direct_dep) + os.system(CHANGE_LOAD_CMD_RPATH % (direct_dep, new_name, lib)) else: assert direct_dep.find('.framework/')>=0 - if use_rpath: - framework_path, rel_path=split_framework_components(direct_dep) - framework_name=os.path.basename(framework_path) - new_name=os.path.join(framework_name, rel_path) - os.system(CHANGE_LOAD_CMD_RPATH % (direct_dep, new_name, lib)) - else: - framework_path, rel_path=split_framework_components(direct_dep) - framework_name=os.path.basename(framework_path) - new_name=os.path.join('../lib', framework_name, rel_path) - os.system(CHANGE_LOAD_CMD % (direct_dep, new_name, lib)) - if use_rpath: - os.system(ADD_RPATH % ('.', lib)) + framework_path, rel_path=split_framework_components(direct_dep) + framework_name=os.path.basename(framework_path) + new_name=os.path.join(framework_name, rel_path) + os.system(CHANGE_LOAD_CMD_RPATH % (direct_dep, new_name, lib)) if exe: os.chmod(lib, 0555) else: os.chmod(lib, 0444) -def copy_deps(dependencies, outdir, use_rpath): +def copy_deps(dependencies, outdir): exe_path=os.path.join(outdir, 'bin') for dep in dependencies: if dep.endswith('.dylib'): @@ -155,29 +150,21 @@ def copy_deps(dependencies, outdir, use_rpath): if not os.path.exists(dep): continue shutil.copy(dep, dst_name) - if use_rpath: - change_id(os.path.basename(dep), dst_name, use_rpath) - else: - change_id('../lib/%s' % os.path.basename(dep), dst_name, use_rpath) - update_load_commands(dst_name, False, use_rpath, exe_path) + change_id(os.path.basename(dep), dst_name) + update_load_commands(dst_name, False, exe_path) else: assert dep.find('.framework/')>=0 framework_path, rel_path=split_framework_components(dep) framework_name=os.path.basename(framework_path) dst_name=os.path.join(outdir, 'lib', framework_name) shutil.copytree(framework_path, dst_name) - if use_rpath: - change_id(os.path.join(dst_name, rel_path), - os.path.join(dst_name, rel_path), use_rpath) - else: - change_id(os.path.join('../lib', framework_name, rel_path), - os.path.join(dst_name, rel_path), use_rpath) + change_id(os.path.join(dst_name, rel_path), + os.path.join(dst_name, rel_path)) os.unlink(os.path.join(dst_name, os.path.splitext(framework_name)[0])) update_load_commands(os.path.join(dst_name, rel_path), False, - use_rpath, exe_path) + exe_path) -def update_pymod_shared_objects(args, path, files): - lib_path, use_rpath=args +def update_pymod_shared_objects(lib_path, path, files): exe_path=os.path.abspath(os.path.join(lib_path, '../bin')) for f in files: if not os.path.exists(os.path.join(path, f)): @@ -187,7 +174,7 @@ def update_pymod_shared_objects(args, path, files): path_to_lib_path=os.path.relpath(lib_path, path) abs_name=os.path.join(path, f) os.system(ADD_RPATH % (path_to_lib_path, abs_name)) - update_load_commands(abs_name, False, use_rpath, exe_path) + update_load_commands(abs_name, False, exe_path) elif ext in ('.pyc', '.pyo'): os.unlink(os.path.join(path, f)) @@ -217,43 +204,30 @@ def get_python_home(): """ return os.path.dirname(sys.modules['os'].__file__) -def check_install_name_tool_capabilities(): - """ - Find out whether install_name_tool supports the add_rpath option. - """ - inst_name_tool=subprocess.Popen('install_name_tool', shell=True, - stderr=subprocess.PIPE) - output=inst_name_tool.communicate()[1] - return output.find('-add_rpath')!=-1 - def make_standalone(stage_dir, outdir, no_includes, force_no_rpath=False, macports_workaround=False): site_packages=get_site_package_dir() - # figure out if install_name_tool supports the -add_rpath option. - use_rpath=True - if not check_install_name_tool_capabilities(): - print "install_name_tool doesn't support the -add_rpath option." - print "I will fallback to the more arcane @executable_path" - use_rpath=False - elif force_no_rpath: - print "I will use the arcane @executable_path" - use_rpath=False if os.path.exists(outdir): shutil.rmtree(outdir) os.system('mkdir -p "%s"' % outdir) os.system('mkdir -p "%s/lib"' % outdir) os.system('mkdir -p "%s/bin"' % outdir) + os.system('mkdir -p "%s/libexec/openstructure"' % outdir) print 'copying shared datafiles' shutil.copytree(os.path.join(stage_dir, 'share'), os.path.join(outdir, 'share')) print 'collecting dependencies' - deps=collect_deps(stage_dir, COMPONENTS, BINARIES, SITE_PACKAGES, + deps=collect_deps(stage_dir, COMPONENTS, BINARIES, LIBEXEC_BINARIES, + SITE_PACKAGES, site_packages) print 'copying dependencies' - copy_deps(deps, outdir, use_rpath) + copy_deps(deps, outdir) print 'copying binaries' - copy_binaries(stage_dir, outdir, BINARIES, SCRIPTS, use_rpath) + copy_binaries(stage_dir, outdir, BINARIES, SCRIPTS, 'bin') + print 'copying libexec binaries' + copy_binaries(stage_dir, outdir, LIBEXEC_BINARIES, LIBEXEC_SCRIPTS, + 'libexec/openstructure') print 'copying pymod' shutil.copytree(os.path.join(stage_dir, 'lib/openstructure'), os.path.join(outdir, 'lib/openstructure')) @@ -275,7 +249,7 @@ def make_standalone(stage_dir, outdir, no_includes, force_no_rpath=False, if os.path.exists(os.path.join(modules_dst, 'site-packages')): shutil.rmtree(os.path.join(modules_dst, 'site-packages')) copy_binaries(os.path.join(python_home, '../..'), outdir, - ['python'], [], use_rpath) + ['python'], [], 'bin') python_bin=os.path.abspath(os.path.join(python_home, '../../bin/python')) else: # For MacPorts it's even more involved. Python is not executed directly @@ -285,11 +259,11 @@ def make_standalone(stage_dir, outdir, no_includes, force_no_rpath=False, path_to_app='../../Resources/Python.app/Contents/MacOS/' exe_path=os.path.join(python_home, path_to_app) copy_binaries(exe_path, outdir, ['python'], [], - use_rpath, append_bin=False) + append_bin=False) python_bin=os.path.join('/opt/local/bin/python') else: copy_binaries(os.path.join(python_home, '../..'), outdir, - ['python'], [], use_rpath) + ['python'], []) python_bin=os.path.abspath(os.path.join(python_home, '../../bin/python')) # remove all versions but the one we are using version_string=sys.version[0:3] @@ -302,15 +276,12 @@ def make_standalone(stage_dir, outdir, no_includes, force_no_rpath=False, if os.path.basename(directory)!=version_string: shutil.rmtree(directory) # replace the python executable - ost_script=os.path.join(outdir, 'bin', 'ost') + ost_script=os.path.join(outdir, 'libexec', 'openstructure', 'ost_config') os.chmod(ost_script, 0666) script=''.join(open(ost_script, 'r').readlines()) script=script.replace(python_bin, '$BIN_DIR/python') open(ost_script, 'w').write(script) os.chmod(ost_script, 0555) - elif use_rpath==False: - print 'BIG FAT WARNING: Creating bundle with @executable_path and default' - print 'Python might not work. Test carefully before deploying.' if no_includes: os.system(REMOVE_HEADERS % outdir) @@ -325,4 +296,4 @@ def make_standalone(stage_dir, outdir, no_includes, force_no_rpath=False, print 'updating link commands of python shared objects' os.path.walk(os.path.join(outdir, 'lib'), update_pymod_shared_objects, - (os.path.join(outdir, 'lib'), use_rpath)) + os.path.join(outdir, 'lib')) diff --git a/modules/bindings/src/CMakeLists.txt b/modules/bindings/src/CMakeLists.txt index 3c178c5f3..7dd88cfe5 100644 --- a/modules/bindings/src/CMakeLists.txt +++ b/modules/bindings/src/CMakeLists.txt @@ -1,5 +1,5 @@ if (COMPILE_TMTOOLS) enable_language(Fortran) - executable(NAME tmalign SOURCES tmalign.f NO_RPATH) - executable(NAME tmscore SOURCES tmscore.f NO_RPATH) + executable(NAME tmalign SOURCES tmalign.f) + executable(NAME tmscore SOURCES tmscore.f) endif() \ No newline at end of file -- GitLab