2017-08-25 06:46:16 +01:00
|
|
|
#!/usr/bin/env python3
|
2021-11-21 23:59:44 +00:00
|
|
|
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
2022-11-02 00:05:16 +00:00
|
|
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
2017-08-25 06:46:16 +01:00
|
|
|
|
2019-05-03 18:14:27 +01:00
|
|
|
import contextlib
|
2023-06-27 20:25:54 +01:00
|
|
|
import logging
|
2019-11-15 21:28:47 +00:00
|
|
|
import os
|
|
|
|
import os.path
|
2022-05-16 21:19:02 +01:00
|
|
|
from pathlib import Path
|
2019-11-15 21:28:47 +00:00
|
|
|
import re
|
2020-08-20 22:27:51 +01:00
|
|
|
import shlex
|
|
|
|
import subprocess
|
|
|
|
import sys
|
|
|
|
|
|
|
|
from setuptools import Command, find_packages, setup
|
2020-01-24 23:24:50 +00:00
|
|
|
from setuptools.command.build_ext import build_ext as _build_ext
|
|
|
|
from setuptools.command.egg_info import egg_info as _egg_info
|
2021-03-31 07:02:09 +01:00
|
|
|
from setuptools.command.sdist import sdist as _sdist
|
2019-11-15 21:28:47 +00:00
|
|
|
from setuptools.extension import Extension
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
|
2023-06-27 23:51:58 +01:00
|
|
|
# setuptools must be imported before distutils (see pypa/setuptools#2230), so
|
|
|
|
# make sure to keep these fallbacks after the other setuptools imports.
|
|
|
|
try:
|
|
|
|
# This was added in setuptools 62.4.0 (released June 13th, 2022).
|
|
|
|
from setuptools.command.build import build as _build
|
|
|
|
except ImportError:
|
|
|
|
from distutils.command.build import build as _build
|
|
|
|
try:
|
|
|
|
# This was added in setuptools 59.0.0 (released November 12th, 2021).
|
|
|
|
from setuptools.errors import BaseError
|
|
|
|
except ImportError:
|
|
|
|
from distutils.errors import DistutilsError as BaseError
|
|
|
|
|
2020-03-30 18:51:04 +01:00
|
|
|
from util import nproc, out_of_date
|
2023-06-27 18:17:22 +01:00
|
|
|
from vmtest.config import KERNEL_FLAVORS, SUPPORTED_KERNEL_VERSIONS
|
2020-03-30 18:51:04 +01:00
|
|
|
|
2023-06-27 20:25:54 +01:00
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
|
2020-01-24 23:38:54 +00:00
|
|
|
class build(_build):
|
|
|
|
def finalize_options(self):
|
|
|
|
super().finalize_options()
|
|
|
|
if self.parallel is None:
|
2020-03-30 18:51:04 +01:00
|
|
|
self.parallel = nproc() + 1
|
2020-01-27 20:20:45 +00:00
|
|
|
|
|
|
|
|
2020-01-24 23:24:50 +00:00
|
|
|
class build_ext(_build_ext):
|
2019-04-03 19:33:37 +01:00
|
|
|
user_options = [
|
|
|
|
("inplace", "i", "put compiled extension into the source directory"),
|
|
|
|
("parallel=", "j", "number of parallel build jobs"),
|
|
|
|
]
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
|
2019-04-03 19:33:37 +01:00
|
|
|
boolean_options = ["inplace"]
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
|
2019-04-03 19:33:37 +01:00
|
|
|
help_options = []
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
|
2021-03-31 07:02:09 +01:00
|
|
|
def _run_autoreconf(self):
|
|
|
|
if out_of_date(
|
|
|
|
"libdrgn/Makefile.in", "libdrgn/Makefile.am", "libdrgn/configure.ac"
|
|
|
|
) or out_of_date("libdrgn/configure", "libdrgn/configure.ac"):
|
2019-05-03 18:14:27 +01:00
|
|
|
try:
|
2021-03-31 07:02:09 +01:00
|
|
|
subprocess.check_call(["autoreconf", "-i", "libdrgn"])
|
2019-05-03 18:14:27 +01:00
|
|
|
except Exception:
|
2020-01-27 20:20:45 +00:00
|
|
|
with contextlib.suppress(FileNotFoundError):
|
2021-03-31 07:02:09 +01:00
|
|
|
os.remove("libdrgn/configure")
|
2019-05-03 18:14:27 +01:00
|
|
|
with contextlib.suppress(FileNotFoundError):
|
2021-03-31 07:02:09 +01:00
|
|
|
os.remove("libdrgn/Makefile.in")
|
2019-05-03 18:14:27 +01:00
|
|
|
raise
|
|
|
|
|
2019-09-04 22:40:47 +01:00
|
|
|
def _run_configure(self):
|
2023-06-27 19:54:29 +01:00
|
|
|
self.mkpath(self.build_temp)
|
2019-05-03 18:14:27 +01:00
|
|
|
makefile = os.path.join(self.build_temp, "Makefile")
|
|
|
|
if not os.path.exists(makefile):
|
2019-04-03 19:33:37 +01:00
|
|
|
args = [
|
|
|
|
os.path.relpath("libdrgn/configure", self.build_temp),
|
|
|
|
"--disable-static",
|
2022-02-01 21:30:51 +00:00
|
|
|
"--enable-python",
|
2019-04-03 19:33:37 +01:00
|
|
|
]
|
2020-01-24 01:54:46 +00:00
|
|
|
try:
|
|
|
|
args.extend(shlex.split(os.environ["CONFIGURE_FLAGS"]))
|
|
|
|
except KeyError:
|
|
|
|
pass
|
2019-05-03 18:14:27 +01:00
|
|
|
try:
|
2022-02-01 21:30:51 +00:00
|
|
|
subprocess.check_call(
|
|
|
|
args,
|
|
|
|
cwd=self.build_temp,
|
|
|
|
env={**os.environ, "PYTHON": sys.executable},
|
|
|
|
)
|
2019-05-03 18:14:27 +01:00
|
|
|
except Exception:
|
|
|
|
with contextlib.suppress(FileNotFoundError):
|
|
|
|
os.remove(makefile)
|
|
|
|
raise
|
2019-04-03 19:33:37 +01:00
|
|
|
|
2021-03-31 07:02:09 +01:00
|
|
|
def _run_make(self, *make_args):
|
2019-09-04 22:40:47 +01:00
|
|
|
args = ["make", "-C", self.build_temp]
|
2019-04-03 19:33:37 +01:00
|
|
|
if self.parallel:
|
|
|
|
args.append(f"-j{self.parallel}")
|
2021-03-31 07:02:09 +01:00
|
|
|
args.extend(make_args)
|
2019-04-03 19:33:37 +01:00
|
|
|
subprocess.check_call(args)
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
|
2021-03-31 07:02:09 +01:00
|
|
|
def make(self, *make_args):
|
|
|
|
self._run_autoreconf()
|
2019-09-04 22:40:47 +01:00
|
|
|
self._run_configure()
|
2021-03-31 07:02:09 +01:00
|
|
|
self._run_make(*make_args)
|
2019-09-04 22:40:47 +01:00
|
|
|
|
2021-03-31 07:02:09 +01:00
|
|
|
def run(self):
|
|
|
|
self.make()
|
2019-04-03 19:33:37 +01:00
|
|
|
so = os.path.join(self.build_temp, ".libs/_drgn.so")
|
|
|
|
if self.inplace:
|
2023-06-27 19:54:29 +01:00
|
|
|
self.copy_file(so, self.get_ext_fullpath("_drgn"))
|
2019-09-06 20:25:59 +01:00
|
|
|
old_inplace, self.inplace = self.inplace, 0
|
2019-04-03 19:33:37 +01:00
|
|
|
build_path = self.get_ext_fullpath("_drgn")
|
2023-06-27 19:54:29 +01:00
|
|
|
self.mkpath(os.path.dirname(build_path))
|
|
|
|
self.copy_file(so, build_path)
|
2019-09-06 20:25:59 +01:00
|
|
|
self.inplace = old_inplace
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
|
2017-08-29 05:16:43 +01:00
|
|
|
|
2019-11-15 21:28:47 +00:00
|
|
|
# Work around pypa/setuptools#436.
|
2020-01-24 23:24:50 +00:00
|
|
|
class egg_info(_egg_info):
|
2019-11-15 21:28:47 +00:00
|
|
|
def run(self):
|
|
|
|
if os.path.exists(".git"):
|
2020-02-21 19:09:04 +00:00
|
|
|
with contextlib.suppress(FileNotFoundError):
|
2019-11-15 21:28:47 +00:00
|
|
|
os.remove(os.path.join(self.egg_info, "SOURCES.txt"))
|
|
|
|
super().run()
|
|
|
|
|
|
|
|
|
2021-03-31 07:02:09 +01:00
|
|
|
class sdist(_sdist):
|
|
|
|
def make_release_tree(self, base_dir, files):
|
|
|
|
super().make_release_tree(base_dir, files)
|
|
|
|
# Add the libdrgn distribution tree. This won't add the file names to
|
|
|
|
# .egg-info/SOURCES.txt, but as far as I can tell that doesn't matter.
|
|
|
|
build_ext = self.get_finalized_command("build_ext")
|
|
|
|
distdir = os.path.join(
|
|
|
|
os.path.relpath(base_dir, build_ext.build_temp), "libdrgn"
|
|
|
|
)
|
|
|
|
build_ext.make("distdir", "distdir=" + distdir)
|
|
|
|
|
|
|
|
|
2020-03-31 08:54:24 +01:00
|
|
|
class test(Command):
|
|
|
|
description = "run unit tests after in-place build"
|
|
|
|
|
|
|
|
user_options = [
|
|
|
|
(
|
|
|
|
"kernel",
|
|
|
|
"K",
|
2022-05-16 22:21:10 +01:00
|
|
|
"run Linux kernel tests in a virtual machine on all supported kernels "
|
2023-06-27 18:17:22 +01:00
|
|
|
f"({', '.join(SUPPORTED_KERNEL_VERSIONS)})",
|
2020-03-31 08:54:24 +01:00
|
|
|
),
|
2022-05-16 22:21:10 +01:00
|
|
|
(
|
|
|
|
"all-kernel-flavors",
|
|
|
|
"F",
|
|
|
|
"when combined with -K, run Linux kernel tests on all supported flavors "
|
|
|
|
f"({', '.join(KERNEL_FLAVORS)}) instead of just the default flavor",
|
|
|
|
),
|
2020-03-31 08:54:24 +01:00
|
|
|
(
|
|
|
|
"extra-kernels=",
|
|
|
|
"k",
|
|
|
|
"additional kernels to run Linux kernel helper tests on in a virtual machine "
|
2020-10-15 00:26:48 +01:00
|
|
|
"(comma-separated list of wildcard patterns matching uploaded kernel releases)",
|
2020-03-31 08:54:24 +01:00
|
|
|
),
|
|
|
|
(
|
|
|
|
"vmtest-dir=",
|
|
|
|
"d",
|
|
|
|
"directory for built artifacts and downloaded kernels for virtual machine tests (default: 'build/vmtest')",
|
|
|
|
),
|
|
|
|
]
|
|
|
|
|
|
|
|
def initialize_options(self):
|
|
|
|
self.kernel = False
|
2022-05-16 22:21:10 +01:00
|
|
|
self.all_kernel_flavors = False
|
2020-03-31 08:54:24 +01:00
|
|
|
self.extra_kernels = ""
|
|
|
|
self.vmtest_dir = None
|
|
|
|
|
|
|
|
def finalize_options(self):
|
|
|
|
self.kernels = [kernel for kernel in self.extra_kernels.split(",") if kernel]
|
|
|
|
if self.kernel:
|
2023-06-27 18:17:22 +01:00
|
|
|
flavors = KERNEL_FLAVORS if self.all_kernel_flavors else [""]
|
2022-05-16 22:21:10 +01:00
|
|
|
self.kernels.extend(
|
2023-06-27 18:17:22 +01:00
|
|
|
kernel + ".*" + flavor
|
|
|
|
for kernel in SUPPORTED_KERNEL_VERSIONS
|
|
|
|
for flavor in flavors
|
2022-05-16 22:21:10 +01:00
|
|
|
)
|
2020-03-31 08:54:24 +01:00
|
|
|
if self.vmtest_dir is None:
|
|
|
|
build_base = self.get_finalized_command("build").build_base
|
|
|
|
self.vmtest_dir = os.path.join(build_base, "vmtest")
|
|
|
|
|
|
|
|
def _run_local(self):
|
|
|
|
import unittest
|
|
|
|
|
|
|
|
argv = ["discover"]
|
|
|
|
if self.verbose:
|
|
|
|
argv.append("-v")
|
|
|
|
test = unittest.main(module=None, argv=argv, exit=False)
|
|
|
|
return test.result.wasSuccessful()
|
|
|
|
|
2023-02-13 22:54:41 +00:00
|
|
|
def _run_vm(self, kernel):
|
2023-02-17 18:27:17 +00:00
|
|
|
from vmtest.kmod import build_kmod
|
2020-03-31 08:54:24 +01:00
|
|
|
import vmtest.vm
|
|
|
|
|
2023-06-27 20:25:54 +01:00
|
|
|
logger.info("running tests in VM on Linux %s", kernel.release)
|
2022-03-26 00:47:56 +00:00
|
|
|
|
2023-02-13 22:54:41 +00:00
|
|
|
kmod = kernel.path.parent / f"drgn_test-{kernel.release}.ko"
|
2023-02-17 18:27:17 +00:00
|
|
|
try:
|
|
|
|
build_kmod(Path(self.vmtest_dir), kernel)
|
|
|
|
except subprocess.CalledProcessError:
|
2022-05-18 00:06:01 +01:00
|
|
|
return False
|
2022-05-16 21:19:02 +01:00
|
|
|
|
2022-02-12 21:48:49 +00:00
|
|
|
command = rf"""
|
2022-01-07 00:49:55 +00:00
|
|
|
set -e
|
|
|
|
|
2022-10-11 08:49:52 +01:00
|
|
|
export PYTHON={shlex.quote(sys.executable)}
|
2022-05-16 21:19:02 +01:00
|
|
|
export DRGN_TEST_KMOD={shlex.quote(str(kmod))}
|
2022-08-01 19:22:18 +01:00
|
|
|
if [ -e /proc/vmcore ]; then
|
2022-01-07 00:49:55 +00:00
|
|
|
"$PYTHON" -Bm unittest discover -t . -s tests/linux_kernel/vmcore {"-v" if self.verbose else ""}
|
|
|
|
else
|
2022-08-01 19:22:18 +01:00
|
|
|
insmod "$DRGN_TEST_KMOD"
|
2022-03-04 23:40:51 +00:00
|
|
|
DRGN_RUN_LINUX_KERNEL_TESTS=1 "$PYTHON" -Bm \
|
|
|
|
unittest discover -t . -s tests/linux_kernel {"-v" if self.verbose else ""}
|
2022-10-12 00:05:14 +01:00
|
|
|
"$PYTHON" -Bm vmtest.enter_kdump
|
2022-01-07 00:49:55 +00:00
|
|
|
# We should crash and not reach this.
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
"""
|
2020-03-31 08:54:24 +01:00
|
|
|
try:
|
2020-04-17 23:11:54 +01:00
|
|
|
returncode = vmtest.vm.run_in_vm(
|
2023-02-13 20:44:29 +00:00
|
|
|
command, kernel, Path("/"), Path(self.vmtest_dir)
|
2020-04-17 23:11:54 +01:00
|
|
|
)
|
2023-06-27 20:25:54 +01:00
|
|
|
except vmtest.vm.LostVMError:
|
|
|
|
logger.exception("error on Linux %s", kernel.release)
|
2022-05-18 00:06:01 +01:00
|
|
|
return False
|
2023-06-27 20:25:54 +01:00
|
|
|
logger.info("Tests in VM on Linux %s returned %d", kernel.release, returncode)
|
2022-05-18 00:06:01 +01:00
|
|
|
return returncode == 0
|
2020-03-31 08:54:24 +01:00
|
|
|
|
|
|
|
def run(self):
|
2022-12-20 00:25:56 +00:00
|
|
|
import urllib.error
|
|
|
|
|
2023-02-17 18:27:17 +00:00
|
|
|
from vmtest.config import ARCHITECTURES, Kernel
|
|
|
|
from vmtest.download import DownloadCompiler, DownloadKernel, download_in_thread
|
2020-03-31 08:54:24 +01:00
|
|
|
|
2022-05-18 00:06:01 +01:00
|
|
|
if os.getenv("GITHUB_ACTIONS") == "true":
|
|
|
|
|
|
|
|
@contextlib.contextmanager
|
|
|
|
def github_workflow_group(title):
|
|
|
|
print("::group::" + title, flush=True)
|
|
|
|
try:
|
|
|
|
yield
|
|
|
|
finally:
|
|
|
|
print("::endgroup::", flush=True)
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
@contextlib.contextmanager
|
|
|
|
def github_workflow_group(title):
|
|
|
|
yield
|
|
|
|
|
2020-03-31 08:54:24 +01:00
|
|
|
# Start downloads ASAP so that they're hopefully done by the time we
|
|
|
|
# need them.
|
2022-12-20 00:25:56 +00:00
|
|
|
try:
|
2023-02-17 18:27:17 +00:00
|
|
|
to_downlad = []
|
|
|
|
if self.kernels:
|
|
|
|
to_downlad.append(DownloadCompiler(ARCHITECTURES["x86_64"]))
|
|
|
|
for pattern in self.kernels:
|
|
|
|
to_downlad.append(DownloadKernel(ARCHITECTURES["x86_64"], pattern))
|
|
|
|
with download_in_thread(Path(self.vmtest_dir), to_downlad) as downloads:
|
2022-12-20 00:25:56 +00:00
|
|
|
if self.kernels:
|
2023-06-27 20:25:54 +01:00
|
|
|
logger.info("downloading kernels in the background")
|
2022-12-20 00:25:56 +00:00
|
|
|
|
|
|
|
with github_workflow_group("Build extension"):
|
|
|
|
self.run_command("egg_info")
|
|
|
|
self.reinitialize_command("build_ext", inplace=1)
|
|
|
|
self.run_command("build_ext")
|
2022-05-18 00:06:01 +01:00
|
|
|
|
2022-12-20 00:25:56 +00:00
|
|
|
passed = []
|
|
|
|
failed = []
|
2020-03-31 08:54:24 +01:00
|
|
|
|
2022-12-20 00:25:56 +00:00
|
|
|
with github_workflow_group("Run unit tests"):
|
|
|
|
if self.kernels:
|
2023-06-27 20:25:54 +01:00
|
|
|
logger.info("running tests locally")
|
2022-12-20 00:25:56 +00:00
|
|
|
if self._run_local():
|
|
|
|
passed.append("local")
|
|
|
|
else:
|
|
|
|
failed.append("local")
|
2020-03-31 08:54:24 +01:00
|
|
|
|
2023-02-17 18:27:17 +00:00
|
|
|
for kernel in downloads:
|
|
|
|
if not isinstance(kernel, Kernel):
|
|
|
|
continue
|
2023-01-04 22:25:55 +00:00
|
|
|
with github_workflow_group(
|
2023-02-13 22:54:41 +00:00
|
|
|
f"Run integration tests on Linux {kernel.release}"
|
2023-01-04 22:25:55 +00:00
|
|
|
):
|
2023-02-13 22:54:41 +00:00
|
|
|
if self._run_vm(kernel):
|
|
|
|
passed.append(kernel.release)
|
2023-01-04 22:25:55 +00:00
|
|
|
else:
|
2023-02-13 22:54:41 +00:00
|
|
|
failed.append(kernel.release)
|
2022-12-20 00:25:56 +00:00
|
|
|
|
|
|
|
if passed:
|
2023-06-27 20:25:54 +01:00
|
|
|
logger.info("Passed: %s", ", ".join(passed))
|
2022-12-20 00:25:56 +00:00
|
|
|
if failed:
|
2023-06-27 20:25:54 +01:00
|
|
|
logger.error("Failed: %s", ", ".join(failed))
|
2022-12-20 00:25:56 +00:00
|
|
|
except urllib.error.HTTPError as e:
|
|
|
|
if e.code == 403:
|
|
|
|
print(e, file=sys.stderr)
|
|
|
|
print("Headers:", e.headers, file=sys.stderr)
|
|
|
|
print("Body:", e.read().decode(), file=sys.stderr)
|
|
|
|
raise
|
2020-03-31 08:54:24 +01:00
|
|
|
|
|
|
|
if failed:
|
2023-06-27 23:51:58 +01:00
|
|
|
raise BaseError("some tests failed")
|
2020-03-31 08:54:24 +01:00
|
|
|
else:
|
2023-06-27 20:25:54 +01:00
|
|
|
logger.info("all tests passed")
|
2020-03-31 08:54:24 +01:00
|
|
|
|
|
|
|
|
2020-01-23 20:09:48 +00:00
|
|
|
def get_version():
|
2020-10-20 10:27:22 +01:00
|
|
|
try:
|
|
|
|
with open("drgn/internal/version.py", "r") as f:
|
|
|
|
version_py = f.read()
|
|
|
|
except FileNotFoundError:
|
|
|
|
version_py = None
|
2020-01-23 20:09:48 +00:00
|
|
|
|
2020-10-20 10:27:22 +01:00
|
|
|
# The public version always comes from configure.ac.
|
2020-01-23 20:09:48 +00:00
|
|
|
with open("libdrgn/configure.ac", "r") as f:
|
2021-03-31 07:02:09 +01:00
|
|
|
public_version = re.search(
|
|
|
|
r"AC_INIT\(\[libdrgn\], \[([^]]*)\]", f.read()
|
|
|
|
).group(1)
|
2020-10-20 10:27:22 +01:00
|
|
|
# Default local version if we fail.
|
|
|
|
local_version = "+unknown"
|
|
|
|
|
|
|
|
# If this is a git repository, use a git-describe(1)-esque local version.
|
|
|
|
# Otherwise, get the local version saved in the sdist.
|
setup.py: handle git not being installed
My previous change to call git unconditionally caused Packit failures,
presumably because git isn't installed for the build:
Traceback (most recent call last):
File "/builddir/build/BUILD/drgn-0.0.22+71.g2f97cc0/setup.py", line 411, in <module>
version=get_version(),
^^^^^^^^^^^^^
File "/builddir/build/BUILD/drgn-0.0.22+71.g2f97cc0/setup.py", line 343, in get_version
subprocess.call(
File "/usr/lib64/python3.11/subprocess.py", line 389, in call
with Popen(*popenargs, **kwargs) as p:
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib64/python3.11/subprocess.py", line 1024, in __init__
self._execute_child(args, executable, preexec_fn, close_fds,
File "/usr/lib64/python3.11/subprocess.py", line 1901, in _execute_child
raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: 'git'
We shouldn't bother calling git if .git doesn't exist.
Fixes: 2e9e66cedcb7 ("setup.py: use stricter check for git repository")
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2023-02-22 02:12:54 +00:00
|
|
|
if os.path.exists(".git") and (
|
2023-02-21 19:31:24 +00:00
|
|
|
subprocess.call(
|
|
|
|
["git", "--git-dir=.git", "rev-parse"], stderr=subprocess.DEVNULL
|
|
|
|
)
|
|
|
|
== 0
|
|
|
|
):
|
2020-10-20 10:27:22 +01:00
|
|
|
# Read the Docs modifies the working tree (namely, docs/conf.py). We
|
|
|
|
# don't want the documentation to display a dirty version, so ignore
|
|
|
|
# modifications for RTD builds.
|
|
|
|
dirty = os.getenv("READTHEDOCS") != "True" and bool(
|
2020-01-23 20:09:48 +00:00
|
|
|
subprocess.check_output(
|
2020-10-20 10:27:22 +01:00
|
|
|
["git", "status", "-uno", "--porcelain"],
|
|
|
|
# Use the environment variable instead of --no-optional-locks
|
|
|
|
# to support Git < 2.14.
|
|
|
|
env={**os.environ, "GIT_OPTIONAL_LOCKS": "0"},
|
2020-01-23 20:09:48 +00:00
|
|
|
)
|
|
|
|
)
|
2020-10-20 10:27:22 +01:00
|
|
|
|
|
|
|
try:
|
|
|
|
count = int(
|
|
|
|
subprocess.check_output(
|
|
|
|
["git", "rev-list", "--count", f"v{public_version}.."],
|
|
|
|
stderr=subprocess.DEVNULL,
|
|
|
|
universal_newlines=True,
|
|
|
|
)
|
|
|
|
)
|
|
|
|
except subprocess.CalledProcessError:
|
2023-06-27 20:25:54 +01:00
|
|
|
logger.warning("warning: v%s tag not found", public_version)
|
2020-10-20 10:27:22 +01:00
|
|
|
else:
|
|
|
|
if count == 0:
|
|
|
|
local_version = "+dirty" if dirty else ""
|
|
|
|
else:
|
|
|
|
commit = subprocess.check_output(
|
|
|
|
["git", "rev-parse", "--short", "HEAD"], universal_newlines=True
|
|
|
|
).strip()
|
|
|
|
local_version = f"+{count}.g{commit}"
|
|
|
|
if dirty:
|
|
|
|
local_version += ".dirty"
|
|
|
|
else:
|
|
|
|
if version_py is None:
|
|
|
|
# This isn't a proper sdist (maybe a git archive).
|
2023-06-27 20:25:54 +01:00
|
|
|
logger.warning("warning: drgn/internal/version.py not found")
|
2020-10-20 10:27:22 +01:00
|
|
|
else:
|
|
|
|
# The saved version must start with the public version.
|
|
|
|
match = re.search(
|
2022-02-12 21:48:49 +00:00
|
|
|
rf'^__version__ = "{re.escape(public_version)}([^"]*)"$',
|
2021-01-22 19:45:11 +00:00
|
|
|
version_py,
|
|
|
|
re.M,
|
2020-10-20 10:27:22 +01:00
|
|
|
)
|
|
|
|
if match:
|
|
|
|
local_version = match.group(1)
|
|
|
|
else:
|
2023-06-27 20:25:54 +01:00
|
|
|
logger.warning("warning: drgn/internal/version.py is invalid")
|
2020-10-20 10:27:22 +01:00
|
|
|
|
|
|
|
version = public_version + local_version
|
|
|
|
# Update version.py if necessary.
|
2021-01-22 19:17:18 +00:00
|
|
|
new_version_py = f'__version__ = "{version}"\n'
|
2020-10-20 10:27:22 +01:00
|
|
|
if new_version_py != version_py:
|
|
|
|
with open("drgn/internal/version.py", "w") as f:
|
|
|
|
f.write(new_version_py)
|
2020-01-23 20:09:48 +00:00
|
|
|
return version
|
|
|
|
|
|
|
|
|
2020-01-11 01:14:52 +00:00
|
|
|
with open("README.rst", "r") as f:
|
|
|
|
long_description = f.read()
|
|
|
|
|
2019-04-03 19:33:37 +01:00
|
|
|
|
|
|
|
setup(
|
|
|
|
name="drgn",
|
2020-01-23 20:09:48 +00:00
|
|
|
version=get_version(),
|
2020-02-25 19:43:01 +00:00
|
|
|
packages=find_packages(include=["drgn", "drgn.*"]),
|
|
|
|
package_data={"drgn": ["../_drgn.pyi", "py.typed"]},
|
2019-04-03 19:33:37 +01:00
|
|
|
# This is here so that setuptools knows that we have an extension; it's
|
|
|
|
# actually built using autotools/make.
|
|
|
|
ext_modules=[Extension(name="_drgn", sources=[])],
|
2020-03-31 08:54:24 +01:00
|
|
|
cmdclass={
|
|
|
|
"build": build,
|
|
|
|
"build_ext": build_ext,
|
|
|
|
"egg_info": egg_info,
|
2021-03-31 07:02:09 +01:00
|
|
|
"sdist": sdist,
|
2020-03-31 08:54:24 +01:00
|
|
|
"test": test,
|
|
|
|
},
|
2023-01-12 22:40:03 +00:00
|
|
|
entry_points={"console_scripts": ["drgn=drgn.cli:_main"]},
|
2020-01-11 01:14:52 +00:00
|
|
|
python_requires=">=3.6",
|
2019-04-03 19:33:37 +01:00
|
|
|
author="Omar Sandoval",
|
|
|
|
author_email="osandov@osandov.com",
|
2022-08-19 09:21:32 +01:00
|
|
|
description="Programmable debugger",
|
2020-01-11 01:14:52 +00:00
|
|
|
long_description=long_description,
|
|
|
|
long_description_content_type="text/x-rst",
|
2019-04-03 19:33:37 +01:00
|
|
|
url="https://github.com/osandov/drgn",
|
2020-01-11 01:14:52 +00:00
|
|
|
project_urls={
|
|
|
|
"Bug Tracker": "https://github.com/osandov/drgn/issues",
|
|
|
|
"Documentation": "https://drgn.readthedocs.io",
|
|
|
|
},
|
2022-11-02 00:05:16 +00:00
|
|
|
license="LGPL-2.1-or-later",
|
2020-01-11 01:14:52 +00:00
|
|
|
classifiers=[
|
|
|
|
"Development Status :: 3 - Alpha",
|
|
|
|
"Environment :: Console",
|
|
|
|
"Intended Audience :: Developers",
|
2022-11-02 00:05:16 +00:00
|
|
|
"License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)",
|
2020-01-11 01:14:52 +00:00
|
|
|
"Operating System :: POSIX :: Linux",
|
|
|
|
"Programming Language :: Python :: 3",
|
|
|
|
"Topic :: Software Development :: Debuggers",
|
|
|
|
],
|
2019-04-03 19:33:37 +01:00
|
|
|
)
|