From d2507660c26a623bac3aab57c530ef2f7c1fc108 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Wed, 2 Jun 2021 20:02:45 +1000 Subject: [PATCH] [linux] Get CLI working. yum->dnf. doctor improvements. --- .../wails/internal/commands/doctor/doctor.go | 24 +- .../system/packagemanager/{yum.go => dnf.go} | 33 +-- .../system/packagemanager/packagemanager.go | 9 +- v2/pkg/commands/build/desktop_linux.go | 183 +++++++++++++- v2/pkg/commands/build/packager_linux.go | 237 ++++++++---------- 5 files changed, 327 insertions(+), 159 deletions(-) rename v2/internal/system/packagemanager/{yum.go => dnf.go} (77%) diff --git a/v2/cmd/wails/internal/commands/doctor/doctor.go b/v2/cmd/wails/internal/commands/doctor/doctor.go index 9fa98e16..ced0af84 100644 --- a/v2/cmd/wails/internal/commands/doctor/doctor.go +++ b/v2/cmd/wails/internal/commands/doctor/doctor.go @@ -25,11 +25,15 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error { app.PrintBanner() + logger.Print("Scanning system - Please wait (this may take a long time)...") + // Get system info info, err := system.GetInfo() if err != nil { + logger.Println("Failed.") return err } + logger.Println("Done.") // Start a new tabwriter w := new(tabwriter.Writer) @@ -116,6 +120,8 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error { if len(dependenciesMissing) == 0 && dependenciesAvailableRequired == 0 { logger.Println("Your system is ready for Wails development!") + } else { + logger.Println("Your system has missing dependencies!\n") } if dependenciesAvailableRequired != 0 { @@ -125,15 +131,15 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error { if dependenciesAvailableOptional != 0 { logger.Println("Optional package(s) installation details: \n" + info.Dependencies.InstallAllOptionalCommand()) } - - if len(externalPackages) > 0 { - for _, p := range externalPackages { - if p.Optional { - print("[Optional] ") - } - logger.Println("Install " + p.Name + ": " + p.InstallCommand) - } - } + // + //if len(externalPackages) > 0 { + // for _, p := range externalPackages { + // if p.Optional { + // print("[Optional] ") + // } + // logger.Println("Install " + p.Name + ": " + p.InstallCommand) + // } + //} if len(dependenciesMissing) != 0 { // TODO: Check if apps are available locally and if so, adjust the diagnosis diff --git a/v2/internal/system/packagemanager/yum.go b/v2/internal/system/packagemanager/dnf.go similarity index 77% rename from v2/internal/system/packagemanager/yum.go rename to v2/internal/system/packagemanager/dnf.go index de2d6d1c..b7a760f2 100644 --- a/v2/internal/system/packagemanager/yum.go +++ b/v2/internal/system/packagemanager/dnf.go @@ -9,23 +9,23 @@ import ( "github.com/wailsapp/wails/v2/internal/shell" ) -// Yum represents the Yum manager -type Yum struct { +// Dnf represents the Dnf manager +type Dnf struct { name string osid string } -// NewYum creates a new Yum instance -func NewYum(osid string) *Yum { - return &Yum{ - name: "yum", +// NewDnf creates a new Dnf instance +func NewDnf(osid string) *Dnf { + return &Dnf{ + name: "dnf", osid: osid, } } // Packages returns the libraries that we need for Wails to compile // They will potentially differ on different distributions or versions -func (y *Yum) Packages() packagemap { +func (y *Dnf) Packages() packagemap { return packagemap{ "libgtk-3": []*Package{ {Name: "gtk3-devel", SystemPackage: true, Library: true}, @@ -43,6 +43,9 @@ func (y *Yum) Packages() packagemap { "npm": []*Package{ {Name: "npm", SystemPackage: true}, }, + "upx": []*Package{ + {Name: "upx", SystemPackage: true, Optional: true}, + }, "docker": []*Package{ { SystemPackage: false, @@ -57,16 +60,16 @@ func (y *Yum) Packages() packagemap { } // Name returns the name of the package manager -func (y *Yum) Name() string { +func (y *Dnf) Name() string { return y.name } // PackageInstalled tests if the given package name is installed -func (y *Yum) PackageInstalled(pkg *Package) (bool, error) { +func (y *Dnf) PackageInstalled(pkg *Package) (bool, error) { if pkg.SystemPackage == false { return false, nil } - stdout, _, err := shell.RunCommand(".", "yum", "info", "installed", pkg.Name) + stdout, _, err := shell.RunCommand(".", "dnf", "info", "installed", pkg.Name) if err != nil { _, ok := err.(*exec.ExitError) if ok { @@ -87,11 +90,11 @@ func (y *Yum) PackageInstalled(pkg *Package) (bool, error) { } // PackageAvailable tests if the given package is available for installation -func (y *Yum) PackageAvailable(pkg *Package) (bool, error) { +func (y *Dnf) PackageAvailable(pkg *Package) (bool, error) { if pkg.SystemPackage == false { return false, nil } - stdout, _, err := shell.RunCommand(".", "yum", "info", pkg.Name) + stdout, _, err := shell.RunCommand(".", "dnf", "info", pkg.Name) // We add a space to ensure we get a full match, not partial match if err != nil { _, ok := err.(*exec.ExitError) @@ -111,14 +114,14 @@ func (y *Yum) PackageAvailable(pkg *Package) (bool, error) { } // InstallCommand returns the package manager specific command to install a package -func (y *Yum) InstallCommand(pkg *Package) string { +func (y *Dnf) InstallCommand(pkg *Package) string { if pkg.SystemPackage == false { return pkg.InstallCommand[y.osid] } - return "sudo yum install " + pkg.Name + return "sudo dnf install " + pkg.Name } -func (y *Yum) getPackageVersion(pkg *Package, output string) { +func (y *Dnf) getPackageVersion(pkg *Package, output string) { splitOutput := strings.Split(output, " ") if len(splitOutput) > 0 { pkg.Version = splitOutput[1] diff --git a/v2/internal/system/packagemanager/packagemanager.go b/v2/internal/system/packagemanager/packagemanager.go index 10c884a8..7e15594a 100644 --- a/v2/internal/system/packagemanager/packagemanager.go +++ b/v2/internal/system/packagemanager/packagemanager.go @@ -9,12 +9,11 @@ import ( "github.com/wailsapp/wails/v2/internal/shell" ) - // A list of package manager commands var pmcommands = []string{ "eopkg", "apt", - "yum", + "dnf", "pacman", "emerge", "zypper", @@ -38,8 +37,8 @@ func newPackageManager(pmname string, osid string) PackageManager { return NewEopkg(osid) case "apt": return NewApt(osid) - case "yum": - return NewYum(osid) + case "dnf": + return NewDnf(osid) case "pacman": return NewPacman(osid) case "emerge": @@ -77,7 +76,7 @@ func Dependancies(p PackageManager) (DependencyList, error) { if installed { dependency.Installed = true dependency.Version = pkg.Version - if !pkg.Library { + if !pkg.SystemPackage { dependency.Version = AppVersion(name) } } else { diff --git a/v2/pkg/commands/build/desktop_linux.go b/v2/pkg/commands/build/desktop_linux.go index 2c8fee12..1ad17de8 100644 --- a/v2/pkg/commands/build/desktop_linux.go +++ b/v2/pkg/commands/build/desktop_linux.go @@ -33,7 +33,10 @@ func (d *DesktopBuilder) compileIcon(assetDir string, iconFile string) error { if err != nil { return err } - f.Close() + err = f.Close() + if err != nil { + return err + } var buf strings.Builder @@ -52,3 +55,181 @@ func (d *DesktopBuilder) compileIcon(assetDir string, iconFile string) error { return err } + +// We will compile all tray icons found at /assets/trayicons/*.png into the application +func (d *DesktopBuilder) processTrayIcons(assetDir string, options *Options) error { + // + // var err error + // + // // Get all the tray icon filenames + // trayIconDirectory := filepath.Join(options.ProjectData.BuildDir, "tray") + // + // // If the directory doesn't exist, create it + // if !fs.DirExists(trayIconDirectory) { + // err = fs.MkDirs(trayIconDirectory) + // if err != nil { + // return err + // } + // } + // + // var trayIconFilenames []string + // trayIconFilenames, err = filepath.Glob(trayIconDirectory + "/*.png") + // if err != nil { + // log.Fatal(err) + // return err + // } + // + // // Setup target + // targetFilename := "trayicons" + // targetFile := filepath.Join(assetDir, targetFilename+".h") + // d.addFileToDelete(targetFile) + // + // var dataBytes []byte + // + // // Use a strings builder + // var cdata strings.Builder + // + // // Write header + // header := `// trayicons.h + //// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL. + //// This file was auto-generated. DO NOT MODIFY. + // + //` + // cdata.WriteString(header) + // + // var variableList slicer.StringSlicer + // + // // Loop over icons + // for count, filename := range trayIconFilenames { + // + // // Load the tray icon + // dataBytes, err = ioutil.ReadFile(filename) + // if err != nil { + // return err + // } + // + // iconname := strings.TrimSuffix(filepath.Base(filename), ".png") + // trayIconName := fmt.Sprintf("trayIcon%dName", count) + // variableList.Add(trayIconName) + // cdata.WriteString(fmt.Sprintf("const unsigned char %s[] = { %s0x00 };\n", trayIconName, d.convertToHexLiteral([]byte(iconname)))) + // + // trayIconLength := fmt.Sprintf("trayIcon%dLength", count) + // variableList.Add(trayIconLength) + // lengthAsString := strconv.Itoa(len(dataBytes)) + // cdata.WriteString(fmt.Sprintf("const unsigned char %s[] = { %s0x00 };\n", trayIconLength, d.convertToHexLiteral([]byte(lengthAsString)))) + // + // trayIconData := fmt.Sprintf("trayIcon%dData", count) + // variableList.Add(trayIconData) + // cdata.WriteString(fmt.Sprintf("const unsigned char %s[] = { ", trayIconData)) + // + // // Convert each byte to hex + // for _, b := range dataBytes { + // cdata.WriteString(fmt.Sprintf("0x%x, ", b)) + // } + // + // cdata.WriteString("0x00 };\n") + // } + // + // // Write out main trayIcons data + // cdata.WriteString("const unsigned char *trayIcons[] = { ") + // cdata.WriteString(variableList.Join(", ")) + // if len(trayIconFilenames) > 0 { + // cdata.WriteString(", ") + // } + // cdata.WriteString("0x00 };\n") + // + // err = ioutil.WriteFile(targetFile, []byte(cdata.String()), 0600) + // if err != nil { + // return err + // } + return nil +} + +// We will compile all dialog icons found at /icons/dialog/*.png into the application +func (d *DesktopBuilder) processDialogIcons(assetDir string, options *Options) error { + + // var err error + // + // // Get all the dialog icon filenames + // dialogIconDirectory := filepath.Join(options.ProjectData.BuildDir, "dialog") + // var dialogIconFilenames []string + // + // // If the directory does not exist, create it + // if !fs.DirExists(dialogIconDirectory) { + // err = fs.MkDirs(dialogIconDirectory) + // if err != nil { + // return err + // } + // } + // + // dialogIconFilenames, err = filepath.Glob(dialogIconDirectory + "/*.png") + // if err != nil { + // log.Fatal(err) + // return err + // } + // + // // Setup target + // targetFilename := "userdialogicons" + // targetFile := filepath.Join(assetDir, targetFilename+".h") + // d.addFileToDelete(targetFile) + // + // var dataBytes []byte + // + // // Use a strings builder + // var cdata strings.Builder + // + // // Write header + // header := `// userdialogicons.h + //// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL. + //// This file was auto-generated. DO NOT MODIFY. + // + //` + // cdata.WriteString(header) + // + // var variableList slicer.StringSlicer + // + // // Loop over icons + // for count, filename := range dialogIconFilenames { + // + // // Load the tray icon + // dataBytes, err = ioutil.ReadFile(filename) + // if err != nil { + // return err + // } + // + // iconname := strings.TrimSuffix(filepath.Base(filename), ".png") + // dialogIconName := fmt.Sprintf("userDialogIcon%dName", count) + // variableList.Add(dialogIconName) + // cdata.WriteString(fmt.Sprintf("const unsigned char %s[] = { %s0x00 };\n", dialogIconName, d.convertToHexLiteral([]byte(iconname)))) + // + // dialogIconLength := fmt.Sprintf("userDialogIcon%dLength", count) + // variableList.Add(dialogIconLength) + // lengthAsString := strconv.Itoa(len(dataBytes)) + // cdata.WriteString(fmt.Sprintf("const unsigned char %s[] = { %s0x00 };\n", dialogIconLength, d.convertToHexLiteral([]byte(lengthAsString)))) + // + // dialogIconData := fmt.Sprintf("userDialogIcon%dData", count) + // variableList.Add(dialogIconData) + // cdata.WriteString(fmt.Sprintf("const unsigned char %s[] = { ", dialogIconData)) + // + // // Convert each byte to hex + // for _, b := range dataBytes { + // cdata.WriteString(fmt.Sprintf("0x%x, ", b)) + // } + // + // cdata.WriteString("0x00 };\n") + // } + // + // // Write out main dialogIcons data + // cdata.WriteString("const unsigned char *userDialogIcons[] = { ") + // cdata.WriteString(variableList.Join(", ")) + // if len(dialogIconFilenames) > 0 { + // cdata.WriteString(", ") + // } + // cdata.WriteString("0x00 };\n") + // + // err = ioutil.WriteFile(targetFile, []byte(cdata.String()), 0600) + // if err != nil { + // return err + // } + return nil +} diff --git a/v2/pkg/commands/build/packager_linux.go b/v2/pkg/commands/build/packager_linux.go index df16209a..61436eb7 100644 --- a/v2/pkg/commands/build/packager_linux.go +++ b/v2/pkg/commands/build/packager_linux.go @@ -1,134 +1,113 @@ package build -import ( - "io/ioutil" - "os" - "path/filepath" - "strings" - - "github.com/leaanthony/slicer" - "github.com/wailsapp/wails/v2/internal/fs" - "github.com/wailsapp/wails/v2/internal/shell" -) - -func deleteLinuxPackFiles(appDirBase string) { - // Delete appdir - appDir := filepath.Join(appDirBase, "AppDir") - os.RemoveAll(appDir) -} - -func packageApplication(options *Options) error { - - // Check we have AppImage tools - - // Create AppImage build directory - buildDirectory, err := getApplicationBuildDirectory(options, "linux") - if err != nil { - return err - } - - defer deleteLinuxPackFiles(buildDirectory) - - // Get the name of the application and ensure we lower+kebab case it - name := filepath.Base(options.ProjectData.OutputFilename) - - // Calculate asset directory - assetDir := getPackageAssetsDirectory() - - // Copy default icon if one doesn't exist - baseBuildDirectory, err := getBuildBaseDirectory(options) - if err != nil { - return err - } - iconFile := filepath.Join(baseBuildDirectory, "icon.png") - if !fs.FileExists(iconFile) { - err = fs.CopyFile(defaultIconPath(), iconFile) - if err != nil { - return err - } - } - - // Copy Icon - targetIcon := filepath.Join(buildDirectory, name+".png") - err = fs.CopyFile(iconFile, targetIcon) - if err != nil { - return err - } - - // Copy app.desktop - dotDesktopFile := filepath.Join(baseBuildDirectory, "linux", name+".desktop") - if !fs.FileExists(dotDesktopFile) { - bytes, err := ioutil.ReadFile(filepath.Join(assetDir, "app.desktop")) - if err != nil { - return err - } - appDesktop := string(bytes) - appDesktop = strings.ReplaceAll(appDesktop, `{{.Name}}`, name) - err = ioutil.WriteFile(dotDesktopFile, []byte(appDesktop), 0644) - if err != nil { - return err - } - } - - // Copy AppRun file - // targetFilename = filepath.Join(buildDirectory, "AppRun") - // if !fs.FileExists(targetFilename) { - // bytes, err := ioutil.ReadFile(filepath.Join(assetDir, "AppRun")) - // if err != nil { - // return err - // } - // appRun := string(bytes) - // appRun = strings.ReplaceAll(appRun, `{{.OutputFilename}}`, name) - - // err = ioutil.WriteFile(targetFilename, []byte(appRun), 0644) - // if err != nil { - // return err - // } - // } - - // Copy Binary - sourceFile := filepath.Join(options.ProjectData.Path, options.ProjectData.OutputFilename) - targetFile := filepath.Join(buildDirectory, options.ProjectData.OutputFilename) - err = fs.CopyFile(sourceFile, targetFile) - if err != nil { - return err - } - err = os.Chmod(targetFile, 0777) - if err != nil { - return err - } - - /** Pack App **/ - - // Make file executable - // Set environment variable: OUTPUT=outputfilename - command := shell.NewCommand("linuxdeploy-x86_64.AppImage") - command.Dir(buildDirectory) - - argslice := slicer.String() - argslice.Add("--appdir", "AppDir") - argslice.Add("-d", filepath.Join("..", name+".desktop")) - argslice.Add("-i", name+".png") - argslice.Add("-e", name) - argslice.Add("--output", "appimage") - command.AddArgs(argslice.AsSlice()) - - command.Env("OUTPUT", name+".AppImage") - - err = command.Run() - if err != nil { - println(command.Stdout()) - println(command.Stderr()) - return err - } - - // Copy app to project dir - - println(buildDirectory) +func packageApplication(_ *Options) error { + // + //// Check we have AppImage tools + // + //// Create AppImage build directory + //buildDirectory, err := getApplicationBuildDirectory(options, "linux") + //if err != nil { + // return err + //} + // + //defer deleteLinuxPackFiles(buildDirectory) + // + //// Get the name of the application and ensure we lower+kebab case it + //name := filepath.Base(options.ProjectData.OutputFilename) + // + //// Calculate asset directory + //assetDir := getPackageAssetsDirectory() + // + //// Copy default icon if one doesn't exist + //baseBuildDirectory, err := getBuildBaseDirectory(options) + //if err != nil { + // return err + //} + //iconFile := filepath.Join(baseBuildDirectory, "icon.png") + //if !fs.FileExists(iconFile) { + // err = fs.CopyFile(defaultIconPath(), iconFile) + // if err != nil { + // return err + // } + //} + // + //// Copy Icon + //targetIcon := filepath.Join(buildDirectory, name+".png") + //err = fs.CopyFile(iconFile, targetIcon) + //if err != nil { + // return err + //} + // + //// Copy app.desktop + //dotDesktopFile := filepath.Join(baseBuildDirectory, "linux", name+".desktop") + //if !fs.FileExists(dotDesktopFile) { + // bytes, err := ioutil.ReadFile(filepath.Join(assetDir, "app.desktop")) + // if err != nil { + // return err + // } + // appDesktop := string(bytes) + // appDesktop = strings.ReplaceAll(appDesktop, `{{.Name}}`, name) + // err = ioutil.WriteFile(dotDesktopFile, []byte(appDesktop), 0644) + // if err != nil { + // return err + // } + //} + // + //// Copy AppRun file + //// targetFilename = filepath.Join(buildDirectory, "AppRun") + //// if !fs.FileExists(targetFilename) { + //// bytes, err := ioutil.ReadFile(filepath.Join(assetDir, "AppRun")) + //// if err != nil { + //// return err + //// } + //// appRun := string(bytes) + //// appRun = strings.ReplaceAll(appRun, `{{.OutputFilename}}`, name) + // + //// err = ioutil.WriteFile(targetFilename, []byte(appRun), 0644) + //// if err != nil { + //// return err + //// } + //// } + // + //// Copy Binary + //sourceFile := filepath.Join(options.ProjectData.Path, options.ProjectData.OutputFilename) + //targetFile := filepath.Join(buildDirectory, options.ProjectData.OutputFilename) + //err = fs.CopyFile(sourceFile, targetFile) + //if err != nil { + // return err + //} + //err = os.Chmod(targetFile, 0777) + //if err != nil { + // return err + //} + // + ///** Pack App **/ + // + //// Make file executable + //// Set environment variable: OUTPUT=outputfilename + //command := shell.NewCommand("linuxdeploy-x86_64.AppImage") + //command.Dir(buildDirectory) + // + //argslice := slicer.String() + //argslice.Add("--appdir", "AppDir") + //argslice.Add("-d", filepath.Join("..", name+".desktop")) + //argslice.Add("-i", name+".png") + //argslice.Add("-e", name) + //argslice.Add("--output", "appimage") + //command.AddArgs(argslice.AsSlice()) + // + //command.Env("OUTPUT", name+".AppImage") + // + //err = command.Run() + //if err != nil { + // println(command.Stdout()) + // println(command.Stderr()) + // return err + //} + // + //// Copy app to project dir + // + //println(buildDirectory) return nil } - -func deleteDirectory(directory string) { - os.RemoveAll(directory) -}