/** * Implement the `-deps` and `-makedeps` switches, which output dependencies of modules for build tools. * * The grammar of the `-deps` output is: * --- * ImportDeclaration * ::= BasicImportDeclaration [ " : " ImportBindList ] [ " -> " * ModuleAliasIdentifier ] "\n" * * BasicImportDeclaration * ::= ModuleFullyQualifiedName " (" FilePath ") : " Protection|"string" * " [ " static" ] : " ModuleFullyQualifiedName " (" FilePath ")" * * FilePath * - any string with '(', ')' and '\' escaped with the '\' character * --- * * Make dependencies as generated by `-makedeps` look like this: * --- * source/app.d: * source/importa.d \ * source/importb.d * --- * * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/deps.d, makedeps.d) * Documentation: https://dlang.org/phobos/dmd_deps.html * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/deps.d */ module dmd.deps; import core.stdc.stdio : printf; import core.stdc.string : strcmp; import dmd.common.outbuffer; import dmd.dimport : Import; import dmd.dmodule : Module; import dmd.globals : Param, Output; import dmd.hdrgen : visibilityToBuffer; import dmd.id : Id; import dmd.utils : escapePath; /** * Add an import expression to module dependencies * Params: * moduleDeps = output settings for `-deps` * makeDeps = output settings for `-makedeps` * fileNameZ = 0-termminated string containing the import expression's resolved filename * importString = raw string passed to import exp * imod = module import exp is in */ void addImportExpDep(ref Output moduleDeps, ref Output makeDeps, const(char)[] fileNameZ, const(char)[] importString, Module imod) { if (moduleDeps.buffer !is null) { OutBuffer* ob = moduleDeps.buffer; if (!moduleDeps.name) ob.writestring("depsFile "); ob.writestring(imod.toPrettyChars()); ob.writestring(" ("); escapePath(ob, imod.srcfile.toChars()); ob.writestring(") : "); if (moduleDeps.name) ob.writestring("string : "); ob.write(importString); ob.writestring(" ("); escapePath(ob, fileNameZ.ptr); ob.writestring(")"); ob.writenl(); } if (makeDeps.doOutput) { makeDeps.files.push(fileNameZ.ptr); } } /** * Add an import statement to module dependencies * Params: * moduleDeps = output settings * imp = import to add * imod = module that the import is in */ void addImportDep(ref Output moduleDeps, Import imp, Module imod) { // object self-imports itself, so skip that // https://issues.dlang.org/show_bug.cgi?id=7547 // don't list pseudo modules __entrypoint.d, __main.d // https://issues.dlang.org/show_bug.cgi?id=11117 // https://issues.dlang.org/show_bug.cgi?id=11164 if (moduleDeps.buffer is null || (imp.id == Id.object && imod.ident == Id.object) || strcmp(imod.ident.toChars(), "__main") == 0) return; OutBuffer* ob = moduleDeps.buffer; if (!moduleDeps.name) ob.writestring("depsImport "); ob.writestring(imod.toPrettyChars()); ob.writestring(" ("); escapePath(ob, imod.srcfile.toChars()); ob.writestring(") : "); // use visibility instead of sc.visibility because it couldn't be // resolved yet, see the comment above visibilityToBuffer(*ob, imp.visibility); ob.writeByte(' '); if (imp.isstatic) { ob.writestring("static "); } ob.writestring(": "); foreach (pid; imp.packages) { ob.printf("%s.", pid.toChars()); } ob.writestring(imp.id.toString()); ob.writestring(" ("); if (imp.mod) escapePath(ob, imp.mod.srcfile.toChars()); else ob.writestring("???"); ob.writeByte(')'); foreach (i, name; imp.names) { if (i == 0) ob.writeByte(':'); else ob.writeByte(','); auto _alias = imp.aliases[i]; if (!_alias) { ob.printf("%s", name.toChars()); _alias = name; } else ob.printf("%s=%s", _alias.toChars(), name.toChars()); } if (imp.aliasId) ob.printf(" -> %s", imp.aliasId.toChars()); ob.writenl(); }