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

RPM Packaging support #3265

Open
wants to merge 6 commits into
base: v3-alpha
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions v3/cmd/wails3/main.go
Expand Up @@ -46,6 +46,7 @@ func main() {
generate.NewSubCommandFunction("constants", "Generate JS constants from Go", commands.GenerateConstants)
generate.NewSubCommandFunction(".desktop", "Generate .desktop file", commands.GenerateDotDesktop)
generate.NewSubCommandFunction("appimage", "Generate Linux AppImage", commands.GenerateAppImage)
generate.NewSubCommandFunction("rpm", "Generate Linux RPM", commands.GenerateRPM)
generate.NewSubCommandFunction("runtime", "Generate the latest compiled runtime", commands.GenerateRuntime)

plugin := app.NewSubCommand("plugin", "Plugin tools")
Expand Down
40 changes: 40 additions & 0 deletions v3/internal/commands/build_assets/rpm/app.spec
@@ -0,0 +1,40 @@
%global debug_package %{nil}

Name: @NAME@
Summary: @SUMMARY@
Version: @VERSION@
Release: 1%{?dist}
License: MIT

Source0: %{name}
Source1: %{name}.desktop
Source2: %{name}.png

%description
@DESCRIPTION@

%install
mkdir -p %{buildroot}%{_bindir} %{buildroot}%{_datadir}/{applications,pixmaps}

cp %{SOURCE0} %{buildroot}%{_bindir}/%{name}
cp %{SOURCE1} %{buildroot}%{_datadir}/applications/%{name}.desktop
cp %{SOURCE2} %{buildroot}%{_datadir}/pixmaps/%{name}.png

%post
# Install the desktop entry
update-desktop-database &> /dev/null || :

%postun
# Uninstall the desktop entry
update-desktop-database &> /dev/null || :


%files
%{_bindir}/%{name}
%{_datadir}/applications/%{name}.desktop
%{_datadir}/pixmaps/%{name}.png


%changelog
* Sat Feb 17 2024 @AUTHOR@ <@AUTHOR_EMAIL@> - %{version}-1
- Initial build
84 changes: 84 additions & 0 deletions v3/internal/commands/rpm.go
@@ -0,0 +1,84 @@
package commands

import (
_ "embed"
"errors"
"fmt"
"github.com/pterm/pterm"
"github.com/wailsapp/wails/v3/internal/s"
"os"
"path/filepath"
)

type GenerateRPMOptions struct {
Binary string `description:"The binary to package including path"`
Icon string `description:"Path to the icon"`
DesktopFile string `description:"Path to the desktop file"`
OutputDir string `description:"Path to the output directory" default:"."`
BuildDir string `description:"Path to the build directory"`
}

func GenerateRPM(options *GenerateRPMOptions) error {

defer func() {
pterm.DefaultSpinner.Stop()
}()

if options.Binary == "" {
return fmt.Errorf("binary not provided")
}
if options.Icon == "" {
return fmt.Errorf("icon path not provided")
}
if options.DesktopFile == "" {
return fmt.Errorf("desktop file path not provided")
}
if options.BuildDir == "" {
// Create temp directory
var err error
options.BuildDir, err = os.MkdirTemp("", "wails-rpm-*")
if err != nil {
return err
}
}
var err error
options.OutputDir, err = filepath.Abs(options.OutputDir)
if err != nil {
return err
}

pterm.Println(pterm.LightYellow("RPM Generator v1.0.0"))

return generateRPM(options)
}

func generateRPM(options *GenerateRPMOptions) error {
numberOfSteps := 5
p, _ := pterm.DefaultProgressbar.WithTotal(numberOfSteps).WithTitle("Generating RPM").Start()

// Get the last path of the binary and normalise the name
name := normaliseName(filepath.Base(options.Binary))

log(p, "Preparing RPMBUILD Directory: "+options.BuildDir)

sources := filepath.Join(options.BuildDir, "SOURCES")
s.MKDIR(sources)
s.COPY(options.Binary, sources)
s.COPY(options.DesktopFile, sources)
s.COPY(filepath.Join(options.BuildDir, name+".png"), sources)
s.CHMOD(filepath.Join(sources, filepath.Base(options.Binary)), 0755)

// Build RPM
if !s.EXISTS("/usr/bin/rpmbuild") {
return errors.New("You need to install \"rpm-build\" tool to build RPM.")
}
log(p, fmt.Sprintf("Running rpmbuild -bb --define \"_rpmdir %s\" --define \"_sourcedir %s\" %s.spec", options.BuildDir, sources, name))
_, err := s.EXEC(fmt.Sprintf("rpmbuild -bb --define \"_rpmdir %s\" --define \"_sourcedir %s\" %s.spec", options.BuildDir, sources, name))
if err != nil {
fmt.Println(err.Error())
return err
}

log(p, "RPM created.")
return nil
}
3 changes: 3 additions & 0 deletions v3/internal/doctor/packagemanager/dnf.go
Expand Up @@ -43,6 +43,9 @@ func (y *Dnf) Packages() Packagemap {
{Name: "npm", SystemPackage: true},
{Name: "nodejs-npm", SystemPackage: true},
},
"rpm-build": []*Package{
{Name: "rpm-build", SystemPackage: true, Optional: true},
},
}
}

