Compare commits

...

2 Commits

Author SHA1 Message Date
Timon Ringwald
003af32f46 more error messages 2022-08-17 18:47:09 +02:00
Timon Ringwald
a5861ca989 added various error messages and warnings 2022-08-17 18:30:45 +02:00
3 changed files with 111 additions and 54 deletions

59
compile.go Normal file
View File

@ -0,0 +1,59 @@
package main
import (
"fmt"
"os/exec"
"sync"
)
func Compile(cfg *CompileConfig, ch chan<- *CompileReport, wg *sync.WaitGroup) {
filename := fmt.Sprintf("%s_%s_%s%s", ProjectName, cfg.OS, cfg.Arch, cfg.FileExt)
ch <- &CompileReport{Config: cfg, State: StateCompiling}
compileCmd := exec.Command("go", "build", "-o", filename)
compileCmd.Dir = ModulePath
if err := compileCmd.Start(); err != nil {
ch <- &CompileReport{Config: cfg, State: StateCompileError}
wg.Done()
return
}
if err := compileCmd.Wait(); err != nil {
ch <- &CompileReport{Config: cfg, State: StateCompileError}
wg.Done()
return
}
Compress(filename, cfg, ch, wg)
// uncomment for independent compile and compress tasks
// (slightly slower in tests, most likely because of more context switches)
/*
ch <- &CompileReport{Config: cfg, State: StateWaiting}
go Runner.Run(func() { Compress(filename, cfg, ch, wg) })
*/
}
func Compress(filename string, cfg *CompileConfig, ch chan<- *CompileReport, wg *sync.WaitGroup) {
defer wg.Done()
ch <- &CompileReport{Config: cfg, State: StateCompressing}
if !*NoCompress && cfg.Compress {
compressCmd := exec.Command("upx", "--best", filename)
compressCmd.Dir = ModulePath
if err := compressCmd.Start(); err != nil {
ch <- &CompileReport{Config: cfg, State: StateCompressError}
return
}
if err := compressCmd.Wait(); err != nil {
ch <- &CompileReport{Config: cfg, State: StateCompressError}
return
}
}
ch <- &CompileReport{Config: cfg, State: StateDone}
}

View File

