Something went wrong. Try again.
(I'm so sorry!) Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195# SPDX-License-Identifier: GPL-2.0"""Setup script for perf python extension.
This script is used to build and install the perf python binding.It handles compiler-specific flags, especially for clang, and configuresthe setuptools Extension."""
import osimport shleximport shutilimport subprocessimport sysconfig
from setuptools import setup, Extensionfrom setuptools.command.build_ext import build_ext as _build_extfrom setuptools.command.install_lib import install_lib as _install_lib
def clang_has_option(cc: str, cc_args: list[str], src_feature_tests: str, option: str) -> bool: """Check if clang supports a specific option.
Args: cc: The compiler executable. cc_args: Compiler arguments from CC environment variable. src_feature_tests: Path to the feature tests directory. option: The compiler option to check (e.g., "-mcet").
Returns: True if the option is supported, False otherwise. """ error_substrings = ( b"unknown argument", b"is not supported", b"unknown warning option" ) cmd = [cc] + cc_args + [ option, "-o", "/dev/null", os.path.join(src_feature_tests, "test-hello.c") ] try: res = subprocess.run(cmd, stderr=subprocess.PIPE, stdout=subprocess.DEVNULL, check=False) cc_output = res.stderr.splitlines() except OSError: return False return not any(any(error in line for error in error_substrings) for line in cc_output)
def filter_clang_options(cc: str, cc_args: list[str], src_feature_tests: str) -> None: """Filter out unsupported clang options from sysconfig CFLAGS and OPT.
Args: cc: The compiler executable. cc_args: Compiler arguments from CC environment variable. src_feature_tests: Path to the feature tests directory. """ config_vars = sysconfig.get_config_vars() for var in ('CFLAGS', 'OPT'): if var not in config_vars: continue
# Split into individual flags using shlex to preserve quoted arguments flags = shlex.split(config_vars[var])
# Remove -specs=... flags = [f for f in flags if not f.startswith("-specs=")]
options = ( "-mcet", "-fcf-protection", "-fstack-clash-protection", "-fstack-protector-strong", "-fno-semantic-interposition", "-ffat-lto-objects", "-ftree-loop-distribute-patterns", "-gno-variable-location-views" ) for option in options: if not clang_has_option(cc, cc_args, src_feature_tests, option): # Remove the option and any variant (e.g. -option=...) flags = [f for f in flags if not f.startswith(option)]
# Re-join flags preserving quoting config_vars[var] = shlex.join(flags)
class BuildExt(_build_ext): """Custom build_ext command to set output directories."""
def __init__(self, *args, **kwargs): self.build_lib = None self.build_temp = None super().__init__(*args, **kwargs)
def finalize_options(self) -> None: _build_ext.finalize_options(self) build_lib = os.getenv('PYTHON_EXTBUILD_LIB') build_tmp = os.getenv('PYTHON_EXTBUILD_TMP') if build_lib: self.build_lib = build_lib if build_tmp: self.build_temp = build_tmp
class InstallLib(_install_lib): """Custom install_lib command to set output directory."""
def __init__(self, *args, **kwargs): self.build_dir = None super().__init__(*args, **kwargs)
def finalize_options(self) -> None: _install_lib.finalize_options(self) build_lib = os.getenv('PYTHON_EXTBUILD_LIB') if build_lib: self.build_dir = build_lib
def run(self): _install_lib.run(self) srctree = os.getenv('srctree', '.') src_perf = os.path.join(srctree, 'tools/perf') shutil.copy2(os.path.join(src_perf, 'python/perf.pyi'), self.install_dir)
def main() -> None: """Main entry point for the setup script.""" cc_env = os.getenv("CC") assert cc_env, "Environment variable CC not set"
# Safe parsing of CC environment variable which might contain options/quotes cc_tokens = shlex.split(cc_env) cc = cc_tokens[0] cc_args = cc_tokens[1:]
# Run CC -v to check if it is clang. try: cc_info = subprocess.run( [cc, "-v"], stderr=subprocess.PIPE, stdout=subprocess.DEVNULL, check=False ) cc_is_clang = b"clang version" in cc_info.stderr except OSError as e: raise RuntimeError(f"Failed to execute compiler '{cc}': {e}") from e
srctree = os.getenv('srctree') assert srctree, "Environment variable srctree, for the Linux sources, not set" src_feature_tests = f'{srctree}/tools/build/feature'
if cc_is_clang: filter_clang_options(cc, cc_args, src_feature_tests)
# switch off several checks (need to be at the end of cflags list) cflags = [ '-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter', '-Wno-redundant-decls' ] if cc_is_clang: cflags += ["-Wno-unused-command-line-argument"] if clang_has_option( cc, cc_args, src_feature_tests, "-Wno-cast-function-type-mismatch" ): cflags += ["-Wno-cast-function-type-mismatch"] else: cflags += ['-Wno-cast-function-type']
# The python headers have mixed code with declarations (decls after asserts, for instance) cflags += ["-Wno-declaration-after-statement"]
src_perf = f'{srctree}/tools/perf'
perf = Extension( 'perf', sources=[os.path.join(src_perf, 'util/python.c')], include_dirs=['util/include'], extra_compile_args=cflags, )
setup( name='perf', version='0.1', description='Interface with the Linux profiling infrastructure', author='Arnaldo Carvalho de Melo', author_email='acme@redhat.com', license='GPLv2', url='http://perf.wiki.kernel.org', ext_modules=[perf], cmdclass={'build_ext': BuildExt, 'install_lib': InstallLib}, )
if __name__ == '__main__': main()