....
notes:
- post-order (children before parents) order is what makes sense for
-liblistbecause it keeps module resolution in line with analysis construct resolution: the latter can only operate on the transitive closure of libraries declared as deps, not reverse dependencies - by ordering the elab-time library search order the same way, we provide consistency
- further, this (post-order instead of pre-order) is what makes sense from a
composition standpoint: a library author gets to choose their dependencies
(or at least, is aware of them and runs elab on their own designs with
said dependencies) but cannot choose or know anything about reverse
dependencies
- thus, it's reasonable to expect a library author to deal with undesired name collisions between the library and its dependencies but its not reasonable to expect a library author to deal with name collision issues coming from a reverse dependency
- for example, say we have library dependency chain:
A -> B -> C- and lets say
Bhas a module that usesfrobfromCbut thatAalso has afrobmodule - post-order gives us:
C,B,A: under this schemeB's use offrobwill correctly resolve toC- this is the same as when
Bwas elaborated (in testing) withoutA
- this is the same as when
- pre-order would give us:
A,B,C: under this schemeB's use offrobwould incorrectly resolve toA!- the author of
Bdoesn't really have any way to anticipate this or a way to deal with it (short of writingconfigfiles and such)
- the author of
- and lets say
- the counterargument to the above is the opposite scenario, e.g. say we
have the same library dependency chain
A -> B -> Cbut:Ahas a module thattopthat instantiatesfoo(also defined inA)Calso has a modulefoo- when using the post-order ordering (
C,B,A),A::top's instantiation offoo(incorrectly) resolves toC::foo - a few things distinguish this case from the above:
- this case arises during A's development and is a result of a choice
(the use of
Bwhich pulls inC) that's made by or at least known to the developers ofA - by contrast the case above only comes up when
Bis composed into something; spookier - here it's reasonable to expect
A's devs to work around this - this particular case is also trivially avoidable with
-liblist_work
- this case arises during A's development and is a result of a choice
(the use of
there are, however, thornier cases where the composition of multiple libraries with common dependencies can cause resolution issues; for example:
flowchart TD
e
d --> e
c
b --> c & d
a --> e & b
sv_library(name = "e", ...)
sv_library(name = "d", deps = [":e"], ...)
sv_library(name = "c", ...)
sv_library(name = "b", deps = [":c", ":d"], ...)
sv_library(name = "a", deps = [":e", ":b"], ...)
sv_top(name = "d_top", lib = ":d") # lib-order: e, d
sv_top(name = "b_top", lib = ":b") # lib-order: c, e, d, b
sv_top(name = "a_top", lib = ":a") # lib-order: e, c, d, b, alet's say that:
dhas a moduledeltathat instantiates modulefoofromecalso has a modulefoo
for d_top, everything works fine: d::delta will resolve foo to e::foo
for b_top there is breakage: d::delta will resolve foo to c::foo
however in a_top, because a specified a dep on e, it is pulled to the
start of the library search order and so d::delta once again resolves to
e::foo...
we could solve this specific case by arranging for the lib-order of b_top to
be e, d, c, b (i.e. shift around the order of deps on b_top) but this
isn't a general solution, i.e. you can craft scenarios where no static ordering
of libraries (even with -liblist_work) results in all modules being specified
as desired...
I think the "solution" for such cases is "rename your modules" or "write some
V2K configs"...