# Dependency Specifications for Compilation

Dependencies are specified for components, libraries, and interfaces.
To avoid ambiguity, we'll describe a component, library, or interface to be a software *blob*.
A blob's dependencies are the set of libraries and interfaces required for its proper execution.
Interfaces and libraries also *export* functionality for use by other software blobs.
Linking these software dependencies (between a dependent software blob, and the interface or library that exports the functionality) requires that the build system understand the include paths, library paths, and library outputs.

This document discusses the means of concretely resolving these dependencies, and focuses on the *build system*'s dependency resolution integration.
The dependencies between *components* for a specific system graph (i.e. the structure of components linked together via interfaces) is covered separately when discussing *composing* a system.

## Dependency Specifications

Dependencies are specified in the top-level `Makefile` for the specific component (or library or interface).
These are in `src/components/lib/*/Makefile` for libraries, and `src/components/interface/*/Makefile` and `src/components/interface/*/*/Makefile` for interfaces^[Note that currently, the second path is largely ignored.].
The required `Makefile` variables are discussed in the following sections.

These specifications culminate in the following dependency relations within the core Composite software.

![Software dependencies in Composite. Teal hexagons are *component* implementations, slate rectangles are *interfaces*, and gray ellipses are *libraries*.](./resources/dependencies.pdf)

![A different rendering of the software dependencies in Composite. Teal hexagons are *component* implementations, slate rectangles are *interfaces*, and gray ellipses are *libraries*.](./resources/dependencies_ranked.pdf)

### Interface and library dependencies

The core dependencies of a blob include the interfaces and libraries for which it requires `.h` and object files to compile.
These are all specified using the interface and library names, not the names of specific files generated by the libraries or interfaces.

The list of interfaces is a space separated list:

``` make
INTERFACE_DEPENDENCIES = init
```

The list of libraries is also a space separated list:

``` make
LIBRARY_DEPENDENCIES = component kernel
```

Specifying these will automatically set up the `-I` paths, the `-L` and `-l` paths corresponding to the depended on libraries and interfaces, and will compile with any mandatory libraries appropriately.

All of the following must specify these dependencies:

- component implementations,
- interfaces, and
- libraries.

Notes:

- Most components depend on the `init` interface to denote which component should provide their initialization.
	The depended-on component is often the scheduler, but might be the capmgr, or the constructor if the client is very low-level.
- Most components depend on the `capmgr_create` interface, as it denotes which component is the capability manager that is allowed to manage their kernel resources.

### Library and interface object outputs

Most libraries, and some interfaces generate static libraries (as `lib*.a` archives of `*.o` files) that are linked in with clients to satisfy undefined symbols.
The names of the output library files are specified as:

``` make
LIBRARY_OUTPUT = (libname|ifname)
```

In such a case, either a `liblibname.a` or a `libifname.a` file is looked for when satisfying dependencies.

**Mandatory object libraries.**
Some libraries and interfaces output a `*.o` object file that is *mandatory linked* with clients.
This is *rare* as normally you only want to link with a client if the client has undefined symbols satisfied by you, in which case static libraries are the correct solution.
However, some libraries provide boot-up code, and other code that does not satisfy an undefined symbol within the client, instead providing necessary code that either provides data-structures, or invokes the client code.
If you aren't sure, you should *not* use mandatory object files.
A library's output file is specified as follows:

``` make
OBJECT_OUTPUT = libfile
```

This will create the file `libfile.lib.o` which will be mandatorily linked into any dependent blob.

These specifications are applicable to

- libraries, and
- interfaces.

Additionally, libraries must specify their list of include paths.
Each library should provide a number of `.h` files to specify their functional types, and many libraries might impose their own location for those headers.
Thus, libraries can provide a relative specification for where those paths are (in a space-separated list):

``` make
INCLUDE_PATHS = .
```

This specification is applicable only to

- libraries.

Notes for library output:

- The names all correspond to the logical names of the libraries.
	For example, `component`, not `libcomponent.a` or `component.lib.o`.
- The build processes is assumed to not generate files with identical names to those
generated by the build process.

### Component exports

Components are often specifically implemented to provide one or more interfaces.
These interfaces are typically specified in a space-separated list:

``` make
INTERFACE_EXPORTS = init sched
```

This specification will force the component to be linked with the corresponding server stubs for the corresponding interfaces, and will include them in the compilation `-I` paths.

This specification is applicable only to

- components.

## Example specifications

> TODO

## Debugging

Most bugs with mis-specification center around dependencies and exports can be debugged using a few mechanisms.

1. If there is a compilation error around not finding a `.h` file, then there are likely missing dependencies.
	Figure out where the missing `.h` file is, and add the corresponding dependency.
2. If there are unresolved symbols, viewing the compilation logs, and use `nm` or `objdump` to determine which symbols are unresolved, and from which object file.
	Then trace back to figure out which exports or dependencies are missing.
3. Look at the specific `-L*`, `-l*`, and `-I*` values in the compilation process, and verify that they line up with your expectations (i.e., they aren't missing specific expected dependencies).
