Skip to content

Commit

Permalink
Refactor common module to avoid setuptools import
Browse files Browse the repository at this point in the history
We do not need the setuptools import used while building packages in
ppbt.common. Having that import around breaks relenv runtime when trying
to setup the toolchain.
  • Loading branch information
dwoz committed Sep 27, 2024
1 parent ed11d22 commit 09d32eb
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 84 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
0.1.8
=====
- Refactor to support early import of ppbt.common at relenv runtime.


0.1.7
=====
- Use tar instead of tarfile to create toolchain tarballs
Expand Down
72 changes: 7 additions & 65 deletions src/ppbt/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@
import shutil
import subprocess
import sys
import tarfile
import time
import urllib.error
import urllib.request

from setuptools.build_meta import build_sdist, build_wheel

import ppbt.common

CT_NG_VER = "1.26.0"
CT_URL = "http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-{version}.tar.bz2"
CT_GIT_REPO = "https://github.com/crosstool-ng/crosstool-ng.git"
Expand All @@ -35,69 +36,10 @@
_build_sdist = build_sdist


class BuildError(RuntimeError):
class BuildError(ppbt.common.PPBTException, RuntimeError):
"""Generic build error."""


def build_arch():
"""
Return the current machine.
"""
machine = platform.machine()
return machine.lower()


def get_triplet(machine=None, plat=None):
"""
Get the target triplet for the specified machine and platform.
If any of the args are None, it will try to deduce what they should be.
:param machine: The machine for the triplet
:type machine: str
:param plat: The platform for the triplet
:type plat: str
:raises BuildError: If the platform is unknown
:return: The target triplet
:rtype: str
"""
if not plat:
plat = sys.platform
if not machine:
machine = build_arch()
if plat == "darwin":
return f"{machine}-macos"
elif plat == "win32":
return f"{machine}-win"
elif plat == "linux":
return f"{machine}-linux-gnu"
else:
raise BuildError(f"Unknown platform {plat}")


def extract_archive(to_dir, archive):
"""
Extract an archive to a specific location.
:param to_dir: The directory to extract to
:type to_dir: str
:param archive: The archive to extract
:type archive: str
"""
if archive.endswith("tgz"):
read_type = "r:gz"
elif archive.endswith("xz"):
read_type = "r:xz"
elif archive.endswith("bz2"):
read_type = "r:bz2"
else:
read_type = "r"
with tarfile.open(archive, read_type) as t:
t.extractall(to_dir)


def get_download_location(url, dest):
"""
Get the full path to where the url will be downloaded to.
Expand Down Expand Up @@ -224,7 +166,7 @@ def build_ppbt(branch=None, use_tempdir=True):
if not ctngdir.exists():
url = CT_URL.format(version=CT_NG_VER)
archive = download_url(url, build)
extract_archive(build, archive)
ppbt.common.extract_archive(build, archive)

os.chdir(ctngdir)
ctng = ctngdir / "ct-ng"
Expand All @@ -237,15 +179,15 @@ def build_ppbt(branch=None, use_tempdir=True):
runcmd(["make"])
print(f"Using compiled ct-ng: {ctng}")

arch = build_arch()
arch = ppbt.common.build_arch()
machine = platform.machine()
toolchain = cwd / "src" / "ppbt" / "_toolchain"

print(f"toolchain: {toolchain}")

toolchain.mkdir(exist_ok=True)

triplet = get_triplet(arch)
triplet = ppbt.common.get_triplet(arch)
archdir = build / triplet
print(f"Arch dir is {archdir}")
if archdir.exists():
Expand Down Expand Up @@ -296,7 +238,7 @@ def build_ppbt(branch=None, use_tempdir=True):
else:
print(f"Fetchin patchelf source: {PATCHELF_SOURCE}")
archive = download_url(PATCHELF_SOURCE, build)
extract_archive(build, archive)
ppbt.common.extract_archive(build, archive)
os.chdir(source)

if patchelf.exists():
Expand Down
105 changes: 86 additions & 19 deletions src/ppbt/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,42 +8,109 @@
import csv
import logging
import pathlib
import platform
import sys
import tarfile

from .build import build_arch, extract_archive, get_triplet
__version__ = "0.1.8"

log = logging.getLogger(__name__)

__version__ = "0.1.7"

triplet = get_triplet(build_arch())
class PPBTException(Exception):
"""
Base class for all ppbt exceptions.
archive = pathlib.Path(__file__).parent / "_toolchain" / f"{triplet}.tar.xz"
toolchain = pathlib.Path(__file__).parent / "_toolchain" / triplet
toolchain_root = pathlib.Path(__file__).parent / "_toolchain"
"""


def get_triplet(machine=None, plat=None):
"""
Get the target triplet for the specified machine and platform.
If any of the args are None, it will try to deduce what they should be.
:param machine: The machine for the triplet
:type machine: str
:param plat: The platform for the triplet
:type plat: str
:raises BuildError: If the platform is unknown
:return: The target triplet
:rtype: str
"""
if not plat:
plat = sys.platform
if not machine:
machine = build_arch()
if plat == "darwin":
return f"{machine}-macos"
elif plat == "win32":
return f"{machine}-win"
elif plat == "linux":
return f"{machine}-linux-gnu"
else:
raise PPBTException(f"Unknown platform {plat}")


def build_arch():
"""
Return the current machine.
"""
machine = platform.machine()
return machine.lower()


TRIPLET = get_triplet(build_arch())
ARCHIVE = pathlib.Path(__file__).parent / "_toolchain" / f"{TRIPLET}.tar.xz"
TOOLCHAIN_ROOT = pathlib.Path(__file__).parent / "_toolchain"
TOOLCHAIN = TOOLCHAIN_ROOT / TRIPLET

# This is not reliable, the version can be modified by setuptools at build time.
distinfo = (
DISTINFO = (
pathlib.Path(__file__).resolve().parent.parent / f"ppbt-{__version__}.dist-info"
)

log = logging.getLogger(__name__)

def extract_archive(to_dir, archive):
"""
Extract an archive to a specific location.
:param to_dir: The directory to extract to
:type to_dir: str
:param archive: The archive to extract
:type archive: str
"""
if archive.endswith("tgz"):
read_type = "r:gz"
elif archive.endswith("xz"):
read_type = "r:xz"
elif archive.endswith("bz2"):
read_type = "r:bz2"
else:
read_type = "r"
with tarfile.open(archive, read_type) as t:
t.extractall(to_dir)


def extract(overwrite=False):
"""
Extract the toolchain tarball.
"""
if toolchain.exists() and not overwrite:
if TOOLCHAIN.exists() and not overwrite:
log.debug("Toolchain directory exists")
else:
log.info("Extract archive")
extract_archive(toolchain_root, str(archive))
record = distinfo / "RECORD"
extract_archive(TOOLCHAIN_ROOT, str(ARCHIVE))
record = DISTINFO / "RECORD"
if record.exists():
records = []
log.info("Update pkg metadata")
with open(record, "r") as fp:
for row in csv.reader(fp):
records.append(row)
with open(str(archive) + ".record", "r") as fp:
with open(str(ARCHIVE) + ".record", "r") as fp:
for row in csv.reader(fp):
records.append(row)
records = sorted(records, key=lambda _: _[0])
Expand All @@ -57,18 +124,18 @@ def environ(auto_extract=False):
"""
Toolchain build environment.
"""
if not toolchain.exists():
if not TOOLCHAIN.exists():
if auto_extract:
extract()
else:
raise RuntimeError("Toolchain not extracted")
basebin = toolchain / "bin" / triplet
basebin = TOOLCHAIN / "bin" / TRIPLET
return {
"TOOLCHAIN_PATH": f"{toolchain}",
"TOOLCHAIN_PATH": f"{TOOLCHAIN}",
"CC": f"{basebin}-gcc",
"CXX": f"{basebin}-g++",
"CFLAGS": f"-I{toolchain}/{triplet}/sysroot/usr/include",
"CPPFLAGS": f"-I{toolchain}/{triplet}/sysroot/usr/include",
"CMAKE_FLAGS": f"-I{toolchain}/{triplet}/sysroot/usr/include",
"LDFLAGS": f"-L{toolchain}/{triplet}/sysroot/lib",
"CFLAGS": f"-I{TOOLCHAIN}/{TRIPLET}/sysroot/usr/include",
"CPPFLAGS": f"-I{TOOLCHAIN}/{TRIPLET}/sysroot/usr/include",
"CMAKE_FLAGS": f"-I{TOOLCHAIN}/{TRIPLET}/sysroot/usr/include",
"LDFLAGS": f"-L{TOOLCHAIN}/{TRIPLET}/sysroot/lib",
}

0 comments on commit 09d32eb

Please sign in to comment.