MAINT Use tee to pipe stdout to build.log from buildpkg (#2293)

This makes it so that buildpkg generates build.log on its own
even when it isn't run from buildall. This is helpful because
when working on a specific package it is nicer to run buildpkg
directly so you can see the build on the console. However, it
is frustrating when you want to grep the build log for instance
that there isn't a build log.

This tees stdout into a build log from insidde buildpkg. It also
fixes the issue with overwriting build.log when nothing needs to
be done (though that issue I think was also fixed in December by
calling needs_build from buildall). Now buildall can just redirect
the subprocess output to /dev/null.
This commit is contained in:
Hood Chatham 2022-03-20 20:24:39 -07:00 committed by GitHub
parent 165ad56fa2
commit abba842fd9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 51 deletions

View File

@ -119,59 +119,42 @@ class Package(BasePackage):
def build(self, outputdir: Path, args) -> None:
with open(self.pkgdir / "build.log.tmp", "w") as f:
p = subprocess.run(
[
sys.executable,
"-m",
"pyodide_build",
"buildpkg",
str(self.pkgdir / "meta.yaml"),
"--cflags",
args.cflags,
"--cxxflags",
args.cxxflags,
"--ldflags",
args.ldflags,
"--target-install-dir",
args.target_install_dir,
"--host-install-dir",
args.host_install_dir,
# Either this package has been updated and this doesn't
# matter, or this package is dependent on a package that has
# been updated and should be rebuilt even though its own
# files haven't been updated.
"--force-rebuild",
],
check=False,
stdout=f,
stderr=subprocess.STDOUT,
p = subprocess.run(
[
sys.executable,
"-m",
"pyodide_build",
"buildpkg",
str(self.pkgdir / "meta.yaml"),
"--cflags",
args.cflags,
"--cxxflags",
args.cxxflags,
"--ldflags",
args.ldflags,
"--target-install-dir",
args.target_install_dir,
"--host-install-dir",
args.host_install_dir,
# Either this package has been updated and this doesn't
# matter, or this package is dependent on a package that has
# been updated and should be rebuilt even though its own
# files haven't been updated.
"--force-rebuild",
],
check=False,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
log_dir = Path(args.log_dir).resolve() if args.log_dir else None
if log_dir and (self.pkgdir / "build.log").exists():
log_dir.mkdir(exist_ok=True, parents=True)
shutil.copy(
self.pkgdir / "build.log",
log_dir / f"{self.name}.log",
)
# Don't overwrite build log if we didn't build the file.
# If the file didn't need to be rebuilt, the log will have exactly two lines.
rebuilt = True
with open(self.pkgdir / "build.log.tmp") as f:
try:
next(f)
next(f)
next(f)
except StopIteration:
rebuilt = False
if rebuilt:
shutil.move(self.pkgdir / "build.log.tmp", self.pkgdir / "build.log")
log_dir = Path(args.log_dir).resolve() if args.log_dir else None
if log_dir and (self.pkgdir / "build.log").exists():
log_dir.mkdir(exist_ok=True, parents=True)
shutil.copy(
self.pkgdir / "build.log",
log_dir / f"{self.name}.log",
)
else:
(self.pkgdir / "build.log.tmp").unlink()
if p.returncode != 0:
print(f"Error building {self.name}. Printing build logs.")

View File

@ -678,6 +678,16 @@ def build_package(
f"directory at the path {srcpath}, but that path does not exist."
)
import os
import subprocess
import sys
tee = subprocess.Popen(["tee", pkg_root / "build.log"], stdin=subprocess.PIPE)
# Cause tee's stdin to get a copy of our stdin/stdout (as well as that
# of any child processes we spawn)
os.dup2(tee.stdin.fileno(), sys.stdout.fileno()) # type: ignore[union-attr]
os.dup2(tee.stdin.fileno(), sys.stderr.fileno()) # type: ignore[union-attr]
with chdir(pkg_root), get_bash_runner() as bash_runner:
bash_runner.env["PKG_VERSION"] = version
if not continue_: