Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ jobs:
- lint

env:
DEVELOPER_DIR: /Applications/Xcode_16.4.app/Contents/Developer
DEVELOPER_DIR: /Applications/Xcode_26.0.app/Contents/Developer

steps:
- uses: actions/checkout@v4
Expand Down
15 changes: 15 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ default.extend-identifiers.IMAGEIO_PNG_FILTER_PAETH = "IMAGEIO_PNG_FILTER_PAETH"
# In framework-crates/objc2-io-bluetooth/translation-config.toml
default.extend-identifiers.kBluetoothHCIEvnetMaskLinkSupervisionTimeoutChangedEvent = "kBluetoothHCIEvnetMaskLinkSupervisionTimeoutChangedEvent"
default.extend-identifiers.kBluetoothHCIEvnetMaskEnhancedFlushCompleteEvent = "kBluetoothHCIEvnetMaskEnhancedFlushCompleteEvent"
# In BackgroundAssets, BA is short of that framework.
default.extend-words.BA = "BA"
# Used in Metal, LOD = level of detail
default.extend-words.lod = "lod"

Expand Down
4 changes: 4 additions & 0 deletions crates/header-translator/configs/libc.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,7 @@ gnustep = true

# HACK: Define `task_port_t` in the using crate (it's a simple alias to `task_t`).
external.task_port_t.module = "__builtin__"

# Redefined by CoreFoundation with a name that makes it hard to see
# that this is `libc::malloc_zone_t`.
struct._malloc_zone_t.renamed = "malloc_zone_t"
24 changes: 22 additions & 2 deletions crates/header-translator/configs/skipped.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ DriverKit = "Uses C++ classes"

ActivityKit = "Swift-only"
AdAttributionKit = "Swift-only"
AlarmKit = "Mostly Swift-only"
AppIntents = "Swift-only"
Assignables = "Swift-only"
AutomatedDeviceEnrollment = "Swift-only"
Expand All @@ -39,15 +40,22 @@ CoreTransferable = "Swift-only"
CreateML = "Swift-only"
CreateMLComponents = "Swift-only"
CryptoKit = "Swift-only"
DeclaredAgeRange = "Swift-only"
DeveloperToolsSupport = "Swift-only"
DeviceActivity = "Swift-only"
DockKit = "Swift-only"
EnergyKit = "Swift-only"
ExtensionFoundation = "Swift-only"
FamilyControls = "Swift-only"
FinanceKit = "Swift-only"
FinanceKitUI = "Swift-only"
FoundationModels = "Swift-only"
GeoToolbox = "Swift-only"
GroupActivities = "Swift-only"
IdentityDocumentServices = "Swift-only"
IdentityDocumentServicesUI = "Swift-only"
ImagePlayground = "Swift-only"
ImmersiveMediaSupport = "Swift-only"
JournalingSuggestions = "Swift-only"
LightweightCodeRequirements = "Swift-only"
LiveCommunicationKit = "Swift-only"
Expand All @@ -59,23 +67,31 @@ ManagedSettingsUI = "Swift-only"
MarketplaceKit = "Swift-only"
MatterSupport = "Swift-only"
MusicKit = "Swift-only"
PaperKit = "Swift-only"
PermissionKit = "Swift-only"
ProximityReader = "Swift-only"
RealityFoundation = "Swift-only"
RealityKit = "Swift-only"
RelevanceKit = "Swift-only"
RoomPlan = "Swift-only"
SecureElementCredential = "Swift-only"
SwiftData = "Swift-only"
SwiftUI = "Swift-only"
SwiftUICore = "Swift-only"
TabletopKit = "Swift-only"
TabularData = "Swift-only"
TelephonyMessagingKit = "Swift-only"
Testing = "Swift-only"
TipKit = "Swift-only"
Translation = "Swift-only"
TranslationUIProvider = "Swift-only"
VisionEntitlementServices = "Mostly Swift-only"
VisionKit = "Swift-only"
VisualIntelligence = "Swift-only"
WeatherKit = "Swift-only"
WidgetKit = "Mostly Swift-only"
WiFiAware = "Swift-only"
WirelessInsights = "Swift-only"
WorkoutKit = "Swift-only"

