> Thanks. So to be perfectly clear: 'l' isn't known to the engine, which
> implies that any target name I use on the command-line is never passed
> directly to the engine (e.g. using `bjam.update()`, with the Python
> frontend), but is looked up in the b2 logic and translated to a
> registered target name that is known by the engine. Right ?
 
That is correct.

> And a related question: where is the path schema defined that generates
> a file name including different features (such as
> 'bin/gcc-6.3.1/debug/libl.so') ? And how is that schema chosen by a
> given target ? Is it used by all targets, whether the given features
> affect the target build or not ?
 
Each metatarget takes the given build request* and constructs virtual targets.
Virtual targets are targets that are to be built and contain property sets on them.
To construct the path to the target, a combination of the location of where the
metatarget was declared and the features within the property set are used.
The location of the metatarget is already a path, but the property set needs
to first be converted to a path. This is done using the as-path() rule in property.jam.
 
The path is generated when the virtual target is actualized. See the actual-name()
method on the abstract-file-target class in virtual-target.jam
 
* a build request is all of the properties and targets passed on the command line
that are mixed with all of the default properties (non-optional features). This
build request is applied to every metatarget to construct a virtual-target which
is then actualized to a low-level engine target.
 
Aaron