def get_build_install_script(self, build: targets.Build) -> str: service_scripts = self.get_service_scripts(build) if service_scripts: install = build.sh_get_command("cp", relative_to="pkgbuild") extras_dir = build.get_extras_root(relative_to="pkgbuild") install_dir = build.get_install_dir(self, relative_to="pkgbuild") ensuredir = build.target.get_action("ensuredir", build) if TYPE_CHECKING: assert isinstance(ensuredir, targets.EnsureDirAction) commands = [] for path, _content in service_scripts.items(): path = path.relative_to("/") commands.append( ensuredir.get_script(path=str((install_dir / path).parent)) ) args: dict[str, str | None] = { str(extras_dir / path): None, str(install_dir / path): None, } cmd = build.sh_format_command(install, args) commands.append(cmd) return "\n".join(commands) else: return ""
def get_build_install_script(self, build: targets.Build) -> str: script = super().get_build_install_script(build) installdest = build.get_install_dir(self, relative_to="pkgbuild") make = build.sh_get_command("make") return script + textwrap.dedent(f"""\ {make} DESTDIR=$(pwd)/"{installdest}" install_sw """)
def _get_make_env(self, build: targets.Build, wd: str) -> str: openssl_pkg = build.get_package("openssl") libffi_pkg = build.get_package("libffi") uuid_pkg = build.get_package("uuid") zlib_pkg = build.get_package("zlib") env = build.get_ld_env([openssl_pkg, libffi_pkg, uuid_pkg, zlib_pkg], wd) return " ".join(env)
def get_configure_script(self, build: targets.Build) -> str: sdir = build.get_source_dir(self, relative_to="pkgbuild") configure = sdir / "configure" configure_flags = { "--prefix": str(build.get_full_install_prefix()), } return build.sh_format_command(configure, configure_flags)
def get_install_list_script(self, build: targets.Build) -> str: script = super().get_install_list_script(build) openssl_pkg = build.get_package("openssl") python = build.sh_get_command("python", package=self) if build.is_bundled(openssl_pkg): sslpath = ("import ssl; " "print(ssl.get_default_verify_paths().openssl_cafile)") script += f'\n"{python}" -c "{sslpath}"' return script
def get_build_install_script(self, build: targets.Build) -> str: script = super().get_build_install_script(build) cargo = build.sh_get_command("cargo") sed = build.sh_get_command("sed") installdest = build.get_temp_dir(self, relative_to="pkgbuild") src = build.get_source_dir(self, relative_to="pkgbuild") bindir = build.get_install_path("systembin").relative_to("/") install_bindir = (build.get_install_dir(self, relative_to="pkgbuild") / bindir) if isinstance(build.target, targets.linux.LinuxMuslTarget): target = "--target x86_64-unknown-linux-musl" else: target = "" env = build.sh_append_global_flags({}) env["RUST_BACKTRACE"] = "1" env_str = build.sh_format_command("env", env, force_args_eq=True) script += textwrap.dedent(f"""\ {sed} -i -e '/\\[package\\]/,/\\[.*\\]/{{ s/^version\\s*=.*/version = "{self.version.text}"/; }}' \\ "{src}/Cargo.toml" {env_str} \\ {cargo} install {target} \\ --verbose --verbose \\ --root "{installdest}" \\ --path "{src}" \\ --locked mkdir -p "{install_bindir}" cp -a "{installdest}/bin/"* "{install_bindir}/" """) return script
def get_install_list_script(self, build: targets.Build) -> str: common_script = super().get_install_list_script(build) prefix = build.get_full_install_prefix() dest = build.get_install_dir(self, relative_to="pkgbuild") pkgname = getattr(self, "dist_name", None) if pkgname is None: pkgname = self.pretty_name if pkgname.startswith("pypkg-"): pkgname = pkgname[len("pypkg-"):] dist_name = pkgname.replace("-", "_") pyscript = textwrap.dedent(f"""\ import pathlib import site sitepackages = pathlib.Path(site.getsitepackages(["{prefix}"])[0]) abs_sitepackages = ( pathlib.Path("{dest}") / sitepackages.relative_to('/') ) record = ( abs_sitepackages / f'{dist_name}-{self.pretty_version}.dist-info' / 'RECORD' ) if not record.exists(): raise RuntimeError(f'no wheel RECORD for {pkgname}') with open(record) as f: for entry in f: filename = entry.split(',')[0] install_path = (sitepackages / filename).resolve() print(install_path.relative_to('/')) """) scriptfile_name = f"_gen_install_list_from_wheel_{self.unique_name}.py" wheel_files = build.sh_write_python_helper(scriptfile_name, pyscript, relative_to="pkgbuild") if common_script: return f"{common_script}\n{wheel_files}" else: return wheel_files
def sh_get_build_wheel_env(self, build: targets.Build, *, site_packages_var: str) -> dict[str, str]: env = dict(super().sh_get_build_wheel_env( build, site_packages_var=site_packages_var)) sdir = build.get_source_dir(self, relative_to="pkgbuild") env["EXTRA_PYTHONPATH"] = str(sdir) return env
def read_support_files( self, build: targets.Build, file_glob: str, binary: bool = False ) -> dict[str, str] | dict[str, bytes]: mod = sys.modules[type(self).__module__] path = pathlib.Path(mod.__file__).parent / file_glob result = {} for pathname in glob.glob(str(path)): path = pathlib.Path(pathname) mode = "rb" if binary else "r" with open(path, mode) as f: content = f.read() name = path.name if not binary and name.endswith(".in"): content = build.format_package_template(content, self) name = name[:-3] name = name.replace("SLOT", self.slot) name = name.replace( "IDENTIFIER", build.target.get_package_system_ident(build, self), ) result[name] = content return result
def get_configure_script(self, build: targets.Build) -> str: sdir = build.get_source_dir(self, relative_to="pkgbuild") configure = sdir / "configure" configure_flags = { "--disable-all-programs": None, "--enable-libuuid": None, } return self.sh_configure(build, configure, configure_flags)
def get_configure_script(self, build: targets.Build) -> str: sdir = build.get_source_dir(self, relative_to="pkgbuild") configure = sdir / "configure" configure_flags = { "--disable-multi-os-directory": None, } return self.sh_configure(build, configure, configure_flags)
def get_build_script(self, build: targets.Build) -> str: make = build.sh_get_command("make") return textwrap.dedent( f"""\ {make} """ )
def get_configure_script(self, build: targets.Build) -> str: sdir = build.get_source_dir(self, relative_to="pkgbuild") configure = sdir / "source" / "configure" configure_flags = { "--disable-samples": None, "--disable-tests": None, "--enable-rpath": None, } return self.sh_configure(build, configure, configure_flags)
def get_build_install_script(self, build: targets.Build) -> str: common_script = super().get_build_install_script(build) python = build.sh_get_command("python", package=self) root = build.get_install_dir(self, relative_to="pkgbuild") wheeldir_script = 'import pathlib; print(pathlib.Path(".").resolve())' pkgname = getattr(self, "dist_name", None) if pkgname is None: pkgname = self.name if pkgname.startswith("pypkg-"): pkgname = pkgname[len("pypkg-"):] if pkgname == "wheel": binary = False else: binary = True env = { "PIP_DISABLE_PIP_VERSION_CHECK": "1", } env_str = build.sh_format_command("env", env, force_args_eq=True) wheel_install = textwrap.dedent(f"""\ _wheeldir=$("{python}" -c '{wheeldir_script}') {env_str} \\ "{python}" -m pip install \\ --no-build-isolation \\ --ignore-installed \\ --no-index \\ --no-deps \\ --upgrade \\ --force-reinstall \\ --no-warn-script-location -f "file://${{_wheeldir}}" \\ {'--only-binary' if binary else '--no-binary'} :all: \\ --root "{root}" \\ "{pkgname}" """) if common_script: return f"{common_script}\n{wheel_install}" else: return wheel_install
def write_file_list_script( self, build: targets.Build, listname: str, entries: list[str] ) -> str: installdest = build.get_install_dir(self, relative_to="pkgbuild") paths: dict[str, str | pathlib.Path] = {} for aspect in ("systembin", "bin", "data", "include", "lib", "legal"): path = build.get_install_path(aspect).relative_to("/") paths[f"{aspect}dir"] = path paths["prefix"] = build.get_full_install_prefix().relative_to("/") paths["exesuffix"] = build.get_exe_suffix() processed_entries = [] for entry in entries: processed_entries.append( entry.strip().format(**paths).replace("/", os.sep) ) pyscript = textwrap.dedent( """\ import glob import pathlib tmp = pathlib.Path({installdest!r}) patterns = {patterns} for pattern in patterns: for path in glob.glob(str(tmp / pattern), recursive=True): p = pathlib.Path(path) if p.exists(): print(p.relative_to(tmp)) """ ).format( installdest=str(installdest), patterns=pprint.pformat(processed_entries), ) scriptfile_name = f"_gen_{listname}_list_{self.unique_name}.py" return build.sh_write_python_helper( scriptfile_name, pyscript, relative_to="pkgbuild" )
def get_build_tools(self, build: targets.Build) -> dict[str, pathlib.Path]: bindir = build.get_install_path("bin").relative_to("/") datadir = build.get_install_path("data") libdir = build.get_install_path("lib") temp_install_path = build.get_build_dir(self) / "_install" # Since we are using a temporary Postgres installation, # pg_config will return paths together with the temporary # installation prefix, so we need to wrap it to strip # it from certain paths. wrapper = textwrap.dedent(f"""\ import pathlib import subprocess import sys path = ( pathlib.Path(__file__).parent.parent.parent / '{temp_install_path}' ).resolve() pgc = path / '{bindir}' / 'pg_config' proc = subprocess.run( [pgc] + sys.argv[1:], check=True, stdout=subprocess.PIPE, universal_newlines=True) for line in proc.stdout.split('\\n'): if ('{datadir}' in line or ('{libdir}' in line and 'pgxs' not in line)): line = line.replace(str(path), '') print(line) """) wrapper_cmd = build.write_helper("pg_config_wrapper.py", wrapper, relative_to="sourceroot") return { "pg_config_wrapper": wrapper_cmd, "pg_config": temp_install_path / "pg_config_wrapper", }
def get_build_install_script(self, build: targets.Build) -> str: script = super().get_build_install_script(build) srcdir = build.get_source_dir(self, relative_to="pkgbuild") dest = build.get_install_dir(self, relative_to="pkgbuild") datadir = build.get_install_path("data") script += textwrap.dedent(f"""\ mkdir -p "{dest}/{datadir}" cp -a "{srcdir}/tests" "{dest}/{datadir}" mkdir -p "{dest}/{datadir}/data/" cp -a ./share/* "{dest}/{datadir}/data/" chmod 644 "{dest}/{datadir}/data/"* """) if build.target.is_portable(): bindir = build.get_install_path("bin").relative_to("/") ep_helper_pkg = build.get_package("pyentrypoint") ep_helper = ( build.get_temp_dir(ep_helper_pkg, relative_to="pkgbuild") / "bin" / "pyentrypoint") script += textwrap.dedent(f"""\ for p in "{dest}/{bindir}"/*; do if [ -f "$p" ]; then mv "$p" "${{p}}.py" cp "{ep_helper}" "$p" fi done """) return script
def get_build_install_script(self, build: targets.Build) -> str: script = super().get_build_install_script(build) installdest = build.get_install_dir(self, relative_to="pkgbuild") make = build.sh_get_command("make") openssl_pkg = build.get_package("openssl") if build.is_bundled(openssl_pkg): # We must bundle the CA certificates if OpenSSL is bundled. python = build.sh_get_command("python", package=self) temp = build.get_temp_root(relative_to="pkgbuild") sslpath = ("import ssl; " "print(ssl.get_default_verify_paths().openssl_cafile)") certifipath = "import certifi; " "print(certifi.where())" extra_install = textwrap.dedent(f"""\ "{python}" -m pip install \\ --upgrade --force-reinstall \\ --root "{temp}" "certifi" sslpath=$("{python}" -c "{sslpath}") ssl_instpath="$(pwd)/{installdest}/${{sslpath}}" mkdir -p "$(dirname ${{ssl_instpath}})" certifipath=$("{python}" -c "{certifipath}") cp "${{certifipath}}" "${{ssl_instpath}}" """) else: extra_install = "" env = self._get_make_env(build, "$(pwd)") script += textwrap.dedent(f"""\ {make} -j1 DESTDIR=$(pwd)/"{installdest}" {env} \ ENSUREPIP=no install {extra_install} """) return script
def _get_edgedb_catalog_version(self, build: targets.Build) -> str: source = pathlib.Path(build.get_source_dir(self, relative_to="fsroot")) defines = source / "edb" / "buildmeta.py" if not defines.exists(): defines = source / "edb" / "server" / "defines.py" with open(defines, "r") as f: for line in f: if line.startswith("EDGEDB_CATALOG_VERSION = "): return str(int(line[len("EDGEDB_CATALOG_VERSION = "):])) else: raise RuntimeError("cannot determine EDGEDB_CATALOG_VERSION")
def sh_configure( self, build: targets.Build, path: str | pathlib.Path, args: Mapping[str, str | pathlib.Path | None], ) -> str: conf_args = dict(args) shlib_paths = self.get_shlib_paths(build) ldflags = [] for shlib_path in shlib_paths: ldflags.extend( build.target.get_shlib_path_run_time_ldflags( build, shlex.quote(str(shlib_path)) ) ) if ldflags: build.sh_append_flags(conf_args, "LDFLAGS", ldflags) if "--prefix" not in args: conf_args["--prefix"] = str(build.get_full_install_prefix()) conf_args = build.sh_append_global_flags(conf_args) return build.sh_format_command(path, conf_args, force_args_eq=True)
def get_build_install_script(self, build: targets.Build) -> str: script = "" licenses = self.get_license_files_pattern() if licenses: sdir = build.get_source_dir(self, relative_to="pkgbuild") legaldir = build.get_install_path("legal").relative_to("/") lic_dest = ( build.get_install_dir(self, relative_to="pkgbuild") / legaldir ) prefix = str(lic_dest / self.name) script += textwrap.dedent( f"""\ mkdir -p "{lic_dest}" for _lic_src in "{sdir}"/{licenses}; do if [ -e "$_lic_src" ]; then cp "$_lic_src" "{prefix}-$(basename "$_lic_src")" fi done """ ) return script
def sh_get_build_wheel_env(self, build: targets.Build, *, site_packages_var: str) -> dict[str, str]: env = dict(super().sh_get_build_wheel_env( build, site_packages_var=site_packages_var)) bindir = build.get_install_path("bin").relative_to("/") if build.target.is_portable(): runstate = "" else: runstate = str(build.get_install_path("runstate") / "edgedb") shared_dir = (build.get_install_path("data") / "data").relative_to("/") temp_root = build.get_temp_root(relative_to="pkgsource") src_python = build.sh_get_command("python", package=self, relative_to="pkgsource") rel_bindir_script = ";".join(( "import os.path", "rp = os.path.relpath", f"sp = rp('{site_packages_var}', start='{temp_root}')", f"print(rp('{bindir}', start=os.path.join(sp, 'edb')))", )) pg_config = f'!"$("{src_python}" -c "{rel_bindir_script}")"/pg_config' rel_datadir_script = ";".join(( "import os.path", "rp = os.path.relpath", f"sp = rp('{site_packages_var}', start='{temp_root}')", f"print(rp('{shared_dir}', start=os.path.join(sp, 'edb')))", )) data_dir = f'!"$("{src_python}" -c "{rel_datadir_script}")"' env["EDGEDB_BUILD_PG_CONFIG"] = pg_config env["EDGEDB_BUILD_RUNSTATEDIR"] = runstate env["EDGEDB_BUILD_SHARED_DIR"] = data_dir return env
def get_before_install_script(self, build: targets.Build) -> str: dataroot = build.get_install_path("localstate") / "lib" / "edgedb" action = build.target.get_action("adduser", build) assert isinstance(action, targets.AddUserAction) user_script = action.get_script( name="edgedb", group="edgedb", homedir=str(dataroot), shell=True, system=True, description="EdgeDB Server", ) return user_script
def get_configure_script(self, build: targets.Build) -> str: sdir = shlex.quote( str(build.get_source_dir(self, relative_to="pkgbuild"))) copy_sources = f"test ./ -ef {sdir} || cp -a {sdir}/* ./" configure = "./Configure" configure_flags = { "--openssldir": str(build.get_full_install_prefix() / "etc" / "ssl"), "--libdir": str(build.get_install_path("lib")), "no-ssl3": None, "shared": None, "enable-ec_nistp_64_gcc_128": None, } cfgcmd = self.sh_configure(build, configure, configure_flags) if platform.system() == "Darwin": # Force 64-bit build cfgcmd = f"KERNEL_BITS=64 {cfgcmd}" return "\n\n".join([ copy_sources, cfgcmd, ])
def get_build_script(self, build: targets.Build) -> str: make = build.sh_get_command("make") wrapper_path = pathlib.Path("_install") / "pg_config_wrapper" wrapper_cmd = build.sh_get_command("pg_config_wrapper", relative_to="pkgbuild") bash = build.sh_get_command("bash") make_pg_config_wrapper = textwrap.dedent(f"""\ echo '#!{bash}' >> "{wrapper_path}" echo 'set -ex' >> "{wrapper_path}" echo 'pushd "$(dirname $0)/../" >/dev/null' >> "{wrapper_path}" echo '{wrapper_cmd}' '"${{@}}"' >> "{wrapper_path}" echo 'popd >/dev/null' >> "{wrapper_path}" chmod +x "{wrapper_path}" """) return textwrap.dedent(f"""\ {make} {make} -C contrib {make} DESTDIR=$(pwd)/_install install {make} -C contrib DESTDIR=$(pwd)/_install install {make_pg_config_wrapper} """)
def get_exposed_commands(self, build: targets.Build) -> list[pathlib.Path]: bindir = build.get_install_path("bin") return [ bindir / "edgedb-server", ]
def get_build_script(self, build: targets.Build) -> str: # Run edgedb-server --bootstrap to produce stdlib cache # for the benefit of faster bootstrap in the package. common_script = super().get_build_script(build) pg_pkg = build.get_package("postgresql-edgedb") icu_pkg = build.get_package("icu") openssl_pkg = build.get_package("openssl") uuid_pkg = build.get_package("uuid") build_python = build.sh_get_command("python") temp_dir = build.get_temp_dir(self, relative_to="pkgbuild") cachedir = temp_dir / "_datacache" pg_temp_install_path = ( build.get_build_dir(pg_pkg, relative_to="pkgbuild") / "_install") bindir = build.get_install_path("bin").relative_to("/") libdir = build.get_install_path("lib").relative_to("/") pg_config = pg_temp_install_path / bindir / "pg_config" pg_libpath = pg_temp_install_path / libdir temp_install_dir = build.get_temp_root( relative_to="pkgbuild") / build.get_full_install_prefix( ).relative_to("/") sitescript = ( f"import site; " f'print(site.getsitepackages(["{temp_install_dir}"])[0])') runstatescript = "import tempfile; " "print(tempfile.mkdtemp())" abspath = ( "import pathlib, sys; print(pathlib.Path(sys.argv[1]).resolve())") ld_env = " ".join( build.get_ld_env( deps=[icu_pkg, openssl_pkg, uuid_pkg], wd="${_wd}", extra=["${_ldlibpath}"], )) if platform.system() == "Darwin": # Workaround SIP madness on macOS and allow popen() calls # in postgres to inherit DYLD_LIBRARY_PATH. extraenv = "PGOVERRIDESTDSHELL=1" else: extraenv = "" data_cache_script = textwrap.dedent(f"""\ mkdir -p "{cachedir}" _tempdir=$("{build_python}" -c '{runstatescript}') if [ "$(whoami)" = "root" ]; then chown nobody "{cachedir}" chown nobody "${{_tempdir}}" _sudo="sudo -u nobody" else _sudo="" fi _pythonpath=$("{build_python}" -c '{sitescript}') _pythonpath=$("{build_python}" -c '{abspath}' "${{_pythonpath}}") _cachedir=$("{build_python}" -c '{abspath}' "{cachedir}") _pg_config=$("{build_python}" -c '{abspath}' "{pg_config}") _ldlibpath=$("{build_python}" -c '{abspath}' "{pg_libpath}") _build_python=$("{build_python}" -c '{abspath}' "{build_python}") _wd=$("{build_python}" -c '{abspath}' "$(pwd)") ( cd ../; ${{_sudo}} env \\ {ld_env} {extraenv} \\ PYTHONPATH="${{_pythonpath}}" \\ _EDGEDB_BUILDMETA_PG_CONFIG_PATH="${{_pg_config}}" \\ _EDGEDB_WRITE_DATA_CACHE_TO="${{_cachedir}}" \\ "${{_build_python}}" \\ -m edb.server.main \\ --data-dir="${{_tempdir}}" \\ --runstate-dir="${{_tempdir}}" \\ --bootstrap-only rm -rf "${{_tempdir}}" ) mkdir ./share/ cp "${{_cachedir}}"/* ./share/ pwd ls -al ./share/ """) return f"{common_script}\n{data_cache_script}"
def get_configure_script(self, build: targets.Build) -> str: extra_version = "" system = platform.system() if system.endswith("BSD"): uuid_lib = "bsd" elif system == "Linux" or system == "Darwin": # macOS actually ships the e2fs version despite being a "BSD" uuid_lib = "e2fs" else: raise NotImplementedError(f"unsupported target system: {system}") sdir = build.get_source_dir(self, relative_to="pkgbuild") configure = sdir / "configure" configure_flags: dict[str, str | pathlib.Path | None] = { "--sysconfdir": build.get_install_path("sysconf"), "--datarootdir": build.get_install_path("data"), "--bindir": build.get_install_path("bin"), "--libdir": build.get_install_path("lib"), "--includedir": build.get_install_path("include"), "--with-extra-version": extra_version, "--with-icu": None, "--without-pam": None, "--without-zlib": None, "--with-openssl": None, "--with-uuid": uuid_lib, "--without-readline": None, } icu_pkg = build.get_package("icu") if build.is_bundled(icu_pkg): icu_path = build.get_install_dir(icu_pkg, relative_to="pkgbuild") icu_path /= build.get_full_install_prefix().relative_to("/") icu_rel_path = f'$(pwd)/"{icu_path}"' configure_flags["ICU_CFLAGS"] = f"!-I{icu_rel_path}/include/" icu_ldflags = build.sh_get_bundled_shlib_ldflags( icu_pkg, relative_to="pkgbuild") configure_flags["ICU_LIBS"] = f"!{icu_ldflags}" uuid_pkg = build.get_package("uuid") if build.is_bundled(uuid_pkg): uuid_path = build.get_install_dir(uuid_pkg, relative_to="pkgbuild") uuid_path /= build.get_full_install_prefix().relative_to("/") uuid_rel_path = f'$(pwd)/"{uuid_path}"' configure_flags["UUID_CFLAGS"] = f"!-I{uuid_rel_path}/include/" uuid_ldflags = build.sh_get_bundled_shlib_ldflags( uuid_pkg, relative_to="pkgbuild") configure_flags["UUID_LIBS"] = f"!{uuid_ldflags}" openssl_pkg = build.get_package("openssl") if build.is_bundled(openssl_pkg): openssl_root = build.get_install_dir(openssl_pkg, relative_to="pkgbuild") openssl_path = (openssl_root / build.get_full_install_prefix().relative_to("/")) openssl_rel_path = f'$(pwd)/"{openssl_path}"' configure_flags[ "OPENSSL_CFLAGS"] = f"!-I{openssl_rel_path}/include/" openssl_ldflags = build.sh_get_bundled_shlib_ldflags( openssl_pkg, relative_to="pkgbuild") configure_flags["OPENSSL_LIBS"] = f"!{openssl_ldflags}" ldflags = f"!-L{openssl_rel_path}/lib" if system == "Darwin": # ./configure tries to compile and test a program # and it fails because openssl is not yet installed # at its install_name location. configure_flags["DYLD_FALLBACK_LIBRARY_PATH"] = openssl_root else: ldflags += f'" "-Wl,-rpath-link,{openssl_rel_path}/lib' configure_flags["LDFLAGS"] = ldflags if build.target.has_capability("tzdata"): zoneinfo = build.target.get_resource_path(build, "tzdata") configure_flags["--with-system-tzdata"] = zoneinfo if build.target.has_capability("systemd"): configure_flags["--with-systemd"] = None if (build.extra_optimizations_enabled() and build.supports_lto() and build.uses_modern_gcc()): build.sh_append_flags( configure_flags, "CFLAGS", ( "-flto", "-fuse-linker-plugin", "-ffat-lto-objects", "-flto-partition=none", ), ) return self.sh_configure(build, configure, configure_flags)
def get_include_paths(self, build: targets.Build) -> list[pathlib.Path]: return [build.get_full_install_prefix() / "include"]
def get_configure_script(self, build: targets.Build) -> str: sdir = build.get_source_dir(self, relative_to="pkgbuild") configure = sdir / "configure" return self.sh_configure(build, configure, {})