[swift-dev] Feature Proposal to improve Mixed Frameworks support

Daniel Dunbar daniel_dunbar at apple.com
Thu Jun 29 18:35:56 CDT 2017


> On Jun 29, 2017, at 10:43 AM, Jordan Rose via swift-dev <swift-dev at swift.org> wrote:
> 
> Thanks for following through on this, Gonzalo! (The two of us talked about this briefly at WWDC.) My idea was a little less clever than yours: just always include the internal members in the main header unless you provide the name of a second header to put them in. (I called this flag -emit-objc-internal-header-path.) That's not quite as flexible, but does remove all the guesswork, at least for generated headers.

Doesn't that mean downstream Obj-C clients get bogus code completion results?

> I filed a bug to track this work: SR-5221 <https://bugs.swift.org/browse/SR-5221>.

Cool, this sounds like a nice feature to me, I have heard several complaints about needing to mark things public unnecessarily.

 - Daniel

> 
> Jordan
> 
> 
>> On Jun 29, 2017, at 06:35, Gonzalo Larralde via swift-dev <swift-dev at swift.org <mailto:swift-dev at swift.org>> wrote:
>> 
>> I wanted to bring a few points into attention to discuss potential improvements on Mixed Frameworks support. The current status for Mixed Frameworks present some challenges, one specifically being how the Swift compiler generates the ObjC Interface Header. 
>> 
>> At this moment, there's a detection procedure based on the presence of an entry point definition (either using the main file argument, or @UIApplicationMain). The ObjC Interface Header writer (swift/lib/PrintAsObjC/PrintAsObjC.cpp) is using this detection to determine if the minimum accessibility level to be exported is either `internal` (for app targets) or `public` (for framework targets). This can be observed here: https://github.com/apple/swift/blob/master/lib/FrontendTool/FrontendTool.cpp#L652-L657 <https://github.com/apple/swift/blob/master/lib/FrontendTool/FrontendTool.cpp#L652-L657>
>> 
>> The result of this is a difference on how default visibility is exposed to ObjC code in the same compilation scope.
>> 
>> Having this initial piece of code:
>> 
>> ```
>> public class Test: NSObject {
>> 	public foo() {}
>> 	func bar() {}
>> }
>> ```
>> 
>> results on the following Interface Header for Main App targets
>> 
>> <target-name>-swift.h
>> ```
>> @interface Test : NSObject
>> - (void)foo;
>> - (void)bar;
>> @end
>> ```
>> 
>> and the following for Frameworks
>> 
>> <target-name>-swift.h
>> ```
>> @interface Test : NSObject
>> - (void)foo;
>> @end
>> ```
>> 
>> This is clearly correct for the publicly visible interface of the framework, but not quite the expected result for the ObjC code compiled in the same target. In that scenario it would make more sense to me that all the `internal` methods are visible.
>> 
>> A potential solution for this problem is to generate two Interface Headers, one that exports all the `public` and `open` entities and members, and an additional header exposing internal entities and declaring categories to public entities and exposing internal members.
>> 
>> Something like:
>> 
>> <target-name>-swift-internal.h
>> ```
>> @interface Test (InternalMembers)
>> - (void)bar;
>> @end
>> ```
>> 
>> After that it'll be Xcode's responsability to create both files, and mark them as Public and Project in the Headers Build Phase.
>> 
>> An initial implementation that I think would make sense in case this solution is accepted could be modifying the signature of `swift::printAsObjC` to require the list of access levels to export as a bitmask instead of just getting the minimum. That will enable the exporter to create the following set of files:
>> 
>> * Internal, Public, Open > <target-name>-swift.h for app targets
>> * Public, Open > <target-name>-swift.h for framework targets
>> * Internal > <target-name>-swift-internal.h for the internal entities and members on framework targets.
>> 
>> To make this happen a new argument needs to be passed to the compiler call. When it's not passed the default behaviour would remain the same, but when it is the behaviour needs to be explicitly defined. One option is to just get the explicit list of access levels to export (something like `-export=internal,public,open`) or export levels to be defined (0 for app targets, 1 for public framework targets and 2 for the internal header framework targets for example)
>> 
>> I hope this feature proposal is complete enough to properly define the scope and discuss the viability of a possible solution. Otherwise please let me know.
>> 
>> Thanks.
>> 
>> --
>> Slds,
>> 
>> Gonzalo.
>> _______________________________________________
>> swift-dev mailing list
>> swift-dev at swift.org <mailto:swift-dev at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-dev
> 
> _______________________________________________
> swift-dev mailing list
> swift-dev at swift.org
> https://lists.swift.org/mailman/listinfo/swift-dev

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-dev/attachments/20170629/637ffda0/attachment.html>


More information about the swift-dev mailing list