Add -fvisibility=hidden to macOS dynamic framework and export required symbols#7326
Add -fvisibility=hidden to macOS dynamic framework and export required symbols#7326kkaefer wants to merge 2 commits into
Conversation
ad42e10 to
68d0843
Compare
There was a problem hiding this comment.
In addition to the comments below, the contributor documentation needs to be updated to note that MGLTypes.h needs to be imported and MGL_EXTERN needs to be used on all new public symbols:
| ensuring that your use adheres to the relevant terms of use. | ||
| */ | ||
| IB_DESIGNABLE | ||
| MGL_EXTERN |
There was a problem hiding this comment.
Does Interface Builder still recognize MGLMapView as a designable? IB’s Objective-C scanner unfortunately doesn’t know anything about macros.
There was a problem hiding this comment.
How do I find out whether IB does that? I'm not familiar with it.
There was a problem hiding this comment.
There was a problem hiding this comment.
I tried this, but couldn't get to a conclusive answer since Xcode's rebuilding is very erratic and it doesn't seem to detect changed files. From what I could tell, it worked both in the MGL_EXTERN IB_DESIGNABLE order and the other way around. I changed the order though so that IB_DESIGNABLE now is directly before @interface.
| The MGLAccountManager object provides a global way to set a Mapbox API access | ||
| token. | ||
| */ | ||
| MGL_EXTERN |
There was a problem hiding this comment.
If I’m not mistaken, placing this macro on a separate line between the comment block and the signature breaks Quick Help, which only looks one line up to find a comment block. Would this macro work if we stick it above the comment block, or better yet on the same line as @interface? We should also make sure jazzy – which like Quick Help also relies on Clang to parse out comment blocks – is OK with whatever we end up with.
There was a problem hiding this comment.
What is Quick Help? How do I invoke Quick Help?
There was a problem hiding this comment.
⌥ + click on class, property or method.
There was a problem hiding this comment.
@frederoni I cannot confirm that behavior; it works for me with the macro as well.
| @param latitude The latitude of the point at the center of the viewport. | ||
| @param size The size of the viewport. | ||
| @return An altitude measured in meters. */ | ||
| MGL_EXTERN |
There was a problem hiding this comment.
Do we really need to extern symbols in headers with private or project visibility? What about symbols declared in .m files, then?
There was a problem hiding this comment.
Theoretically we shouldn't, since it should be all internal to the binary we're building, however the test target also includes this private header, and linking the lib to the test fails without exporting this symbol. Another way would be to not export this, and change the test so that it doesn't require this symbol, or to move this symbol to the public header.
There was a problem hiding this comment.
Ah, OK, so we need this on anything with Private visibility but not Project visibility (using Xcode terminology here).
68d0843 to
2f6c3e1
Compare
|
|
||
| 1. Ensure that the symbol is pure Objective-C and does not rely on any language features specific to Objective-C++ or the C11 dialect of C – so no namespaced types or classes named with emoji! 🙃 Most projects that depend on this SDK are either written in pure Objective-C (GNU99 dialect) or Swift, which cannot yet bridge C++ types. | ||
| 1. Name the symbol according to [Cocoa naming conventions](https://developer.apple.com/library/prerelease/content/documentation/Cocoa/Conceptual/CodingGuidelines/CodingGuidelines.html#//apple_ref/doc/uid/10000146i). Use the `MGL` class prefix to avoid conflicts with client code. If the symbol has an analogue in MapKit, name the symbol according to MapKit. | ||
| 1. Add the macro `MGL_EXTERN` prior to the declaration. To get this macro, include `MGLTypes.h`. |
There was a problem hiding this comment.
My mistake, this belongs in the next section (which could mention standalone functions as well). This section is for adding anything to a public header, including a property or method.
7fed07e to
76925d2
Compare
| @note You are responsible for getting permission to use the map data and for | ||
| ensuring that your use adheres to the relevant terms of use. | ||
| */ | ||
| MGL_EXTERN |
There was a problem hiding this comment.
Putting MGL_EXTERN keyword on a separate line before the IB_DESIGNABLE keyword seems to break Quick Help and the index in general in Xcode 8.2. If you ⌥-click a member of a class or open the code completion popup, you get the documentation about the class itself rather than the member. If you ⌘-click to jump to the definition of a member, you get the line above it instead.
release-ios-v3.4.0 on this line:


macos-sdk-symbol-visibility on the same line:


Putting the two keywords on the same line seems to fix the problem, but I’ve only tried this so far inside macos.xcodeproj so far.
76925d2 to
ba873e0
Compare
|
I'm concerned that we're going to forget to add MGL_EXTERN to a new public class at some point and we won't catch it before a developer notices that their project won't link. Ideally, we'd have tests that cover every class, but we generally don't have tests for UI classes yet. Also, we'd still have to be vigilant about new classes getting pro forma tests. Very often we forget to add a new helper class to the jazzy table of contents, even though we know to look for that change. (Sometimes a PR adds a significant class with some helper classes.) |
If we would have tests that would cover every MGL class, the test scheme would link and we wouldn't be able to catch incorrect symbol visibility in time? If that's not the case, it would be fairly easy to use the Objective-C runtime to get a list of all loaded classes and validate visibility on them in a unit test. |
I'm not worried about classes we already have. I'm worried about a PR that adds a few public classes, one of which is significant enough that the contributor remembers to make it visible, while they overlook the fact that the other helper classes are also public (or have Private target membership!) and need to be visible. If we're vigilant enough to remind the contributor to add a pro forma "test", we'd already be vigilant enough to remind them to add the macro in the first place. But I estimate that we'd miss a class until after a prerelease about 30% of the time without an automated system. The only way "test everything" would work is if we gather code coverage and already had 100% code coverage, so that every dip in coverage would be detectable.
This PR is about linker visibility, not runtime visibility. How would we distinguish between a class that's invisible because it should be versus one that's invisible because we forgot to add the macro? NSClassFromString() has to be able to return all classes, including private, invisible classes. Otherwise the class code could never run. Maybe there's a way to enumerate SourceKitten's generated public symbol list, mangle the symbols, and ensure that they have the right entry in otool output for the framework? Sounds really complicated. |
e4ef4d4 to
b4b3c51
Compare
b4b3c51 to
b7623c8
Compare
|
I removed the |


Fix for #7281