From aac59c640702c6a20a438fadc27e2cb67805e67e Mon Sep 17 00:00:00 2001 From: jld3103 Date: Thu, 3 Oct 2019 12:24:44 +0200 Subject: [PATCH 1/2] Add support for darwin-bundle --- cmd/build.go | 17 ++++ cmd/packaging.go | 12 +++ cmd/packaging/darwin-bundle.go | 150 +++++++++++++++++++++++++++++++++ cmd/packaging/packaging.go | 5 ++ 4 files changed, 184 insertions(+) create mode 100644 cmd/packaging/darwin-bundle.go diff --git a/cmd/build.go b/cmd/build.go index c93027dc..22e2a589 100644 --- a/cmd/build.go +++ b/cmd/build.go @@ -52,6 +52,7 @@ func init() { buildCmd.AddCommand(buildLinuxSnapCmd) buildCmd.AddCommand(buildLinuxDebCmd) buildCmd.AddCommand(buildDarwinCmd) + buildCmd.AddCommand(buildDarwinBundleCmd) buildCmd.AddCommand(buildWindowsCmd) rootCmd.AddCommand(buildCmd) } @@ -113,6 +114,22 @@ var buildDarwinCmd = &cobra.Command{ }, } +var buildDarwinBundleCmd = &cobra.Command{ + Use: "darwin-bundle", + Short: "Build a desktop release for darwin and package it for OSX bundle", + Run: func(cmd *cobra.Command, args []string) { + assertHoverInitialized() + packaging.AssertPackagingFormatInitialized("darwin-bundle") + + if !packaging.DockerInstalled() { + os.Exit(1) + } + + buildNormal("darwin", nil) + packaging.BuildDarwinBundle() + }, +} + var buildWindowsCmd = &cobra.Command{ Use: "windows", Short: "Build a desktop release for windows", diff --git a/cmd/packaging.go b/cmd/packaging.go index 4c307d79..990646ee 100644 --- a/cmd/packaging.go +++ b/cmd/packaging.go @@ -9,6 +9,7 @@ import ( func init() { initPackagingCmd.AddCommand(initLinuxSnapCmd) initPackagingCmd.AddCommand(initLinuxDebCmd) + initPackagingCmd.AddCommand(initDarwinBundleCmd) rootCmd.AddCommand(initPackagingCmd) } @@ -38,3 +39,14 @@ var initLinuxDebCmd = &cobra.Command{ packaging.InitLinuxDeb() }, } + +var initDarwinBundleCmd = &cobra.Command{ + Use: "darwin-bundle", + Short: "Create configuration files for OSX bundle packaging", + Run: func(cmd *cobra.Command, args []string) { + assertHoverInitialized() + packaging.DockerInstalled() + + packaging.InitDarwinBundle() + }, +} diff --git a/cmd/packaging/darwin-bundle.go b/cmd/packaging/darwin-bundle.go new file mode 100644 index 00000000..37ba6c38 --- /dev/null +++ b/cmd/packaging/darwin-bundle.go @@ -0,0 +1,150 @@ +package packaging + +import ( + "github.com/otiai10/copy" + "os" + "path/filepath" + + "github.com/go-flutter-desktop/hover/internal/build" + "github.com/go-flutter-desktop/hover/internal/log" + "github.com/go-flutter-desktop/hover/internal/pubspec" +) + +func InitDarwinBundle() { + projectName := pubspec.GetPubSpec().Name + packagingFormat := "darwin-bundle" + createPackagingFormatDirectory(packagingFormat) + bundleDirectoryPath := packagingFormatPath(packagingFormat) + bundleContentsDirectoryPath, err := filepath.Abs(filepath.Join(bundleDirectoryPath, projectName+".app", "Contents")) + if err != nil { + log.Errorf("Failed to resolve absolute path for Contents directory: %v", err) + os.Exit(1) + } + err = os.MkdirAll(bundleContentsDirectoryPath, 0775) + if err != nil { + log.Errorf("Failed to create Contents directory %s: %v", bundleContentsDirectoryPath, err) + os.Exit(1) + } + bundleMacOSDirectoryPath, err := filepath.Abs(filepath.Join(bundleContentsDirectoryPath, "MacOS")) + if err != nil { + log.Errorf("Failed to resolve absolute path for MacOS directory: %v", err) + os.Exit(1) + } + err = os.MkdirAll(bundleMacOSDirectoryPath, 0775) + if err != nil { + log.Errorf("Failed to create MacOS directory %s: %v", bundleMacOSDirectoryPath, err) + os.Exit(1) + } + bundleResourcesDirectoryPath, err := filepath.Abs(filepath.Join(bundleContentsDirectoryPath, "Resources")) + if err != nil { + log.Errorf("Failed to resolve absolute path for Resources directory: %v", err) + os.Exit(1) + } + err = os.MkdirAll(bundleResourcesDirectoryPath, 0775) + if err != nil { + log.Errorf("Failed to create Resources directory %s: %v", bundleResourcesDirectoryPath, err) + os.Exit(1) + } + + infoFilePath, err := filepath.Abs(filepath.Join(bundleContentsDirectoryPath, "Info.plist")) + if err != nil { + log.Errorf("Failed to resolve absolute path for Info.plist file %s: %v", infoFilePath, err) + os.Exit(1) + } + + infoFile, err := os.Create(infoFilePath) + if err != nil { + log.Errorf("Failed to create Info.plist file %s: %v", infoFilePath, err) + os.Exit(1) + } + infoFileContent := []string{ + ``, + ``, + ``, + ``, + ` CFBundleDevelopmentRegion`, + ` English`, + ` CFBundleExecutable`, + ` ` + projectName + ``, + ` CFBundleGetInfoString`, + ` ` + projectName + ``, + ` CFBundleIconFile`, + ` icon.icns`, + ` CFBundleIdentifier`, + ` `, + ` CFBundleInfoDictionaryVersion`, + ` 6.0`, + ` CFBundleLongVersionString`, + ` `, + ` CFBundleName`, + ` `, + ` CFBundlePackageType`, + ` APPL`, + ` CFBundleShortVersionString`, + ` `, + ` CFBundleSignature`, + ` ????`, + ` CFBundleVersion`, + ` `, + ` CSResourcesFileMapped`, + ` `, + ` NSHumanReadableCopyright`, + ` `, + ``, + ``, + } + + for _, line := range infoFileContent { + if _, err := infoFile.WriteString(line + "\n"); err != nil { + log.Errorf("Could not write Info.plist file: %v", err) + os.Exit(1) + } + } + err = infoFile.Close() + if err != nil { + log.Errorf("Could not close Info.plist file: %v", err) + os.Exit(1) + } + createDockerfile(packagingFormat) + + printInitFinished(packagingFormat) +} + +func BuildDarwinBundle() { + projectName := pubspec.GetPubSpec().Name + packagingFormat := "darwin-bundle" + tmpPath := getTemporaryBuildDirectory(projectName, packagingFormat) + log.Infof("Packaging bundle in %s", tmpPath) + + err := copy.Copy(build.OutputDirectoryPath("darwin"), filepath.Join(tmpPath, projectName+".app", "Contents", "MacOS")) + if err != nil { + log.Errorf("Could not copy build folder: %v", err) + os.Exit(1) + } + err = copy.Copy(packagingFormatPath(packagingFormat), filepath.Join(tmpPath)) + if err != nil { + log.Errorf("Could not copy packaging configuration folder: %v", err) + os.Exit(1) + } + + outputFileName := projectName + ".app" + outputFilePath := filepath.Join(build.OutputDirectoryPath("darwin-bundle"), outputFileName) + runDockerPackaging(tmpPath, packagingFormat, []string{"png2icns", projectName + ".app/Contents/Resources/icon.icns", projectName + ".app/Contents/MacOS/assets/icon.png"}) + + err = os.RemoveAll(outputFilePath) + if err != nil { + log.Errorf("Could not remove previous bundle directory: %v", err) + os.Exit(1) + } + err = os.Rename(filepath.Join(tmpPath, outputFileName), outputFilePath) + if err != nil { + log.Errorf("Could not move bundle directory: %v", err) + os.Exit(1) + } + err = os.RemoveAll(tmpPath) + if err != nil { + log.Errorf("Could not remove temporary build directory: %v", err) + os.Exit(1) + } + printPackagingFinished(packagingFormat) +} diff --git a/cmd/packaging/packaging.go b/cmd/packaging/packaging.go index 84cef80b..3cdb1354 100644 --- a/cmd/packaging/packaging.go +++ b/cmd/packaging/packaging.go @@ -109,6 +109,11 @@ func createDockerfile(packagingFormat string) { dockerFileContent = []string{ "FROM ubuntu:bionic", } + } else if packagingFormat == "darwin-bundle" { + dockerFileContent = []string{ + "FROM ubuntu:bionic", + "RUN apt-get update && apt-get install icnsutils -y", + } } else { log.Errorf("Tried to create Dockerfile for unknown packaging format %s", packagingFormat) os.Exit(1) From b17687d93093611aef3ac452acadb8f342ea7ee2 Mon Sep 17 00:00:00 2001 From: jld3103 Date: Thu, 3 Oct 2019 15:58:03 +0200 Subject: [PATCH 2/2] Add support for darwin-pkg --- cmd/build.go | 20 ++- cmd/common.go | 48 +----- cmd/packaging.go | 12 ++ cmd/packaging/darwin-bundle.go | 14 +- cmd/packaging/darwin-pkg.go | 145 +++++++++++++++++++ cmd/packaging/packaging.go | 8 + internal/androidmanifest/android-manifest.go | 54 +++++++ 7 files changed, 247 insertions(+), 54 deletions(-) create mode 100644 cmd/packaging/darwin-pkg.go create mode 100644 internal/androidmanifest/android-manifest.go diff --git a/cmd/build.go b/cmd/build.go index 22e2a589..c054ad11 100644 --- a/cmd/build.go +++ b/cmd/build.go @@ -19,6 +19,7 @@ import ( "github.com/go-flutter-desktop/hover/internal/versioncheck" "github.com/go-flutter-desktop/hover/internal/build" "github.com/go-flutter-desktop/hover/internal/pubspec" + "github.com/go-flutter-desktop/hover/internal/androidmanifest" "github.com/go-flutter-desktop/hover/cmd/packaging" ) @@ -53,6 +54,7 @@ func init() { buildCmd.AddCommand(buildLinuxDebCmd) buildCmd.AddCommand(buildDarwinCmd) buildCmd.AddCommand(buildDarwinBundleCmd) + buildCmd.AddCommand(buildDarwinPkgCmd) buildCmd.AddCommand(buildWindowsCmd) rootCmd.AddCommand(buildCmd) } @@ -130,6 +132,22 @@ var buildDarwinBundleCmd = &cobra.Command{ }, } +var buildDarwinPkgCmd = &cobra.Command{ + Use: "darwin-pkg", + Short: "Build a desktop release for darwin and package it for OSX pkg installer", + Run: func(cmd *cobra.Command, args []string) { + assertHoverInitialized() + packaging.AssertPackagingFormatInitialized("darwin-pkg") + + if !packaging.DockerInstalled() { + os.Exit(1) + } + + buildNormal("darwin", nil) + packaging.BuildDarwinPkg() + }, +} + var buildWindowsCmd = &cobra.Command{ Use: "windows", Short: "Build a desktop release for windows", @@ -495,7 +513,7 @@ func buildCommand(targetOS string, vmArguments []string, outputBinaryPath string pubspec.GetPubSpec().Version, currentTag, pubspec.GetPubSpec().Name, - androidOrganizationName())) + androidmanifest.AndroidOrganizationName())) outputCommand := []string{ "go", diff --git a/cmd/common.go b/cmd/common.go index 9738baad..fa2e8bb8 100644 --- a/cmd/common.go +++ b/cmd/common.go @@ -2,16 +2,14 @@ package cmd import ( "bufio" - "encoding/xml" - "io/ioutil" "os" "os/exec" "path/filepath" "strings" - "github.com/go-flutter-desktop/hover/internal/pubspec" "github.com/go-flutter-desktop/hover/internal/build" "github.com/go-flutter-desktop/hover/internal/log" + "github.com/go-flutter-desktop/hover/internal/pubspec" ) func initBinaries() { @@ -103,47 +101,3 @@ func askForConfirmation() bool { } return false } - -// AndroidManifest is a file that describes the essential information about -// an android app. -type AndroidManifest struct { - Package string `xml:"package,attr"` -} - -// androidOrganizationName fetch the android package name (default: -// 'com.example'). -// Can by set upon flutter create (--org flag) -// -// If errors occurs when reading the android package name, the string value -// will correspond to 'hover.failed.to.retrieve.package.name' -func androidOrganizationName() string { - // Default value - androidManifestFile := "android/app/src/main/AndroidManifest.xml" - - // Open AndroidManifest file - xmlFile, err := os.Open(androidManifestFile) - if err != nil { - log.Errorf("Failed to retrieve the organization name: %v", err) - return "hover.failed.to.retrieve.package.name" - } - defer xmlFile.Close() - - byteXMLValue, err := ioutil.ReadAll(xmlFile) - if err != nil { - log.Errorf("Failed to retrieve the organization name: %v", err) - return "hover.failed.to.retrieve.package.name" - } - - var androidManifest AndroidManifest - err = xml.Unmarshal(byteXMLValue, &androidManifest) - if err != nil { - log.Errorf("Failed to retrieve the organization name: %v", err) - return "hover.failed.to.retrieve.package.name" - } - javaPackage := strings.Split(androidManifest.Package, ".") - orgName := strings.Join(javaPackage[:len(javaPackage)-1], ".") - if orgName == "" { - return "hover.failed.to.retrieve.package.name" - } - return orgName -} diff --git a/cmd/packaging.go b/cmd/packaging.go index 990646ee..dd1b6bdd 100644 --- a/cmd/packaging.go +++ b/cmd/packaging.go @@ -10,6 +10,7 @@ func init() { initPackagingCmd.AddCommand(initLinuxSnapCmd) initPackagingCmd.AddCommand(initLinuxDebCmd) initPackagingCmd.AddCommand(initDarwinBundleCmd) + initPackagingCmd.AddCommand(initDarwinPkgCmd) rootCmd.AddCommand(initPackagingCmd) } @@ -50,3 +51,14 @@ var initDarwinBundleCmd = &cobra.Command{ packaging.InitDarwinBundle() }, } + +var initDarwinPkgCmd = &cobra.Command{ + Use: "darwin-pkg", + Short: "Create configuration files for OSX pkg installer packaging", + Run: func(cmd *cobra.Command, args []string) { + assertHoverInitialized() + packaging.DockerInstalled() + + packaging.InitDarwinPkg() + }, +} diff --git a/cmd/packaging/darwin-bundle.go b/cmd/packaging/darwin-bundle.go index 37ba6c38..4fbbf7cd 100644 --- a/cmd/packaging/darwin-bundle.go +++ b/cmd/packaging/darwin-bundle.go @@ -1,13 +1,15 @@ package packaging import ( - "github.com/otiai10/copy" "os" "path/filepath" + "github.com/otiai10/copy" + "github.com/go-flutter-desktop/hover/internal/build" "github.com/go-flutter-desktop/hover/internal/log" "github.com/go-flutter-desktop/hover/internal/pubspec" + "github.com/go-flutter-desktop/hover/internal/androidmanifest" ) func InitDarwinBundle() { @@ -71,21 +73,21 @@ func InitDarwinBundle() { ` CFBundleIconFile`, ` icon.icns`, ` CFBundleIdentifier`, - ` `, + ` ` + androidmanifest.AndroidOrganizationName() + ``, ` CFBundleInfoDictionaryVersion`, ` 6.0`, ` CFBundleLongVersionString`, - ` `, + ` ` + pubspec.GetPubSpec().Version + ``, ` CFBundleName`, - ` `, + ` ` + projectName + ``, ` CFBundlePackageType`, ` APPL`, ` CFBundleShortVersionString`, - ` `, + ` ` + pubspec.GetPubSpec().Version + ``, ` CFBundleSignature`, ` ????`, ` CFBundleVersion`, - ` `, + ` ` + pubspec.GetPubSpec().Version + ``, ` CSResourcesFileMapped`, ` `, ` NSHumanReadableCopyright`, diff --git a/cmd/packaging/darwin-pkg.go b/cmd/packaging/darwin-pkg.go new file mode 100644 index 00000000..ffeb11be --- /dev/null +++ b/cmd/packaging/darwin-pkg.go @@ -0,0 +1,145 @@ +package packaging + +import ( + "os" + "path/filepath" + + "github.com/otiai10/copy" + + "github.com/go-flutter-desktop/hover/internal/build" + "github.com/go-flutter-desktop/hover/internal/log" + "github.com/go-flutter-desktop/hover/internal/pubspec" + "github.com/go-flutter-desktop/hover/internal/androidmanifest" +) + +func InitDarwinPkg() { + projectName := pubspec.GetPubSpec().Name + packagingFormat := "darwin-pkg" + if _, err := os.Stat(packagingFormatPath("darwin-bundle")); os.IsNotExist(err) { + log.Errorf("You have to init `darwin-bundle` first. Run `hover init-packaging darwin-bundle`") + os.Exit(1) + } + createPackagingFormatDirectory(packagingFormat) + pkgDirectoryPath := packagingFormatPath(packagingFormat) + + basePkgDirectoryPath, err := filepath.Abs(filepath.Join(pkgDirectoryPath, "flat", "base.pkg")) + if err != nil { + log.Errorf("Failed to resolve absolute path for base.pkg directory: %v", err) + os.Exit(1) + } + err = os.MkdirAll(basePkgDirectoryPath, 0775) + if err != nil { + log.Errorf("Failed to create base.pkg directory %s: %v", basePkgDirectoryPath, err) + os.Exit(1) + } + + packageInfoFilePath, err := filepath.Abs(filepath.Join(basePkgDirectoryPath, "PackageInfo")) + if err != nil { + log.Errorf("Failed to resolve absolute path for PackageInfo file %s: %v", packageInfoFilePath, err) + os.Exit(1) + } + packageInfoFile, err := os.Create(packageInfoFilePath) + if err != nil { + log.Errorf("Failed to create PackageInfo file %s: %v", packageInfoFilePath, err) + os.Exit(1) + } + packageInfoFileContent := []string{ + ``, + ` `, + ` `, + ` `, + ``, + } + + for _, line := range packageInfoFileContent { + if _, err := packageInfoFile.WriteString(line + "\n"); err != nil { + log.Errorf("Could not write PackageInfo file: %v", err) + os.Exit(1) + } + } + err = packageInfoFile.Close() + if err != nil { + log.Errorf("Could not close PackageInfo file: %v", err) + os.Exit(1) + } + + distributionFilePath, err := filepath.Abs(filepath.Join(pkgDirectoryPath, "flat", "Distribution")) + if err != nil { + log.Errorf("Failed to resolve absolute path for Distribution file %s: %v", distributionFilePath, err) + os.Exit(1) + } + distributionFile, err := os.Create(distributionFilePath) + if err != nil { + log.Errorf("Failed to create Distribution file %s: %v", packageInfoFilePath, err) + os.Exit(1) + } + distributionFileContent := []string{ + ``, + ``, + ` ` + projectName + ``, + ` `, + ` `, + ` `, + ` `, + ` `, + ` `, + ` `, + ` #base.pkg`, + ``, + } + + for _, line := range distributionFileContent { + if _, err := distributionFile.WriteString(line + "\n"); err != nil { + log.Errorf("Could not write Distribution file: %v", err) + os.Exit(1) + } + } + err = distributionFile.Close() + if err != nil { + log.Errorf("Could not close Distribution file: %v", err) + os.Exit(1) + } + + createDockerfile(packagingFormat) + + printInitFinished(packagingFormat) +} + +func BuildDarwinPkg() { + log.Infof("Building darwin-bundle first") + BuildDarwinBundle() + projectName := pubspec.GetPubSpec().Name + packagingFormat := "darwin-pkg" + tmpPath := getTemporaryBuildDirectory(projectName, packagingFormat) + log.Infof("Packaging pkg in %s", tmpPath) + + err := copy.Copy(build.OutputDirectoryPath("darwin-bundle"), filepath.Join(tmpPath, "flat", "root", "Applications")) + if err != nil { + log.Errorf("Could not copy build folder: %v", err) + os.Exit(1) + } + err = copy.Copy(packagingFormatPath(packagingFormat), filepath.Join(tmpPath)) + if err != nil { + log.Errorf("Could not copy packaging configuration folder: %v", err) + os.Exit(1) + } + + outputFileName := projectName + " " + pubspec.GetPubSpec().Version + " Installer.pkg" + outputFilePath := filepath.Join(build.OutputDirectoryPath("darwin-pkg"), outputFileName) + runDockerPackaging(tmpPath, packagingFormat, []string{ + "(cd flat/root && find . | cpio -o --format odc --owner 0:80 | gzip -c ) > flat/base.pkg/Payload", + "&&", "mkbom -u 0 -g 80 flat/root flat/base.pkg/Bom", + "&&", "(cd flat && xar --compression none -cf '../" + projectName + " " + pubspec.GetPubSpec().Version + " Installer.pkg' * )", + }) + err = os.Rename(filepath.Join(tmpPath, outputFileName), outputFilePath) + if err != nil { + log.Errorf("Could not move pkg directory: %v", err) + os.Exit(1) + } + err = os.RemoveAll(tmpPath) + if err != nil { + log.Errorf("Could not remove temporary build directory: %v", err) + os.Exit(1) + } + printPackagingFinished(packagingFormat) +} diff --git a/cmd/packaging/packaging.go b/cmd/packaging/packaging.go index 3cdb1354..7cde9d8b 100644 --- a/cmd/packaging/packaging.go +++ b/cmd/packaging/packaging.go @@ -114,6 +114,14 @@ func createDockerfile(packagingFormat string) { "FROM ubuntu:bionic", "RUN apt-get update && apt-get install icnsutils -y", } + } else if packagingFormat == "darwin-pkg" { + dockerFileContent = []string{ + "FROM ubuntu:bionic", + "RUN apt-get update && apt-get install cpio git make g++ wget libxml2-dev libssl1.0-dev zlib1g-dev -y", + "WORKDIR /tmp", + "RUN git clone https://github.com/hogliux/bomutils && cd bomutils && make > /dev/null && make install > /dev/null", + "RUN wget https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/xar/xar-1.5.2.tar.gz && tar -zxvf xar-1.5.2.tar.gz > /dev/null && cd xar-1.5.2 && ./configure > /dev/null && make > /dev/null && make install > /dev/null", + } } else { log.Errorf("Tried to create Dockerfile for unknown packaging format %s", packagingFormat) os.Exit(1) diff --git a/internal/androidmanifest/android-manifest.go b/internal/androidmanifest/android-manifest.go new file mode 100644 index 00000000..ab969e0c --- /dev/null +++ b/internal/androidmanifest/android-manifest.go @@ -0,0 +1,54 @@ +package androidmanifest + +import ( + "encoding/xml" + "io/ioutil" + "os" + "strings" + + "github.com/go-flutter-desktop/hover/internal/log" +) + +// AndroidManifest is a file that describes the essential information about +// an android app. +type AndroidManifest struct { + Package string `xml:"package,attr"` +} + +// AndroidOrganizationName fetch the android package name (default: +// 'com.example'). +// Can by set upon flutter create (--org flag) +// +// If errors occurs when reading the android package name, the string value +// will correspond to 'hover.failed.to.retrieve.package.name' +func AndroidOrganizationName() string { + // Default value + androidManifestFile := "android/app/src/main/AndroidManifest.xml" + + // Open AndroidManifest file + xmlFile, err := os.Open(androidManifestFile) + if err != nil { + log.Errorf("Failed to retrieve the organization name: %v", err) + return "hover.failed.to.retrieve.package.name" + } + defer xmlFile.Close() + + byteXMLValue, err := ioutil.ReadAll(xmlFile) + if err != nil { + log.Errorf("Failed to retrieve the organization name: %v", err) + return "hover.failed.to.retrieve.package.name" + } + + var androidManifest AndroidManifest + err = xml.Unmarshal(byteXMLValue, &androidManifest) + if err != nil { + log.Errorf("Failed to retrieve the organization name: %v", err) + return "hover.failed.to.retrieve.package.name" + } + javaPackage := strings.Split(androidManifest.Package, ".") + orgName := strings.Join(javaPackage[:len(javaPackage)-1], ".") + if orgName == "" { + return "hover.failed.to.retrieve.package.name" + } + return orgName +}