package rosa import ( "slices" "strings" ) var ( _make = H("make") _makeEarly = H("make-early") ) // MakeHelper wraps the make program and its surrounding build system. type MakeHelper struct { // Do not include default extras. OmitDefaults bool // Command to generate the build system. Generate string // Runs before make. ScriptMakeEarly string // Runs before check. ScriptCheckEarly string // Runs after install. Script string // Remain in current directory. InPlace bool // Whether to skip running the configure script. SkipConfigure bool // Alternative name for the configure script. ConfigureName string // Add autoconf arguments regardless of ConfigureName. ForceAutoconf bool // Flags passed to the configure script. Configure []KV // Host target triple, zero value is equivalent to the Rosa OS triple. Host string // Target triple, zero value is equivalent to the Rosa OS triple. Build string // Do not clear program prefix/suffix. DefaultName bool // Omit the target argument. AutoTarget bool // Use the dependency-free [GenericHelper] make. Early bool // Extra make targets. Make []string // Whether to skip the check target. SkipCheck bool // Whether to skip the check target during stage0. SkipCheckEarly bool // Name of the check target, zero value is equivalent to "check". Check []string // Replaces the default install command. Install string } var _ Helper = new(MakeHelper) // tools returns make and other optional dependencies. func (attr *MakeHelper) tools(Toolchain) P { h := _make if attr != nil && attr.Early { h = _makeEarly } if attr == nil || !attr.OmitDefaults { return P{ h, _awk, _coreutils, } } return P{h} } // inputs is a noop. func (*MakeHelper) inputs() P { return nil } // wantsChmod returns whether the build system needs to be generated. func (attr *MakeHelper) wantsChmod() bool { return attr != nil && attr.Generate != "" } // wantsWrite is equivalent to wantsChmod. func (attr *MakeHelper) wantsWrite() bool { return attr.wantsChmod() } // scriptEarly returns the optional build system generation segment. func (attr *MakeHelper) scriptEarly() string { if attr == nil { return "" } generate := attr.Generate if len(generate) > 0 && generate[len(generate)-1] != '\n' { generate += "\n" } return generate } // wantsDir requests a new directory in TMPDIR, or omits the cd statement if InPlace. func (attr *MakeHelper) wantsDir() (string, bool) { if attr != nil && attr.InPlace { return helperInPlace, false } return "/cure/", true } // script generates the cure script. func (attr *MakeHelper) script(t Toolchain, name string) string { if attr == nil { attr = new(MakeHelper) } cross, arch := t.cross(), t.Arch() var configure string target := t.triple() if cross { configure += ` export CC='clang --target=` + target + ` --sysroot=/system/` + arch + `' export CXX='clang++ --target=` + target + ` --sysroot=/system/` + arch + `' ` } if !attr.SkipConfigure { if attr.ConfigureName == "" { configure += `/usr/src/` + name + `/configure` } else { configure += attr.ConfigureName } if attr.ForceAutoconf || attr.ConfigureName == "" { configure += ` \ --prefix=/system` host := target build := host if cross { build = triple(t.native().Arch()) } if attr.Host != "" { host = attr.Host } if attr.Host != `""` { if !attr.DefaultName { configure += ` \ --program-prefix='' \ --program-suffix=''` } if cross { configure += ` \ --with-sysroot='/system/` + arch + `'` } configure += ` \ --host=` + host if !attr.AutoTarget { configure += ` \ --target=` + host } } if attr.Build != "" { build = attr.Build } if attr.Build != `""` { configure += ` \ --build=` + build } } if len(attr.Configure) > 0 { const sep = " \\\n\t" configure += sep + strings.Join( slices.Collect(func(yield func(string) bool) { for _, v := range attr.Configure { s := v[0] if v[0] != "" && v[0][0] >= 'a' && v[0][0] <= 'z' { s = "--" + s } else if len(v[0]) > 1 && v[0][0] == 'D' && v[0][1] >= 'a' && v[0][1] <= 'z' { s = "-" + s } if v[1] != "" { if v[0] != "" { s += "=" } s += v[1] } if !yield(s) { return } } }), sep, ) } } scriptMake := ` make \ ` + jobsFlagE + ` \ ` + loadFlagE if len(attr.Make) > 0 { scriptMake += " \\\n\t" + strings.Join(attr.Make, " \\\n\t") } scriptMake += "\n" if !attr.SkipCheck && t.opts&OptSkipCheck == 0 && (!attr.SkipCheckEarly || !t.stage.isStage0()) { scriptMake += attr.ScriptCheckEarly + `make \ ` + jobsFlagE + ` \ ` + loadFlagE + ` \ AM_COLOR_TESTS=always \ ` if len(attr.Check) > 0 { scriptMake += strings.Join(attr.Check, " \\\n\t") } else { scriptMake += "check" } scriptMake += "\n" } scriptInstall := attr.Install if scriptInstall == "" { scriptInstall = "make DESTDIR=/work install" } scriptInstall += "\n" return configure + attr.ScriptMakeEarly + scriptMake + scriptInstall + attr.Script }