package main import ( "errors" "fmt" "os" "path/filepath" "strings" "time" "go.wit.com/lib/debian" "go.wit.com/lib/gui/shell" "go.wit.com/lib/protobuf/argvpb" "go.wit.com/lib/protobuf/gitpb" "go.wit.com/log" "google.golang.org/protobuf/types/known/timestamppb" ) func buildPackage(repo *gitpb.Repo) (bool, error) { filename := me.pb.Package arch := me.pb.Architecture version := me.pb.Version log.Info("version is:", version) debname := filename + "_" + version + "_" + arch + ".deb" var fulldebname string if argv.OutDir == "" { fulldebname = debname } else { fulldebname = filepath.Join(argv.OutDir, debname) } if shell.Exists(fulldebname) { log.Info("debian package already built: " + fulldebname) return true, errors.New("debian package already built: " + fulldebname) } var fullfilename string _, fullfilename = filepath.Split(filename) if fullfilename == "" { log.Info("fullfilename =", fullfilename) badExit(log.Errorf("binary name was blank")) } if fullfilename == "." { log.Info("fullfilename =", fullfilename) badExit(log.Errorf("binary name was .")) } if shell.Exists(fullfilename) { repo.RunVerbose([]string{"rm", "-f", fullfilename}) } if shell.Exists(fullfilename) { // something wrong return false, errors.New("binary existed before build") } if argv.Release { os.Unsetenv("GO111MODULE") cmd := []string{"go"} cmd = append(cmd, "install") if argv.Verbose { cmd = append(cmd, "-v") cmd = append(cmd, "-x") } cmd = append(cmd, repo.Namespace+"@v"+version) if err := shell.PathExecVerbose("", cmd); err != nil { badExit(err) return false, fmt.Errorf("go build err %v", err) } /* cmd = []string{"go"} cmd = append(cmd, "build") if argv.Verbose { cmd = append(cmd, "-v") cmd = append(cmd, "-x") } cmd = append(cmd, "this should be the path") if err := shell.PathExecVerbose("", cmd); err != nil { badExit(err) return false, fmt.Errorf("go build err %v", err) } */ log.Warn("build worked") } else { // set the GO111 build var to true. pass the versions to the compiler manually os.Setenv("GO111MODULE", "off") if argv.Arch == "riscv64" { os.Setenv("GOARCH", "riscv64") // GOOS=windows GOARCH=amd64 GO111MODULE=off go build -v -o wit.exe \ } cmd := []string{"go", "build"} // set standard ldflag options now := time.Now() var datestamp string datestamp = log.Sprintf("%d", now.Unix()) log.Info("datestamp =", datestamp) // add some standard golang flags var ldflags string if argv.Release { // * -w: Omit the DWARF symbol table. // * -s: Omit the symbol table and debug information. ldflags += "-s -w " } gitversion := repo.GetCurrentVersion() if gitversion == "" { ldflags += "-X main.VERSION=" + version + " " } else { // use the more accurate git version in the binary itself ldflags += "-X main.VERSION=" + gitversion + " " } ldflags += "-X main.BUILDTIME=" + datestamp + " " ldflags += "-X main.GUIVERSION=" + version + "" // todo: git this from the filesystem cmd = append(cmd, "-ldflags", ldflags) // add any flags from the command line // this might not actually work // todo: test this for _, flag := range argv.Ldflags { cmd = append(cmd, "-ldflags", "-X "+flag) } me.pb.BuildDate = timestamppb.New(time.Now()) err := repo.RunVerbose(cmd) if err != nil { return false, fmt.Errorf("go build err %v", err) } log.Warn("go build worked") } if shell.Exists("files") { repo.RunVerbose([]string{"rm", "-rf", "files"}) // log.Info("running sync") repo.RunVerbose([]string{"sync"}) if shell.Exists("files") { log.Warn("rm failed for some reason") return false, errors.New("rm files/") } } repo.RunVerbose([]string{"sync"}) // for some reason the next check fails sometimes? if shell.Exists("files") { // probably the 'shell' package id being stupid and not waiting for the process to actually exit log.Warn("rm failed. files/ still exists. is golang doing these in parallel?") return false, errors.New("rm files/") } if err := os.MkdirAll("files/DEBIAN", os.ModePerm); err != nil { return false, errors.New("mkdir files/DEBIAN") } if err := os.MkdirAll("files/usr/bin", os.ModePerm); err != nil { log.Warn("mkdir failed") return false, errors.New("mkdir files/usr/bin") } if os.Getenv("GO_DEB_CUSTOM") == "true" { // skip cp & strip on custom 'control' files // probably deprecate this log.Info("REPO GO_DEB_CUSTOM=true means binary is not copied") } else { _, fname := filepath.Split(repo.GetFullPath()) cmd := []string{"cp", fname, "files/usr/bin"} log.Info("REPO FILENAME cp", cmd) if err := repo.RunVerbose(cmd); err != nil { log.Warn("cp failed") return false, err } if argv.Arch == "amd64" { cmd = []string{"strip", "files/usr/bin/" + fname} if err := repo.RunVerbose(cmd); err != nil { log.Warn("strip failed") return false, err } } } // put the README in there (if missing, generate it?) var readme string = "" if shell.Exists("README.md") { readme = "README.md" } if shell.Exists("README") { readme = "README" } if readme != "" { path := filepath.Join("files/usr/share/doc/" + filename) if err := os.MkdirAll(path, os.ModePerm); err != nil { return false, errors.New("mkdir failed on files/usr/share/doc") } if err := repo.RunVerbose([]string{"cp", readme, path}); err != nil { return false, err } } if shell.Exists("postinst") { repo.RunVerbose([]string{"cp", "postinst", "files/DEBIAN/"}) } // experiment for the toolkit package // if the git repo has a "./build" script run it before packaging // this way the user can put custom files in the .deb package if shell.Exists("build") { log.Info(repo.FullPath, "FOUND ./build HERE") repo.RunVerbose([]string{"./build"}) } else { log.Info(repo.FullPath, "NOT FOUND ./build HERE") } r := repo.Run([]string{"du", "-s"}) if len(r.Stdout) != 1 { argvpb.BadExit("du -s files/ failed", r.Error) } me.pb.DebInfo.InstalledSize = strings.Fields(r.Stdout[0])[0] controlfile := debian.MakeControlFile(me.pb) controlfile += "\n" log.Info(controlfile) if err := os.WriteFile("files/DEBIAN/control", []byte(controlfile), 0644); err != nil { argvpb.BadExit("write err files/DEBIAN/control", err) } cmd := []string{"dpkg-deb", "--root-owner-group", "--build", "files", fulldebname} result := repo.RunVerbose(cmd) if shell.Exists(fulldebname) { } else { log.Warn("CMD FAILED", cmd, result) log.Warn("build failed: full name was not created:", fulldebname) return false, errors.New("dpkg-deb --build failed") } repo.RunVerbose([]string{"dpkg-deb", "-I", fulldebname}) repo.RunVerbose([]string{"dpkg-deb", "-c", fulldebname}) // cleanup files if shell.Exists("files") { if argv.KeepFiles { log.Info("keeping the build files/") } else { repo.RunVerbose([]string{"rm", "-rf", "files"}) // log.Info("running sync") repo.RunVerbose([]string{"sync"}) if shell.Exists("files") { log.Warn("rm -rf files/ failed. Run() returned false") return false, errors.New("rm files/") } } } return true, nil }