mirror of
https://github.com/feather-wallet/feather.git
synced 2025-01-03 17:39:49 +00:00
guix: .zip for mac releases
This commit is contained in:
parent
4efb3564c0
commit
aa78e57148
9 changed files with 17 additions and 143 deletions
|
@ -276,20 +276,14 @@ configure_file("${CMAKE_SOURCE_DIR}/contrib/installers/windows/setup.nsi.in" "${
|
||||||
|
|
||||||
if(APPLE AND CMAKE_CROSSCOMPILING)
|
if(APPLE AND CMAKE_CROSSCOMPILING)
|
||||||
set(macos_app "Feather.app")
|
set(macos_app "Feather.app")
|
||||||
configure_file(contrib/macdeploy/background.tiff contrib/macdeploy/background.tiff COPYONLY)
|
|
||||||
configure_file(contrib/macdeploy/Info.plist.in ${macos_app}/Contents/Info.plist @ONLY)
|
configure_file(contrib/macdeploy/Info.plist.in ${macos_app}/Contents/Info.plist @ONLY)
|
||||||
configure_file(src/assets/images/appicons/appicon.icns ${macos_app}/Contents/Resources/appicon.icns COPYONLY)
|
configure_file(src/assets/images/appicons/appicon.icns ${macos_app}/Contents/Resources/appicon.icns COPYONLY)
|
||||||
|
|
||||||
set(xorrisofs_options)
|
|
||||||
if(DEFINED ENV{SOURCE_DATE_EPOCH})
|
|
||||||
set(xorrisofs_options -volume_date all_file_dates =$ENV{SOURCE_DATE_EPOCH})
|
|
||||||
endif()
|
|
||||||
add_custom_target(deploy
|
add_custom_target(deploy
|
||||||
COMMAND "${CMAKE_COMMAND}" --install "${CMAKE_BINARY_DIR}" --config "$<CONFIG>" --prefix "${CMAKE_BINARY_DIR}/release" --strip
|
COMMAND "${CMAKE_COMMAND}" --install "${CMAKE_BINARY_DIR}" --config "$<CONFIG>" --prefix "${CMAKE_BINARY_DIR}/release" --strip
|
||||||
COMMAND "${CMAKE_COMMAND}" -E make_directory "${CMAKE_BINARY_DIR}/${macos_app}/Contents/MacOS"
|
COMMAND "${CMAKE_COMMAND}" -E make_directory "${CMAKE_BINARY_DIR}/${macos_app}/Contents/MacOS"
|
||||||
COMMAND "${CMAKE_COMMAND}" -E rename "${CMAKE_BINARY_DIR}/bin/$<TARGET_FILE_NAME:feather>" "${CMAKE_BINARY_DIR}/${macos_app}/Contents/MacOS/feather"
|
COMMAND "${CMAKE_COMMAND}" -E rename "${CMAKE_BINARY_DIR}/bin/$<TARGET_FILE_NAME:feather>" "${CMAKE_BINARY_DIR}/${macos_app}/Contents/MacOS/feather"
|
||||||
COMMAND PYTHONPATH=${PYTHONPATH} INSTALL_NAME_TOOL=${CMAKE_INSTALL_NAME_TOOL} OTOOL=${OTOOL} STRIP=${CMAKE_STRIP} ${CMAKE_SOURCE_DIR}/contrib/macdeploy/macdeployqtplus ${macos_app} ${PACKAGE_NAME}
|
COMMAND PYTHONPATH=${PYTHONPATH} INSTALL_NAME_TOOL=${CMAKE_INSTALL_NAME_TOOL} OTOOL=${OTOOL} STRIP=${CMAKE_STRIP} ${CMAKE_SOURCE_DIR}/contrib/macdeploy/macdeployqtplus ${macos_app} ${PACKAGE_NAME} -zip
|
||||||
COMMAND xorrisofs -D -l -V "${PACKAGE_NAME}" -no-pad -r -dir-mode 0755 -o ${PACKAGE_NAME}.dmg ${CMAKE_BINARY_DIR}/dist -- ${xorrisofs_options}
|
|
||||||
VERBATIM
|
VERBATIM
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
package=native_ds_store
|
|
||||||
$(package)_version=1.3.0
|
|
||||||
$(package)_download_path=https://github.com/dmgbuild/ds_store/archive/
|
|
||||||
$(package)_file_name=v$($(package)_version).tar.gz
|
|
||||||
$(package)_sha256_hash=76b3280cd4e19e5179defa23fb594a9dd32643b0c80d774bd3108361d94fb46d
|
|
||||||
$(package)_install_libdir=$(build_prefix)/lib/python3/dist-packages
|
|
||||||
|
|
||||||
define $(package)_build_cmds
|
|
||||||
python3 setup.py build
|
|
||||||
endef
|
|
||||||
|
|
||||||
define $(package)_stage_cmds
|
|
||||||
mkdir -p $($(package)_install_libdir) && \
|
|
||||||
python3 setup.py install --root=$($(package)_staging_dir) --prefix=$(build_prefix) --install-lib=$($(package)_install_libdir)
|
|
||||||
endef
|
|
|
@ -1,15 +0,0 @@
|
||||||
package=native_mac_alias
|
|
||||||
$(package)_version=2.2.0
|
|
||||||
$(package)_download_path=https://github.com/dmgbuild/mac_alias/archive/
|
|
||||||
$(package)_file_name=v$($(package)_version).tar.gz
|
|
||||||
$(package)_sha256_hash=421e6d7586d1f155c7db3e7da01ca0dacc9649a509a253ad7077b70174426499
|
|
||||||
$(package)_install_libdir=$(build_prefix)/lib/python3/dist-packages
|
|
||||||
|
|
||||||
define $(package)_build_cmds
|
|
||||||
python3 setup.py build
|
|
||||||
endef
|
|
||||||
|
|
||||||
define $(package)_stage_cmds
|
|
||||||
mkdir -p $($(package)_install_libdir) && \
|
|
||||||
python3 setup.py install --root=$($(package)_staging_dir) --prefix=$(build_prefix) --install-lib=$($(package)_install_libdir)
|
|
||||||
endef
|
|
|
@ -5,7 +5,7 @@ linux_packages := eudev liblzma libarchive libfuse libsquashfuse libappimage app
|
||||||
linux_native_packages = native_patchelf
|
linux_native_packages = native_patchelf
|
||||||
|
|
||||||
darwin_packages :=
|
darwin_packages :=
|
||||||
darwin_native_packages = native_cctools native_libtapi native_clang native_ds_store native_mac_alias
|
darwin_native_packages = native_cctools native_libtapi native_clang
|
||||||
|
|
||||||
mingw32_packages = icu4c
|
mingw32_packages = icu4c
|
||||||
mingw32_native_packages = native_cmake
|
mingw32_native_packages = native_cmake
|
||||||
|
|
|
@ -353,7 +353,7 @@ mkdir -p "$DISTSRC"
|
||||||
case "$HOST" in
|
case "$HOST" in
|
||||||
*darwin*)
|
*darwin*)
|
||||||
make -C build deploy ${V:+V=1}
|
make -C build deploy ${V:+V=1}
|
||||||
mv build/feather.dmg "${OUTDIR}/${DISTNAME}.dmg"
|
mv build/feather.zip "${OUTDIR}/${DISTNAME}.zip"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
(gnu packages bash)
|
(gnu packages bash)
|
||||||
(gnu packages bison)
|
(gnu packages bison)
|
||||||
(gnu packages certs)
|
(gnu packages certs)
|
||||||
(gnu packages cdrom)
|
|
||||||
(gnu packages check)
|
(gnu packages check)
|
||||||
(gnu packages cmake)
|
(gnu packages cmake)
|
||||||
(gnu packages commencement)
|
(gnu packages commencement)
|
||||||
|
@ -680,5 +679,5 @@ inspecting signatures in Mach-O binaries.")
|
||||||
((string-contains target "-linux-")
|
((string-contains target "-linux-")
|
||||||
(list (make-bitcoin-cross-toolchain target) cmake))
|
(list (make-bitcoin-cross-toolchain target) cmake))
|
||||||
((string-contains target "darwin")
|
((string-contains target "darwin")
|
||||||
(list clang-toolchain-10 binutils cmake xorriso python-signapple))
|
(list clang-toolchain-10 binutils cmake python-signapple))
|
||||||
(else '())))))
|
(else '())))))
|
||||||
|
|
|
@ -6,7 +6,7 @@ The `macdeployqtplus` script should not be run manually. Instead, after building
|
||||||
make deploy
|
make deploy
|
||||||
```
|
```
|
||||||
|
|
||||||
When complete, it will have produced `Bitcoin-Core.dmg`.
|
When complete, it will have produced `Feather.zip`.
|
||||||
|
|
||||||
## SDK Extraction
|
## SDK Extraction
|
||||||
|
|
||||||
|
@ -60,10 +60,10 @@ previous stage) as the first argument.
|
||||||
|
|
||||||
The `sha256sum` of the generated TAR.GZ archive should be `df75d30ecafc429e905134333aeae56ac65fac67cb4182622398fd717df77619`.
|
The `sha256sum` of the generated TAR.GZ archive should be `df75d30ecafc429e905134333aeae56ac65fac67cb4182622398fd717df77619`.
|
||||||
|
|
||||||
## Deterministic macOS DMG Notes
|
## Deterministic macOS App Notes
|
||||||
|
|
||||||
Working macOS DMGs are created in Linux by combining a recent `clang`, the Apple
|
macOS Applications are created in Linux by combining a recent `clang` and the Apple
|
||||||
`binutils` (`ld`, `ar`, etc) and DMG authoring tools.
|
`binutils` (`ld`, `ar`, etc).
|
||||||
|
|
||||||
Apple uses `clang` extensively for development and has upstreamed the necessary
|
Apple uses `clang` extensively for development and has upstreamed the necessary
|
||||||
functionality so that a vanilla clang can take advantage. It supports the use of `-F`,
|
functionality so that a vanilla clang can take advantage. It supports the use of `-F`,
|
||||||
|
@ -93,20 +93,16 @@ created using these tools. The build process has been designed to avoid includin
|
||||||
SDK's files in Guix's outputs. All interim tarballs are fully deterministic and may be freely
|
SDK's files in Guix's outputs. All interim tarballs are fully deterministic and may be freely
|
||||||
redistributed.
|
redistributed.
|
||||||
|
|
||||||
[`xorrisofs`](https://www.gnu.org/software/xorriso/) is used to create the DMG.
|
|
||||||
|
|
||||||
A background image is added to DMG files by inserting a `.DS_Store` during creation.
|
|
||||||
|
|
||||||
As of OS X 10.9 Mavericks, using an Apple-blessed key to sign binaries is a requirement in
|
As of OS X 10.9 Mavericks, using an Apple-blessed key to sign binaries is a requirement in
|
||||||
order to satisfy the new Gatekeeper requirements. Because this private key cannot be
|
order to satisfy the new Gatekeeper requirements. Because this private key cannot be
|
||||||
shared, we'll have to be a bit creative in order for the build process to remain somewhat
|
shared, we'll have to be a bit creative in order for the build process to remain somewhat
|
||||||
deterministic. Here's how it works:
|
deterministic. Here's how it works:
|
||||||
|
|
||||||
- Builders use Guix to create an unsigned release. This outputs an unsigned DMG which
|
- Builders use Guix to create an unsigned release. This outputs an unsigned ZIP which
|
||||||
users may choose to bless and run. It also outputs an unsigned app structure in the form
|
users may choose to bless and run. It also outputs an unsigned app structure in the form
|
||||||
of a tarball, which also contains all of the tools that have been previously (deterministically)
|
of a tarball, which also contains all of the tools that have been previously (deterministically)
|
||||||
built in order to create a final DMG.
|
built in order to create a final DMG.
|
||||||
- The Apple keyholder uses this unsigned app to create a detached signature, using the
|
- The Apple keyholder uses this unsigned app to create a detached signature, using the
|
||||||
script that is also included there. Detached signatures are available from this [repository](https://github.com/bitcoin-core/bitcoin-detached-sigs).
|
script that is also included there. Detached signatures are available from this [repository](https://github.com/bitcoin-core/bitcoin-detached-sigs).
|
||||||
- Builders feed the unsigned app + detached signature back into Guix. It uses the
|
- Builders feed the unsigned app + detached signature back into Guix. It uses the
|
||||||
pre-built tools to recombine the pieces into a deterministic DMG.
|
pre-built tools to recombine the pieces into a deterministic ZIP.
|
||||||
|
|
Binary file not shown.
|
@ -18,8 +18,6 @@
|
||||||
|
|
||||||
import sys, re, os, platform, shutil, stat, subprocess, os.path
|
import sys, re, os, platform, shutil, stat, subprocess, os.path
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
from ds_store import DSStore
|
|
||||||
from mac_alias import Alias
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from subprocess import PIPE, run
|
from subprocess import PIPE, run
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
@ -384,7 +382,7 @@ def deployPlugins(appBundleInfo: ApplicationBundleInfo, deploymentInfo: Deployme
|
||||||
|
|
||||||
ap = ArgumentParser(description="""Improved version of macdeployqt.
|
ap = ArgumentParser(description="""Improved version of macdeployqt.
|
||||||
|
|
||||||
Outputs a ready-to-deploy app in a folder "dist" and optionally wraps it in a .dmg file.
|
Outputs a ready-to-deploy app in a folder "dist" and optionally wraps it in a .zip file.
|
||||||
Note, that the "dist" folder will be deleted before deploying on each run.
|
Note, that the "dist" folder will be deleted before deploying on each run.
|
||||||
|
|
||||||
Optionally, Qt translation files (.qm) can be added to the bundle.""")
|
Optionally, Qt translation files (.qm) can be added to the bundle.""")
|
||||||
|
@ -394,8 +392,8 @@ ap.add_argument("appname", nargs=1, metavar="appname", help="name of the app bei
|
||||||
ap.add_argument("-verbose", nargs="?", const=True, help="Output additional debugging information")
|
ap.add_argument("-verbose", nargs="?", const=True, help="Output additional debugging information")
|
||||||
ap.add_argument("-no-plugins", dest="plugins", action="store_false", default=True, help="skip plugin deployment")
|
ap.add_argument("-no-plugins", dest="plugins", action="store_false", default=True, help="skip plugin deployment")
|
||||||
ap.add_argument("-no-strip", dest="strip", action="store_false", default=True, help="don't run 'strip' on the binaries")
|
ap.add_argument("-no-strip", dest="strip", action="store_false", default=True, help="don't run 'strip' on the binaries")
|
||||||
ap.add_argument("-dmg", nargs="?", const="", metavar="basename", help="create a .dmg disk image")
|
|
||||||
ap.add_argument("-translations-dir", nargs=1, metavar="path", default=None, help="Path to Qt's translations. Base translations will automatically be added to the bundle's resources.")
|
ap.add_argument("-translations-dir", nargs=1, metavar="path", default=None, help="Path to Qt's translations. Base translations will automatically be added to the bundle's resources.")
|
||||||
|
ap.add_argument("-zip", nargs="?", const="", metavar="zip", help="create a .zip containing the app bundle")
|
||||||
|
|
||||||
config = ap.parse_args()
|
config = ap.parse_args()
|
||||||
|
|
||||||
|
@ -416,12 +414,9 @@ if os.path.exists("dist"):
|
||||||
print("+ Removing existing dist folder +")
|
print("+ Removing existing dist folder +")
|
||||||
shutil.rmtree("dist")
|
shutil.rmtree("dist")
|
||||||
|
|
||||||
if os.path.exists(appname + ".dmg"):
|
if os.path.exists(appname + ".zip"):
|
||||||
print("+ Removing existing DMG +")
|
print("+ Removing existing .zip +")
|
||||||
os.unlink(appname + ".dmg")
|
os.unlink(appname + ".zip")
|
||||||
|
|
||||||
if os.path.exists(appname + ".temp.dmg"):
|
|
||||||
os.unlink(appname + ".temp.dmg")
|
|
||||||
|
|
||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
|
|
||||||
|
@ -496,61 +491,9 @@ with open(os.path.join(applicationBundle.resourcesPath, "qt.conf"), "wb") as f:
|
||||||
|
|
||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
|
|
||||||
print("+ Generating .DS_Store +")
|
|
||||||
|
|
||||||
output_file = os.path.join("dist", ".DS_Store")
|
|
||||||
|
|
||||||
ds = DSStore.open(output_file, 'w+')
|
|
||||||
|
|
||||||
ds['.']['bwsp'] = {
|
|
||||||
'WindowBounds': '{{300, 280}, {500, 343}}',
|
|
||||||
'PreviewPaneVisibility': False,
|
|
||||||
}
|
|
||||||
|
|
||||||
icvp = {
|
|
||||||
'gridOffsetX': 0.0,
|
|
||||||
'textSize': 12.0,
|
|
||||||
'viewOptionsVersion': 1,
|
|
||||||
'backgroundImageAlias': b'\x00\x00\x00\x00\x02\x1e\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd1\x94\\\xb0H+\x00\x05\x00\x00\x00\x98\x0fbackground.tiff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x99\xd19\xb0\xf8\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\r\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b.background\x00\x00\x10\x00\x08\x00\x00\xd1\x94\\\xb0\x00\x00\x00\x11\x00\x08\x00\x00\xd19\xb0\xf8\x00\x00\x00\x01\x00\x04\x00\x00\x00\x98\x00\x0e\x00 \x00\x0f\x00b\x00a\x00c\x00k\x00g\x00r\x00o\x00u\x00n\x00d\x00.\x00t\x00i\x00f\x00f\x00\x0f\x00\x02\x00\x00\x00\x12\x00\x1c/.background/background.tiff\x00\x14\x01\x06\x00\x00\x00\x00\x01\x06\x00\x02\x00\x00\x0cMacintosh HD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xce\x97\xab\xc3H+\x00\x00\x01\x88[\x88\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02u\xab\x8d\xd1\x94\\\xb0devrddsk\xff\xff\xff\xff\x00\x00\t \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07bitcoin\x00\x00\x10\x00\x08\x00\x00\xce\x97\xab\xc3\x00\x00\x00\x11\x00\x08\x00\x00\xd1\x94\\\xb0\x00\x00\x00\x01\x00\x14\x01\x88[\x88\x00\x16\xa9\t\x00\x08\xfaR\x00\x08\xfaQ\x00\x02d\x8e\x00\x0e\x00\x02\x00\x00\x00\x0f\x00\x1a\x00\x0c\x00M\x00a\x00c\x00i\x00n\x00t\x00o\x00s\x00h\x00 \x00H\x00D\x00\x13\x00\x01/\x00\x00\x15\x00\x02\x00\x14\xff\xff\x00\x00\xff\xff\x00\x00',
|
|
||||||
'backgroundColorBlue': 1.0,
|
|
||||||
'iconSize': 96.0,
|
|
||||||
'backgroundColorGreen': 1.0,
|
|
||||||
'arrangeBy': 'none',
|
|
||||||
'showIconPreview': True,
|
|
||||||
'gridSpacing': 100.0,
|
|
||||||
'gridOffsetY': 0.0,
|
|
||||||
'showItemInfo': False,
|
|
||||||
'labelOnBottom': True,
|
|
||||||
'backgroundType': 2,
|
|
||||||
'backgroundColorRed': 1.0
|
|
||||||
}
|
|
||||||
alias = Alias().from_bytes(icvp['backgroundImageAlias'])
|
|
||||||
alias.volume.name = appname
|
|
||||||
alias.volume.posix_path = '/Volumes/' + appname
|
|
||||||
icvp['backgroundImageAlias'] = alias.to_bytes()
|
|
||||||
ds['.']['icvp'] = icvp
|
|
||||||
|
|
||||||
ds['.']['vSrn'] = ('long', 1)
|
|
||||||
|
|
||||||
ds['Applications']['Iloc'] = (370, 156)
|
|
||||||
ds['Feather.app']['Iloc'] = (128, 156)
|
|
||||||
|
|
||||||
ds.flush()
|
|
||||||
ds.close()
|
|
||||||
|
|
||||||
# ------------------------------------------------
|
|
||||||
|
|
||||||
if platform.system() == "Darwin":
|
if platform.system() == "Darwin":
|
||||||
subprocess.check_call(f"codesign --deep --force --sign - {target}", shell=True)
|
subprocess.check_call(f"codesign --deep --force --sign - {target}", shell=True)
|
||||||
|
|
||||||
print("+ Installing background.tiff +")
|
|
||||||
|
|
||||||
bg_path = os.path.join('dist', '.background', 'background.tiff')
|
|
||||||
os.mkdir(os.path.dirname(bg_path))
|
|
||||||
|
|
||||||
tiff_path = os.path.join('contrib', 'macdeploy', 'background.tiff')
|
|
||||||
shutil.copy2(tiff_path, bg_path)
|
|
||||||
|
|
||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
|
|
||||||
print("+ Generating symlink for /Applications +")
|
print("+ Generating symlink for /Applications +")
|
||||||
|
@ -559,36 +502,8 @@ os.symlink("/Applications", os.path.join('dist', "Applications"))
|
||||||
|
|
||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
|
|
||||||
if config.dmg is not None:
|
if config.zip is not None:
|
||||||
|
shutil.make_archive('{}'.format(appname), format='zip', root_dir='dist', base_dir='Feather.app')
|
||||||
print("+ Preparing .dmg disk image +")
|
|
||||||
|
|
||||||
if verbose:
|
|
||||||
print("Determining size of \"dist\"...")
|
|
||||||
size = 0
|
|
||||||
for path, dirs, files in os.walk("dist"):
|
|
||||||
for file in files:
|
|
||||||
size += os.path.getsize(os.path.join(path, file))
|
|
||||||
size += int(size * 0.15)
|
|
||||||
|
|
||||||
if verbose:
|
|
||||||
print("Creating temp image for modification...")
|
|
||||||
|
|
||||||
tempname: str = appname + ".temp.dmg"
|
|
||||||
|
|
||||||
run(["hdiutil", "create", tempname, "-srcfolder", "dist", "-format", "UDRW", "-size", str(size), "-volname", appname], check=True, universal_newlines=True)
|
|
||||||
|
|
||||||
if verbose:
|
|
||||||
print("Attaching temp image...")
|
|
||||||
output = run(["hdiutil", "attach", tempname, "-readwrite"], check=True, universal_newlines=True, stdout=PIPE).stdout
|
|
||||||
|
|
||||||
print("+ Finalizing .dmg disk image +")
|
|
||||||
|
|
||||||
run(["hdiutil", "detach", f"/Volumes/{appname}"], universal_newlines=True)
|
|
||||||
|
|
||||||
run(["hdiutil", "convert", tempname, "-format", "UDZO", "-o", appname, "-imagekey", "zlib-level=9"], check=True, universal_newlines=True)
|
|
||||||
|
|
||||||
os.unlink(tempname)
|
|
||||||
|
|
||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue