Add -fvisibility=hidden to macOS dynamic framework and export required symbols#7509
Conversation
|
Grr, this seems to be broken as well... |
|
Let's try approving this to see if we can merge it. |
There was a problem hiding this comment.
From a cursory look through the headers included from the umbrella header, it looks like you’ve exported all the public classes and constants without any omissions. That must’ve been pretty tedious. 😄
What about protocols and categories? Do they need to be exported as well?
My concerns from #7326 (comment) still hold. Documenting the need to use MGL_EXPORT in DEVELOPING.md is a good step but not enough to avoid latent bugs. Consider what’ll happen when we merge a PR like #7377 that made a previously private class public while adding and removing other public classes.
What we need is an automated way to discover public classes. In #7569, I introduced a dependency on SourceKitten and used it (plus a regular expression) to discover all public symbols and preprocess their documentation comments. We could employ something very similar to find public classes and constants that lack the MGL_EXPORT keyword and even insert the keyword if it’s missing.
Once you restore the framework import statements, I’ll approve this PR because it solves an exigent build issue (lots of warnings). However, we’ll need to address the maintainability issue before long; otherwise, I’ll have to revert the visibility changes before the next macOS SDK release.
| @@ -1,11 +1,12 @@ | |||
| #import <Foundation/Foundation.h> | |||
There was a problem hiding this comment.
Apparently we need these import statements or else Swift declarations in the generated documentation lack specific types: realm/jazzy#609. Importing required system frameworks is good practice anyways, unless you use a precompiled header that imports them.
(Sorry, I started this review a couple weeks ago but forgot to publish it.)
There was a problem hiding this comment.
MGLTypes.h imports Foundation.h
There was a problem hiding this comment.
As mentioned in that jazzy ticket, this header itself must import Foundation.h. It's unfortunate, but that shouldn't pose a problem for the visibility changes you're making, should it?
There was a problem hiding this comment.
I’m not sure why, but we don’t seem to be affected by realm/jazzy#609 even with these changes. Running make xdocument turns up some broken Swift declarations, but that happens on master too. (@incanus may have a stronger opinion than I about explicitly importing frameworks in headers. My concern was limited to jazzy output.)
b7623c8 to
38dab67
Compare
No, we only need to export compiled code, but protocols/categories are a header-only feature. |
| `style` and obtain the background layer using the `-[MGLStyle layerWithIdentifier:]` | ||
| method and passing `background` for the identifier. | ||
| */ | ||
| MGL_EXPORT |
There was a problem hiding this comment.
This change will get blown away as soon as anyone invokes make style-code. Make this change in platform/darwin/src/MGLStyleLayer.h.ejs and run make style-code to propagate the change to all the affected headers.
| @@ -1,11 +1,12 @@ | |||
| #import <Foundation/Foundation.h> | |||
There was a problem hiding this comment.
I’m not sure why, but we don’t seem to be affected by realm/jazzy#609 even with these changes. Running make xdocument turns up some broken Swift declarations, but that happens on master too. (@incanus may have a stronger opinion than I about explicitly importing frameworks in headers. My concern was limited to jazzy output.)
Protocols are header-only in Objective-C, but a category may or may not have an implementation in a translation unit separate from the categorized class. (Otherwise, it’s a class extension.) See platform/darwin/src/NSValue+MGLAdditions.m for example. |
38dab67 to
e8c4ac2
Compare
|
I've rebuilt this PR based on SourceKitten's output. Here are the changes:
These symbols are not exposed in the public headers, but the Xcode CI unit tests include the private headers and needs them to be visible in the library. These types of symbols are not checked by the above script, but we'll catch those easily because the test will fail to run on CI.
|
I checked this and it seems they don't need the |
1ec5
left a comment
There was a problem hiding this comment.
In addition to the logistical comments below, can you add a blurb to the macOS changelog if a significant size reduction results from these changes?
|
|
||
| #import <Foundation/Foundation.h> | ||
|
|
||
| #define MGL_EXPORT __attribute__((visibility ("default"))) |
There was a problem hiding this comment.
How do we decide when something goes in MGLFoundation.h versus MGLTypes.h? Should we bring more macros over here, like the nullability and lightweight generics shims?
There was a problem hiding this comment.
As per convention in other system frameworks, it has things that are required in virtually every header file. Most other *Foundation.h files I checked only have the export (or extern) macro.
|
|
||
| To add an Objective-C class, protocol, category, typedef, enumeration, or global constant to the macOS SDK’s public interface: | ||
|
|
||
| 1. _(Optional.)_ Add the macro `MGL_EXPORT` prior to the declaration for classes and global constants. To use this macro, include `MGLFoundation.h`. You can check whether all public symbols are exported correctly by running `platform/darwin/scripts/check-public-symbols.js macOS`. |
There was a problem hiding this comment.
If someone working on the iOS SDK adds a class to a header in platform/darwin/src/, that’ll cause the class to become public in the macOS SDK too. So we should add a note about running this script to the iOS DEVELOPING.md as well?
|
|
||
| To add an Objective-C class, protocol, category, typedef, enumeration, or global constant to the macOS SDK’s public interface: | ||
|
|
||
| 1. _(Optional.)_ Add the macro `MGL_EXPORT` prior to the declaration for classes and global constants. To use this macro, include `MGLFoundation.h`. You can check whether all public symbols are exported correctly by running `platform/darwin/scripts/check-public-symbols.js macOS`. |
There was a problem hiding this comment.
Can we make this invocation a little more memorable by adding a Make rule?
There was a problem hiding this comment.
Added make check-public-symbols
There was a problem hiding this comment.
Great. Can you refer to make check-public-symbols in both DEVELOPING.md documents? Thanks!
|
|
||
| /// Project version number for Mapbox. | ||
| FOUNDATION_EXPORT double MapboxVersionNumber; | ||
| FOUNDATION_EXPORT MGL_EXPORT double MapboxVersionNumber; |
There was a problem hiding this comment.
Make sure MapboxVersionNumber and MapboxVersionString are correctly set in the output build. I would hope that Xcode isn’t dependent on the particular syntax used to declare these constants, but you never know.
There was a problem hiding this comment.
I get this linker error referencing MapboxVersonNumber within Swift code:
Undefined symbols for architecture x86_64:
"_MapboxVersionNumber", referenced from:
Invincibility.ViewController.viewDidLoad () -> () in ViewController.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Reproduces with or without MGL_EXPORT. Doesn’t reproduce on master as of 654061c.
There was a problem hiding this comment.
From a C build perspective, this is very weird. FOUNDATION_EXPORT is only macro for extern, meaning it should be defined in some translation unit (but it's not). Should we manually define this version number?
There was a problem hiding this comment.
Looks like Xcode automatically generates a file called Mapbox_vers.c
e8c4ac2 to
43d16e9
Compare
There was a problem hiding this comment.
We're now also adding the visibility change to the auto-generated file.
There was a problem hiding this comment.
Clever hack. (I think this build setting is usually used for Apple to prepend a class prefix like “NS” or “UI” to the variable name.)
There was a problem hiding this comment.
Added a test here to check linkage. This is not a Swift-specific issue; it also happened with Objective-C.
There was a problem hiding this comment.
Note that MapboxVersionString is also available to Objective-C (but not to Swift, owing to its type). I assume it’s also covered by VERSION_INFO_PREFIX.
|
iOS builds are failing because the iOS version of Mapbox.h doesn’t import MGLFoundation.h: |
ee1d84c to
59088d3
Compare
1ec5
left a comment
There was a problem hiding this comment.
Looks great, thanks for fixing this!
59088d3 to
e26042e
Compare
Reroll of #7326, which apparently has broken CI statuses.
Fixes #7326
Fixes #7281