Skip to content
This repository was archived by the owner on Aug 8, 2023. It is now read-only.

Add -fvisibility=hidden to macOS dynamic framework and export required symbols#7509

Merged
kkaefer merged 3 commits into
masterfrom
7509-macos-sdk-symbol-visibility
Jan 4, 2017
Merged

Add -fvisibility=hidden to macOS dynamic framework and export required symbols#7509
kkaefer merged 3 commits into
masterfrom
7509-macos-sdk-symbol-visibility

Conversation

@kkaefer
Copy link
Copy Markdown
Member

@kkaefer kkaefer commented Dec 21, 2016

Reroll of #7326, which apparently has broken CI statuses.

Fixes #7326
Fixes #7281

@mention-bot
Copy link
Copy Markdown

@kkaefer, thanks for your PR! By analyzing this pull request, we identified @1ec5, @boundsj and @incanus to be potential reviewers.

@kkaefer
Copy link
Copy Markdown
Member Author

kkaefer commented Dec 21, 2016

Grr, this seems to be broken as well...

@kkaefer kkaefer requested review from 1ec5 and incanus January 2, 2017 10:09
@kkaefer
Copy link
Copy Markdown
Member Author

kkaefer commented Jan 2, 2017

Let's try approving this to see if we can merge it.

Copy link
Copy Markdown
Contributor

@1ec5 1ec5 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MGLTypes.h imports Foundation.h

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.)

@1ec5 1ec5 force-pushed the 7509-macos-sdk-symbol-visibility branch from b7623c8 to 38dab67 Compare January 2, 2017 11:46
@kkaefer
Copy link
Copy Markdown
Member Author

kkaefer commented Jan 2, 2017

What about protocols and categories? Do they need to be exported as well?

No, we only need to export compiled code, but protocols/categories are a header-only feature.

1ec5
1ec5 previously requested changes Jan 3, 2017
`style` and obtain the background layer using the `-[MGLStyle layerWithIdentifier:]`
method and passing `background` for the identifier.
*/
MGL_EXPORT
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fixed

@@ -1,11 +1,12 @@
#import <Foundation/Foundation.h>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.)

@1ec5
Copy link
Copy Markdown
Contributor

1ec5 commented Jan 3, 2017

What about protocols and categories? Do they need to be exported as well?

No, we only need to export compiled code, but protocols/categories are a header-only feature.

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.

@kkaefer kkaefer force-pushed the 7509-macos-sdk-symbol-visibility branch from 38dab67 to e8c4ac2 Compare January 3, 2017 15:18
@kkaefer
Copy link
Copy Markdown
Member Author

kkaefer commented Jan 3, 2017

I've rebuilt this PR based on SourceKitten's output.

Here are the changes:

  • Moved the MGL_EXPORT macro to a MGLFoundation.h to mirror other Cocoa frameworks usage of the *_EXPORT macro.
  • Left includes for Foundation.h in place
  • Added a script that checks all exported symbols for presence of a MGL_EXPORT macro
  • Added the automated script to make xpackage

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.

  • MGLAttributionButton
  • MGLAltitudeForZoomLevel
  • MGLZoomLevelForAltitude
  • MGLFeaturesFromMBGLFeatures
  • MGLTileSetFromTileURLTemplates
  • MGLGeoJSONOptionsFromDictionary

@kkaefer kkaefer dismissed 1ec5’s stale review January 3, 2017 15:24

rebuild PR

@kkaefer kkaefer requested a review from 1ec5 January 3, 2017 15:25
@kkaefer
Copy link
Copy Markdown
Member Author

kkaefer commented Jan 3, 2017

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.

I checked this and it seems they don't need the MGL_EXPORT statement and are automatically exported. The CI tests + macOS app uses some of those symbols and can be successfully linked.

Copy link
Copy Markdown
Contributor

@1ec5 1ec5 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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")))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread platform/macos/DEVELOPING.md Outdated

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`.
Copy link
Copy Markdown
Contributor

@1ec5 1ec5 Jan 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Comment thread platform/macos/DEVELOPING.md Outdated

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`.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make this invocation a little more memorable by adding a Make rule?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added make check-public-symbols

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor

@1ec5 1ec5 Jan 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like Xcode automatically generates a file called Mapbox_vers.c

@kkaefer
Copy link
Copy Markdown
Member Author

kkaefer commented Jan 4, 2017

can you add a blurb to the macOS changelog if a significant size reduction results from these changes?

There is no size reduction with this PR. This already happened in #7130. This one is just a followup that also compiles the Objective-C code with -fvisibility=hidden to fix #7281.

@kkaefer kkaefer force-pushed the 7509-macos-sdk-symbol-visibility branch from e8c4ac2 to 43d16e9 Compare January 4, 2017 11:14
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're now also adding the visibility change to the auto-generated file.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.)

Comment thread platform/darwin/test/MGLVersionNumber.m Outdated
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a test here to check linkage. This is not a Swift-specific issue; it also happened with Objective-C.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it is.

@1ec5
Copy link
Copy Markdown
Contributor

1ec5 commented Jan 4, 2017

iOS builds are failing because the iOS version of Mapbox.h doesn’t import MGLFoundation.h:

❌  /Users/vagrant/git/platform/darwin/src/MGLAccountManager.h:3:9: include of non-modular header inside framework module 'Mapbox.MGLAccountManager'

#import "MGLFoundation.h"
        ^

@kkaefer kkaefer force-pushed the 7509-macos-sdk-symbol-visibility branch 2 times, most recently from ee1d84c to 59088d3 Compare January 4, 2017 21:22
Copy link
Copy Markdown
Contributor

@1ec5 1ec5 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, thanks for fixing this!

@kkaefer kkaefer force-pushed the 7509-macos-sdk-symbol-visibility branch from 59088d3 to e26042e Compare January 4, 2017 21:32
@kkaefer kkaefer merged commit b515762 into master Jan 4, 2017
@kkaefer kkaefer deleted the 7509-macos-sdk-symbol-visibility branch January 4, 2017 22:06
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants