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..65b10f91a61c --- /dev/null +++ b/test/runnable/test2968.d @@ -0,0 +1,24 @@ +// DISABLED: win linux freebsd dragonflybsd netbsd + +pragma(framework, "CoreFoundation"); + +struct __CFArray; //try to call some CF functions with arrays +alias CFArrayRef = __CFArray*; +alias CFIndex = long; + +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() +{ + + 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)); + } +}