CC dependencies Last updated June 1, 2022

Support for C/C++ deps is still under development. What’s there works but the interface will likely change since there are still some issues to be worked out, such as how best to support different link modes and options for each CC dependency.

A "CC dependency" is usually a C/C++ library, but CC dependencies need not necessarily be produced from C/C++ source code. Rather the term refers to the standard file format for object files, archives, etc., which is historically is closely associated with C. Many other languages (including OCaml, Rust, Go, etc.) are capable of producing such files; OBazl uses 'CC' terminology (e.g. CC library, cc_deps) to refer to such files no matter what language was used to produce them.

CC Libraries

A library is a collection of code units. CC libraries come in several flavors:

  • an unpackaged collection of object files (with .o extension)

  • a static 'library': a collection of code units (object files) packaged as an archive file, whose extension (by convention) is .a.

  • a dynamic shared 'library': code units (object files) packaged as a dynamic shared object (DSO) file. Yes, the terminology conflates two distinct concepts; OBazl generally treats 'dynamic' and 'shared' as synonyms. On Linux, these are .so files; on MacOS, they are .dylib files (but MacOS also supports .so files).

CC Linkmode

Rules producing CC libs commonly produce both a static archive (.a files) and one or more shared libraries (.so or .dylib files). In Obazl rules, link mode determines which type of library is used for linking. Possible values:

  • static: statically link to .a file.

  • dynamic: depending on the OS, link to .dylib file (MacOS) or .so file (Linux or MacOS).

  • shared: synonym for 'dynamic'

  • default: 'static' on Linux, 'dynamic' on MacOS.

NOTE The 'default' linkmode is configurable. The default value for linkmode 'default' is as noted above. To override the default for all rules, pass command-line option --@ocaml//linkmode; for example, to set default value for linkmode 'default' to 'dynamic' pass --@ocaml//linkmode:dynamic.

Dynamic Loading ('Plugins')

[TODO: document dynamic loading of CC deps; compare OCaml *.cmxs files. Distinction between linking and loading.]

Static Binaries

Executable binaries can be linked in several ways:

  • Dynamic - all deps are shared libs

  • Partially static - non-system libs may be statically linked, but system libs are dynamically linked

  • Fully static — all dependencies, including system libraries, are statically linked, resulting in a complete standalone executabe.

WARNING MacOS does not support statically linked executables. See Statically linked binaries on Mac OS X

Dependency Cycles

Legacy packages may include circular or mutual dependencies. Bazel disallows such dependencies.

Example: libfqfft/evaluation_domain/domains and libfqfft/polynomial_arithmetic are mutually dependent.

In this case listing each in the deps attribute of the other will fail, since Bazel will detect the dependency cycle.

The "proper" way to address this is to refactor the packages to eliminate the cycles. But we cannot do that with legacy code we do not control.

The workaround seems to be to use 'include_prefix' …​ This will make compilation work, at the cost of removing at least one of the dependencies, so a change in one will not force a recompile of the other. [Why does this work?]

MacOS

Linking dynamic libs to an executable on MacOS is an open issue. The workaround for now is to link to static libs.

Demo: [demos/interop/cc_deps]()

Resources: