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
#includefrom 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
.cppthat 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
.cppthat 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.