package rosa import ( "slices" "strings" "hakurei.app/pkg" ) var ( _muon = H("muon") _meson = H("meson") ) // MesonHelper builds and tests a meson project. type MesonHelper struct { // Use muon instead of meson. Muon bool // Runs after setup. ScriptCompileEarly string // Runs after compile. ScriptCompiled string // Runs after install. Script string // Flags passed to the setup command. Setup []KV // Test suites to skip. SkipTests []string // Whether to skip meson test. SkipTest bool // Run tests with interactive input/output. InteractiveTest bool } var _ Helper = new(MesonHelper) // tools returns hardcoded meson runtime dependencies. func (attr *MesonHelper) tools(t Toolchain) P { m := _muon if attr.isPython() { m = _meson } if t.cross() { return P{m, _qemu} } return P{m} } // paths returns the cross-compiler mfile, or nil if not cross-compiling. func (*MesonHelper) paths(t Toolchain) []pkg.ExecPath { if !t.cross() { return nil } arch, mesonArch, target := t.Arch(), t.linuxArch(), t.triple() return []pkg.ExecPath{pkg.Path( AbsSystem.Append("mfile"), false, pkg.NewFile("mfile-"+arch, []byte(`# meson env2mfile [binaries] # Compilers c = ['clang', '--target=`+target+`', '--sysroot=/system/`+arch+`'] cpp = ['clang++', '--target=`+target+`', '--sysroot=/system/`+arch+`'] pkg-config = ['pkg-config'] exe_wrapper = ['qemu-`+mesonArch+`', '-L', '/system/`+arch+`'] # Other binaries ar = ['llvm-ar'] ranlib = ['llvm-ranlib'] strip = ['llvm-strip'] [built-in options] [properties] sys_root = '/system/`+arch+`' pkg_config_libdir = [ '/system/`+arch+`/system/lib/pkgconfig', '/system/`+arch+`/system/share/pkgconfig' ] [host_machine] cpu = '`+mesonArch+`' cpu_family = '`+mesonArch+`' endian = 'little' system = 'linux' subsystem = 'linux' kernel = 'linux' `)), )} } // inputs is a noop. func (*MesonHelper) inputs() P { return nil } // wantsChmod returns false. func (*MesonHelper) wantsChmod() bool { return false } // wantsWrite returns false. func (*MesonHelper) wantsWrite() bool { return false } // scriptEarly returns the zero value. func (*MesonHelper) scriptEarly() string { return "" } // wantsDir requests a new directory in TMPDIR. func (*MesonHelper) wantsDir() (string, bool) { return `"$(mktemp -d)"`, false } // isPython returns whether the legacy python implementation is used. func (attr *MesonHelper) isPython() bool { return attr == nil || !attr.Muon || len(attr.SkipTests) != 0 || attr.InteractiveTest } // script generates the cure script. func (attr *MesonHelper) script(t Toolchain, name string) string { if attr == nil { attr = new(MesonHelper) } scriptCompiled := attr.ScriptCompiled if len(scriptCompiled) > 0 && scriptCompiled[0] != '\n' { scriptCompiled = "\n" + scriptCompiled } python := attr.isPython() muon := "muon" compile := " samu " + jobsFlagE destdir := "-d" if python { muon = "meson" compile = " compile " + jobsFlagE + " " + loadFlagE destdir = "--destdir" } var scriptTest string if !attr.SkipTest && t.opts&OptSkipCheck == 0 { scriptTest = ` ` + muon + ` test \ ` + jobsFlagE + ` \ -t 10` if python { scriptTest += ` \ --print-errorlogs` } else { scriptTest += " -Rv" } if attr.InteractiveTest { scriptTest += ` \ --interactive` } for _, suite := range attr.SkipTests { scriptTest += " \\\n\t--no-suite='" + suite + "'" } } var setupArgs string if t.cross() { setupArgs += " --cross-file=/system/mfile" } return ` ` + muon + ` setup` + setupArgs + ` \ ` + strings.Join(slices.Collect(func(yield func(string) bool) { for _, v := range append([]KV{ {"wrap_mode", "nofallback"}, {"prefix", "/system"}, {"buildtype", "release"}, }, attr.Setup...) { s := v[0] if v[1] != "" { s = "-D" + s + "=" + v[1] } if !yield(s) { return } } }), " \\\n\t") + ` \ '/usr/src/` + name + `' ` + muon + compile + scriptCompiled + scriptTest + ` ` + muon + ` install \ ` + destdir + ` /work ` + attr.Script }