diff --git a/src/bpm/main.go b/src/bpm/main.go index 69f625c..6602f7a 100644 --- a/src/bpm/main.go +++ b/src/bpm/main.go @@ -92,6 +92,7 @@ func main() { currentFlagSet.String("installation-reason", "", "Specify the installation reason to use for the specified packages") currentFlagSet.BoolP("reinstall", "r", false, "Reinstall the specified packages") currentFlagSet.BoolP("reinstall-all", "a", false, "Reinstall the specified packages and their dependencies") + currentFlagSet.IntP("jobs", "j", bpmlib.CompilationBPMConfig.CompilationJobs, "Set the amount of concurrent processes to use for source package compilation") setupFlagsAndHelp(currentFlagSet, fmt.Sprintf("bpm %s ", subcommand), "Install the specified packages", os.Args[2:]) installPackages() @@ -141,6 +142,7 @@ func main() { currentFlagSet.BoolP("no-sync", "n", false, "Do not sync databases") currentFlagSet.Bool("allow-downgrades", false, "Allow package downgrades") currentFlagSet.BoolP("optional", "o", false, "Install all optional dependencies") + currentFlagSet.IntP("jobs", "j", bpmlib.CompilationBPMConfig.CompilationJobs, "Set the amount of concurrent processes to use for source package compilation") setupFlagsAndHelp(currentFlagSet, fmt.Sprintf("bpm %s ", subcommand), "Update installed packages", os.Args[2:]) updatePackages() @@ -163,6 +165,7 @@ func main() { currentFlagSet.BoolP("keep", "k", false, "Keep compilation files after successful package compilation") currentFlagSet.BoolP("output-directory", "o", false, "Set the output directory for the binary packages") currentFlagSet.Int("output-fd", -1, "Set the file descriptor output package names will be written to") + currentFlagSet.IntP("jobs", "j", bpmlib.CompilationBPMConfig.CompilationJobs, "Set the amount of concurrent processes to use for source package compilation") setupFlagsAndHelp(currentFlagSet, fmt.Sprintf("bpm %s ", subcommand), "Compile source packages and convert them to binary ones", os.Args[2:]) compilePackage() @@ -486,6 +489,7 @@ func installPackages() { installationReason, _ := currentFlagSet.GetString("installation-reason") reinstall, _ := currentFlagSet.GetBool("reinstall") reinstallAll, _ := currentFlagSet.GetBool("reinstall-all") + compilationJobs, _ := currentFlagSet.GetInt("jobs") // Get packages packages := currentFlagSet.Args() @@ -556,6 +560,9 @@ func installPackages() { return } + // Set compilation job count + operation.CompilationJobs = compilationJobs + // Exit if operation contains no actions if len(operation.Actions) == 0 { fmt.Println("No action needs to be taken") @@ -900,6 +907,7 @@ func updatePackages() { noSync, _ := currentFlagSet.GetBool("no-sync") allowDowngrades, _ := currentFlagSet.GetBool("allow-downgrades") installOptional, _ := currentFlagSet.GetBool("optional") + compilationJobs, _ := currentFlagSet.GetInt("jobs") // Check for required permissions if os.Getuid() != 0 { @@ -948,6 +956,9 @@ func updatePackages() { return } + // Set compilation job count + operation.CompilationJobs = compilationJobs + // Exit if operation contains no actions if len(operation.Actions) == 0 { fmt.Println("No action needs to be taken") @@ -1126,6 +1137,7 @@ func compilePackage() { skipChecks, _ := currentFlagSet.GetBool("skip-checks") outputDirectory, _ := currentFlagSet.GetString("output-directory") outputFd, _ := currentFlagSet.GetInt("output-fd") + compilationJobs, _ := currentFlagSet.GetInt("jobs") // Get files sourcePackages := currentFlagSet.Args() @@ -1319,7 +1331,7 @@ func compilePackage() { return } - outputBpmPackages, err := bpmlib.CompileSourcePackage(sourcePackage, outputDirectory, skipChecks, keepCompilationFiles, verbose) + outputBpmPackages, err := bpmlib.CompileSourcePackage(sourcePackage, outputDirectory, compilationJobs, skipChecks, keepCompilationFiles, verbose) if err != nil { // Remove unused packages cleanupFunc() diff --git a/src/bpmlib/compilation.go b/src/bpmlib/compilation.go index 5b9e143..4c36e8c 100644 --- a/src/bpmlib/compilation.go +++ b/src/bpmlib/compilation.go @@ -11,6 +11,7 @@ import ( "os/exec" "path" "path/filepath" + "runtime" "slices" "strconv" "strings" @@ -23,7 +24,12 @@ import ( var rootCompilationUID = "65534" var rootCompilationGID = "65534" -func CompileSourcePackage(archiveFilename, outputDirectory string, skipChecks, keepCompilationFiles, verbose bool) (outputBpmPackages map[string]string, err error) { +func CompileSourcePackage(archiveFilename, outputDirectory string, compilationJobs int, skipChecks, keepCompilationFiles, verbose bool) (outputBpmPackages map[string]string, err error) { + // Set compilation jobs + if compilationJobs <= 0 || compilationJobs > runtime.NumCPU() { + compilationJobs = runtime.NumCPU() + } + // Initialize map outputBpmPackages = make(map[string]string) @@ -139,8 +145,27 @@ func CompileSourcePackage(archiveFilename, outputDirectory string, skipChecks, k env = append(env, "BPM_PKG_REVISION="+strconv.Itoa(bpmpkg.PkgInfo.Revision)) env = append(env, "BPM_PKG_URL="+bpmpkg.PkgInfo.Url) env = append(env, "BPM_PKG_ARCH="+bpmpkg.PkgInfo.OutputArch) + env = append(env, "BPM_JOBS="+strconv.Itoa(compilationJobs)) env = append(env, CompilationBPMConfig.CompilationEnvironment...) + // Set common flags used for limiting job count + makeflags := "" + env = slices.DeleteFunc(env, func(s string) bool { + if strings.HasPrefix(s, "MAKEFLAGS=") { + makeflags = s + " " + return true + } else if strings.HasPrefix(s, "CMAKE_BUILD_PARALLEL_LEVEL=") { + return true + } else if strings.HasPrefix(s, "CARGO_BUILD_JOBS=") { + return true + } + + return false + }) + env = append(env, makeflags+"-j"+strconv.Itoa(compilationJobs)) + env = append(env, "CMAKE_BUILD_PARALLEL_LEVEL="+strconv.Itoa(compilationJobs)) + env = append(env, "CARGO_BUILD_JOBS="+strconv.Itoa(compilationJobs)) + // Execute prepare and build functions in source.sh script cmd := exec.Command("bash", "-c", "set -a\n"+ // Source and export functions and variables in source.sh script diff --git a/src/bpmlib/config.go b/src/bpmlib/config.go index 33afda8..70af00f 100644 --- a/src/bpmlib/config.go +++ b/src/bpmlib/config.go @@ -21,6 +21,7 @@ type configDatabase struct { type CompilationBPMConfigStruct struct { PrivilegeEscalatorCmd string `yaml:"privilege_escalator_cmd"` + CompilationJobs int `yaml:"compilation_jobs"` CompilationEnvironment []string `yaml:"compilation_env"` } diff --git a/src/bpmlib/operations.go b/src/bpmlib/operations.go index 848a849..6ed2372 100644 --- a/src/bpmlib/operations.go +++ b/src/bpmlib/operations.go @@ -15,6 +15,7 @@ type BPMOperation struct { Actions []OperationAction UnresolvedDepends []string Changes map[string]string + CompilationJobs int RootDir string compiledPackages map[string]string @@ -670,7 +671,7 @@ func (operation *BPMOperation) Execute(verbose, force bool) (err error) { // Compile source package if not compiled already if _, ok := operation.compiledPackages[pkgNameToInstall]; !ok { - outputBpmPackages, err := CompileSourcePackage(value.File, compiledDir, false, false, verbose) + outputBpmPackages, err := CompileSourcePackage(value.File, compiledDir, operation.CompilationJobs, false, false, verbose) if err != nil { return fmt.Errorf("could not compile source package (%s): %s\n", value.File, err) }