line / rules_apple_line

LINE's Apple rules for Bazel
Apache License 2.0
207 stars 18 forks source link

Access internal ObjC properties in mixed modules #37

Closed makadaw closed 2 years ago

makadaw commented 3 years ago

Hi folks, I have looked into Bazel for a project with mixed modules and found one difference. According to Apple docs https://developer.apple.com/documentation/swift/imported_c_and_objective-c_apis/importing_swift_into_objective-c

Methods and properties that are marked with the internal modifier and declared within a class that inherits from an Objective-C class are accessible to the Objective-C runtime. However, they're inaccessible at compile time and don't appear in the generated header for a framework target.

Swift declarations of @objc properties and methods with internal access level should be available in ObjC files of the same module. And Xcode working according to the doc. My module declaration is fairly simple:

mixed_static_framework(
    name = "MyModule",
    srcs = glob(["MyModule/*.m", "MyModule/*.swift"]),
    hdrs = glob(["MyModule/*.h"]),
    umbrella_header = "MyModule/MyModule.h",
)

Also, I can access generated Swift header only via #import "MyModule-Swift.h" and can't with #import <MyModule/MyModule-Swift.h>" Is this Xcode internal feature or I'm doing something wrong?

thii commented 3 years ago

It's possible. This rule aren't currently generating a header map for the Swift header, so you will need to add additional flags to objc_copts, for example:

https://github.com/line/rules_apple_line/blob/9bd940ec3929c405d857cb1afc2cbef7300cad90/examples/ios/Mixed/BUILD#L6-L18 https://github.com/line/rules_apple_line/blob/9bd940ec3929c405d857cb1afc2cbef7300cad90/examples/ios/Mixed/MXDObjcGreeter.m#L16

makadaw commented 3 years ago

@thii thanks for the response. I found the problem with header files. I did all declarations in one BUILD file (did it for a fast prototype) and Bazel didn't create subfolders in BINDIR.

Still didn't find how internal @objc properties work in the frameworks. Xcode can access them in ObjC code, but Bazel can't.

thii commented 3 years ago

If you have a package at path/to/MyModule, then the flag is -I$(BINDIR)/path/to. If you put everything in a top-level BUILD file, then you can only import the header by #import "MyModule-Swift.h".