From dff4651349187aef81772701d769f1f53e6d763b Mon Sep 17 00:00:00 2001 From: Gabriel Gerlero Date: Sun, 24 Dec 2023 06:17:56 -0300 Subject: [PATCH] Improve install_name fixing --- Makefile | 4 +-- fix_install_names.sh | 34 ------------------------- relativize_install_names.py | 51 +++++++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 36 deletions(-) delete mode 100755 fix_install_names.sh create mode 100755 relativize_install_names.py diff --git a/Makefile b/Makefile index 17a844e..9480b1a 100644 --- a/Makefile +++ b/Makefile @@ -111,13 +111,13 @@ build/$(APP_NAME).app/Contents/%: Contents/% mkdir -p $(@D) cp -a $< $@ -build/$(APP_NAME).app/Contents/Resources/$(APP_NAME).dmg: build/$(APP_NAME)-build.sparsebundle build/$(APP_NAME).app/Contents/Resources/icon.icns fix_install_names.sh +build/$(APP_NAME).app/Contents/Resources/$(APP_NAME).dmg: build/$(APP_NAME)-build.sparsebundle build/$(APP_NAME).app/Contents/Resources/icon.icns relativize_install_names.py [ ! -d $(VOLUME) ] || hdiutil detach $(VOLUME) hdiutil attach \ build/$(APP_NAME)-build.sparsebundle \ -shadow cd $(VOLUME) \ - && "$(CURDIR)/fix_install_names.sh" + && "$(CURDIR)/relativize_install_names.py" cp build/$(APP_NAME).app/Contents/Resources/icon.icns $(VOLUME)/.VolumeIcon.icns SetFile -c icnC $(VOLUME)/.VolumeIcon.icns SetFile -a C $(VOLUME) diff --git a/fix_install_names.sh b/fix_install_names.sh deleted file mode 100755 index c6f952e..0000000 --- a/fix_install_names.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash -e - -# ----------------------------------------------------------------------------- -# Fix install names of libraries and binaries so that they load the MPI-enabled -# variants of libraries by default (instead of the "dummy" ones that don't work -# in parallel). -# -# This makes the installation less prone to runtime errors caused by the dummy -# libraries being loaded as a consequence of the System Integrity Protection -# (SIP) feature of macOS, which can clear the $DYLD_LIBRARY_PATH set by -# OpenFOAM. -# -# Discussed at https://develop.openfoam.com/Development/openfoam/-/issues/2801 -# ----------------------------------------------------------------------------- - -source etc/bashrc - -fix_install_names() { - for dummylib in $FOAM_LIBBIN/dummy/lib*; do - install_name_tool \ - -change \ - "$dummylib" \ - "$FOAM_LIBBIN/$FOAM_MPI/$(basename "$dummylib")" \ - "$1" - done -} - -for lib in $FOAM_LIBBIN/lib*; do - fix_install_names "$lib" -done - -for bin in $FOAM_APPBIN/*; do - fix_install_names "$bin" -done diff --git a/relativize_install_names.py b/relativize_install_names.py new file mode 100755 index 0000000..0659026 --- /dev/null +++ b/relativize_install_names.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 + +import os +import subprocess +import itertools + +from pathlib import Path + +OPENFOAM_VERSION = int(subprocess.run(["bin/foamEtcFile", "-show-api"], stdout=subprocess.PIPE, check=True).stdout) + +libs = {} + +# Find names of OpenFOAM libraries +if OPENFOAM_VERSION < 2312: # References are already relative in OpenFOAM >= 2312 + # See https://develop.openfoam.com/Development/openfoam/-/issues/2948 + MPI_LIB_PATH = list(Path("platforms").glob("*/lib/*mpi*"))[0] + DUMMY_LIB_PTH = list(Path("platforms").glob("*/lib/dummy"))[0] + + for openfoam_lib in Path("platforms").glob("*/lib/**/*.dylib"): + # Replace references to dummy MPI libraries with the actual MPI libraries + if openfoam_lib.parent == DUMMY_LIB_PTH: + libs[openfoam_lib] = MPI_LIB_PATH / openfoam_lib.name + else: + libs[openfoam_lib] = openfoam_lib + +# Find names of dependency libraries +DEPS_PATH = Path("usr") +DEPS_PATH_RESOLVED = DEPS_PATH.resolve() # In case "usr" is a symlink +for dep_path in (DEPS_PATH_RESOLVED / "opt").iterdir(): + dep_libs = itertools.chain(dep_path.rglob("*.so"), dep_path.rglob("*.dylib")) + for dep_lib in dep_libs: + libs[dep_lib] = DEPS_PATH / dep_lib.relative_to(DEPS_PATH_RESOLVED) + + +def relativize_install_names(file): + otool_stdout = subprocess.run(["otool", "-L", file], stdout=subprocess.PIPE, check=True).stdout.decode() + for old_path,new_path in libs.items(): + if str(old_path.absolute()) in otool_stdout: + new_relative_path = os.path.relpath(new_path, start=file.parent) + subprocess.run(["install_name_tool", + "-change", + old_path.absolute(), + f"@loader_path/{new_relative_path}", + file]) + + +for lib in Path("platforms").glob("*/lib/**/*.dylib"): + relativize_install_names(lib) + +for bin in Path("platforms").glob("*/bin/*"): + relativize_install_names(bin)