1313 path: string
1414 dirty: bool
1515 files: Table [string , FileInfo ]
16- dependencies: seq [ tuple [module: string , features: seq [string ] ]]
16+ dependencies: Table [ string , seq [string ]]
1717
1818var dry = false
1919var force = false
@@ -82,7 +82,7 @@ proc toCamelCase(str: string): string =
8282proc toPascalCase (str: string ): string =
8383 return str.splitCase.parts.joinCase (Pascal )
8484
85- proc readDependencies (str: string , modules: Table [string , ModuleInfo ]): seq [ tuple [module: string , features: seq [string ] ]] =
85+ proc readDependencies (str: string , modules: Table [string , ModuleInfo ]): Table [ string , seq [string ]] =
8686 try :
8787 let f = readFile (str)
8888 for l in f.splitLines:
@@ -93,19 +93,18 @@ proc readDependencies(str: string, modules: Table[string, ModuleInfo]): seq[tupl
9393 let features = parts[1 ..^ 1 ]
9494 if not modules.contains (name):
9595 echo & " Unknown module dependency '{ name} ' for module '{ str} ' "
96- result . incl ( name, features)
96+ result [ name] = features
9797 if l.startsWith (" import " ) or l.startsWith (" import " ):
9898 let i = l.find (" import" )
9999 if l.contains (" std/" ):
100100 continue
101101 for dep in l[(i + 6 )..^ 1 ].split ({',' , '[' , ']' }):
102102 let name = dep.strip
103103 if name != " " and modules.contains (name):
104- result .incl (name, @ [])
104+ discard result .mgetOrPut (name, @ [])
105105
106106 except CatchableError as e:
107107 echo & " Failed to read file dependencies from '{ str} ': { e.msg} "
108- return @ []
109108
110109proc gatherModules (): Table [string , ModuleInfo ] =
111110 try :
@@ -146,6 +145,20 @@ proc gatherModules(): Table[string, ModuleInfo] =
146145 let dependencies = readDependencies (result [module].path, result )
147146 result [module].dependencies = dependencies
148147
148+ # Collect recursive dependencies for each module
149+ for module in result .keys:
150+ var queue = @ [module]
151+ var visited = initHashSet [string ]()
152+ while queue.len > 0 :
153+ let m = queue.pop ()
154+ if m in visited:
155+ continue
156+ visited.incl m
157+ if m in result :
158+ for dep in result [m].dependencies.pairs:
159+ queue.add dep[0 ]
160+ result [module].dependencies.mgetOrPut (dep[0 ], @ []).incl (dep[1 ])
161+
149162 except OSError as e:
150163 echo & " Failed to gather modules: { e.msg} "
151164
@@ -214,21 +227,24 @@ proc buildDirtyModules(modules: Table[string, ModuleInfo]) =
214227 continue
215228
216229 try :
217- echo & " Build { name} ({ m.path} ) { m.dependencies.mapIt (it.module & \ " \" & it.features.join(\" :\" )).join(\" , \" )}"
230+ # echo &"Build {name} ({m.path}) {m.dependencies.mapIt(it.module & \" \" & it.features.join(\":\")).join(\", \")}"
231+ echo & " Build { name} ({ m.path} ) { m.dependencies} "
218232
219233 if logVerbose:
220234 for (file, info) in m.files.pairs:
221235 echo & " { file} { info} "
222236
223- let builtinDeps = @ [" log" ]
224- let dependencies = (m.dependencies.mapIt (it.module) & builtinDeps).join (" ," )
237+ var dependencies = @ [" log" ]
238+ for module in m.dependencies.keys:
239+ dependencies.add module
240+ let dependenciesStr = dependencies.join (" ," )
225241 let features = collect:
226- for dep in m.dependencies:
227- for f in dep. features:
242+ for features in m.dependencies.values :
243+ for f in features:
228244 & " -d:feat{ f} "
229245 let allFeatures = features.join (" " )
230246 let opt = if not debug or name == " text" : " speed" else : " none"
231- let cmd = & " nim c --colors:on --hints:off -o:native_plugins/{ name} .dll --nimcache:nimcache/{ name} --app:lib -d:useDynlib -d:nevModuleName={ name} -d:nevDeps={ dependencies } { allFeatures} --path:modules --cc:clang --passC:-Wno-incompatible-function-pointer-types --passL:-ladvapi32.lib --passL:-luser32.lib --passC:-std=gnu11 --opt:{ opt} --lineDir:off -d:mallocImport -d:exposeScriptingApi=true { m.path} "
247+ let cmd = & " nim c --colors:on --hints:off -o:native_plugins/{ name} .dll --nimcache:nimcache/{ name} --app:lib -d:useDynlib -d:nevModuleName={ name} -d:nevDeps={ dependenciesStr } { allFeatures} --path:modules --cc:clang --passC:-Wno-incompatible-function-pointer-types --passL:-ladvapi32.lib --passL:-luser32.lib --passC:-std=gnu11 --opt:{ opt} --lineDir:off -d:mallocImport -d:exposeScriptingApi=true { m.path} "
232248 if parallel:
233249 while cmds.len >= 10 :
234250 for i in countdown (cmds.high, 0 ):
@@ -299,10 +315,10 @@ proc buildDirtyModules(modules: Table[string, ModuleInfo]) =
299315 inDegree[name] = 0
300316 graph[name] = @ []
301317 for (name, m) in modules.pairs:
302- for dep in m.dependencies:
303- if dep. module in modules:
304- graph[name].add (dep. module)
305- inc inDegree, dep. module
318+ for module in m.dependencies.keys :
319+ if module in modules:
320+ graph[name].add (module)
321+ inc inDegree, module
306322 var queue: seq [string ] = @ []
307323 for name in modules.keys:
308324 if name in inDegree and inDegree[name] > 0 :
@@ -320,11 +336,11 @@ proc buildDirtyModules(modules: Table[string, ModuleInfo]) =
320336 var sortedNames = topoSort (modules)
321337 if sortedNames.toSet ().len != modules.len:
322338 proc printCycles (modules: Table [string , ModuleInfo ], path: seq [string ]) =
323- for dep in modules[path[^ 1 ]].dependencies:
324- if dep. module in path:
325- echo & " Cycle " , path & dep. module
339+ for module in modules[path[^ 1 ]].dependencies.keys :
340+ if module in path:
341+ echo & " Cycle " , path & module
326342 continue
327- printCycles (modules, path & dep. module)
343+ printCycles (modules, path & module)
328344
329345 for module in modules.keys:
330346 printCycles (modules, @ [module])
0 commit comments