@ -27,6 +27,8 @@ var (
ColorError = color.New(color.FgRed, color.Bold) ColorError = color.New(color.FgRed, color.Bold)
ColorInProgress = color.New(color.FgBlue) ColorInProgress = color.New(color.FgBlue)
ColorDone = color.New(color.FgGreen, color.Bold) ColorDone = color.New(color.FgGreen, color.Bold)
ColorWarn = color.New(color.FgYellow, color.Bold)
) )
func (s CompileState) String() string { func (s CompileState) String() string {

104
main.go
View File

@ -1,21 +1,29 @@
package main package main
import ( import (
"errors"
"flag" "flag"
"fmt" "fmt"
"os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strconv" "strconv"
"strings"
"sync" "sync"
"time" "time"
"git.milar.in/milarin/channel" "git.milar.in/milarin/channel"
) )
var ModulePath string // globals
var ProjectName string var (
ModulePath string
ProjectName string
Runner channel.Runner
)
// command line arguments
var ( var (
OS = flag.String("os", "", "comma-separated list of operating systems to compile for (empty for all)") OS = flag.String("os", "", "comma-separated list of operating systems to compile for (empty for all)")
Arch = flag.String("arch", "", "comma-separated list of architectures to compile for (empty for all)") Arch = flag.String("arch", "", "comma-separated list of architectures to compile for (empty for all)")
@ -25,21 +33,41 @@ var (
NumThreads = flag.Int("t", runtime.NumCPU(), "amount of threads (0 = infinite)") NumThreads = flag.Int("t", runtime.NumCPU(), "amount of threads (0 = infinite)")
) )
var Runner channel.Runner
func main() { func main() {
var err error var err error
flag.Parse() flag.Parse()
if err := FillCompileConfigs(); err != nil {
panic(err)
}
ModulePath, err = filepath.Abs(flag.Arg(0)) ModulePath, err = filepath.Abs(flag.Arg(0))
if err != nil { if err != nil {
panic(err) panic(err)
} }
ProjectName = filepath.Base(ModulePath)
if _, err := exec.LookPath("go"); err != nil {
ColorError.Fprintln(os.Stderr, "go not found in PATH. compilation not possible")
return
}
if !*NoCompress {
if _, err := exec.LookPath("upx"); err != nil {
ColorWarn.Fprintln(os.Stderr, "upx not found in PATH. file compression not possible")
*NoCompress = true
}
}
if err := FillCompileConfigs(); err != nil {
ColorError.Fprintln(os.Stderr, fmt.Errorf("target architectures could not be determined: %w", err))
return
}
if _, err := os.Stat(filepath.Join(ModulePath, "go.mod")); errors.Is(err, os.ErrNotExist) {
ColorError.Fprintf(os.Stderr, "no Go module found at '%s'\n", ModulePath)
return
}
if err := DetermineProjectName(); err != nil {
ColorError.Fprintln(os.Stderr, fmt.Errorf("project name could not be determined: %w", err))
return
}
ch := make(chan *CompileReport, len(CompileConfigs)) ch := make(chan *CompileReport, len(CompileConfigs))
wg := new(sync.WaitGroup) wg := new(sync.WaitGroup)
@ -65,58 +93,26 @@ func main() {
<-doneCh // wait for Watch <-doneCh // wait for Watch
if !*Silent { if !*Silent {
fmt.Printf("compilation took %s (using %s threads)\n", end.Sub(start), GetThreadCount()) fmt.Printf("compilation took %s (using %s threads)\n", end.Sub(start), GetThreadCountString())
} }
} }
func Compile(cfg *CompileConfig, ch chan<- *CompileReport, wg *sync.WaitGroup) { func DetermineProjectName() error {
filename := fmt.Sprintf("%s_%s_%s%s", ProjectName, cfg.OS, cfg.Arch, cfg.FileExt) data, err := os.ReadFile(filepath.Join(ModulePath, "go.mod"))
if err != nil {
ch <- &CompileReport{Config: cfg, State: StateCompiling} return err
compileCmd := exec.Command("go", "build", "-o", filename)
compileCmd.Dir = ModulePath
if err := compileCmd.Start(); err != nil {
ch <- &CompileReport{Config: cfg, State: StateCompileError}
wg.Done()
return
}
if err := compileCmd.Wait(); err != nil {
ch <- &CompileReport{Config: cfg, State: StateCompileError}
wg.Done()
return
} }
Compress(filename, cfg, ch, wg) for _, line := range strings.Split(string(data), "\n") {
if strings.HasPrefix(line, "module ") {
// uncomment for independent compile and compress tasks fullName := strings.TrimPrefix(line, "module ")
/* parts := strings.Split(fullName, "/")
ch <- &CompileReport{Config: cfg, State: StateWaiting} ProjectName = parts[len(parts)-1]
go Runner.Run(func() { Compress(filename, cfg, ch, wg) }) return nil
*/
}
func Compress(filename string, cfg *CompileConfig, ch chan<- *CompileReport, wg *sync.WaitGroup) {
defer wg.Done()
ch <- &CompileReport{Config: cfg, State: StateCompressing}
if !*NoCompress && cfg.Compress {
compressCmd := exec.Command("upx", "--best", filename)
compressCmd.Dir = ModulePath
if err := compressCmd.Start(); err != nil {
ch <- &CompileReport{Config: cfg, State: StateCompressError}
return
}
if err := compressCmd.Wait(); err != nil {
ch <- &CompileReport{Config: cfg, State: StateCompressError}
return
} }
} }
ch <- &CompileReport{Config: cfg, State: StateDone} return errors.New("malformed syntax in go.mod file")
} }
func GetRunner() channel.Runner { func GetRunner() channel.Runner {
@ -127,7 +123,7 @@ func GetRunner() channel.Runner {
} }
} }
func GetThreadCount() string { func GetThreadCountString() string {
if *NumThreads == 0 { if *NumThreads == 0 {
return "infinitely many" return "infinitely many"
} }