Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add use-csa option for analysing cheribuild projects with Clang Static Analyzer #401

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
32 changes: 32 additions & 0 deletions pycheribuild/config/compilation_targets.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,10 @@ def default_install_dir(self, install_dir: DefaultInstallDir) -> Path:
return self.sysroot_dir
return super().default_install_dir(install_dir)

@classmethod
def _get_csa_project(cls) -> "type[BuildLLVMInterface]":
raise NotImplementedError()

@property
def c_compiler(self) -> Path:
return self._compiler_dir / "clang"
Expand Down Expand Up @@ -176,6 +180,18 @@ def nm(self) -> Path:
def strip_tool(self) -> Path:
return self._compiler_dir / "llvm-strip"

@property
def ccc_analyzer(self) -> Path:
return self._get_csa_project().get_native_install_path(self.config) / "libexec/ccc-analyzer"

@property
def cxx_analyzer(self) -> Path:
return self._get_csa_project().get_native_install_path(self.config) / "libexec/c++-analyzer"

@property
def scan_build(self) -> Path:
return self._get_csa_project().get_native_install_path(self.config) / "bin/scan-build"

@classmethod
@abstractmethod
def triple_for_target(
Expand Down Expand Up @@ -638,6 +654,10 @@ def _get_run_project(self, xtarget: "CrossCompileTarget", caller: SimpleProject)
result = SimpleProject.get_instance_for_target_name("run", xtarget, caller.config, caller)
return typing.cast(LaunchFreeBSDInterface, result)

@classmethod
def _get_csa_project(cls) -> "type[BuildLLVMInterface]":
return typing.cast("type[BuildLLVMInterface]", SimpleProject.get_class_for_target_name("cheri-csa", None))

@classmethod
def is_cheribsd(cls) -> bool:
return True
Expand Down Expand Up @@ -725,6 +745,10 @@ def essential_compiler_and_linker_flags_impl(cls, instance: "CheriBSDTargetInfo"
result.extend(cheribsd_morello_version_dependent_flags(version, xtarget.is_cheri_purecap()))
return result

@classmethod
def _get_csa_project(cls) -> "type[BuildLLVMInterface]":
return typing.cast("type[BuildLLVMInterface]", SimpleProject.get_class_for_target_name("morello-csa", None))


# FIXME: This is completely wrong since cherios is not cheribsd, but should work for now:
class CheriOSTargetInfo(CheriBSDTargetInfo):
Expand Down Expand Up @@ -1093,6 +1117,14 @@ def nm(self) -> Path:
def strip_tool(self) -> Path:
return self.bindir / (self.binary_prefix + "strip")

@property
def ccc_analyzer(self) -> Path:
raise NotImplementedError

@property
def cxx_analyzer(self) -> Path:
raise NotImplementedError

@classmethod
def essential_compiler_and_linker_flags_impl(cls, *args, **kwargs) -> "list[str]":
# This version of GCC should work without any additional flags
Expand Down
16 changes: 16 additions & 0 deletions pycheribuild/config/target_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,14 @@ def nm(self) -> Path: ...
@abstractmethod
def strip_tool(self) -> Path: ...

@property
@abstractmethod
def ccc_analyzer(self) -> Path: ...

@property
@abstractmethod
def cxx_analyzer(self) -> Path: ...

@classmethod
@abstractmethod
def essential_compiler_and_linker_flags_impl(
Expand Down Expand Up @@ -635,6 +643,14 @@ def nm(self) -> Path:
def strip_tool(self) -> Path:
return self.c_compiler.parent / "strip"

@property
def ccc_analyzer(self) -> Path:
raise NotImplementedError

@property
def cxx_analyzer(self) -> Path:
raise NotImplementedError

@classmethod
def is_freebsd(cls) -> bool:
return OSInfo.IS_FREEBSD
Expand Down
4 changes: 4 additions & 0 deletions pycheribuild/projects/cmake.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ def custom_target_name(base_target: str, xtarget: CrossCompileTarget) -> str:
cross_install_dir = DefaultInstallDir.ROOTFS_OPTBASE
supported_architectures = CompilationTargets.ALL_SUPPORTED_CHERIBSD_TARGETS

@classmethod
def can_build_with_csa(cls) -> bool:
return True

def linkage(self):
# We always want to build the CheriBSD CTest binary static so that we can use in QEMU without needing libuv.
assert "libuv" in self.dependencies
Expand Down
21 changes: 19 additions & 2 deletions pycheribuild/projects/cross/cheribsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -1005,8 +1005,8 @@ def _setup_cross_toolchain_config(self) -> None:
if not xccinfo.is_clang:
self.ask_for_confirmation("Cross compiler is not clang, are you sure you want to continue?")
self.cross_toolchain_config.set_env(
XCC=self.CC,
XCXX=self.CXX,
XCC=self.cc_wrapper,
XCXX=self.cxx_wrapper,
XCPP=self.CPP,
X_COMPILER_TYPE=xccinfo.compiler, # This is needed otherwise the build assumes it should build with $CC
)
Expand Down Expand Up @@ -1196,9 +1196,14 @@ def _buildkernel(
# Don't build a compiler if we are using and external toolchain (only build config, etc)
if not self.use_bootstrapped_toolchain:
kernel_toolchain_opts.set_with_options(LLD_BOOTSTRAP=False, CLANG=False, CLANG_BOOTSTRAP=False)
kernel_toolchain_opts.exclude_from_csa = True
self.run_make("kernel-toolchain", options=kernel_toolchain_opts)
self.kernel_toolchain_exists = True
self.info("Building kernels for configs:", " ".join(kernconfs))

if self.use_csa:
kernel_make_args.set(BUILD_WITH_STRICT_TMPPATH=False) # Look for perl in PATH

self.run_make(
"buildkernel",
options=kernel_make_args,
Expand Down Expand Up @@ -1523,6 +1528,10 @@ def add_cross_build_options(self) -> None:
# links from /usr/bin/mail to /usr/bin/Mail won't work on case-insensitve fs
self.make_args.set_with_options(MAIL=False)

if self.use_csa:
ccinfo = self.get_compiler_info(self.host_CC)
self.make_args.set_env(COMPILER_TYPE=ccinfo.compiler)

def libcompat_name(self) -> str:
if self.crosscompile_target.is_cheri_purecap():
return "lib64"
Expand Down Expand Up @@ -1917,6 +1926,14 @@ def setup_config_options(cls, kernel_only_target=False, install_directory_help=N
"build the libraries and skip all binaries",
)

@classmethod
def can_build_with_csa(cls) -> bool:
return True

@classproperty
def extra_scan_build_args(self) -> "list[str]":
return ["-disable-checker", "alpha.core.PointerSub"]

def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
self.extra_kernels_with_mfs: "list[str]" = []
Expand Down
4 changes: 4 additions & 0 deletions pycheribuild/projects/cross/compiler_rt.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ class BuildCompilerRt(CrossCompileCMakeProject):
_check_install_dir_conflict = False
supported_architectures = CompilationTargets.ALL_SUPPORTED_CHERIBSD_AND_HOST_TARGETS

@classmethod
def can_build_with_csa(cls) -> bool:
return True

def setup(self):
# For the NATIVE variant we want to install to the compiler resource dir:
if self.compiling_for_host():
Expand Down
6 changes: 5 additions & 1 deletion pycheribuild/projects/cross/dlmalloc.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ class DLMalloc(CrossCompileProject):
make_kind = MakeCommandKind.GnuMake
native_install_dir = DefaultInstallDir.CHERI_SDK

@classmethod
def can_build_with_csa(cls) -> bool:
return True

@classmethod
def setup_config_options(cls, **kwargs):
super().setup_config_options(**kwargs)
Expand Down Expand Up @@ -119,7 +123,7 @@ def setup(self):
self.make_args.set(DEBUG=self.debug)
self.make_args.set(CAPREVOKE=self.revoke)
self.make_args.set(SRCDIR=self.source_dir)
self.make_args.set_env(CC=self.CC, CFLAGS=commandline_to_str(self.default_compiler_flags + self.CFLAGS))
self.make_args.set_env(CC=self.cc_wrapper, CFLAGS=commandline_to_str(self.default_compiler_flags + self.CFLAGS))
if not self.compiling_for_host():
self.make_args.set_env(CHERI_SDK=self.target_info.sdk_root_dir)

Expand Down
4 changes: 4 additions & 0 deletions pycheribuild/projects/cross/libcxx.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ class BuildLibCXXRT(_CxxRuntimeCMakeProject):
repository = GitRepository("https://github.com/CTSRD-CHERI/libcxxrt.git")
supported_architectures = CompilationTargets.ALL_SUPPORTED_CHERIBSD_AND_BAREMETAL_AND_HOST_TARGETS

@classmethod
def can_build_with_csa(cls) -> bool:
return True

@classmethod
def dependencies(cls, config: CheriConfig) -> "tuple[str, ...]":
result = super().dependencies(config)
Expand Down
40 changes: 40 additions & 0 deletions pycheribuild/projects/cross/llvm.py
Original file line number Diff line number Diff line change
Expand Up @@ -871,3 +871,43 @@ def update(self):
src_dir=self.source_dir / "tools/lldb",
revision=self.lldb_revision,
)


class BuildCheriLLVMWithCSA(BuildCheriLLVM):
repository = GitRepository(
"https://github.com/rems-project/llvm-project.git", force_branch=True, default_branch="cheri-csa"
)
default_directory_basename = "cheri-csa"
target = "cheri-csa"
_default_install_dir_fn = ComputedDefaultValue(
function=lambda config, project: config.output_root / "cheri-csa", as_string="$INSTALL_ROOT/cheri-csa"
)

skip_misc_llvm_tools = True
included_projects = ["clang"]
skip_static_analyzer = False
hide_options_from_help = True

@classmethod
def get_native_install_path(cls, config: CheriConfig):
return config.output_root / "cheri-csa"


class BuildMorelloLLVMWithCSA(BuildMorelloLLVM):
repository = GitRepository(
"https://github.com/rems-project/llvm-project.git", force_branch=True, default_branch="morello-csa-llvm-14"
)
default_directory_basename = "morello-csa"
target = "morello-csa"
_default_install_dir_fn = ComputedDefaultValue(
function=lambda config, project: config.output_root / "morello-csa", as_string="$INSTALL_ROOT/morello-csa"
)

skip_misc_llvm_tools = True
included_projects = ["clang"]
skip_static_analyzer = False
hide_options_from_help = True

@classmethod
def get_native_install_path(cls, config: CheriConfig):
return config.output_root / "morello-csa"
8 changes: 6 additions & 2 deletions pycheribuild/projects/cross/newlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ def custom_target_name(base_target: str, xtarget: CrossCompileTarget) -> str:
return base_target + "-baremetal-" + xtarget.base_arch_suffix
return base_target + "-" + xtarget.generic_target_suffix

@classmethod
def can_build_with_csa(cls) -> bool:
return True

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
assert self._install_prefix == Path("/", self.target_info.target_triple)
Expand Down Expand Up @@ -99,8 +103,8 @@ def setup(self):
bindir = self.sdk_bindir
self.add_configure_vars(
AS_FOR_TARGET=str(self.CC), # + target_cflags,
CC_FOR_TARGET=str(self.CC), # + target_cflags,
CXX_FOR_TARGET=str(self.CXX), # + target_cflags,
CC_FOR_TARGET=str(self.cc_wrapper), # + target_cflags,
CXX_FOR_TARGET=str(self.cxx_wrapper), # + target_cflags,
AR_FOR_TARGET=self.target_info.ar,
STRIP_FOR_TARGET=self.target_info.strip_tool,
OBJCOPY_FOR_TARGET=bindir / "objcopy",
Expand Down
4 changes: 4 additions & 0 deletions pycheribuild/projects/cross/sqlite.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ class BuildSQLite(CrossCompileAutotoolsProject):
"https://github.com/CTSRD-CHERI/sqlite.git", default_branch="3.22.0-cheri", force_branch=True
)

@classmethod
def can_build_with_csa(cls) -> bool:
return True

def check_system_dependencies(self) -> None:
super().check_system_dependencies()
# XXX: Disabling amalgamation should remove the requirement for tclsh, but it seems the build still invokes it.
Expand Down
4 changes: 4 additions & 0 deletions pycheribuild/projects/cross/zlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@
class BuildZlib(CrossCompileAutotoolsProject):
repository = GitRepository("https://github.com/CTSRD-CHERI/zlib.git")

@classmethod
def can_build_with_csa(cls) -> bool:
return True

# Enable the same hacks as nginx since this isn't really autoconf...
add_host_target_build_config_options = False
_configure_understands_enable_static = False
Expand Down
Loading
Loading