From ad7867dd1358d8df4359875719bd0f7afc94afcb Mon Sep 17 00:00:00 2001 From: Ben Jones Date: Mon, 25 Nov 2019 19:22:10 -0700 Subject: [PATCH 1/2] fix issue 2968 by adding a new pragma(framework) to add appropraite flags to the link command on macos --- changelog/pragma_framework.dd | 3 +++ src/dmd/dsymbolsem.d | 30 +++++++++++++++++++++++++++ src/dmd/globals.d | 1 + src/dmd/globals.h | 1 + src/dmd/id.d | 1 + src/dmd/json.d | 8 +++++++ src/dmd/link.d | 11 +++++++++- src/dmd/toobj.d | 18 ++++++++++++++++ test/compilable/extra-files/json2.out | 1 + test/runnable/test2968.d | 24 +++++++++++++++++++++ 10 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 changelog/pragma_framework.dd create mode 100644 test/runnable/test2968.d diff --git a/changelog/pragma_framework.dd b/changelog/pragma_framework.dd new file mode 100644 index 000000000000..1d4fb4a5fe74 --- /dev/null +++ b/changelog/pragma_framework.dd @@ -0,0 +1,3 @@ +This add the new pragma(framework, FRAMEWORK_NAME) + +It adds the arguments "-framework FRAMEWORK_NAME" to the linker commandline. \ No newline at end of file diff --git a/src/dmd/dsymbolsem.d b/src/dmd/dsymbolsem.d index fb3549fb1bef..f618db320afb 100644 --- a/src/dmd/dsymbolsem.d +++ b/src/dmd/dsymbolsem.d @@ -1902,6 +1902,36 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor } goto Lnodecl; } + else if (pd.ident == Id.framework) + { + if (!pd.args || pd.args.dim != 1) + pd.error("string expected for framework name"); + else + { + auto se = semanticString(sc, (*pd.args)[0], "framework name"); + if (!se) + goto Lnodecl; + (*pd.args)[0] = se; + + auto name = se.peekString().xarraydup; + if (global.params.verbose) + message("framework %s", name.ptr); + if (global.params.moduleDeps && !global.params.moduleDepsFile) + { + OutBuffer* ob = global.params.moduleDeps; + Module imod = sc.instantiatingModule(); + ob.writestring("depsFramework "); + ob.writestring(imod.toPrettyChars()); + ob.writestring(" ("); + escapePath(ob, imod.srcfile.toChars()); + ob.writestring(") : "); + ob.writestring(name); + ob.writenl(); + } + mem.xfree(name.ptr); + } + goto Lnodecl; + } else if (pd.ident == Id.startaddress) { if (!pd.args || pd.args.dim != 1) diff --git a/src/dmd/globals.d b/src/dmd/globals.d index 7b74cc6992b0..eabc81b8461a 100644 --- a/src/dmd/globals.d +++ b/src/dmd/globals.d @@ -267,6 +267,7 @@ extern (C++) struct Param Array!bool linkswitchIsForCC; Array!(const(char)*) libfiles; Array!(const(char)*) dllfiles; + Array!(const(char)*) frameworks; const(char)[] deffile; const(char)[] resfile; const(char)[] exefile; diff --git a/src/dmd/globals.h b/src/dmd/globals.h index 2c77ced9cff8..60138a0b0145 100644 --- a/src/dmd/globals.h +++ b/src/dmd/globals.h @@ -236,6 +236,7 @@ struct Param Array linkswitchIsForCC; Array libfiles; Array dllfiles; + Array frameworks; DString deffile; DString resfile; DString exefile; diff --git a/src/dmd/id.d b/src/dmd/id.d index 889aa48fd9c3..aec37d4fbb41 100644 --- a/src/dmd/id.d +++ b/src/dmd/id.d @@ -322,6 +322,7 @@ immutable Msgtable[] msgtable = // For pragma's { "Pinline", "inline" }, { "lib" }, + { "framework"}, { "linkerDirective" }, { "mangle" }, { "msg" }, diff --git a/src/dmd/json.d b/src/dmd/json.d index e677cbaedfd6..53222a6d85db 100644 --- a/src/dmd/json.d +++ b/src/dmd/json.d @@ -931,6 +931,14 @@ public: } arrayEnd(); + propertyStart("frameworks"); + arrayStart(); + foreach (framework; global.params.frameworks) + { + item(framework.toDString); + } + arrayEnd(); + propertyStart("ddocFiles"); arrayStart(); foreach (ddocFile; global.params.ddocfiles) diff --git a/src/dmd/link.d b/src/dmd/link.d index 2d645b8415c9..6dfaef6b025e 100644 --- a/src/dmd/link.d +++ b/src/dmd/link.d @@ -639,7 +639,9 @@ public int runLINK() * 4. libraries specified by pragma(lib), which were appended * to global.params.libfiles. These are prefixed with "-l" * 5. dynamic libraries passed to the command line (global.params.dllfiles) - * 6. standard libraries. + * 6. frameworks specified by pragma(framework), which were appended + * to the global.params.frameworks as -framework FRAMEWORK_NAME + * 7. standard libraries. */ // STEP 1 @@ -698,6 +700,13 @@ public int runLINK() } // STEP 6 + foreach (framework; global.params.frameworks) + { + argv.push("-framework"); + argv.push(mem.xstrdup(framework)); + } + + // STEP 7 /* D runtime libraries must go after user specified libraries * passed with -l. */ diff --git a/src/dmd/toobj.d b/src/dmd/toobj.d index 84fa30d241fd..752d2982dae8 100644 --- a/src/dmd/toobj.d +++ b/src/dmd/toobj.d @@ -754,6 +754,24 @@ void toObjFile(Dsymbol ds, bool multiobj) global.params.libfiles.push(name); } } + else if (pd.ident == Id.framework) + { + assert(pd.args && pd.args.dim == 1); + printf("got a framework\n"); + Expression e = (*pd.args)[0]; + + assert(e.op == TOK.string_); + + StringExp se = cast(StringExp)e; + char *name = cast(char *)mem.xmalloc(se.numberOfCodeUnits() + 1); + se.writeTo(name, true); + + /* Append the framework name to the list to be passed + * to the linker. + */ + global.params.frameworks.push(name); + + } else if (pd.ident == Id.startaddress) { assert(pd.args && pd.args.dim == 1); diff --git a/test/compilable/extra-files/json2.out b/test/compilable/extra-files/json2.out index d5414e9bc9fe..1e403da4b81b 100644 --- a/test/compilable/extra-files/json2.out +++ b/test/compilable/extra-files/json2.out @@ -5,6 +5,7 @@ "cwd": "VALUE_REMOVED_FOR_TEST", "ddocFiles": [], "defFile": null, + "frameworks": [], "importPaths": [ "compilable", "../../druntime/import", diff --git a/test/runnable/test2968.d b/test/runnable/test2968.d new file mode 100644 index 000000000000..4700aa43e897 --- /dev/null +++ b/test/runnable/test2968.d @@ -0,0 +1,24 @@ +// DISABLED: win linux freebsd dragonflybsd netbsd + +struct __CFArray; //try to call some CF functions with strings +alias CFArrayRef = __CFArray*; +alias CFIndex = long; + +extern(Objective-C) CFArrayRef CFArrayCreate(void* allocator, const void** values, long numValues, void* cbs); +extern(Objective-C) CFIndex CFArrayGetCount(CFArrayRef theArray); +extern(Objective-C) const(void *) CFArrayGetValueAtIndex(CFArrayRef theArray, CFIndex idx); + +pragma(framework, "Foundation"); + +void main() +{ + + ulong[5] array = [1,2,3,4,5]; + auto cfa = CFArrayCreate(null, cast(void**)array.ptr, array.length, null); + const length = CFArrayGetCount(cfa); + assert(length == array.length); + foreach (i, x; array) + { + assert(x == cast(ulong) CFArrayGetValueAtIndex(cfa, i)); + } +} From ccc6b8a6faa952cf44792a5fb68b4aab138b4820 Mon Sep 17 00:00:00 2001 From: Ben Jones Date: Tue, 26 Nov 2019 09:10:07 -0700 Subject: [PATCH 2/2] fix testcase --- test/runnable/test2968.d | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/runnable/test2968.d b/test/runnable/test2968.d index 4700aa43e897..65b10f91a61c 100644 --- a/test/runnable/test2968.d +++ b/test/runnable/test2968.d @@ -1,14 +1,14 @@ // DISABLED: win linux freebsd dragonflybsd netbsd -struct __CFArray; //try to call some CF functions with strings +pragma(framework, "CoreFoundation"); + +struct __CFArray; //try to call some CF functions with arrays alias CFArrayRef = __CFArray*; alias CFIndex = long; -extern(Objective-C) CFArrayRef CFArrayCreate(void* allocator, const void** values, long numValues, void* cbs); -extern(Objective-C) CFIndex CFArrayGetCount(CFArrayRef theArray); -extern(Objective-C) const(void *) CFArrayGetValueAtIndex(CFArrayRef theArray, CFIndex idx); - -pragma(framework, "Foundation"); +extern(C) CFArrayRef CFArrayCreate(void* allocator, const void** values, long numValues, void* cbs); +extern(C) CFIndex CFArrayGetCount(CFArrayRef theArray); +extern(C) const(void *) CFArrayGetValueAtIndex(CFArrayRef theArray, CFIndex idx); void main() {