Swift Bundler

repository·main·Indexed 19 days ago

https://github.com/moreswift/swift-bundler

An Xcodeproj-less tool for creating cross-platform Swift applications. It provides specialized bundlers for Apple platforms (Darwin App Bundler), Android (APK Bundler), Linux (Generic, AppImage, and RPM), and Windows (Generic and MSI). It supports scaffolding SwiftUI apps, generating Xcode support, and configuring Windows installers via WiX and TOML.

Tokens
19.3K
Snippets
104
Records
124
Agent score
65%

What's inside Swift Bundler

  1. Overview of Swift Bundler

    main

    Swift Bundler is a tool built on top of the Swift Package Manager (SPM) designed to enable cross-platform Swift development for macOS, iOS, tvOS, Linux, and Windows. It provides a consistent development experience across these platforms while allowing for platform-specific configurations.

    While Swift Bundler is framework-agnostic, it is highly recommended to use SwiftCrossUI for a native user experience across all supported platforms.

  2. Use the Generic Windows bundler

    main

    The genericWindows bundler is the default bundler when targeting Windows. It bundles your main executable, required dynamic libraries, and resources into a single flat directory.

    This is the recommended bundler for Windows development because it is fast and produces inspectable output. You can distribute applications created with this bundler by zipping the resulting directory, provided that users have the necessary system dependencies installed.

  3. Customize MSI installers using WXS in TOML

    main

    Swift Bundler uses WiX to create MSIs. You can customize the generated MSI by providing additional WXS configuration via the msi.wxs_extras field in your app's TOML configuration. These objects are appended to the generated project.wxs file (located at .build/bundler/apps/YourApp/project.wxs).

    WXS to TOML Mapping

    The msi.wxs_extras syntax mirrors WXS XML using TOML:

    • Elements $\rightarrow$ TOML tables (dictionaries).
    • XML Tag Name $\rightarrow$ The tag field.
    • Raw Text Content $\rightarrow$ The content field.
    • Child Elements $\rightarrow$ The children field.
    • Attributes $\rightarrow$ Standalone fields in the table.

    Example Conversion:

    XML:

    <Heart BPM="100">
      <Ventricle Side="left" Health="90%"></Ventricle>
      <Stent Age="5y">Bob's first stent</Stent>
    </Heart>

    TOML:

    [apps.YourApp]
    msi.wxs_extras = [
      {
        tag = "Heart",
        BPM = "100",
        children = [
          { tag = "Ventricle", Side = "left", Health = "90%" },
          { tag = "Stent", Age = "5y", content = "Bob's first stent" },
        ],
      },
    ]
  4. Available bundlers by platform

    main

    Swift Bundler provides specialized bundlers categorized by target operating system:

    Apple Platforms (Darwin)

    • Darwin App Bundler: For creating standard macOS/iOS/etc. app bundles.

    Android

    • APK Bundler: For generating Android application packages.

    Linux

    • Generic Linux Bundler: For standard Linux distributions.
    • AppImage Bundler: For creating portable Linux applications.
    • RPM Bundler: For Red Hat-based distributions.

    Windows

    • Generic Windows Bundler: For standard Windows executables.
    • MSI Bundler: For creating Windows Installer packages.
  5. Use the Base template for common files

    main

    You can create a directory named Base within your template repository. The Base directory acts as a foundation for all templates in that repository.

    • Application: The Base directory is applied first during the package creation process.
    • Use Case: Use it to store common files like .gitignore that should exist in every package regardless of the specific template used.
    • Overriding: A specific template can override files from the Base template by including files with the exact same name.
  6. Use overlays for platform-specific configuration

    main

    Overlays allow you to define configuration properties that only apply under certain conditions, such as a specific platform or bundler. Use the [[apps.AppName.overlays]] syntax with a condition key.

    Common conditions include:

    • platform(linux)
    • platform(macOS)
    • platform(macCatalyst)
    • bundler(linuxRPM)
    [[apps.HelloWorld.overlays]]
    condition = "platform(linux)"
    dbus_activatable = true
    url_schemes = ["hello", "hello-linux"]
    
    [[apps.HelloWorld.overlays]]
    condition = "platform(macCatalyst)"
    interface_idiom = "mac"
  7. Use variables in custom templates

    main

    When creating custom templates, you can use placeholders to dynamically inject package information into file contents and file paths.

    • File Paths: Any occurrence of {{VARIABLE}} in a file's relative path is replaced with the variable's value.
    • File Contents: For files ending with the .template extension, any occurrence of {{VARIABLE}} within the content is replaced, and the .template extension is stripped from the resulting file.

    Available Variables:

    • PACKAGE: The name of the package.
    • IDENTIFIER: The package's identifier (e.g., com.example.MyApp).
  8. Manage subprojects and custom builders

    main

    Subprojects are dependencies outside of SwiftPM (e.g., CMake projects). You define them in the [projects.ProjectName] section.

    • source: Can be local(path) or git(url). If using git, you must specify a revision.
    • builder: The name of the builder used to build this project.

    Projects can define multiple products:

    • type: Can be dynamicLibrary, staticLibrary, or executable.
    • output_directory: The directory within the build directory where the product is located (defaults to .).

    Builders are defined in the [builders.BuilderName] section. Currently, the only supported kind is wholeProject.

    [projects.cmakeproj]
    source = "local(./cmakeproj)"
    builder = "CMakeBuilder"
    
    [projects.cmakeproj.products.hello]
    type = "dynamicLibrary"
    output_directory = "."
    
    [builders.CMakeBuilder]
    product = "CMakeBuilder"
    kind = "wholeProject"
  9. Run your Android app on a device or emulator

    main

    You can deploy and run your Android application using the run command.

    • To run on a physical Android device, use the --device flag followed by the device name.
    • To run on an Android emulator, use the --simulator flag followed by the emulator name.
    # Run on a physical device
    swift-bundler run --device "Your Pixel 8a"
    
    # Run on an emulator
    swift-bundler run --simulator "Pixel 8a"
  10. Create a custom Swift Bundler template

    main

    To create a custom template, follow these steps to set up a template repository structure:

    1. Create a template repository: This is a parent directory containing multiple template directories.
    2. Create a template directory: Inside the repository, create a directory named after your template (e.g., MyTemplate). Note that Base is a reserved name and directory names must not start with a ..
    3. Configure Template.toml: Create a Template.toml file inside your template directory to define its metadata.
    4. Add template files: Add any files you want included in the generated package.

    Important Requirements:

    • Indentation: All files must use tabs (not spaces) for indentation. This ensures the create command's --indentation option works correctly.
    • Variables: You can use {{PACKAGE}} (the package name) and {{IDENTIFIER}} (the package identifier) within file contents and paths.
    • File Extensions: Files ending in .template will have their variables replaced and the .template extension removed in the final output.
    description = "My first package template."
    platforms = ["macOS", "iOS"] # Valid values: `macOS`, `iOS`