Skip to content

compile

FreeBodyEngine.cli.cpp.compile #

CPP_EXT = '.cpp' module-attribute #

EXTENSION_NAME = '_fbcpp' module-attribute #

GEN_DIR_NAME = 'gen' module-attribute #

HEADER_EXTS = ('.hpp', '.h') module-attribute #

SCRIPTS_DIR_NAME = 'cpp_scripts' module-attribute #

BoundFile(abs_path, code_path) #

One .cpp/.hpp/.h file, parsed for //@bind markers, plus how it needs to be fed into the combined build:

  • a header is always safe to #include from the generated bindings shim (that's what headers are for), so it's never compiled on its own - only ever pulled in wherever it's #included.
  • a .cpp that binds a class/struct has to be #included into the bindings shim too, since pybind11 needs the full type definition (size, constructors, method pointers) available where it's bound - a forward declaration isn't enough the way it is for a free function. To avoid defining that class's (non-inline) members twice
  • once from compiling the .cpp itself, once from the shim #includeing it - a "class-bound" .cpp is treated like a header too: pulled in only via the shim, not compiled as its own translation unit. (A class meant to be both Python-bound and called from other .cpp files needs to live in a header anyway, for the same reason any normal C++ class shared across files does.)
  • a .cpp that only binds free functions doesn't have this problem - a forward declaration is all pybind11 needs to reference a function
  • so it's compiled normally as its own translation unit (giving it completely ordinary extern linkage other files can also call into) and the shim just forward-declares whatever it binds.

Parses abs_path for //@bind markers immediately (via CppBindingGenerator) and computes this file's safe, collision-free identifier (see safe_name).

abs_path = abs_path instance-attribute #

generator = CppBindingGenerator(open(abs_path, encoding='utf-8').read(), self.stem) instance-attribute #

has_bindings property #

True if this file declared any bound classes or free functions.

include_only property #

True if this file must only ever be pulled in via #include (never compiled as its own translation unit) - see the class docstring.

is_class_bound_cpp property #

True if this is a non-header .cpp that binds at least one class/struct (see the class docstring for why that changes how it's compiled).

is_header = abs_path.endswith(HEADER_EXTS) instance-attribute #

register_fn_name property #

The name of the generated C++ function that registers this file's bindings into a pybind11 module.

rel_path = os.path.relpath(abs_path, code_path) instance-attribute #

safe_name = f'{safe_rel}_{hashlib.blake2b(self.rel_path.encode(), digest_size=4).hexdigest()}' instance-attribute #

stem = os.path.splitext(os.path.basename(abs_path))[0] instance-attribute #

compile_cpp_scripts(code_path, python_executable, platform_name=None, force=False, quiet=False) #

(re)builds every bound .cpp/.hpp/.h file under code_path into one shared extension module (cpp_scripts/_fbcpp.<...>), plus one import-able Python shim per bound file (cpp_scripts/<stem>.py). Only actually invokes the compiler when something changed since the last call (tracked by content hash in cpp_scripts/data.json) - pass force=True to ignore that and rebuild from scratch.

Returns "unchanged" (nothing to do), "no-sources" (no .cpp/.hpp/.h files at all), "ok", or "failed".

compile_handler(env, args) #

CLI entry point for fb compile_scripts / fb cs. Recompiles every .cpp/.hpp/.h file under the project's code directory that changed since the last run into one shared extension module, so the project's C++ files can #include each other and call into each other's functions/classes exactly like any normal multi-file C++ project, while each one is still individually import-able from Python by its own file name.

discover_files(code_path) #

Finds every .cpp/.hpp/.h under the project's code directory, excluding the generated cpp_scripts/ output directory itself.

generate_setup_py(sources, include_dirs, cxx_standard_flag) #

Renders a setup.py that builds sources into the _fbcpp extension module via pybind11/setuptools.

hash_source(source) #

Returns a stable content hash of source, used to detect whether a file has changed since the last compile.