-
Notifications
You must be signed in to change notification settings - Fork 49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added target_os cfg feature to header translator #433
base: master
Are you sure you want to change the base?
Conversation
Hmm. Looks like the submodule diff in CI is failing as this generates a new things. |
Yeah, that's intentional - you should be able to fork the |
Well, I updated the submodule ref to a my branch and it's obviously not there. I guess the better way to do this is to merge madsmtm/objc2-generated#6 and then update the ref. |
The result looks nice so far, two things though:
I think it worked? Also, you don't need to submit PRs to
We'll probably need a build script for that in the meantime like we do for Sorry for the hazzle btw, I haven't gotten around to writing better docs for how to contribute to |
Ah yes. rust-lang/rust#96901 is the not yet stabilized feature for future reference. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looked it through, it's really good so far, and the output is definitely an improvement!
A few of these are nits, but since they don't interfere with the actual functionality, including the doc_auto_cfg
feature (try it with +nightly --features=unstable-docsrs
, they're not that important.
Also, I think you have a newer Xcode version than the one icrate
is currently built with (which is Xcode 14.2 as pr. the README), which is why the build is failing. I'll try to find some time to update it this week, or perhaps you can do it? (in a separate PR, for the CI part change the DEVELOPER_DIR
env variable)
I realize I may be asking a lot here, if you don't feel like doing some of the work I've outlined, it's perfectly fine, your contribution is still very valuable as-is!
.collect::<Vec<String>>() | ||
.join(","); | ||
if !unavailable_oses.is_empty() { | ||
write!(f, "#[cfg(not(any({unavailable_oses})))]")?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know that the headers expose this as "unavailability", but I think it would look nicer in the docs if it was inverted; e.g. that #[cfg(not(any(target_os = "watchos")))]
became #[cfg(any(target_os = "tvos", target_os = "ios", target_os = "macos"))]
instead (this is also how Apple's own docs does it).
This interferes with GNUStep of course, but perhaps we can just code in a manual override there for all of AppKit
and Foundation
for now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually spent a little bit of time doing both variants - all(not(target_os = "ios"), any(taget_os = "macos", target_os = "tvos", target_os = "watchos"))
. I didn't like it as then everything had a cfg attribute.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I agree with that part
@@ -29,20 +102,27 @@ struct Versions { | |||
|
|||
#[derive(Debug, Clone, PartialEq)] | |||
pub struct Availability { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#[deprecated]
now also appears on impl ClassType
, which is incorrect.
So perhaps we should split out the Unavailable
from Availability
(and maybe rename it to PlatformCfg
)? Since that part is always going to be a cfg
-gate, which has interactions with higher-level cfg
-gates (and must propagate to imports like generated/[Framework]/mod.rs
), while introduced
and deprecated
will always only need to apply to the statement/method/field they're associated with.
Maybe it would even make sense to add PlatformCfg
as a field of ItemIdentifier
? Since these two are access so often together.
crates/header-translator/src/main.rs
Outdated
@@ -269,7 +269,7 @@ fn parse_sdk(index: &Index<'_>, sdk: &SdkPath, llvm_target: &str, config: &Confi | |||
preprocessing = false; | |||
// No more includes / macro expansions after this line | |||
let file = library.files.get_mut(&file_name).expect("file"); | |||
for stmt in Stmt::parse(&entity, &context) { | |||
for stmt in Stmt::parse(&entity, &context, &library.unavailability) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of passing the (un-)availability around everywhere like this, I think it would be fine to introduce a few optional fields in Context<'_>
that carried this information (since the context is already passed everywhere).
This would also be useful for other things in the future.
So something like (you can freely add only the stuff you need now, just expanding on the example to show the idea):
struct Context<'a> {
// ... Existing fields
/// Set whenever we know what the current library is.
current_library: Cell<Option<Arc<Library>>>,
/// Set when parsing methods, struct fields, enum fields, ...
current_type: Cell<Option<(ItemIdentifier, Unavailability)>>,
}
impl Context<'_> {
fn library(&self) -> Arc<Library> {
self.current_library.clone().take()
}
fn in_library<R>(&self, library: Arc<Library>, f: impl FnOnce(&Self) -> R) -> R {
self.current_library.set(Some(library));
let result = f(self);
self.current_library.set(None);
result
}
// ... Similar methods for the others
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did part of this by adding current_unavailability
to Context
. In this specific case library
is a &mut Library
and so passing it in as even a Arc<Library>
would require a clone
(I think?). Library
doesn't derive(Clone)
and I didn't feel like adding that. It's definitely cleaner but I'm not in love with it.
let unavailable = availability.unavailable.clone(); | ||
write!(f, "{unavailable}")?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should go inside the extern_static!
call, and the macro itself in icrate/src/macros.rs
should instead be updated to allow it - otherwise, the cfg
attribute will be improperly picked up by auto_doc_cfg
(it currently works though because generated/[Framework]/mod.rs
re-applies the attribute).
Same goes for typed_enum!
and typed_extensible_enum!
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, reflecting on this a bit more, perhaps we should instead aim to move as many cfg
attributes as we can to outside macro invocations, to allow the compiler to skip evaluating the macro at all?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, reflecting on this a bit more, perhaps we should instead aim to move as many
cfg
attributes as we can to outside macro invocations, to allow the compiler to skip evaluating the macro at all?
Yeah, I went back and forth on where to put the cfg attributes and felt that outside the macro was better. I should make sure it's consistent though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For some unclear reason, after updating macOS, I ended up with errors on the enum macros so I put the cfg attributes on all the macros (I think). I had to use just the unavailable
part as the #[deprecated]
stuff before the macro causes clippy lint issues. I might try and re-add them.
# The MPMediaQueryAddition definition does not have API_UNAVAILABLE annotations | ||
# where as the MPMediaItem does. This results in problematic conditional compliation: | ||
# https://github.com/phracker/MacOSX-SDKs/blob/041600eda65c6a668f66cb7d56b7d1da3e8bcc93/MacOSX11.3.sdk/System/Library/Frameworks/MediaPlayer.framework/Versions/A/Headers/MPMediaQuery.h#L103-L118 | ||
[class.MPMediaItem.categories.MPMediaQueryAdditions] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suspect this is not the only case (it's just the only one caught since we're compiling for macOS), perhaps it would make sense to change Stmt::Methods::category
to Option<(ItemIdentifier<Option<String>>, Availability)>
?
This is also an argument for adding Unavailable/PlatformCfg
to ItemIdentifier
, then the problem would neatly go away.
…lity-to-target_os
@@ -579,7 +579,7 @@ impl Stmt { | |||
cls: id.clone(), | |||
generics: generics.clone(), | |||
category: ItemIdentifier::with_name(None, entity, context), | |||
availability: Availability::parse(entity, context), | |||
availability: availability.clone(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know that this is the correct way to deal with this. I noticed the generated cfg attributes were gone for superclass functions. I'm guessing that the Availability::parse(entity, context)
here checked the availability of the super not the subclass.
Any news about that PR? What is missing for this to be ready? I'm quite interested to get this working for some projects. |
Hmm. Looks like I need to deal with some merge latest conflicts. I think the thing that was most lacking was generated bindings used xcode 14.2 (latest stable) but CI uses an older version. @madsmtm What do you think?
Glad to hear it! |
I was looking at #408 and this seemed like a nice small unit of work to do on this. I'm not sure what to do with the
ios_app_extension
andmacos_app_extension
booleans in theUnavailable
struct. To disallow the maccatalyst targets, the nice way to do it is with the not yet stabilizedtarget_abi
feature.