AppleScriptKit = "Basically empty nowadays" # requires !swift
Expand All @@ -91,6 +107,7 @@ QTKit = "No headers present in Xcode's SDK"
StickerFoundation = "Basically empty"
StickerKit = "Basically empty"
System = "Deprecated wrapper over libSystem.dylib"
MetalPerformancePrimitives = "Header-only framework used in Metal shaders"

# Deprecated before macOS 10.12 (Rust's minimum supported macOS version)
AudioVideoBridging = "Deprecated, use AVKit/AVFoundation instead (maybe?)"
Expand Down Expand Up @@ -120,11 +137,14 @@ CoreMIDIServer = "Very deprecated"
InterfaceBuilderKit = "TODO. Developer-only"
XcodeKit = "TODO. Developer-only"
StoreKitTest = "TODO. Developer-only"
LiveExecutionResultsLogger = "Removed in Xcode 26"
AGL = "Removed in Xcode 26"

Network = "TODO, see [#646](https://github.com/madsmtm/objc2/issues/646)"
DeviceDiscoveryUI = "Needs Network first"

BrowserKit = "TODO"
SecurityUI = "TODO"
GameSave = "TODO"
TouchController = "TODO"

# LiveExecutionResultsLogger = "Removed in Xcode 26"
# AGL = "Removed in Xcode 26"
41 changes: 37 additions & 4 deletions crates/header-translator/src/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,22 @@ pub struct Location {
impl Location {
fn new(module_path: impl Into<Box<str>>) -> Self {
let module_path = module_path.into();

// We don't care about the difference between the different
// DarwinFoundation modules (for now at least).
if let Some(rest) = module_path.strip_prefix("DarwinFoundation.") {
return Self::new(rest);
}
if let Some(rest) = module_path.strip_prefix("_DarwinFoundation1.") {
return Self::new(rest);
}
if let Some(rest) = module_path.strip_prefix("_DarwinFoundation2.") {
return Self::new(rest);
}
if let Some(rest) = module_path.strip_prefix("_DarwinFoundation3.") {
return Self::new(rest);
}

let module_path = match &*module_path {
// Remove submodules for Objective-C.
name if name.starts_with("ObjectiveC") => "ObjectiveC".into(),
Expand All @@ -83,7 +99,9 @@ impl Location {

// Various macros
name if name.starts_with("os_availability") => "__builtin__".into(),
"DarwinFoundation.cdefs" => "__builtin__".into(),
name if name.starts_with("_AvailabilityInternal") => "__builtin__".into(),
name if name.starts_with("availability") => "__builtin__".into(),
"cdefs" => "__builtin__".into(),
"Darwin.libkern.OSByteOrder" => "__builtin__".into(),
"TargetConditionals" => "__builtin__".into(),
"Darwin.AssertMacros" => "__builtin__".into(),
Expand All @@ -108,7 +126,7 @@ impl Location {
"_Builtin_stdint" | "_stdint" => "__builtin__".into(),
name if name.starts_with("_Builtin_stddef") => "__builtin__".into(),
// Implementation of the above
"DarwinFoundation.types.machine_types" => "__builtin__".into(),
name if name.starts_with("types.machine_types") => "__builtin__".into(),
// UINT_MAX, FLT_MIN, DBL_MAX, etc.
// Handled manually in `expr.rs`.
"_Builtin_limits" => "__builtin__".into(),
Expand All @@ -132,8 +150,8 @@ impl Location {
name if name.starts_with("sys_types") => "__libc__".into(),
name if name.starts_with("Darwin.POSIX") => "__libc__".into(),
name if name.starts_with("_signal") => "__libc__".into(),
"DarwinFoundation.types.sys_types" => "__libc__".into(),
"DarwinFoundation.qos" => "__libc__".into(),
"types.sys_types" => "__libc__".into(),
"qos" => "__libc__".into(),
"_stdio" => "__libc__".into(),
"_time.timespec" => "__libc__".into(),
"_fenv" => "__libc__".into(),
Expand All @@ -149,9 +167,12 @@ impl Location {
"ptrauth" => "__libc__".into(),
"Darwin.uuid" => "__libc__".into(),
"unistd" => "__libc__".into(),
"Darwin.malloc" => "__libc__".into(),
"_stdlib.malloc.malloc_type" => "__libc__".into(),

// Will be moved to the `mach2` crate in `libc` v1.0
name if name.starts_with("Darwin.Mach") => "__libc__".into(),
"mach.port.mach_port_t" => "__libc__".into(),
"mach.mach_port_t" => "__libc__".into(),
"_mach_port_t" => "__libc__".into(),

Expand All @@ -168,6 +189,18 @@ impl Location {
// available without it, which can be quite confusing.
"CoreFoundation.CFBase" => "CoreFoundation".into(),

// UIUtilities "subframework". It doesn't seem to be intentionally
// exposed. It's small enough that we'll just inline it into
// UIKit for now (which is where it was extracted from anyhow).
"UIUtilities.UIGeometry" => "UIKit.UIGeometry".into(),
"UIUtilities.UICoordinateSpace" => "UIKit.UIView".into(),
"UIUtilities.UIDefines" => "UIKit.UIKitDefines".into(),

// Similarly, _LocationEssentials was extracted from CoreLocation.
"_LocationEssentials" => "CoreLocation".into(),
"_LocationEssentials.CLEssentionsAvailability" => "CoreLocation.CLAvailability".into(),
"_LocationEssentials.CLLocationEssentials" => "CoreLocation.CLLocation".into(),

_ => module_path,
};

Expand Down
10 changes: 10 additions & 0 deletions crates/header-translator/src/rust_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,10 @@ impl AttributeParser<'_, '_> {
fn nullable_result(&mut self, position: ParsePosition) -> bool {
self.strip("_Nullable_result", position)
}

fn sending(&mut self, position: ParsePosition) -> bool {
self.strip("__attribute__((swift_attr(\"sending\")))", position)
}
}

impl Drop for AttributeParser<'_, '_> {
Expand Down Expand Up @@ -1456,6 +1460,8 @@ impl Ty {
| "MIDISysexSendRequestUMP"
| "MIDIDriverInterface"
| "cssm_list_element"
| "malloc_zone_t"
| "_malloc_zone_t"
)
) {
// Fake fields, we'll have to define it ourselves
Expand Down Expand Up @@ -1674,6 +1680,10 @@ impl Ty {
parser.set_fn_ptr();
}

// TODO: Use this
// (Swift's @Sendable = Send + Sync, Swift's sending = Send).
let _sending = parser.sending(ParsePosition::Suffix);

let is_const = ty.is_const_qualified() || pointee.is_const_qualified();
let nullability = if let Some(nullability) = unexposed_nullability {
nullability
Expand Down
5 changes: 4 additions & 1 deletion crates/header-translator/src/stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,10 @@ fn verify_objc_decl(entity: &Entity<'_>, _context: &Context<'_>) {
(EntityKind::UnexposedAttr, _) => {
// Parsed in parse_attributes
}
(_, parent_kind) => error!(?parent_kind, "unknown in parent"),
(EntityKind::AnnotateAttr, _) if entity.get_name().unwrap() == "main-thread-only" => {
// Already parsed via. UnexposedAttr.
}
(_, parent_kind) => error!(?entity, ?parent_kind, "unknown in parent"),
}
});
}
Expand Down
Loading