Expand Down
46 changes: 43 additions & 3 deletions v3/internal/templates/_common/Taskfile.tmpl.yml
Expand Up @@ -286,6 +286,7 @@ tasks:
vars:
PRODUCTION: "true"
cmds:
- task: create:rpm
- task: create:appimage

create:appimage:
Expand All @@ -300,7 +301,7 @@ tasks:
cmds:
# Copy binary + icon to appimage dir
- cp {{ "{{.APP_BINARY}}" }} {{ "{{.APP_NAME}}" }}
- cp ../appicon.png appicon.png
- cp ../appicon.png '{{ "{{.APP_NAME}}" }}'.png
# Generate AppImage
- wails3 generate appimage -binary {{ "{{.APP_NAME}}" }} -icon {{ "{{.ICON}}" }} -desktopfile {{ "{{.DESKTOP_FILE}}" }} -outputdir {{ "{{.OUTPUT_DIR}}" }} -builddir {{ "{{.ROOT_DIR}}" }}/build/appimage
vars:
Expand All @@ -310,17 +311,56 @@ tasks:
DESKTOP_FILE: '{{ "{{.APP_NAME}}" }}.desktop'
OUTPUT_DIR: '../../bin'

create:rpm:
summary: Creates a RPM package
dir: build/rpm
platforms: [ linux ]
deps:
- task: build:linux
vars:
PRODUCTION: "true"
- task: generate:linux:dotdesktop
cmds:
# Copy binary + icon to rpmbuild dir
- cp {{ "{{.APP_BINARY}}" }} {{ "{{.APP_NAME}}" }}
- cp ../appicon.png '{{ "{{.APP_NAME}}" }}'.png
- cp ../rpm/app.spec '{{ "{{.APP_NAME}}" }}'.spec
- sed -i -e 's/@NAME@/{{ "{{.APP_NAME}}" }}/g'
-e 's/@SUMMARY@/{{ "{{.APP_SUMMARY}}" }}/g'
-e 's/@VERSION@/{{ "{{.APP_VERSION}}" }}/g'
-e 's/@DESCRIPTION@/{{ "{{.APP_DESC}}" }}/g'
-e 's/@AUTHOR@/{{ "{{.APP_AUTHOR}}" }}/g'
-e 's/@AUTHOR_EMAIL@/{{ "{{.AUTHOR_EMAIL}}" }}/g'
{{ "{{.APP_NAME}}" }}.spec
# Generate RPM
- wails3 generate rpm -binary {{ "{{.APP_NAME}}" }} -icon {{ "{{.ICON}}" }} -desktopfile {{ "{{.DESKTOP_FILE}}" }} -outputdir {{ "{{.OUTPUT_DIR}}" }} -builddir {{ "{{.ROOT_DIR}}" }}/build/rpm
- mv {{ "{{.ROOT_DIR}}" }}/build/rpm/$(uname -m)/*.rpm {{ "{{.OUTPUT_DIR}}" }}
vars:
APP_NAME: '{{ "{{.APP_NAME}}" }}'
istiak101 marked this conversation as resolved.
Show resolved Hide resolved
APP_SUMMARY: 'Hello Wails'
APP_VERSION: '1.0.0'
APP_DESC: 'Hello Wails is demo application developed on Wails.'
APP_URL: 'https://github.com/wailsapp/wails'
APP_AUTHOR: "Lea Anthony"
AUTHOR_EMAIL: "[email protected]"
APP_BINARY: '../../bin/{{ "{{.APP_NAME}}" }}'
ICON: '../appicon.png'
DESKTOP_FILE: '{{ "{{.APP_NAME}}" }}.desktop'
OUTPUT_DIR: '../../bin'

generate:linux:dotdesktop:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be worth passing in the subdirectory to this task rather than doing both. An example of this:

  build-app-prod-darwin:
    summary: Creates a production build of the application
    cmds:
      - task: pre-build
      - task: build-frontend
      - GOOS=darwin GOARCH={{ "{{.ARCH}}" }} go build -tags production -ldflags="-w -s" -o build/bin/{{ "{{.APP_NAME}}" }}
      - task: post-build
    env:
      CGO_CFLAGS: "-mmacosx-version-min=10.13"
      CGO_LDFLAGS: "-mmacosx-version-min=10.13"
      MACOSX_DEPLOYMENT_TARGET: "10.13"
    vars:
      ARCH: $GOARCH

Call with:

  package-darwin-arm64:
    summary: Packages a production build of the application into a `.app` bundle
    platform: darwin
    deps:
      - task: build-app-prod-darwin
        vars:
            ARCH: arm64
      - generate-icons
    cmds:
      - task: create-app-bundle

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure what do you mean. I am quite dumb to be honest. Do you want me to generate rpm separately?

summary: Generates a `.desktop` file
dir: build
sources:
- "appicon.png"
generates:
- '{{ "{{.ROOT_DIR}}"}}/build/appimage/{{ "{{.APP_NAME}}" }}.desktop'
- '{{ "{{.ROOT_DIR}}"}}/build/rpm/{{ "{{.APP_NAME}}" }}.desktop'
cmds:
- mkdir -p {{ "{{.ROOT_DIR}}"}}/build/appimage
- mkdir -p {{ "{{.ROOT_DIR}}"}}/build/{appimage,rpm}
# Run `wails3 generate .desktop -help` for all the options
- wails3 generate .desktop -name "{{ "{{.APP_NAME}}" }}" -exec "{{ "{{.EXEC}}" }}" -icon "{{ "{{.ICON}}" }}" -outputfile {{ "{{.ROOT_DIR}}"}}/build/appimage/{{ "{{.APP_NAME}}" }}.desktop -categories "{{ "{{.CATEGORIES}}" }}"
- wails3 generate .desktop -name "{{ "{{.APP_NAME}}" }}" -exec "{{ "{{.EXEC}}" }}" -icon "{{ "{{.ICON}}" }}" -outputfile {{ "{{.ROOT_DIR}}"}}/build/rpm/{{ "{{.APP_NAME}}" }}.desktop -categories "{{ "{{.CATEGORIES}}" }}"
# -comment "A comment"
# -terminal "true"
# -version "1.0"
Expand All @@ -332,7 +372,7 @@ tasks:
vars:
APP_NAME: '{{ "{{.APP_NAME}}" }}'
EXEC: '{{ "{{.APP_NAME}}" }}'
ICON: 'appicon'
ICON: '{{ "{{.APP_NAME}}" }}'
CATEGORIES: 'Development;'
OUTPUTFILE: '{{ "{{.ROOT_DIR}}"}}/build/appimage/{{ "{{.APP_NAME}}" }}.desktop'

Expand Down
1 change: 1 addition & 0 deletions website/src/pages/changelog.mdx
Expand Up @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add Apple Silicon hardware detection to `wails doctor`. Changed by @almas1992 in [PR](https://github.com/wailsapp/wails/pull/3129)
- Remove quarantine attribute on macOS binaries. Changed by @leaanthony in [PR](https://github.com/wailsapp/wails/pull/3118)
- Added documentation for a common GStreamer error on Linux systems. Changed by [@mkwsnyder](https://github.com/mkwsnyder) in [PR](https://github.com/wailsapp/wails/pull/3134)
- Added RPM packaging support. Added by @istiak101 in [PR](https://github.com/wailsapp/wails/pull/3265)

### Fixed
- Docs for IsZoomControlEnabled and ZoomFactor. Fixed by @leaanthony in [PR](https://github.com/wailsapp/wails/pull/3137)
Expand Down