Once all of your components have been individually compiled, Dana has three main ways to form a working system with them (or to “link” them together). These three linking mechanics are called “automated”, “static” and “dynamic”. The same compiled components can be used in all three linking variants without modification.
Automated linking is the default mode in which Dana operates. Each required interface of each component is automatically linked, at the point of program execution, to the default component implementing that interface (if any). It's good for rapid prototyping and for writing quick little programs here and there. The same programs can be used, without modification, with Dana's other mechanisms for inter-component connection.
Almost all of the examples that come with Dana use automated linking by default. If for example you compile
os/SystemInfo.dn using the Dana compiler, then use the command
You'll see that the program runs as expected, without having to explicitly specify that the component
examples/SysTest.dn should in particular use the component
os/SystemInfo.dn to satisfy its dependency on the
os.SystemInfo interface. It's very important to always keep in mind that, in Dana programs, a required interface is not referring to a specific component but rather to an interface type.
As you might guess, automated linking is primarily based upon simple name equivalence. If there's a component with the same package path as a required interface, with the same file name as the interface's type name, Dana will attempt to use that component to satisfy the dependency.
In some cases however this simple name equivalence isn't enough and we need a little more information. This happens when a component's source file name has no direct relationship to the interfaces that it implements, such as the TCP component which implements both
In these cases Dana uses “manifest” files to assist with the automated linking system. In some folders, like components/net/, you'll therefore notice a file called
This file contains some simple JSON which specifies how to map interface types to component implementations in this sub-package. You can open the file in a text editor to see the format of this mapping. You can also add more mappings to these manifest files as you develop your own components, or use them to override the default name-equivalence mappings.
In detail, when searching for components to satisfy dependencies, Dana uses the following precedence rules:
1. Check for a .manifest file in the folder of the component that declares the required interface; if found, see if that manifest file specifies a default component map this dependency to.
2. Check if there is a component in the folder of the component that declares the required interface, whose package path and compiled object-file name matches the dependency's interface name.
3. Check in Dana's central source tree (i.e. components/) for a .manifest file in the corresponding package path; if found, see if that manifest file specifies a default component map this dependency to.
4. Check in Dana's central source tree for a component in the matching package path of the dependency, whose compiled object-file name matches the dependency's interface name.
If all of these search steps fail to find a candidate component, automated linking will fail for that interface.
Note that the automated linking procedure does not attempt to compile components, it only searches for components that are already compiled.