Skip to content

Instantly share code, notes, and snippets.

@Kvnbbg
Forked from HuangJiaLian/make_dmg.sh
Last active May 18, 2024 21:19
Show Gist options
  • Save Kvnbbg/84871ae4d642c2dd896e0423471b1b52 to your computer and use it in GitHub Desktop.
Save Kvnbbg/84871ae4d642c2dd896e0423471b1b52 to your computer and use it in GitHub Desktop.
Two steps to turn a Python file to a macOS installer
#!/bin/sh
# References
# https://www.pythonguis.com/tutorials/packaging-pyqt5-applications-pyinstaller-macos-dmg/
# https://medium.com/@jackhuang.wz/in-just-two-steps-you-can-turn-a-python-script-into-a-macos-application-installer-6e21bce2ee71
# ---------------------------------------
# Clean up previous builds
# ---------------------------------------
echo "Cleaning up previous builds..."
rm -rf build dist/*
# ---------------------------------------
# Step 1: Convert Python script to an application bundle
# ---------------------------------------
echo "Converting Python script to macOS app bundle..."
# The following command will create a standalone .app from your Python script
pyinstaller --name 'CryptoSafePDF' \
--icon 'CryptoSafePDF.ico' \
--windowed \
--add-data='./strong_beat.wav:.' \
--add-data='./sub_strong_beat.wav:.' \
--add-data='./weak_beat.wav:.' \
main.py
# ---------------------------------------
# Step 2: Convert the application bundle to a DMG (macOS disk image)
# ---------------------------------------
echo "Creating DMG installer..."
# Prepare the folder for DMG creation
mkdir -p dist/dmg
rm -rf dist/dmg/*
cp -r "dist/CryptoSafePDF.app" dist/dmg
# Create the DMG
# Ensure you have 'create-dmg' installed. If not, install using 'brew install create-dmg'
create-dmg \
--volname "CryptoSafePDF" \
--volicon "CryptoSafePDF.ico" \
--window-pos 200 120 \
--window-size 600 300 \
--icon-size 100 \
--icon "CryptoSafePDF.app" 175 120 \
--hide-extension "CryptoSafePDF.app" \
--app-drop-link 425 120 \
"dist/CryptoSafePDF.dmg" \
"dist/dmg/"
echo "Packaging complete. You can find the DMG installer in the dist/ directory."
#!/bin/bash
# CryptoSafePDF Setup and Packaging Script for macOS
# 1. Install Homebrew (if not installed)
if ! command -v brew &>/dev/null; then
echo "Installing Homebrew..."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
else
echo "Homebrew already installed."
fi
# 2. Install create-dmg
if ! brew list create-dmg &>/dev/null; then
echo "Installing create-dmg..."
brew install create-dmg
else
echo "create-dmg already installed."
fi
# 3. Install pyinstaller
if ! pip list | grep pyinstaller &>/dev/null; then
echo "Installing pyinstaller..."
pip install pyinstaller
else
echo "pyinstaller already installed."
fi
# 4. Clean up previous builds
echo "Cleaning up previous builds..."
rm -rf build dist/*
# 5. Convert Python script to an application bundle
echo "Converting Python script to macOS app bundle..."
pyinstaller --name 'CryptoSafePDF' \
--icon 'CryptoSafePDF.ico' \
--windowed \
--add-data='./strong_beat.wav:.' \
--add-data='./sub_strong_beat.wav:.' \
--add-data='./weak_beat.wav:.' \
main.py
# 6. Create the DMG installer
echo "Creating DMG installer..."
mkdir -p dist/dmg
rm -rf dist/dmg/*
cp -r "dist/CryptoSafePDF.app" dist/dmg
create-dmg \
--volname "CryptoSafePDF" \
--volicon "CryptoSafePDF.ico" \
--window-pos 200 120 \
--window-size 600 300 \
--icon-size 100 \
--icon "CryptoSafePDF.app" 175 120 \
--hide-extension "CryptoSafePDF.app" \
--app-drop-link 425 120 \
"dist/CryptoSafePDF.dmg" \
"dist/dmg/"
echo "Packaging complete. You can find the DMG installer in the dist/ directory."
@Kvnbbg
Copy link
Author

Kvnbbg commented Aug 30, 2023

Certainly! If pyinstaller is causing issues, there are other tools and methods to package Python applications:

  1. cx_Freeze:
    It's a set of scripts and modules for freezing Python scripts into executables in a manner similar to pyinstaller, py2exe, etc.

    Install with:

    pip install cx_Freeze

    Basic usage:

    cxfreeze your_script.py --target-dir dist
  2. py2app (for macOS specifically):
    It's a Python setuptools command which will allow you to make standalone macOS application bundles.

    Install with:

    pip install py2app

    Basic usage involves creating a setup.py script:

    from setuptools import setup
    
    APP = ['your_script.py']
    DATA_FILES = []
    OPTIONS = {
        'argv_emulation': True,
        'packages': ['required_package1', 'required_package2'],
    }
    
    setup(
        app=APP,
        data_files=DATA_FILES,
        options={'py2app': OPTIONS},
        setup_requires=['py2app'],
    )

    Then, run:

    python setup.py py2app
  3. Briefcase:
    This is a tool by the BeeWare project that packages Python projects as native apps. It has the advantage of supporting multiple platforms.

    Install with:

    pip install briefcase

    Usage involves more steps as it's intended to be used with a full BeeWare application, but the BeeWare tutorial can guide you through it.

  4. Docker:
    While not a native packaging tool, Docker can help you create a containerized version of your application, ensuring it runs consistently across different environments. This would require the end-user to have Docker installed, though.

Remember: Each tool might have its peculiarities, and the packaging process might need adjustments depending on the complexity of your application, especially regarding dependencies, data files, and binary extensions.

@Kvnbbg
Copy link
Author

Kvnbbg commented Aug 31, 2023

To call and run installer.py from main.py, you can use one of the following methods:

  1. Using the exec Function:
    This method allows you to execute a string as Python code. It's a straightforward way to run another Python script from within a script.

    # main.py
    with open('installer.py', 'r') as file:
        exec(file.read())
  2. Using the subprocess Module:
    This method runs the script as a separate process. It's more versatile and allows for better control over the execution, capturing output, and error handling.

    # main.py
    import subprocess
    
    subprocess.run(["python", "installer.py"])

    Note: Replace python with python3 if that's the command you use to run Python scripts on your system.

  3. Importing as a Module:
    If installer.py is structured in a way that allows it to be imported (i.e., it doesn't execute code when imported), you can simply import it and call its functions.

    # main.py
    import installer
    
    # Call functions from installer.py if needed

    For this to work without modifications, you'd typically structure installer.py with a main guard:

    # installer.py
    def main():
        # All the main code of installer.py
    
    if __name__ == "__main__":
        main()

    Then, in main.py, you can call the main() function of installer.py:

    # main.py
    import installer
    
    installer.main()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment