feat: cli_export
This commit is contained in:
@@ -105,6 +105,8 @@ positional arguments:
|
|||||||
arguments are specified, only do this for the given
|
arguments are specified, only do this for the given
|
||||||
packages. Removes all downloads older than 21 days
|
packages. Removes all downloads older than 21 days
|
||||||
(see config.ini).
|
(see config.ini).
|
||||||
|
export Take binary and all referenced libs to another folder
|
||||||
|
(relink all dylib)
|
||||||
|
|
||||||
optional arguments:
|
optional arguments:
|
||||||
-h, --help show this help message and exit
|
-h, --help show this help message and exit
|
||||||
|
|||||||
66
brew.py
66
brew.py
@@ -577,6 +577,56 @@ def cli_cleanup(args: ArgParams) -> None:
|
|||||||
Log.main(Txt.freedDiskSpace(total_savings, dryRun=args.dry))
|
Log.main(Txt.freedDiskSpace(total_savings, dryRun=args.dry))
|
||||||
|
|
||||||
|
|
||||||
|
def cli_export(args: ArgParams) -> None:
|
||||||
|
'''
|
||||||
|
Take binary and all referenced libs to another folder (relink all dylib)
|
||||||
|
'''
|
||||||
|
queue = [x for x in args.binaries]
|
||||||
|
done = []
|
||||||
|
while queue:
|
||||||
|
src = os.path.realpath(queue.pop(0))
|
||||||
|
|
||||||
|
if not os.path.exists(src):
|
||||||
|
Log.error('file not found', src)
|
||||||
|
continue
|
||||||
|
|
||||||
|
isLib = src.split('.')[-1] in ('dylib', 'bundle', 'so')
|
||||||
|
tgtDir = os.path.join(args.outdir, 'lib') if isLib else args.outdir
|
||||||
|
tgt = os.path.join(tgtDir, os.path.basename(src))
|
||||||
|
|
||||||
|
if os.path.exists(tgt) and not args.force:
|
||||||
|
Log.info('[skip] exists', tgt)
|
||||||
|
continue
|
||||||
|
|
||||||
|
os.makedirs(tgtDir, exist_ok=True)
|
||||||
|
Log.info('copy', tgt)
|
||||||
|
shutil.copy2(src, tgt)
|
||||||
|
|
||||||
|
# detect linked libs and collect changes
|
||||||
|
cmd_args = [] # type: list[str]
|
||||||
|
exe = Dylib(src)
|
||||||
|
for oldRef in exe.dylibs:
|
||||||
|
lnkRef = exe.expand_path(oldRef)
|
||||||
|
assert os.path.exists(lnkRef)
|
||||||
|
lnkTgt = os.path.realpath(lnkRef)
|
||||||
|
if lnkTgt not in done:
|
||||||
|
queue.append(lnkTgt)
|
||||||
|
done.append(lnkTgt)
|
||||||
|
# link only goes one-way, a lib cannot link back to binary
|
||||||
|
newRef = '@loader_path/' + ('' if isLib else 'lib/') \
|
||||||
|
+ os.path.basename(lnkTgt)
|
||||||
|
if oldRef != newRef:
|
||||||
|
cmd_args.extend(['-change', oldRef, newRef])
|
||||||
|
|
||||||
|
# fix dylib
|
||||||
|
if cmd_args:
|
||||||
|
Log.debug(' relink dylib:', cmd_args)
|
||||||
|
Bash.install_name_tool(tgt, cmd_args)
|
||||||
|
Log.debug(' codesign')
|
||||||
|
Bash.codesign(tgt)
|
||||||
|
os.utime(tgt, (os.path.getatime(src), os.path.getmtime(src)))
|
||||||
|
|
||||||
|
|
||||||
# -----------------------------------
|
# -----------------------------------
|
||||||
# CLI
|
# CLI
|
||||||
# -----------------------------------
|
# -----------------------------------
|
||||||
@@ -769,6 +819,12 @@ def parseArgs() -> ArgParams:
|
|||||||
cmd.arg_bool('-n', '--dry-run', dest='dry', help='''
|
cmd.arg_bool('-n', '--dry-run', dest='dry', help='''
|
||||||
Show what would be removed, but do not actually remove anything''')
|
Show what would be removed, but do not actually remove anything''')
|
||||||
|
|
||||||
|
# export
|
||||||
|
cmd = cli.subcommand('export', cli_export)
|
||||||
|
cmd.arg('binaries', nargs='+', help='Binary files to be exported')
|
||||||
|
cmd.arg('outdir', help='Export output directory')
|
||||||
|
cmd.arg_bool('-f', '--force', help='Overwrite existing files in outdir')
|
||||||
|
|
||||||
return cli.parse()
|
return cli.parse()
|
||||||
|
|
||||||
|
|
||||||
@@ -2028,10 +2084,10 @@ class Dylib:
|
|||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def rpaths_expanded(self) -> list[str]:
|
def rpaths_expanded(self) -> list[str]:
|
||||||
''' Apply _expand_path() on all `.rpaths` '''
|
''' Apply expand_path() on all `.rpaths` '''
|
||||||
return [self._expand_path(x) for x in self.rpaths]
|
return [self.expand_path(x) for x in self.rpaths]
|
||||||
|
|
||||||
def _expand_path(self, rpath: str) -> str:
|
def expand_path(self, rpath: str) -> str:
|
||||||
''' Replace `@@HOMEBREW_` placeholders and resolve `@loader_path` '''
|
''' Replace `@@HOMEBREW_` placeholders and resolve `@loader_path` '''
|
||||||
if rpath.startswith('@loader_path'):
|
if rpath.startswith('@loader_path'):
|
||||||
rpath = os.path.dirname(self.path) + rpath[12:]
|
rpath = os.path.dirname(self.path) + rpath[12:]
|
||||||
@@ -2051,7 +2107,7 @@ class Dylib:
|
|||||||
# 3) codesign --verify --force --sign - <file> // resign with no sign
|
# 3) codesign --verify --force --sign - <file> // resign with no sign
|
||||||
args = []
|
args = []
|
||||||
if self.id:
|
if self.id:
|
||||||
new_id = os.path.basename(self.id)
|
new_id = '@loader_path/' + os.path.basename(self.id)
|
||||||
if self.id != new_id:
|
if self.id != new_id:
|
||||||
args.extend(['-id', new_id])
|
args.extend(['-id', new_id])
|
||||||
|
|
||||||
@@ -2110,7 +2166,7 @@ class Dylib:
|
|||||||
break
|
break
|
||||||
|
|
||||||
elif oldRef.startswith('@loader_path/'):
|
elif oldRef.startswith('@loader_path/'):
|
||||||
try_path = self._expand_path(oldRef)
|
try_path = self.expand_path(oldRef)
|
||||||
if os.path.exists(try_path):
|
if os.path.exists(try_path):
|
||||||
newRef = os.path.relpath(try_path, parentDir)
|
newRef = os.path.relpath(try_path, parentDir)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user