From 19347d594ed359d316f913cbc7079d841aebb5bc Mon Sep 17 00:00:00 2001 From: Jeormy Fu Date: Fri, 7 Oct 2022 22:42:25 -0700 Subject: [PATCH] use env variable, fix @rpath deps copy --- dependencies/build.sh | 27 +++--- dependencies/matryoshka_name_tool.py | 13 ++- dependencies/otool_rpath.py | 140 +++++++++++++++++++++++++++ sign.sh | 22 +++-- 4 files changed, 179 insertions(+), 23 deletions(-) create mode 100755 dependencies/otool_rpath.py diff --git a/dependencies/build.sh b/dependencies/build.sh index f81ad07..51f2cef 100755 --- a/dependencies/build.sh +++ b/dependencies/build.sh @@ -1,5 +1,15 @@ #!/bin/bash -set -e +set -xe + +# set the env variable below first! + +: "${LOMOD_PATH:=/Users/jianfu/Work/playground/lomo-backend/cmd/lomod/lomod}" +: "${LOMOC_PATH:=/Users/jianfu/Work/playground/lomo-backend/cmd/lomoc/lomoc}" + +# lomoupg and rsync has no dependencies, just copy binaries +# following processing code for lomoupg, rsync, ffmpeg, exiftool are commented since they are in place and no changes +: "${LOMOUPG_PATH:=/Users/jeromy/.go/src/github.com/lomorage/lomoUpdate/lomoupg}" +: "${RSYNC_PATH:=/Users/jeromy/work/playground/rsync-3.1.3/rsync}" realpath() { [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" @@ -13,13 +23,6 @@ EXIFTOOL_HOME_ABS=$(realpath "deps/exiftool") EXIFTOOL_PATH=$EXIFTOOL_HOME_ABS/exiftool EXIFTOOL_LIB=$EXIFTOOL_HOME_ABS/lib -LOMOD_PATH=/Users/jeromy/.go/src/bitbucket.org/lomoware/lomo-backend/cmd/lomod/lomod -LOMOC_PATH=/Users/jeromy/.go/src/bitbucket.org/lomoware/lomo-backend/cmd/lomoc/lomoc - -# lomoupg and rsync has no dependencies, just copy binaries -LOMOUPG_PATH=/Users/jeromy/.go/src/github.com/lomorage/lomoUpdate/lomoupg -RSYNC_PATH=/Users/jeromy/work/playground/rsync-3.1.3/rsync - FRAMEWORKS_DIR=lomod/Contents/Frameworks BINARY_DIR=lomod/Contents/MacOS @@ -41,10 +44,10 @@ cp $LOMOC_PATH $BINARY_DIR #cp $RSYNC_PATH $BINARY_DIR cd $BINARY_DIR -python ../../../matryoshka_name_tool.py -L /usr/local/ -d ../Frameworks/lomod/ lomoc -python ../../../matryoshka_name_tool.py -L /usr/local/ -d ../Frameworks/lomod/ lomod -#python ../../../matryoshka_name_tool.py -L $FFMPEG_HOME_ABS -d ../Frameworks/ffmpeg/ ffmpeg -#python ../../../matryoshka_name_tool.py -L $FFMPEG_HOME_ABS -d ../Frameworks/ffmpeg/ ffprobe +python3 ../../../matryoshka_name_tool.py -L /opt/homebrew/ -d ../Frameworks/lomod/ lomoc +python3 ../../../matryoshka_name_tool.py -L /opt/homebrew/ -d ../Frameworks/lomod/ lomod +#python3 ../../../matryoshka_name_tool.py -L $FFMPEG_HOME_ABS -d ../Frameworks/ffmpeg/ ffmpeg +#python3 ../../../matryoshka_name_tool.py -L $FFMPEG_HOME_ABS -d ../Frameworks/ffmpeg/ ffprobe install_name_tool -add_rpath @executable_path/../Frameworks/lomod lomoc install_name_tool -add_rpath @executable_path/../Frameworks/lomod lomod diff --git a/dependencies/matryoshka_name_tool.py b/dependencies/matryoshka_name_tool.py index 858bbd7..f4598bb 100644 --- a/dependencies/matryoshka_name_tool.py +++ b/dependencies/matryoshka_name_tool.py @@ -22,6 +22,7 @@ import argparse as ap, errno, os, re, shutil, subprocess as sp import traceback +from otool_rpath import * def make_sure_empty_path_exists(path): try: @@ -65,14 +66,22 @@ def install_name_tool(self,object): line = line.decode('utf-8') libdir_match = self.libdir_pattern.match(line) loader_path = line.strip().startswith('@loader_path') - if libdir_match or loader_path: + rpath = line.strip().startswith('@rpath') + if libdir_match or loader_path or rpath: if libdir_match: dylib = self.dylib_pattern.sub(r'\1',line) - else: + elif loader_path: dylib = line.strip().split(' ')[0].replace('@loader_path', self.args.libdir) + else: + rpaths = otool_rpath([object]) + for rpath in rpaths: + dylib = line.strip().split(' ')[0].replace('@rpath', rpath) + if os.path.exists(dylib): + break if dylib not in self.dylibs_copied: if not self.args.update and not os.path.isfile(self.args.install_libdir + os.path.basename(dylib)): + print("copy %s to %s" % (dylib, self.args.install_libdir)) shutil.copy(dylib, self.args.install_libdir) self.dylibs_copied.add(dylib) target = self.args.install_libdir + os.path.basename(object) \ diff --git a/dependencies/otool_rpath.py b/dependencies/otool_rpath.py new file mode 100755 index 0000000..ff8a67b --- /dev/null +++ b/dependencies/otool_rpath.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python3 + +# TODO: handle LC_UNIXTHREAD register content parsing + +import sys +import os +import pprint +import re +import tempfile +import subprocess + +def line_to_fields_pair(line): + # Time stamp format: %u %(ctime)s + # Example: + # time stamp 2 Thu Jan 1 08:00:02 1970 + # Producer Code: + # printf("\ttime stamp %u ", dl.dylib.timestamp); + # timestamp = (time_t)dl.dylib.timestamp; + # printf("%s", ctime(×tamp)); + l = line.lstrip() + if l.startswith('time stamp '): + return ['time stamp', l[len('time stamp '):-1]] + fields = line.rsplit(maxsplit=1) + # Handle parenthesis + # align 2^4 (16) + # reserved2 6 (size of stubs) + # reserved1 40 (index into indirect symbol table) + # align 2^4 (16) + # name /usr/lib/dyld (offset 12) + # path /Users/user/Qt/5.6/clang_64/lib (offset 12) + + if len(fields) > 1 and fields[1].endswith(')'): + (f0, f1) = fields + # f1 could be '(16)' or + # 'offset 12)' with the '(' in f0 + t = f0.rsplit(sep='(', maxsplit=1) + if len(t) == 2: + f1 = '(' + t[1] + ' ' + f1 + f0 = t[0] + t = f0.rsplit(maxsplit=1) + if len(t) > 1: + fields = [ t[0], t[1] + ' ' + f1 ] + fields[0] = fields[0].strip() + if len(fields) == 1: + fields.append('') + return fields + +def do_load_commands_parse(lines): + #MY-Binary: + #Load command 0 + # cmd LC_SEGMENT_64 + # cmdsize 72 + # segname __PAGEZERO + # vmaddr 0x0000000000000000 + # vmsize 0x0000000100000000 + # fileoff 0 + # filesize 0 + # maxprot 0x00000000 + # initprot 0x00000000 + # nsects 0 + # flags 0x0 + #Load command 1 + # ... + #Section + #compatibility version 5.6.0 + out = [] + for i in lines: + h = i[0] + if not h.isspace() and h.isupper(): + if out: + yield out + out = [ i ] + else: + out.append(i) + if out: + yield out + +def otool_load_commands_parse(lines): + out = [] + for i in do_load_commands_parse(lines): + if len(i) == 1: + l = i[0].strip() + if l.endswith(':'): + o = {'binary': l[:-1]} + else: + o = dict([line_to_fields_pair(l)]) + else: + for x in i: + f = line_to_fields_pair(x) + if len(f) != 2: + raise ValueError + o = dict([line_to_fields_pair(x) for x in i]) + out.append(o) + return out + +def otool_rpath(args): + # Look for: + # Load command 18 + # cmd LC_RPATH + # cmdsize 48 + # path /Users/user/Qt/5.6/clang_64/lib (offset 12) + + def print_usage_exit(): + sys.stderr.write('usage: %s MACHO_FILE\n' % (program_name(),)) + sys.exit(2) + + def find_rpaths(load_commands): + r = re.compile(r'[\s]\(offset [\d]+\)$') + for i in load_commands: + if i.get('cmd') == 'LC_RPATH': + p = i['path'] + m = r.search(p) + if m: + yield p[:m.span()[0]] + else: + yield p + + try: + (macho_binary,) = args + except ValueError: + print_usage_exit() + + tf = tempfile.TemporaryFile(mode='w+') + subprocess.check_call(['otool', '-l', macho_binary], stdout=tf) + tf.seek(0) + l = otool_load_commands_parse(tf) + + ret = [] + for i in find_rpaths(l): + print(i) + if not i.startswith('@'): + ret.append(i) + + return ret + +def program_name(): + return os.path.basename(sys.argv[0]) + +if __name__ == '__main__': + otool_rpath(sys.argv[1:]) diff --git a/sign.sh b/sign.sh index 13c6c0f..7cec203 100755 --- a/sign.sh +++ b/sign.sh @@ -1,18 +1,22 @@ #!/bin/bash set -xe +# find "Developer ID Application" with command below and set env variable IDENTITY +#security find-identity -v +: "${IDENTITY:=11EFF04234720E087A8BF2E3206904BB31F716F4}" + # https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution/customizing_the_notarization_workflow +# add app specific password to key chain, see https://scriptingosx.com/2019/09/notarize-a-command-line-tool/ RELEASE_APP_PATH=$(find ~/Library/Developer/Xcode/DerivedData/LomoAgent*/Build/Products/Release/LomoAgent.app -type d -maxdepth 0) #sudo xattr -rd com.apple.quarantine $RELEASE_APP_PATH -#security find-identity -v codesign --remove-signature "$RELEASE_APP_PATH/Contents/Library/LoginItems/LomoAgentLauncher.app/Contents/Frameworks/"*.dylib -codesign --timestamp --deep -s 4C9293BC4416D5D3AFDC9A8EAE4B26384CB71407 -o runtime -v "$RELEASE_APP_PATH/Contents/Library/LoginItems/LomoAgentLauncher.app/Contents/Frameworks/"*.dylib +codesign --timestamp --deep --force -s $IDENTITY -o runtime -v "$RELEASE_APP_PATH/Contents/Library/LoginItems/LomoAgentLauncher.app/Contents/Frameworks/"*.dylib codesign --remove-signature "$RELEASE_APP_PATH/Contents/Library/LoginItems/LomoAgentLauncher.app" -codesign --timestamp --deep -s 4C9293BC4416D5D3AFDC9A8EAE4B26384CB71407 -o runtime -v "$RELEASE_APP_PATH/Contents/Library/LoginItems/LomoAgentLauncher.app" +codesign --timestamp --deep --force -s $IDENTITY -o runtime -v "$RELEASE_APP_PATH/Contents/Library/LoginItems/LomoAgentLauncher.app" for item in lomoc \ lomod \ @@ -22,17 +26,17 @@ for item in lomoc \ rsync do codesign --remove-signature "$RELEASE_APP_PATH/Contents/MacOS/$item" - codesign --timestamp --deep -s 4C9293BC4416D5D3AFDC9A8EAE4B26384CB71407 -o runtime -v "$RELEASE_APP_PATH/Contents/MacOS/$item" + codesign --timestamp --deep -s $IDENTITY -o runtime -v "$RELEASE_APP_PATH/Contents/MacOS/$item" done codesign --remove-signature "$RELEASE_APP_PATH/Contents/Frameworks/"*.dylib -codesign --timestamp --deep -s 4C9293BC4416D5D3AFDC9A8EAE4B26384CB71407 -o runtime -v "$RELEASE_APP_PATH/Contents/Frameworks/"*.dylib +codesign --timestamp --deep --force -s $IDENTITY -o runtime -v "$RELEASE_APP_PATH/Contents/Frameworks/"*.dylib codesign --remove-signature "$RELEASE_APP_PATH/Contents/Frameworks/ffmpeg/"*.dylib -codesign --timestamp --deep -s 4C9293BC4416D5D3AFDC9A8EAE4B26384CB71407 -o runtime -v "$RELEASE_APP_PATH/Contents/Frameworks/ffmpeg/"*.dylib +codesign --timestamp --deep --force -s $IDENTITY -o runtime -v "$RELEASE_APP_PATH/Contents/Frameworks/ffmpeg/"*.dylib codesign --remove-signature "$RELEASE_APP_PATH/Contents/Frameworks/lomod/"*.dylib -codesign --timestamp --deep -s 4C9293BC4416D5D3AFDC9A8EAE4B26384CB71407 -o runtime -v "$RELEASE_APP_PATH/Contents/Frameworks/lomod/"*.dylib +codesign --timestamp --deep --force -s $IDENTITY -o runtime -v "$RELEASE_APP_PATH/Contents/Frameworks/lomod/"*.dylib for item in Zip \ Commands \ @@ -40,11 +44,11 @@ for item in Zip \ CatCrypto do codesign --remove-signature "$RELEASE_APP_PATH/Contents/Frameworks/$item.framework/Versions/A" - codesign -s 4C9293BC4416D5D3AFDC9A8EAE4B26384CB71407 -o runtime -v "$RELEASE_APP_PATH/Contents/Frameworks/$item.framework/Versions/A" + codesign -s $IDENTITY -o runtime -v "$RELEASE_APP_PATH/Contents/Frameworks/$item.framework/Versions/A" done codesign --remove-signature "$RELEASE_APP_PATH" -codesign --timestamp --deep -s 4C9293BC4416D5D3AFDC9A8EAE4B26384CB71407 -o runtime -v "$RELEASE_APP_PATH" +codesign --timestamp --deep --force -s $IDENTITY -o runtime -v "$RELEASE_APP_PATH" codesign -d -vv "$RELEASE_APP_PATH" codesign -vvv --deep --strict "$RELEASE_APP_PATH"