5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-03 00:09:56 +08:00

Modularize wails (#2009)

Co-authored-by: stffabi <stffabi@users.noreply.github.com>
This commit is contained in:
Lea Anthony 2022-11-03 21:21:40 +11:00 committed by GitHub
parent 0a1c05df16
commit 18b2d315dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 1317 additions and 255 deletions

View File

@ -77,9 +77,9 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
outputFilename := ""
command.StringFlag("o", "Output filename", &outputFilename)
// Clean build directory
cleanBuildDirectory := false
command.BoolFlag("clean", "Clean the build directory before building", &cleanBuildDirectory)
// Clean bin directory
cleanBinDirectory := false
command.BoolFlag("clean", "Clean the bin directory before building", &cleanBinDirectory)
webview2 := "download"
command.StringFlag("webview2", "WebView2 installer strategy: download,embed,browser,error.", &webview2)
@ -190,28 +190,29 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
// Create BuildOptions
buildOptions := &build.Options{
Logger: logger,
OutputType: outputType,
OutputFile: outputFilename,
CleanBuildDirectory: cleanBuildDirectory,
Mode: mode,
Pack: !noPackage,
LDFlags: ldflags,
Compiler: compilerCommand,
SkipModTidy: skipModTidy,
Verbosity: verbosity,
ForceBuild: forceBuild,
IgnoreFrontend: skipFrontend,
Compress: compress,
CompressFlags: compressFlags,
UserTags: userTags,
WebView2Strategy: wv2rtstrategy,
TrimPath: trimpath,
RaceDetector: raceDetector,
WindowsConsole: windowsConsole,
Obfuscated: obfuscated,
GarbleArgs: garbleargs,
SkipBindings: skipBindings,
Logger: logger,
OutputType: outputType,
OutputFile: outputFilename,
CleanBinDirectory: cleanBinDirectory,
Mode: mode,
Pack: !noPackage,
LDFlags: ldflags,
Compiler: compilerCommand,
SkipModTidy: skipModTidy,
Verbosity: verbosity,
ForceBuild: forceBuild,
IgnoreFrontend: skipFrontend,
Compress: compress,
CompressFlags: compressFlags,
UserTags: userTags,
WebView2Strategy: wv2rtstrategy,
TrimPath: trimpath,
RaceDetector: raceDetector,
WindowsConsole: windowsConsole,
Obfuscated: obfuscated,
GarbleArgs: garbleargs,
SkipBindings: skipBindings,
ProjectData: projectOptions,
}
// Start a new tabwriter
@ -225,6 +226,7 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
_, _ = fmt.Fprintf(w, "Compiler: \t%s\n", compilerPath)
_, _ = fmt.Fprintf(w, "Skip Bindings: \t%t\n", skipBindings)
_, _ = fmt.Fprintf(w, "Build Mode: \t%s\n", modeString)
_, _ = fmt.Fprintf(w, "Frontend Directory: \t%s\n", projectOptions.GetFrontendDir())
_, _ = fmt.Fprintf(w, "Obfuscated: \t%t\n", buildOptions.Obfuscated)
if buildOptions.Obfuscated {
_, _ = fmt.Fprintf(w, "Garble Args: \t%s\n", buildOptions.GarbleArgs)
@ -232,7 +234,7 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
_, _ = fmt.Fprintf(w, "Skip Frontend: \t%t\n", skipFrontend)
_, _ = fmt.Fprintf(w, "Compress: \t%t\n", buildOptions.Compress)
_, _ = fmt.Fprintf(w, "Package: \t%t\n", buildOptions.Pack)
_, _ = fmt.Fprintf(w, "Clean Build Dir: \t%t\n", buildOptions.CleanBuildDirectory)
_, _ = fmt.Fprintf(w, "Clean Bin Dir: \t%t\n", buildOptions.CleanBinDirectory)
_, _ = fmt.Fprintf(w, "LDFlags: \t\"%s\"\n", buildOptions.LDFlags)
_, _ = fmt.Fprintf(w, "Tags: \t[%s]\n", strings.Join(buildOptions.UserTags, ","))
_, _ = fmt.Fprintf(w, "Race Detector: \t%t\n", buildOptions.RaceDetector)
@ -358,7 +360,7 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
}
buildOptions.IgnoreFrontend = true
buildOptions.CleanBuildDirectory = false
buildOptions.CleanBinDirectory = false
// Output stats
buildOptions.Logger.Println(fmt.Sprintf("Built '%s' in %s.\n", compiledBinary, time.Since(start).Round(time.Millisecond).String()))

View File

@ -1,13 +1,13 @@
package build
import (
"os"
"path/filepath"
"fmt"
"github.com/wailsapp/wails/v2/cmd/wails/internal"
"github.com/wailsapp/wails/v2/internal/fs"
"github.com/wailsapp/wails/v2/internal/gomod"
"github.com/wailsapp/wails/v2/internal/goversion"
"github.com/wailsapp/wails/v2/pkg/clilogger"
"os"
)
func SyncGoMod(logger *clilogger.CLILogger, updateWailsVersion bool) error {
@ -15,7 +15,10 @@ func SyncGoMod(logger *clilogger.CLILogger, updateWailsVersion bool) error {
if err != nil {
return err
}
gomodFilename := filepath.Join(cwd, "go.mod")
gomodFilename := fs.FindFileInParents(cwd, "go.mod")
if gomodFilename == "" {
return fmt.Errorf("no go.mod file found")
}
gomodData, err := os.ReadFile(gomodFilename)
if err != nil {
return err

View File

@ -166,6 +166,7 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
}
buildOptions := generateBuildOptions(flags)
buildOptions.ProjectData = projectConfig
buildOptions.SkipBindings = flags.skipBindings
buildOptions.Logger = logger
@ -214,7 +215,7 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
// frontend:dev:watcher command.
frontendDevAutoDiscovery := projectConfig.IsFrontendDevServerURLAutoDiscovery()
if command := projectConfig.DevWatcherCommand; command != "" {
closer, devServerURL, err := runFrontendDevWatcherCommand(cwd, command, frontendDevAutoDiscovery)
closer, devServerURL, err := runFrontendDevWatcherCommand(projectConfig.GetFrontendDir(), command, frontendDevAutoDiscovery)
if err != nil {
return err
}
@ -358,8 +359,8 @@ func generateBuildOptions(flags devFlags) *build.Options {
// loadAndMergeProjectConfig reconciles flags passed to the CLI with project config settings and updates
// the project config if necessary
func loadAndMergeProjectConfig(cwd string, flags *devFlags) (*project.Project, error) {
projectConfig, err := project.Load(cwd)
func loadAndMergeProjectConfig(projectFileDirectory string, flags *devFlags) (*project.Project, error) {
projectConfig, err := project.Load(projectFileDirectory)
if err != nil {
return nil, err
}
@ -396,11 +397,11 @@ func loadAndMergeProjectConfig(cwd string, flags *devFlags) (*project.Project, e
}
if flags.wailsjsdir == "" && projectConfig.WailsJSDir != "" {
flags.wailsjsdir = projectConfig.WailsJSDir
flags.wailsjsdir = projectConfig.GetWailsJSDir()
}
if flags.wailsjsdir == "" {
flags.wailsjsdir = "./frontend"
flags.wailsjsdir = projectConfig.GetFrontendDir()
}
if flags.wailsjsdir != projectConfig.WailsJSDir {
@ -433,15 +434,14 @@ func loadAndMergeProjectConfig(cwd string, flags *devFlags) (*project.Project, e
}
// runFrontendDevWatcherCommand will run the `frontend:dev:watcher` command if it was given, ex- `npm run dev`
func runFrontendDevWatcherCommand(cwd string, devCommand string, discoverViteServerURL bool) (func(), string, error) {
func runFrontendDevWatcherCommand(frontendDirectory string, devCommand string, discoverViteServerURL bool) (func(), string, error) {
ctx, cancel := context.WithCancel(context.Background())
scanner := NewStdoutScanner()
dir := filepath.Join(cwd, "frontend")
cmdSlice := strings.Split(devCommand, " ")
cmd := exec.CommandContext(ctx, cmdSlice[0], cmdSlice[1:]...)
cmd.Stderr = os.Stderr
cmd.Stdout = scanner
cmd.Dir = dir
cmd.Dir = frontendDirectory
setParentGID(cmd)
if err := cmd.Start(); err != nil {

3
v2/examples/customlayout/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
build/bin
node_modules
myfrontend/wailsjs

View File

@ -0,0 +1,4 @@
# README
This is an example project that shows how to use a custom layout.
Run `wails build` in the `cmd/customlayout` directory to build the project.

View File

@ -0,0 +1,35 @@
# Build Directory
The build directory is used to house all the build files and assets for your application.
The structure is:
* bin - Output directory
* darwin - macOS specific files
* windows - Windows specific files
## Mac
The `darwin` directory holds files specific to Mac builds.
These may be customised and used as part of the build. To return these files to the default state, simply delete them
and
build with `wails build`.
The directory contains the following files:
- `Info.plist` - the main plist file used for Mac builds. It is used when building using `wails build`.
- `Info.dev.plist` - same as the main plist file but used when building using `wails dev`.
## Windows
The `windows` directory contains the manifest and rc files used when building with `wails build`.
These may be customised for your application. To return these files to the default state, simply delete them and
build with `wails build`.
- `icon.ico` - The icon used for the application. This is used when building using `wails build`. If you wish to
use a different icon, simply replace this file with your own. If it is missing, a new `icon.ico` file
will be created using the `appicon.png` file in the build directory.
- `installer/*` - The files used to create the Windows installer. These are used when building using `wails build`.
- `info.json` - Application details used for Windows builds. The data here will be used by the Windows installer,
as well as the application itself (right click the exe -> properties -> details)
- `wails.exe.manifest` - The main application manifest file.

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

View File

@ -0,0 +1,32 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleName</key>
<string>{{.Info.ProductName}}</string>
<key>CFBundleExecutable</key>
<string>{{.Name}}</string>
<key>CFBundleIdentifier</key>
<string>com.wails.{{.Name}}</string>
<key>CFBundleVersion</key>
<string>{{.Info.ProductVersion}}</string>
<key>CFBundleGetInfoString</key>
<string>{{.Info.Comments}}</string>
<key>CFBundleShortVersionString</key>
<string>{{.Info.ProductVersion}}</string>
<key>CFBundleIconFile</key>
<string>iconfile</string>
<key>LSMinimumSystemVersion</key>
<string>10.13.0</string>
<key>NSHighResolutionCapable</key>
<string>true</string>
<key>NSHumanReadableCopyright</key>
<string>{{.Info.Copyright}}</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsLocalNetworking</key>
<true/>
</dict>
</dict>
</plist>

View File

@ -0,0 +1,27 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleName</key>
<string>{{.Info.ProductName}}</string>
<key>CFBundleExecutable</key>
<string>{{.Name}}</string>
<key>CFBundleIdentifier</key>
<string>com.wails.{{.Name}}</string>
<key>CFBundleVersion</key>
<string>{{.Info.ProductVersion}}</string>
<key>CFBundleGetInfoString</key>
<string>{{.Info.Comments}}</string>
<key>CFBundleShortVersionString</key>
<string>{{.Info.ProductVersion}}</string>
<key>CFBundleIconFile</key>
<string>iconfile</string>
<key>LSMinimumSystemVersion</key>
<string>10.13.0</string>
<key>NSHighResolutionCapable</key>
<string>true</string>
<key>NSHumanReadableCopyright</key>
<string>{{.Info.Copyright}}</string>
</dict>
</plist>

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -0,0 +1,15 @@
{
"fixed": {
"file_version": "{{.Info.ProductVersion}}"
},
"info": {
"0000": {
"ProductVersion": "{{.Info.ProductVersion}}",
"CompanyName": "{{.Info.CompanyName}}",
"FileDescription": "{{.Info.ProductName}}",
"LegalCopyright": "{{.Info.Copyright}}",
"ProductName": "{{.Info.ProductName}}",
"Comments": "{{.Info.Comments}}"
}
}
}

View File

@ -0,0 +1,101 @@
Unicode true
####
## Please note: Template replacements don't work in this file. They are provided with default defines like
## mentioned underneath.
## If the keyword is not defined, "wails_tools.nsh" will populate them with the values from ProjectInfo.
## If they are defined here, "wails_tools.nsh" will not touch them. This allows to use this project.nsi manually
## from outside of Wails for debugging and development of the installer.
##
## For development first make a wails nsis build to populate the "wails_tools.nsh":
## > wails build --target windows/amd64 --nsis
## Then you can call makensis on this file with specifying the path to your binary:
## For a AMD64 only installer:
## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app.exe
## For a ARM64 only installer:
## > makensis -DARG_WAILS_ARM64_BINARY=..\..\bin\app.exe
## For a installer with both architectures:
## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app-amd64.exe -DARG_WAILS_ARM64_BINARY=..\..\bin\app-arm64.exe
####
## The following information is taken from the ProjectInfo file, but they can be overwritten here.
####
## !define INFO_PROJECTNAME "MyProject" # Default "{{.Name}}"
## !define INFO_COMPANYNAME "MyCompany" # Default "{{.Info.CompanyName}}"
## !define INFO_PRODUCTNAME "MyProduct" # Default "{{.Info.ProductName}}"
## !define INFO_PRODUCTVERSION "1.0.0" # Default "{{.Info.ProductVersion}}"
## !define INFO_COPYRIGHT "Copyright" # Default "{{.Info.Copyright}}"
###
## !define PRODUCT_EXECUTABLE "Application.exe" # Default "${INFO_PROJECTNAME}.exe"
## !define UNINST_KEY_NAME "UninstKeyInRegistry" # Default "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}"
####
## !define REQUEST_EXECUTION_LEVEL "admin" # Default "admin" see also https://nsis.sourceforge.io/Docs/Chapter4.html
####
## Include the wails tools
####
!include "wails_tools.nsh"
# The version information for this two must consist of 4 parts
VIProductVersion "${INFO_PRODUCTVERSION}.0"
VIFileVersion "${INFO_PRODUCTVERSION}.0"
VIAddVersionKey "CompanyName" "${INFO_COMPANYNAME}"
VIAddVersionKey "FileDescription" "${INFO_PRODUCTNAME} Installer"
VIAddVersionKey "ProductVersion" "${INFO_PRODUCTVERSION}"
VIAddVersionKey "FileVersion" "${INFO_PRODUCTVERSION}"
VIAddVersionKey "LegalCopyright" "${INFO_COPYRIGHT}"
VIAddVersionKey "ProductName" "${INFO_PRODUCTNAME}"
!include "MUI.nsh"
!define MUI_ICON "..\icon.ico"
!define MUI_UNICON "..\icon.ico"
# !define MUI_WELCOMEFINISHPAGE_BITMAP "resources\leftimage.bmp" #Include this to add a bitmap on the left side of the Welcome Page. Must be a size of 164x314
!define MUI_FINISHPAGE_NOAUTOCLOSE # Wait on the INSTFILES page so the user can take a look into the details of the installation steps
!define MUI_ABORTWARNING # This will warn the user if they exit from the installer.
!insertmacro MUI_PAGE_WELCOME # Welcome to the installer page.
# !insertmacro MUI_PAGE_LICENSE "resources\eula.txt" # Adds a EULA page to the installer
!insertmacro MUI_PAGE_DIRECTORY # In which folder install page.
!insertmacro MUI_PAGE_INSTFILES # Installing page.
!insertmacro MUI_PAGE_FINISH # Finished installation page.
!insertmacro MUI_UNPAGE_INSTFILES # Uinstalling page
!insertmacro MUI_LANGUAGE "English" # Set the Language of the installer
## The following two statements can be used to sign the installer and the uninstaller. The path to the binaries are provided in %1
#!uninstfinalize 'signtool --file "%1"'
#!finalize 'signtool --file "%1"'
Name "${INFO_PRODUCTNAME}"
OutFile "..\..\bin\${INFO_PROJECTNAME}-${ARCH}-installer.exe" # Name of the installer's file.
InstallDir "$PROGRAMFILES64\${INFO_COMPANYNAME}\${INFO_PRODUCTNAME}" # Default installing folder ($PROGRAMFILES is Program Files folder).
ShowInstDetails show # This will always show the installation details.
Function .onInit
!insertmacro wails.checkArchitecture
FunctionEnd
Section
!insertmacro wails.webview2runtime
SetOutPath $INSTDIR
!insertmacro wails.files
CreateShortcut "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}"
CreateShortCut "$DESKTOP\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}"
!insertmacro wails.writeUninstaller
SectionEnd
Section "uninstall"
RMDir /r "$AppData\${PRODUCT_EXECUTABLE}" # Remove the WebView2 DataPath
RMDir /r $INSTDIR
Delete "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk"
Delete "$DESKTOP\${INFO_PRODUCTNAME}.lnk"
!insertmacro wails.deleteUninstaller
SectionEnd

View File

@ -0,0 +1,171 @@
# DO NOT EDIT - Generated automatically by `wails build`
!include "x64.nsh"
!include "WinVer.nsh"
!include "FileFunc.nsh"
!ifndef INFO_PROJECTNAME
!define INFO_PROJECTNAME "{{.Name}}"
!endif
!ifndef INFO_COMPANYNAME
!define INFO_COMPANYNAME "{{.Info.CompanyName}}"
!endif
!ifndef INFO_PRODUCTNAME
!define INFO_PRODUCTNAME "{{.Info.ProductName}}"
!endif
!ifndef INFO_PRODUCTVERSION
!define INFO_PRODUCTVERSION "{{.Info.ProductVersion}}"
!endif
!ifndef INFO_COPYRIGHT
!define INFO_COPYRIGHT "{{.Info.Copyright}}"
!endif
!ifndef PRODUCT_EXECUTABLE
!define PRODUCT_EXECUTABLE "${INFO_PROJECTNAME}.exe"
!endif
!ifndef UNINST_KEY_NAME
!define UNINST_KEY_NAME "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}"
!endif
!define UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINST_KEY_NAME}"
!ifndef REQUEST_EXECUTION_LEVEL
!define REQUEST_EXECUTION_LEVEL "admin"
!endif
RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}"
!ifdef ARG_WAILS_AMD64_BINARY
!define SUPPORTS_AMD64
!endif
!ifdef ARG_WAILS_ARM64_BINARY
!define SUPPORTS_ARM64
!endif
!ifdef SUPPORTS_AMD64
!ifdef SUPPORTS_ARM64
!define ARCH "amd64_arm64"
!else
!define ARCH "amd64"
!endif
!else
!ifdef SUPPORTS_ARM64
!define ARCH "arm64"
!else
!error "Wails: Undefined ARCH, please provide at least one of ARG_WAILS_AMD64_BINARY or ARG_WAILS_ARM64_BINARY"
!endif
!endif
!macro wails.checkArchitecture
!ifndef WAILS_WIN10_REQUIRED
!define WAILS_WIN10_REQUIRED "This product is only supported on Windows 10 (Server 2016) and later."
!endif
!ifndef WAILS_ARCHITECTURE_NOT_SUPPORTED
!define WAILS_ARCHITECTURE_NOT_SUPPORTED "This product can't be installed on the current Windows architecture. Supports: ${ARCH}"
!endif
${If} ${AtLeastWin10}
!ifdef SUPPORTS_AMD64
${if} ${IsNativeAMD64}
Goto ok
${EndIf}
!endif
!ifdef SUPPORTS_ARM64
${if} ${IsNativeARM64}
Goto ok
${EndIf}
!endif
IfSilent silentArch notSilentArch
silentArch:
SetErrorLevel 65
Abort
notSilentArch:
MessageBox MB_OK "${WAILS_ARCHITECTURE_NOT_SUPPORTED}"
Quit
${else}
IfSilent silentWin notSilentWin
silentWin:
SetErrorLevel 64
Abort
notSilentWin:
MessageBox MB_OK "${WAILS_WIN10_REQUIRED}"
Quit
${EndIf}
ok:
!macroend
!macro wails.files
!ifdef SUPPORTS_AMD64
${if} ${IsNativeAMD64}
File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_AMD64_BINARY}"
${EndIf}
!endif
!ifdef SUPPORTS_ARM64
${if} ${IsNativeARM64}
File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_ARM64_BINARY}"
${EndIf}
!endif
!macroend
!macro wails.writeUninstaller
WriteUninstaller "$INSTDIR\uninstall.exe"
SetRegView 64
WriteRegStr HKLM "${UNINST_KEY}" "Publisher" "${INFO_COMPANYNAME}"
WriteRegStr HKLM "${UNINST_KEY}" "DisplayName" "${INFO_PRODUCTNAME}"
WriteRegStr HKLM "${UNINST_KEY}" "DisplayVersion" "${INFO_PRODUCTVERSION}"
WriteRegStr HKLM "${UNINST_KEY}" "DisplayIcon" "$INSTDIR\${PRODUCT_EXECUTABLE}"
WriteRegStr HKLM "${UNINST_KEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\""
WriteRegStr HKLM "${UNINST_KEY}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S"
${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
IntFmt $0 "0x%08X" $0
WriteRegDWORD HKLM "${UNINST_KEY}" "EstimatedSize" "$0"
!macroend
!macro wails.deleteUninstaller
Delete "$INSTDIR\uninstall.exe"
SetRegView 64
DeleteRegKey HKLM "${UNINST_KEY}"
!macroend
# Install webview2 by launching the bootstrapper
# See https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#online-only-deployment
!macro wails.webview2runtime
!ifndef WAILS_INSTALL_WEBVIEW_DETAILPRINT
!define WAILS_INSTALL_WEBVIEW_DETAILPRINT "Installing: WebView2 Runtime"
!endif
SetRegView 64
# If the admin key exists and is not empty then webview2 is already installed
ReadRegStr $0 HKLM "SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv"
${If} $0 != ""
Goto ok
${EndIf}
${If} ${REQUEST_EXECUTION_LEVEL} == "user"
# If the installer is run in user level, check the user specific key exists and is not empty then webview2 is already installed
ReadRegStr $0 HKCU "Software\Microsoft\EdgeUpdate\Clients{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv"
${If} $0 != ""
Goto ok
${EndIf}
${EndIf}
SetDetailsPrint both
DetailPrint "${WAILS_INSTALL_WEBVIEW_DETAILPRINT}"
SetDetailsPrint listonly
InitPluginsDir
CreateDirectory "$pluginsdir\webview2bootstrapper"
SetOutPath "$pluginsdir\webview2bootstrapper"
File "tmp\MicrosoftEdgeWebview2Setup.exe"
ExecWait '"$pluginsdir\webview2bootstrapper\MicrosoftEdgeWebview2Setup.exe" /silent /install'
SetDetailsPrint both
ok:
!macroend

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<assemblyIdentity type="win32" name="com.wails.{{.Name}}" version="{{.Info.ProductVersion}}.0" processorArchitecture="*"/>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
</dependentAssembly>
</dependency>
<asmv3:application>
<asmv3:windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware> <!-- fallback for Windows 7 and 8 -->
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">permonitorv2,permonitor</dpiAwareness> <!-- falls back to per-monitor if per-monitor v2 is not supported -->
</asmv3:windowsSettings>
</asmv3:application>
</assembly>

View File

@ -0,0 +1,27 @@
package main
import (
"context"
"fmt"
)
// App struct
type App struct {
ctx context.Context
}
// NewApp creates a new App application struct
func NewApp() *App {
return &App{}
}
// startup is called when the app starts. The context is saved
// so we can call the runtime methods
func (a *App) startup(ctx context.Context) {
a.ctx = ctx
}
// Greet returns a greeting for the given name
func (a *App) Greet(name string) string {
return fmt.Sprintf("Hello %s, It's show time!", name)
}

View File

@ -0,0 +1,29 @@
package main
import (
"changeme/myfrontend"
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
)
func main() {
// Create an instance of the app structure
app := NewApp()
// Create application with options
err := wails.Run(&options.App{
Title: "customlayout",
Width: 1024,
Height: 768,
Assets: myfrontend.Assets,
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
OnStartup: app.startup,
Bind: []interface{}{
app,
},
})
if err != nil {
println("Error:", err.Error())
}
}

View File

@ -0,0 +1,15 @@
{
"$schema": "https://wails.io/schemas/config.v2.json",
"name": "customlayout",
"outputfilename": "customlayout",
"build:dir": "../../build",
"frontend:dir": "../../myfrontend",
"frontend:install": "npm install",
"frontend:build": "npm run build",
"frontend:dev:watcher": "npm run dev",
"frontend:dev:serverUrl": "auto",
"author": {
"name": "Lea Anthony",
"email": "lea.anthony@gmail.com"
}
}

View File

@ -0,0 +1,34 @@
module changeme
go 1.18
require github.com/wailsapp/wails/v2 v2.1.0
require (
github.com/bep/debounce v1.2.1 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/google/uuid v1.1.2 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
github.com/labstack/echo/v4 v4.9.0 // indirect
github.com/labstack/gommon v0.3.1 // indirect
github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
github.com/leaanthony/gosod v1.0.3 // indirect
github.com/leaanthony/slicer v1.5.0 // indirect
github.com/mattn/go-colorable v0.1.11 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/samber/lo v1.27.1 // indirect
github.com/tkrajina/go-reflector v0.5.5 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.1 // indirect
github.com/wailsapp/mimetype v1.4.1 // indirect
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect
golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
golang.org/x/text v0.3.7 // indirect
)
replace github.com/wailsapp/wails/v2 v2.1.0 => ../..

View File

@ -0,0 +1,79 @@
github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY=
github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck=
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
github.com/labstack/echo/v4 v4.9.0 h1:wPOF1CE6gvt/kmbMR4dGzWvHMPT+sAEUJOwOTtvITVY=
github.com/labstack/echo/v4 v4.9.0/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks=
github.com/labstack/gommon v0.3.1 h1:OomWaJXm7xR6L1HmEtGyQf26TEn7V6X88mktX9kee9o=
github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
github.com/leaanthony/debme v1.2.1 h1:9Tgwf+kjcrbMQ4WnPcEIUcQuIZYqdWftzZkBr+i/oOc=
github.com/leaanthony/debme v1.2.1/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA=
github.com/leaanthony/go-ansi-parser v1.0.1 h1:97v6c5kYppVsbScf4r/VZdXyQ21KQIfeQOk2DgKxGG4=
github.com/leaanthony/go-ansi-parser v1.0.1/go.mod h1:7arTzgVI47srICYhvgUV4CGd063sGEeoSlych5yeSPM=
github.com/leaanthony/gosod v1.0.3 h1:Fnt+/B6NjQOVuCWOKYRREZnjGyvg+mEhd1nkkA04aTQ=
github.com/leaanthony/gosod v1.0.3/go.mod h1:BJ2J+oHsQIyIQpnLPjnqFGTMnOZXDbvWtRCSG7jGxs4=
github.com/leaanthony/slicer v1.5.0 h1:aHYTN8xbCCLxJmkNKiLB6tgcMARl4eWmH9/F+S/0HtY=
github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY=
github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs=
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 h1:acNfDZXmm28D2Yg/c3ALnZStzNaZMSagpbr96vY6Zjc=
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/samber/lo v1.27.1 h1:sTXwkRiIFIQG+G0HeAvOEnGjqWeWtI9cg5/n51KrxPg=
github.com/samber/lo v1.27.1/go.mod h1:it33p9UtPMS7z72fP4gw/EIfQB2eI8ke7GR2wc6+Rhg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M=
github.com/tkrajina/go-reflector v0.5.5 h1:gwoQFNye30Kk7NrExj8zm3zFtrGPqOkzFMLuQZg1DtQ=
github.com/tkrajina/go-reflector v0.5.5/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs=
github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 h1:3MTrJm4PyNL9NBqvYDSj3DHl46qQakyfqfWo4jgfaEM=
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

View File

@ -0,0 +1,6 @@
package myfrontend
import "embed"
//go:embed all:dist
var Assets embed.FS

View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<title>customlayout</title>
</head>
<body>
<div id="app"></div>
<script src="./src/main.js" type="module"></script>
</body>
</html>

View File

@ -0,0 +1,13 @@
{
"name": "frontend",
"private": true,
"version": "0.0.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"devDependencies": {
"vite": "^2.9.9"
}
}

View File

@ -0,0 +1,54 @@
#logo {
display: block;
width: 50%;
height: 50%;
margin: auto;
padding: 10% 0 0;
background-position: center;
background-repeat: no-repeat;
background-size: 100% 100%;
background-origin: content-box;
}
.result {
height: 20px;
line-height: 20px;
margin: 1.5rem auto;
}
.input-box .btn {
width: 60px;
height: 30px;
line-height: 30px;
border-radius: 3px;
border: none;
margin: 0 0 0 20px;
padding: 0 8px;
cursor: pointer;
}
.input-box .btn:hover {
background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%);
color: #333333;
}
.input-box .input {
border: none;
border-radius: 3px;
outline: none;
height: 30px;
line-height: 30px;
padding: 0 10px;
background-color: rgba(240, 240, 240, 1);
-webkit-font-smoothing: antialiased;
}
.input-box .input:hover {
border: none;
background-color: rgba(255, 255, 255, 1);
}
.input-box .input:focus {
border: none;
background-color: rgba(255, 255, 255, 1);
}

View File

@ -0,0 +1,93 @@
Copyright 2016 The Nunito Project Authors (contact@sansoxygen.com),
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

View File

@ -0,0 +1,43 @@
import './style.css';
import './app.css';
import logo from './assets/images/logo-universal.png';
import {Greet} from '../wailsjs/go/main/App';
document.querySelector('#app').innerHTML = `
<img id="logo" class="logo">
<div class="result" id="result">Please enter your name below 👇</div>
<div class="input-box" id="input">
<input class="input" id="name" type="text" autocomplete="off" />
<button class="btn" onclick="greet()">Greet</button>
</div>
</div>
`;
document.getElementById('logo').src = logo;
let nameElement = document.getElementById("name");
nameElement.focus();
let resultElement = document.getElementById("result");
// Setup the greet function
window.greet = function () {
// Get name
let name = nameElement.value;
// Check if the input is empty
if (name === "") return;
// Call App.Greet(name)
try {
Greet(name)
.then((result) => {
// Update result with data back from App.Greet()
resultElement.innerText = result;
})
.catch((err) => {
console.error(err);
});
} catch (err) {
console.error(err);
}
};

View File

@ -0,0 +1,26 @@
html {
background-color: rgba(27, 38, 54, 1);
text-align: center;
color: white;
}
body {
margin: 0;
color: white;
font-family: "Nunito", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto",
"Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif;
}
@font-face {
font-family: "Nunito";
font-style: normal;
font-weight: 400;
src: local(""),
url("assets/fonts/nunito-v16-latin-regular.woff2") format("woff2");
}
#app {
height: 100vh;
text-align: center;
}

View File

@ -60,29 +60,27 @@ func generateBindings(bindings *binding.Bindings) error {
return err
}
if projectConfig.WailsJSDir == "" {
projectConfig.WailsJSDir = filepath.Join(cwd, "frontend")
}
wrapperDir := filepath.Join(projectConfig.WailsJSDir, "wailsjs", "runtime")
_ = os.RemoveAll(wrapperDir)
wailsjsbasedir := filepath.Join(projectConfig.GetWailsJSDir(), "wailsjs")
runtimeDir := filepath.Join(wailsjsbasedir, "runtime")
_ = os.RemoveAll(runtimeDir)
extractor := gosod.New(wrapper.RuntimeWrapper)
err = extractor.Extract(wrapperDir, nil)
err = extractor.Extract(runtimeDir, nil)
if err != nil {
return err
}
targetDir := filepath.Join(projectConfig.WailsJSDir, "wailsjs", "go")
err = os.RemoveAll(targetDir)
goBindingsDir := filepath.Join(wailsjsbasedir, "go")
err = os.RemoveAll(goBindingsDir)
if err != nil {
return err
}
_ = fs.MkDirs(targetDir)
_ = fs.MkDirs(goBindingsDir)
err = bindings.GenerateGoBindings(targetDir)
err = bindings.GenerateGoBindings(goBindingsDir)
if err != nil {
return err
}
wailsJSDir := filepath.Join(projectConfig.WailsJSDir, "wailsjs")
return fs.SetPermissions(wailsJSDir, 0755)
return fs.SetPermissions(wailsjsbasedir, 0755)
}

View File

@ -378,3 +378,27 @@ func FindPathToFile(fsys fs.FS, file string) (string, error) {
}
return "", fmt.Errorf("no index.html found")
}
// FindFileInParents searches for a file in the current directory and all parent directories.
// Returns the absolute path to the file if found, otherwise an empty string
func FindFileInParents(path string, filename string) string {
// Check for bad paths
if _, err := os.Stat(path); err != nil {
return ""
}
var pathToFile string
for {
pathToFile = filepath.Join(path, filename)
if _, err := os.Stat(pathToFile); err == nil {
break
}
parent := filepath.Dir(path)
if parent == path {
return ""
}
path = parent
}
return pathToFile
}

View File

@ -1,6 +1,7 @@
package fs
import (
"github.com/samber/lo"
"os"
"path/filepath"
"testing"
@ -10,22 +11,80 @@ import (
func TestRelativePath(t *testing.T) {
is := is.New(t)
i := is.New(t)
cwd, err := os.Getwd()
is.Equal(err, nil)
i.Equal(err, nil)
// Check current directory
actual := RelativePath(".")
is.Equal(actual, cwd)
i.Equal(actual, cwd)
// Check 2 parameters
actual = RelativePath("..", "fs")
is.Equal(actual, cwd)
i.Equal(actual, cwd)
// Check 3 parameters including filename
actual = RelativePath("..", "fs", "fs.go")
expected := filepath.Join(cwd, "fs.go")
is.Equal(actual, expected)
i.Equal(actual, expected)
}
func Test_FindFileInParents(t *testing.T) {
tests := []struct {
name string
setup func() (startDir string, configDir string)
wantErr bool
}{
{
name: "should error when no wails.json file is found in local or parent dirs",
setup: func() (string, string) {
tempDir := os.TempDir()
testDir := lo.Must(os.MkdirTemp(tempDir, "projectPath"))
_ = os.MkdirAll(testDir, 0755)
return testDir, ""
},
wantErr: true,
},
{
name: "should find wails.json in local path",
setup: func() (string, string) {
tempDir := os.TempDir()
testDir := lo.Must(os.MkdirTemp(tempDir, "projectPath"))
_ = os.MkdirAll(testDir, 0755)
configFile := filepath.Join(testDir, "wails.json")
_ = os.WriteFile(configFile, []byte("{}"), 0755)
return testDir, configFile
},
wantErr: false,
},
{
name: "should find wails.json in parent path",
setup: func() (string, string) {
tempDir := os.TempDir()
testDir := lo.Must(os.MkdirTemp(tempDir, "projectPath"))
_ = os.MkdirAll(testDir, 0755)
parentDir := filepath.Dir(testDir)
configFile := filepath.Join(parentDir, "wails.json")
_ = os.WriteFile(configFile, []byte("{}"), 0755)
return testDir, configFile
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
path, expectedPath := tt.setup()
defer func() {
if expectedPath != "" {
_ = os.Remove(expectedPath)
}
}()
got := FindFileInParents(path, "wails.json")
if got != expectedPath {
t.Errorf("FindFileInParents() got = %v, want %v", got, expectedPath)
}
})
}
}

View File

@ -2,6 +2,7 @@ package project
import (
"encoding/json"
"github.com/samber/lo"
"os"
"path/filepath"
"runtime"
@ -39,7 +40,7 @@ type Project struct {
Path string
// Build directory
BuildDir string
BuildDir string `json:"build:dir"`
// The output filename
OutputFilename string `json:"outputfilename"`
@ -88,6 +89,30 @@ type Project struct {
// Garble
Obfuscated bool `json:"obfuscated"`
GarbleArgs string `json:"garbleargs"`
// Frontend directory
FrontendDir string `json:"frontend:dir"`
}
func (p *Project) GetFrontendDir() string {
if filepath.IsAbs(p.FrontendDir) {
return p.FrontendDir
}
return filepath.Join(p.Path, p.FrontendDir)
}
func (p *Project) GetWailsJSDir() string {
if filepath.IsAbs(p.WailsJSDir) {
return p.WailsJSDir
}
return filepath.Join(p.Path, p.WailsJSDir)
}
func (p *Project) GetBuildDir() string {
if filepath.IsAbs(p.BuildDir) {
return p.BuildDir
}
return filepath.Join(p.Path, p.BuildDir)
}
func (p *Project) GetDevBuildCommand() string {
@ -119,6 +144,70 @@ func (p *Project) Save() error {
return os.WriteFile(p.filename, data, 0755)
}
func (p *Project) setDefaults() {
if p.Path == "" {
p.Path = lo.Must(os.Getwd())
}
if p.Version == "" {
p.Version = "2"
}
// Create default name if not given
if p.Name == "" {
p.Name = "wailsapp"
}
if p.OutputFilename == "" {
p.OutputFilename = p.Name
}
if p.FrontendDir == "" {
p.FrontendDir = "frontend"
}
if p.WailsJSDir == "" {
p.WailsJSDir = p.FrontendDir
}
if p.BuildDir == "" {
p.BuildDir = "build"
}
if p.DebounceMS == 0 {
p.DebounceMS = 100
}
if p.DevServer == "" {
p.DevServer = "localhost:34115"
}
if p.NSISType == "" {
p.NSISType = "multiple"
}
if p.Info.CompanyName == "" {
p.Info.CompanyName = p.Name
}
if p.Info.ProductName == "" {
p.Info.ProductName = p.Name
}
if p.Info.ProductVersion == "" {
p.Info.ProductVersion = "1.0.0"
}
if p.Info.Copyright == nil {
v := "Copyright........."
p.Info.Copyright = &v
}
if p.Info.Comments == nil {
v := "Built using Wails (https://wails.io)"
p.Info.Comments = &v
}
// Fix up OutputFilename
switch runtime.GOOS {
case "windows":
if !strings.HasSuffix(p.OutputFilename, ".exe") {
p.OutputFilename += ".exe"
}
case "darwin", "linux":
if strings.HasSuffix(p.OutputFilename, ".exe") {
p.OutputFilename = strings.TrimSuffix(p.OutputFilename, ".exe")
}
}
}
// Author stores details about the application author
type Author struct {
Name string `json:"name"`
@ -133,69 +222,28 @@ type Info struct {
Comments *string `json:"comments"`
}
// Parse the given JSON data into a Project struct
func Parse(projectData []byte) (*Project, error) {
project := &Project{}
err := json.Unmarshal(projectData, project)
if err != nil {
return nil, err
}
project.setDefaults()
return project, nil
}
// Load the project from the current working directory
func Load(projectPath string) (*Project, error) {
// Attempt to load project.json
projectFile := filepath.Join(projectPath, "wails.json")
rawBytes, err := os.ReadFile(projectFile)
if err != nil {
return nil, err
}
// Unmarshal JSON
var result Project
err = json.Unmarshal(rawBytes, &result)
result, err := Parse(rawBytes)
if err != nil {
return nil, err
}
// Fix up our project paths
result.filename = projectFile
if result.Version == "" {
result.Version = "2"
}
// Create default name if not given
if result.Name == "" {
result.Name = "wailsapp"
}
// Fix up OutputFilename
switch runtime.GOOS {
case "windows":
if !strings.HasSuffix(result.OutputFilename, ".exe") {
result.OutputFilename += ".exe"
}
case "darwin", "linux":
if strings.HasSuffix(result.OutputFilename, ".exe") {
result.OutputFilename = strings.TrimSuffix(result.OutputFilename, ".exe")
}
}
if result.Info.CompanyName == "" {
result.Info.CompanyName = result.Name
}
if result.Info.ProductName == "" {
result.Info.ProductName = result.Name
}
if result.Info.ProductVersion == "" {
result.Info.ProductVersion = "1.0.0"
}
if result.Info.Copyright == nil {
v := "Copyright........."
result.Info.Copyright = &v
}
if result.Info.Comments == nil {
v := "Built using Wails (https://wails.io)"
result.Info.Comments = &v
}
if result.DevServer == "" {
result.DevServer = "localhost:34115"
}
// Return our project data
return &result, nil
return result, nil
}

View File

@ -0,0 +1,129 @@
package project_test
import (
"github.com/samber/lo"
"github.com/wailsapp/wails/v2/internal/project"
"os"
"path/filepath"
"runtime"
"testing"
)
func TestProject_GetFrontendDir(t *testing.T) {
cwd := lo.Must(os.Getwd())
tests := []struct {
name string
inputJSON string
want string
wantError bool
}{
{
name: "Should use 'frontend' by default",
inputJSON: "{}",
want: filepath.ToSlash(filepath.Join(cwd, "frontend")),
wantError: false,
},
{
name: "Should resolve a relative path with no project path",
inputJSON: `{"frontend:dir": "./frontend"}`,
want: filepath.ToSlash(filepath.Join(cwd, "frontend")),
wantError: false,
},
{
name: "Should resolve a relative path with project path set",
inputJSON: `{"frontend:dir": "./frontend", "projectdir": "/home/user/project"}`,
want: "/home/user/project/frontend",
wantError: false,
},
{
name: "Should honour an absolute path",
inputJSON: func() string {
if runtime.GOOS == "windows" {
return `{"frontend:dir": "C:\\frontend", "projectdir": "C:\\project"}`
} else {
return `{"frontend:dir": "/home/myproject/frontend", "projectdir": "/home/user/project"}`
}
}(),
want: func() string {
if runtime.GOOS == "windows" {
return `C:/frontend`
} else {
return `/home/myproject/frontend`
}
}(),
wantError: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
proj, err := project.Parse([]byte(tt.inputJSON))
if err != nil && !tt.wantError {
t.Errorf("Error parsing project: %s", err)
}
got := proj.GetFrontendDir()
got = filepath.ToSlash(got)
if got != tt.want {
t.Errorf("GetFrontendDir() = %v, want %v", got, tt.want)
}
})
}
}
func TestProject_GetBuildDir(t *testing.T) {
cwd := lo.Must(os.Getwd())
tests := []struct {
name string
inputJSON string
want string
wantError bool
}{
{
name: "Should use 'build' by default",
inputJSON: "{}",
want: filepath.ToSlash(filepath.Join(cwd, "build")),
wantError: false,
},
{
name: "Should resolve a relative path with no project path",
inputJSON: `{"build:dir": "./build"}`,
want: filepath.ToSlash(filepath.Join(cwd, "build")),
wantError: false,
},
{
name: "Should resolve a relative path with project path set",
inputJSON: `{"build:dir": "./build", "projectdir": "/home/user/project"}`,
want: "/home/user/project/build",
wantError: false,
},
{
name: "Should honour an absolute path",
inputJSON: func() string {
if runtime.GOOS == "windows" {
return `{"build:dir": "C:\\build", "projectdir": "C:\\project"}`
} else {
return `{"build:dir": "/home/myproject/build", "projectdir": "/home/user/project"}`
}
}(),
want: func() string {
if runtime.GOOS == "windows" {
return `C:/build`
} else {
return `/home/myproject/build`
}
}(),
wantError: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
proj, err := project.Parse([]byte(tt.inputJSON))
if err != nil && !tt.wantError {
t.Errorf("Error parsing project: %s", err)
}
got := proj.GetBuildDir()
got = filepath.ToSlash(got)
if got != tt.want {
t.Errorf("GetFrontendDir() = %v, want %v", got, tt.want)
}
})
}
}

View File

@ -7,11 +7,11 @@ import (
"fmt"
iofs "io/fs"
"os"
"path"
"path/filepath"
"text/template"
"github.com/leaanthony/gosod"
"github.com/samber/lo"
"github.com/wailsapp/wails/v2/internal/fs"
"github.com/wailsapp/wails/v2/internal/project"
)
@ -19,9 +19,12 @@ import (
//go:embed build
var assets embed.FS
const (
rootFolder = "build"
)
// Same as assets but chrooted into /build/
var buildAssets iofs.FS
func init() {
buildAssets = lo.Must(iofs.Sub(assets, "build"))
}
// Install will install all default project assets
func Install(targetDir string) error {
@ -36,20 +39,19 @@ func Install(targetDir string) error {
// GetLocalPath returns the local path of the requested build asset file
func GetLocalPath(projectData *project.Project, file string) string {
return filepath.Clean(filepath.Join(projectData.Path, rootFolder, filepath.FromSlash(file)))
return filepath.Clean(filepath.Join(projectData.GetBuildDir(), filepath.FromSlash(file)))
}
// ReadFile reads the file from the project build folder.
// If the file does not exist it falls back to the embedded file and the file will be written
// to the disk for customisation.
func ReadFile(projectData *project.Project, file string) ([]byte, error) {
fs := os.DirFS(filepath.ToSlash(projectData.Path)) // os.DirFs always operates on "/" as separatator
file = path.Join(rootFolder, file)
localFilePath := GetLocalPath(projectData, file)
content, err := iofs.ReadFile(fs, file)
content, err := os.ReadFile(localFilePath)
if errors.Is(err, iofs.ErrNotExist) {
// The file does not exist, let's read it from the assets FS and write it to disk
content, err := iofs.ReadFile(assets, file)
content, err := iofs.ReadFile(buildAssets, file)
if err != nil {
return nil, err
}
@ -83,8 +85,7 @@ func ReadFileWithProjectData(projectData *project.Project, file string) ([]byte,
// ProjectInfo if necessary.
// It will also write the resolved final file back to the project build folder.
func ReadOriginalFileWithProjectDataAndSave(projectData *project.Project, file string) ([]byte, error) {
file = path.Join(rootFolder, file)
content, err := iofs.ReadFile(assets, file)
content, err := iofs.ReadFile(buildAssets, file)
if err != nil {
return nil, fmt.Errorf("Unable to read file %s: %w", file, err)
}
@ -124,15 +125,15 @@ func resolveProjectData(content []byte, projectData *project.Project) ([]byte, e
}
func writeFileSystemFile(projectData *project.Project, file string, content []byte) error {
path := filepath.Clean(filepath.Join(projectData.Path, filepath.FromSlash(file)))
targetPath := GetLocalPath(projectData, file)
if dir := filepath.Dir(path); !fs.DirExists(dir) {
if dir := filepath.Dir(targetPath); !fs.DirExists(dir) {
if err := fs.MkDirs(dir, 0755); err != nil {
return fmt.Errorf("Unable to create directory: %w", err)
}
}
if err := os.WriteFile(path, content, 0644); err != nil {
if err := os.WriteFile(targetPath, content, 0644); err != nil {
return err
}
return nil

View File

@ -263,9 +263,9 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
}
// Get application build directory
appDir := options.BuildDirectory
if options.CleanBuildDirectory {
err = cleanBuildDirectory(options)
appDir := options.BinDirectory
if options.CleanBinDirectory {
err = cleanBinDirectory(options)
if err != nil {
return err
}
@ -291,6 +291,7 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
cmd.Dir = b.projectData.Path
// Add CGO flags
// TODO: Remove this as we don't generate headers any more
// We use the project/build dir as a temporary place for our generated c headers
buildBaseDir, err := fs.RelativeToCwd("build")
if err != nil {
@ -487,6 +488,9 @@ func (b *BaseBuilder) NpmInstallUsingCommand(sourceDir string, installCommand st
// Shortcut installation
if install == false {
if verbose {
println("Skipping npm install")
}
return nil
}
@ -543,7 +547,10 @@ func (b *BaseBuilder) BuildFrontend(outputLogger *clilogger.CLILogger) error {
verbose := b.options.Verbosity == VERBOSE
frontendDir := filepath.Join(b.projectData.Path, "frontend")
frontendDir := b.projectData.GetFrontendDir()
if !fs.DirExists(frontendDir) {
return fmt.Errorf("frontend directory '%s' does not exist", frontendDir)
}
// Check there is an 'InstallCommand' provided in wails.json
installCommand := b.projectData.InstallCommand

View File

@ -35,38 +35,38 @@ const (
// Options contains all the build options as well as the project data
type Options struct {
LDFlags string // Optional flags to pass to linker
UserTags []string // Tags to pass to the Go compiler
Logger *clilogger.CLILogger // All output to the logger
OutputType string // EG: desktop, server....
Mode Mode // release or dev
ProjectData *project.Project // The project data
Pack bool // Create a package for the app after building
Platform string // The platform to build for
Arch string // The architecture to build for
Compiler string // The compiler command to use
SkipModTidy bool // Skip mod tidy before compile
IgnoreFrontend bool // Indicates if the frontend does not need building
IgnoreApplication bool // Indicates if the application does not need building
OutputFile string // Override the output filename
BuildDirectory string // Directory to use for building the application
CleanBuildDirectory bool // Indicates if the build directory should be cleaned before building
CompiledBinary string // Fully qualified path to the compiled binary
KeepAssets bool // Keep the generated assets/files
Verbosity int // Verbosity level (0 - silent, 1 - default, 2 - verbose)
Compress bool // Compress the final binary
CompressFlags string // Flags to pass to UPX
WebView2Strategy string // WebView2 installer strategy
RunDelve bool // Indicates if we should run delve after the build
WailsJSDir string // Directory to generate the wailsjs module
ForceBuild bool // Force
BundleName string // Bundlename for Mac
TrimPath bool // Use Go's trimpath compiler flag
RaceDetector bool // Build with Go's race detector
WindowsConsole bool // Indicates that the windows console should be kept
Obfuscated bool // Indicates that bound methods should be obfuscated
GarbleArgs string // The arguments for Garble
SkipBindings bool // Skip binding generation
LDFlags string // Optional flags to pass to linker
UserTags []string // Tags to pass to the Go compiler
Logger *clilogger.CLILogger // All output to the logger
OutputType string // EG: desktop, server....
Mode Mode // release or dev
ProjectData *project.Project // The project data
Pack bool // Create a package for the app after building
Platform string // The platform to build for
Arch string // The architecture to build for
Compiler string // The compiler command to use
SkipModTidy bool // Skip mod tidy before compile
IgnoreFrontend bool // Indicates if the frontend does not need building
IgnoreApplication bool // Indicates if the application does not need building
OutputFile string // Override the output filename
BinDirectory string // Directory to use to write the built applications
CleanBinDirectory bool // Indicates if the bin output directory should be cleaned before building
CompiledBinary string // Fully qualified path to the compiled binary
KeepAssets bool // Keep the generated assets/files
Verbosity int // Verbosity level (0 - silent, 1 - default, 2 - verbose)
Compress bool // Compress the final binary
CompressFlags string // Flags to pass to UPX
WebView2Strategy string // WebView2 installer strategy
RunDelve bool // Indicates if we should run delve after the build
WailsJSDir string // Directory to generate the wailsjs module
ForceBuild bool // Force
BundleName string // Bundlename for Mac
TrimPath bool // Use Go's trimpath compiler flag
RaceDetector bool // Build with Go's race detector
WindowsConsole bool // Indicates that the windows console should be kept
Obfuscated bool // Indicates that bound methods should be obfuscated
GarbleArgs string // The arguments for Garble
SkipBindings bool // Skip binding generation
}
// Build the project!
@ -81,48 +81,32 @@ func Build(options *Options) (string, error) {
return "", err
}
// Load project
projectData, err := project.Load(cwd)
if err != nil {
return "", err
}
options.ProjectData = projectData
// Add default path if it doesn't exist
if projectData.Path == "" {
projectData.Path = cwd
}
// wails js dir
if projectData.WailsJSDir != "" {
options.WailsJSDir = projectData.WailsJSDir
} else {
options.WailsJSDir = filepath.Join(cwd, "frontend")
}
options.WailsJSDir = options.ProjectData.GetWailsJSDir()
// Set build directory
options.BuildDirectory = filepath.Join(options.ProjectData.Path, "build", "bin")
options.BinDirectory = filepath.Join(options.ProjectData.GetBuildDir(), "bin")
// Save the project type
projectData.OutputType = options.OutputType
options.ProjectData.OutputType = options.OutputType
// Create builder
var builder Builder
switch projectData.OutputType {
switch options.OutputType {
case "desktop":
builder = newDesktopBuilder(options)
case "dev":
builder = newDesktopBuilder(options)
default:
return "", fmt.Errorf("cannot build assets for output type %s", projectData.OutputType)
return "", fmt.Errorf("cannot build assets for output type %s", options.ProjectData.OutputType)
}
// Set up our clean up method
defer builder.CleanUp()
// Initialise Builder
builder.SetProjectData(projectData)
builder.SetProjectData(options.ProjectData)
hookArgs := map[string]string{
"${platform}": options.Platform + "/" + options.Arch,
@ -263,9 +247,9 @@ func execBuildApplication(builder Builder, options *Options) (string, error) {
// Build amd64 first
options.Arch = "amd64"
options.OutputFile = amd64Filename
options.CleanBuildDirectory = false
options.CleanBinDirectory = false
if options.Verbosity == VERBOSE {
outputLogger.Println("\nBuilding AMD64 Target: %s", filepath.Join(options.BuildDirectory, options.OutputFile))
outputLogger.Println("\nBuilding AMD64 Target: %s", filepath.Join(options.BinDirectory, options.OutputFile))
}
err := builder.CompileProject(options)
if err != nil {
@ -274,9 +258,9 @@ func execBuildApplication(builder Builder, options *Options) (string, error) {
// Build arm64
options.Arch = "arm64"
options.OutputFile = arm64Filename
options.CleanBuildDirectory = false
options.CleanBinDirectory = false
if options.Verbosity == VERBOSE {
outputLogger.Println("Building ARM64 Target: %s", filepath.Join(options.BuildDirectory, options.OutputFile))
outputLogger.Println("Building ARM64 Target: %s", filepath.Join(options.BinDirectory, options.OutputFile))
}
err = builder.CompileProject(options)
@ -287,21 +271,21 @@ func execBuildApplication(builder Builder, options *Options) (string, error) {
if options.Verbosity == VERBOSE {
outputLogger.Println(" Running lipo: lipo -create -output %s %s %s", outputFile, amd64Filename, arm64Filename)
}
_, stderr, err := shell.RunCommand(options.BuildDirectory, "lipo", "-create", "-output", outputFile, amd64Filename, arm64Filename)
_, stderr, err := shell.RunCommand(options.BinDirectory, "lipo", "-create", "-output", outputFile, amd64Filename, arm64Filename)
if err != nil {
return "", fmt.Errorf("%s - %s", err.Error(), stderr)
}
// Remove temp binaries
err = fs.DeleteFile(filepath.Join(options.BuildDirectory, amd64Filename))
err = fs.DeleteFile(filepath.Join(options.BinDirectory, amd64Filename))
if err != nil {
return "", err
}
err = fs.DeleteFile(filepath.Join(options.BuildDirectory, arm64Filename))
err = fs.DeleteFile(filepath.Join(options.BinDirectory, arm64Filename))
if err != nil {
return "", err
}
options.ProjectData.OutputFilename = outputFile
options.CompiledBinary = filepath.Join(options.BuildDirectory, outputFile)
options.CompiledBinary = filepath.Join(options.BinDirectory, outputFile)
} else {
err := builder.CompileProject(options)
if err != nil {
@ -392,7 +376,7 @@ func executeBuildHook(outputLogger *clilogger.CLILogger, options *Options, hookI
outputLogger.Println("%s", strings.Join(args, " "))
}
stdout, stderr, err := shell.RunCommand(options.BuildDirectory, args[0], args[1:]...)
stdout, stderr, err := shell.RunCommand(options.BinDirectory, args[0], args[1:]...)
if options.Verbosity == VERBOSE {
println(stdout)
}

View File

@ -8,7 +8,6 @@ import (
// Builder defines a builder that can build Wails applications
type Builder interface {
SetProjectData(projectData *project.Project)
BuildAssets(*Options) error
BuildFrontend(*clilogger.CLILogger) error
CompileProject(*Options) error
OutputFilename(*Options) string

View File

@ -1,10 +1,5 @@
package build
import (
"github.com/wailsapp/wails/v2/internal/fs"
"github.com/wailsapp/wails/v2/pkg/buildassets"
)
// DesktopBuilder builds applications for the desktop
type DesktopBuilder struct {
*BaseBuilder
@ -15,18 +10,3 @@ func newDesktopBuilder(options *Options) *DesktopBuilder {
BaseBuilder: NewBaseBuilder(options),
}
}
// BuildAssets builds the assets for the desktop application
func (d *DesktopBuilder) BuildAssets(options *Options) error {
// Check assets directory exists
if !fs.DirExists(options.ProjectData.BuildDir) {
// Path to default assets
err := buildassets.Install(options.ProjectData.Path)
if err != nil {
return err
}
}
return nil
}

View File

@ -3,14 +3,12 @@ package build
import (
"bytes"
"fmt"
"image"
"os"
"path/filepath"
"runtime"
"github.com/leaanthony/winicon"
"github.com/tc-hib/winres"
"github.com/tc-hib/winres/version"
"image"
"os"
"path/filepath"
"github.com/jackmordaunt/icns"
"github.com/pkg/errors"
@ -41,10 +39,10 @@ func packageProject(options *Options, platform string) error {
return nil
}
// cleanBuildDirectory will remove an existing build directory and recreate it
func cleanBuildDirectory(options *Options) error {
// cleanBinDirectory will remove an existing bin directory and recreate it
func cleanBinDirectory(options *Options) error {
buildDirectory := options.BuildDirectory
buildDirectory := options.BinDirectory
// Clear out old builds
if fs.DirExists(buildDirectory) {
@ -63,11 +61,6 @@ func cleanBuildDirectory(options *Options) error {
return nil
}
// Gets the platform dependent package assets directory
func getPackageAssetsDirectory() string {
return fs.RelativePath("internal/packager", runtime.GOOS)
}
func packageApplicationForDarwin(options *Options) error {
var err error
@ -78,7 +71,7 @@ func packageApplicationForDarwin(options *Options) error {
bundlename = options.ProjectData.Name + ".app"
}
contentsDirectory := filepath.Join(options.BuildDirectory, bundlename, "/Contents")
contentsDirectory := filepath.Join(options.BinDirectory, bundlename, "/Contents")
exeDir := filepath.Join(contentsDirectory, "/MacOS")
err = fs.MkDirs(exeDir, 0755)
if err != nil {
@ -174,30 +167,7 @@ func packageApplicationForWindows(options *Options) error {
return nil
}
func packageApplicationForLinux(options *Options) error {
// Generate icon
//var err error
//err = generateIcoFile(options)
//if err != nil {
// return err
//}
//
//// Ensure Manifest is present
//err = generateManifest(options)
//if err != nil {
// return err
//}
//
//// Create syso file
//err = compileResources(options)
//if err != nil {
// return err
//}
return nil
}
func generateManifest(options *Options) error {
func packageApplicationForLinux(_ *Options) error {
return nil
}
@ -238,7 +208,7 @@ func compileResources(options *Options) error {
defer func() {
os.Chdir(currentDir)
}()
windowsDir := filepath.Join(options.ProjectData.Path, "build", "windows")
windowsDir := filepath.Join(options.ProjectData.GetBuildDir(), "windows")
err = os.Chdir(windowsDir)
if err != nil {
return err

View File

@ -19,15 +19,39 @@
"type": "string",
"description": "Additional directories to trigger reloads (comma separated). Often, this is only used for advanced asset configurations."
},
"build:dir": {
"type": "string",
"description": "The directory where the build files reside.",
"default": "build",
"examples": [
"./build",
"/absolute/path/to/build",
"C:\\absolute\\path\\to\\build"
]
},
"frontend:dir": {
"type": "string",
"description": "The directory where the frontend files reside.",
"default": "frontend",
"examples": [
"./src",
"/absolute/path/to/frontend",
"C:\\absolute\\path\\to\\frontend"
]
},
"frontend:install": {
"type": "string",
"description": "The command to install dependencies. Run in the frontend directory.",
"examples": [ "npm install" ]
"examples": [
"npm install"
]
},
"frontend:build": {
"type": "string",
"description": "The command to build the assets. Run in the frontend directory.",
"examples": ["npm run build"]
"examples": [
"npm run build"
]
},
"frontend:dev": {
"type": "string",
@ -58,7 +82,7 @@
"type": "string",
"description": "Relative path to the directory where the auto-generated JS modules will be created.",
"format": "uri-reference",
"default": "./frontend"
"default": "The value of frontend:dir"
},
"version": {
"description": "Project config version",