Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace DMG with packages and productbuild #46

Open
sudara opened this issue Sep 1, 2023 · 9 comments
Open

Replace DMG with packages and productbuild #46

sudara opened this issue Sep 1, 2023 · 9 comments
Labels
1.0 help wanted Extra attention is needed

Comments

@sudara
Copy link
Owner

sudara commented Sep 1, 2023

Finally it's time!

The hard part here is making the xml. It should reuse as much info as possible from CMake. Could also look into CMake doing signing and packaging, but I'm scared :)

@sudara sudara added the 1.0 label Sep 1, 2023
@sudara
Copy link
Owner Author

sudara commented Sep 4, 2023

Right now the .dmg config is hard coded and 95% of people prefer a pkg build

@sudara sudara added the help wanted Extra attention is needed label Dec 11, 2023
@tobiashienzsch
Copy link

tobiashienzsch commented Dec 19, 2023

This is what I'm currently using for my freelance projects. The template repo is private unfortunately. A wild mix of your stuff and years of trial and error. 😆

VERSION=$(head -n 1 VERSION)
mkdir -p build

pkgbuild --identifier "${{ env.BUNDLE_ID }}.clap.pkg" --version $VERSION --component "${{ env.TARGET_NAME }}/CLAP/${{ env.PRODUCT_NAME }}.clap" --install-location "/Library/Audio/Plug-Ins/CLAP" "build/${{ env.PRODUCT_NAME }}.clap.pkg"
pkgbuild --identifier "${{ env.BUNDLE_ID }}.au.pkg" --version $VERSION --component "${{ env.TARGET_NAME }}/AU/${{ env.PRODUCT_NAME }}.component" --install-location "/Library/Audio/Plug-Ins/Components" "build/${{ env.PRODUCT_NAME }}.au.pkg"
pkgbuild --identifier "${{ env.BUNDLE_ID }}.vst3.pkg" --version $VERSION --component "${{ env.TARGET_NAME }}/VST3/${{ env.PRODUCT_NAME }}.vst3" --install-location "/Library/Audio/Plug-Ins/VST3" "build/${{ env.PRODUCT_NAME }}.vst3.pkg"

productbuild --synthesize --package "build/${{ env.PRODUCT_NAME }}.au.pkg" --package "build/${{ env.PRODUCT_NAME }}.vst3.pkg" --package "build/${{ env.PRODUCT_NAME }}.clap.pkg" distribution.xml

# Not necessary, but by default the individual targets are not selectable. All are installed, without
# showing the options (3 in this case). I'm not proud of the script :)
python3 package/installer.py "${{ env.PRODUCT_NAME }}" "$VERSION" distribution.xml distribution-patched.xml
echo "unpatched"
cat distribution.xml
echo "patched"
cat distribution-patched.xml

productbuild --distribution distribution-patched.xml --resources package --package-path build "build/${{ env.PRODUCT_NAME }}-unsigned.pkg"
productsign --sign "${{ env.APPLE_INSTALLER_DEV }}" "build/${{ env.PRODUCT_NAME }}-unsigned.pkg" "build/${{ env.PRODUCT_NAME }}.pkg"
"""
https://developer.apple.com/library/archive/documentation/DeveloperTools/Reference/DistributionDefinitionRef/Chapters/Introduction.html
http://thegreyblog.blogspot.com/2014/06/os-x-creating-packages-from-command_2.html
https://github.com/surge-synthesizer/surge/blob/main/scripts/installer_mac/make_installer.sh
"""

import sys
from xml.etree import ElementTree


def main():
    # Commandline args
    product_name = sys.argv[1]
    version = sys.argv[2]
    in_file = sys.argv[3]
    out_file = sys.argv[4]

    # Read xml
    tree = ElementTree.parse(in_file)
    root = tree.getroot()

    # Make plugin formats selectable
    options = root.find("options")
    options.set("customize", "always")
    options.set("rootVolumeOnly", "true")

    # Fix choices tree
    outline = root.find("choices-outline")
    default_group = outline.find("line")
    choices = default_group.findall("line")
    for choice in choices:
        outline.append(choice)
    outline.remove(default_group)

    for choice in root.findall("choice"):
        # Remove default choice
        if choice.get("id") == "default":
            root.remove(choice)
            continue

        # Add choice title
        # clap = com.company.plugin-template.clap.pkg
        format_name = choice.get("id").split(".")[-2]

        choice.set("title", f"{product_name} {format_name.upper()}")
        choice.set("visible", "true")
        choice.set("start_selected", "true")

    # Include domain
    domain = ElementTree.Element("domain")
    domain.set("enable_anywhere", "false")
    domain.set("enable_currentUserHome", "false")
    domain.set("enable_localSystem", "true")
    root.insert(0, domain)

    # Include EULA
    eula = ElementTree.Element("license")
    eula.set("file", "EULA")
    eula.set("mime-type", "text/plain")
    root.insert(0, eula)

    # Include title
    title = ElementTree.Element("title")
    title.text = f"{product_name} {version}"
    root.insert(0, title)

    # Write xml
    tree.write(out_file, encoding="utf-8", xml_declaration=True)

    return 0


if __name__ == '__main__':
    sys.exit(main())

@sudara
Copy link
Owner Author

sudara commented Dec 19, 2023

