From 803bf6493630b0d3597076075736591d83a664ff Mon Sep 17 00:00:00 2001 From: "Richard (Rikki) Andrew Cattermole" Date: Wed, 18 Sep 2024 19:21:07 +1200 Subject: [PATCH] Implement pragma compile on import bugzilla #24869 --- changelog/dmd.pragma.compileonimport.dd | 30 +++++++++++++++++++ compiler/src/dmd/frontend.h | 1 + compiler/src/dmd/id.d | 1 + compiler/src/dmd/main.d | 24 +++++++-------- compiler/src/dmd/pragmasem.d | 12 ++++++++ compiler/test/runnable/compileonimport.d | 10 +++++++ .../runnable/imports/compileonimportlib.d | 7 +++++ 7 files changed, 73 insertions(+), 12 deletions(-) create mode 100644 changelog/dmd.pragma.compileonimport.dd create mode 100644 compiler/test/runnable/compileonimport.d create mode 100644 compiler/test/runnable/imports/compileonimportlib.d diff --git a/changelog/dmd.pragma.compileonimport.dd b/changelog/dmd.pragma.compileonimport.dd new file mode 100644 index 000000000000..b366ba1c9689 --- /dev/null +++ b/changelog/dmd.pragma.compileonimport.dd @@ -0,0 +1,30 @@ +Add a new pragma to compile on import + +The pragma ``compileOnImport``, will convert an imported module into one that will be compiled into your binary. + +This is the same behavior as the ``-i`` switch, except it is a pragma in a module. + +A library module: + +```d +module mylib; +pragma(compileOnImport); + +void callMe() { + import std.stdio; + writeln("Hello!"); +} +``` + +The user module: + +```d +module theuser; +import mylib; + +void main() { + callMe(); // Hello! +} +``` + +Compile with ``dmd -I. theuser.d`` diff --git a/compiler/src/dmd/frontend.h b/compiler/src/dmd/frontend.h index 845e4889e95a..4b4ee557ae12 100644 --- a/compiler/src/dmd/frontend.h +++ b/compiler/src/dmd/frontend.h @@ -8583,6 +8583,7 @@ struct Id final static Identifier* startaddress; static Identifier* crt_constructor; static Identifier* crt_destructor; + static Identifier* compileOnImport; static Identifier* tohash; static Identifier* tostring; static Identifier* getmembers; diff --git a/compiler/src/dmd/id.d b/compiler/src/dmd/id.d index f676361d958b..63a913a77f18 100644 --- a/compiler/src/dmd/id.d +++ b/compiler/src/dmd/id.d @@ -352,6 +352,7 @@ immutable Msgtable[] msgtable = { "startaddress" }, { "crt_constructor" }, { "crt_destructor" }, + { "compileOnImport" }, // For special functions { "tohash", "toHash" }, diff --git a/compiler/src/dmd/main.d b/compiler/src/dmd/main.d index 27b3e5b8f977..b06173f54e79 100644 --- a/compiler/src/dmd/main.d +++ b/compiler/src/dmd/main.d @@ -567,20 +567,20 @@ private int tryMain(size_t argc, const(char)** argv, ref Param params) message("semantic3 %s", m.toChars()); m.semantic3(null); } - if (includeImports) + + // Will be empty if no module has pragma(compileOnImport) or -i is passed to compiler. + // Note: DO NOT USE foreach here because Module.amodules.length can + // change on each iteration of the loop + for (size_t i = 0; i < compiledImports.length; i++) { - // Note: DO NOT USE foreach here because Module.amodules.length can - // change on each iteration of the loop - for (size_t i = 0; i < compiledImports.length; i++) - { - auto m = compiledImports[i]; - assert(m.isRoot); - if (params.v.verbose) - message("semantic3 %s", m.toChars()); - m.semantic3(null); - modules.push(m); - } + auto m = compiledImports[i]; + assert(m.isRoot); + if (params.v.verbose) + message("semantic3 %s", m.toChars()); + m.semantic3(null); + modules.push(m); } + Module.runDeferredSemantic3(); if (global.errors) removeHdrFilesAndFail(params, modules); diff --git a/compiler/src/dmd/pragmasem.d b/compiler/src/dmd/pragmasem.d index 3a455fb3d1a8..76c1f339115b 100644 --- a/compiler/src/dmd/pragmasem.d +++ b/compiler/src/dmd/pragmasem.d @@ -320,6 +320,18 @@ void pragmaDeclSemantic(PragmaDeclaration pd, Scope* sc) .error(pd.loc, "%s `%s` takes no argument", pd.kind, pd.toPrettyChars); return declarations(); } + else if (pd.ident == Id.compileOnImport) + { + import dmd.compiler; + + if (!sc._module.isRoot()) + { + sc._module.importedFrom = sc._module; + compiledImports.push(sc._module); + } + + return declarations(); + } else if (!global.params.ignoreUnsupportedPragmas) { error(pd.loc, "unrecognized `pragma(%s)`", pd.ident.toChars()); diff --git a/compiler/test/runnable/compileonimport.d b/compiler/test/runnable/compileonimport.d new file mode 100644 index 000000000000..5af110719a81 --- /dev/null +++ b/compiler/test/runnable/compileonimport.d @@ -0,0 +1,10 @@ +/* +REQUIRED_ARGS: -Irunnable/imports +*/ +module compileonimport; +import compileonimportlib; + +void main() { + bool v = runMe(); + assert(v); +} diff --git a/compiler/test/runnable/imports/compileonimportlib.d b/compiler/test/runnable/imports/compileonimportlib.d new file mode 100644 index 000000000000..ebc12b366989 --- /dev/null +++ b/compiler/test/runnable/imports/compileonimportlib.d @@ -0,0 +1,7 @@ +module compileonimportlib; + +pragma(compileOnImport); + +bool runMe() { + return true; +}