Hey thanks for contributing this! Makes a big difference and resolving this is top of my mind. I definitely want to stay away from XML templates, so this is a great starting place <3

@sudara sudara changed the title Add productbuild support Replace DMG with packages and productbuild Apr 26, 2024
@sudara sudara mentioned this issue Apr 26, 2024
@zsliu98
Copy link
Contributor

zsliu98 commented May 6, 2024

Hi @sudara . Would you like to take a look at https://github.com/zsliu98/pamplejuce ? If you think it is OK, I will submit a pull request 😊 There are several things I am not certain about:

  • I didn't include the standalone app cause I am not familiar with it.
  • I am not familiar with the code-signing process. The only thing that I know is that we may need an additional APPLE_INSTALLER_DEV to sign the package. Cause I do not have certifications on my personal account, I have also added several checks to skip the process if the certification is not available. Could you please check whether the code-signing process is correct?
  • I have to compress the final package into a tar archive in order to keep the package icon. Does that sound correct?

@sudara
Copy link
Owner Author

sudara commented May 15, 2024

@zsliu98 Hey that's awesome, thanks for sharing this!

Yes, you are right, an additional secret is required, called DEVELOPER_ID_INSTALLER. For Pamplejuce, signing should not be skippable. Signing on macOS is basically mandatory, it's pretty tough for people to figure out how to install otherwise.

We don't want a tar at the end, but actually a DMG! Ironic, but that's the normal container for delivering pkg files on macOS. I believe we can notarize the tar or the pkg, either way.

I would have to look more carefully about what's happening in the python, I'm not really familiar with all the options, etc!

I think it would work to start a branch for this, but we might need to iterate together a bit to get it nice, so it's up to you if you have the energy to work back and forth!

@zsliu98
Copy link
Contributor

zsliu98 commented May 17, 2024

@sudara I have changed the final installer to a dmg (with the pkg inside). You can easily make the signing mandatory by removing the skip conditions in the action yml.

The Python file has nothing to do with the signing. It generates the unsigned pkg and attaches the icon (if pamplejuce.icns exists).

Yes, a new branch is better. I would like to submit a pull request if you create a new branch (something like macos_pkg). As I am not familiar with the code-signing part, you may need to add additional signing or remove unnecessary signing.

@sudara
Copy link
Owner Author

sudara commented Jul 21, 2024

Finally coming up on personally needing this.

Since we have all important env variables already exported from cmake, I'm considering having the xml be explicit in the repo and using envsubst (brew install gettext) to replace out env variables in the xml. It seems like a good combo of explicitness and reusability.

@zsliu98
Copy link
Contributor

zsliu98 commented Jul 22, 2024

FYI here is the XML file from one of my repo:

<?xml version='1.0' encoding='utf8'?>
<installer-gui-script minSpecVersion="1">
	<title>ZL Equalizer 0.3.3</title>
	<readme file="Readme.rtf" />
	<options customize="always" rootVolumeOnly="true" hostArchitectures="x86_64,arm64" />
	<domain enable_anywhere="false" enable_currentUserHome="false" enable_localSystem="true" />
	<choices-outline>
		<line choice="com.zlaudio.plugins.ZLEqualizer.vst3.pkg" />
		<line choice="com.zlaudio.plugins.ZLEqualizer.au.pkg" />
		<line choice="com.zlaudio.plugins.ZLEqualizer.aax.pkg" />
	</choices-outline>
	<pkg-ref id="com.zlaudio.plugins.ZLEqualizer.vst3.pkg" version="0.3.3" onConclusion="none">Builds/ZL Equalizer.vst3.pkg</pkg-ref>
	<choice id="com.zlaudio.plugins.ZLEqualizer.vst3.pkg" visible="true" start_selected="true" title="ZL Equalizer VST3">
		<pkg-ref id="com.zlaudio.plugins.ZLEqualizer.vst3.pkg" />
	</choice>
	<pkg-ref id="com.zlaudio.plugins.ZLEqualizer.au.pkg" version="0.3.3" onConclusion="none">Builds/ZL Equalizer.au.pkg</pkg-ref>
	<choice id="com.zlaudio.plugins.ZLEqualizer.au.pkg" visible="true" start_selected="true" title="ZL Equalizer AU">
		<pkg-ref id="com.zlaudio.plugins.ZLEqualizer.au.pkg" />
	</choice>
	<pkg-ref id="com.zlaudio.plugins.ZLEqualizer.aax.pkg" version="0.3.3" onConclusion="none">Builds/ZL Equalizer.aax.pkg</pkg-ref>
	<choice id="com.zlaudio.plugins.ZLEqualizer.aax.pkg" visible="true" start_selected="true" title="ZL Equalizer AAX">
		<pkg-ref id="com.zlaudio.plugins.ZLEqualizer.aax.pkg" />
	</choice>
</installer-gui-script>

envsubst is much more explicit than python code. However, if we want different targets, we may have to edit the XML file each time.

@sudara
Copy link
Owner Author

sudara commented Jul 22, 2024

@zsliu98 Thanks for sharing!

if we want different targets, we may have to edit the XML file each time.

Yeah, that's definitely the trade-off...I think if all variables are taken care of, it's a good base for customization, but I'll give it a go to see how it feels...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
1.0 help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

3 participants