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
17 changes: 8 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# apple-sys

Apple platforms have a rather monotonous programming environment compared to other platforms. On several development machines, we will dependably obtain the same [bindgen](https://github.com/rust-lang/rust-bindgen) result. Then why not simply having bindgen configurations for the frameworks?
Apple platforms have a rather monotonous programming environment compared to other platforms. On several development machines, we will dependably obtain the same [bindgen](https://github.com/rust-lang/rust-bindgen) result. Then why not simply have bindgen configurations for the frameworks?

## Workspace Structure

Expand Down Expand Up @@ -43,20 +43,17 @@ use apple_sys::{CoreFoundation, IOKit};
// IOKit::<any name>
```

### Prebuilt Bindings
### Prebuilt vs Bindgen

By default, `apple-sys` generates bindings from your local SDK at build time. If you want faster builds without requiring Xcode SDK, enable the `prebuilt` feature:
By default, `apple-sys` uses prebuilt bindings, so no local SDK is required. If you need to generate bindings from your local SDK instead, disable default features and enable `bindgen`:

```toml
apple-sys = { version = "0.3", features = ["CoreFoundation", "prebuilt"] }
apple-sys = { version = "0.3", default-features = false, features = ["bindgen", "CoreFoundation"] }
```

Prebuilt bindings are available via `apple-sys-prebuilt-macosx` (macOS) and
`apple-sys-prebuilt-iphoneos` (iOS).

## apple-bindgen

The bindgen tool is installable and generating the same result to apple-sys crates.
The bindgen tool is installable and generates the same result as apple-sys crates.
To create a new `-sys` project, starting with `apple-bindgen` result will be a convenient way.

Install:
Expand All @@ -81,7 +78,7 @@ $ apple-bindgen analyze-deps AppKit --sdk macosx

## Examples

The `apple-sys` crate includes 188 examples demonstrating usage of various Apple frameworks. Each example targets a specific framework.
The `apple-sys` crate includes numerous examples demonstrating usage of various Apple frameworks. Each example targets a specific framework.

```sh
# Run an example (requires the corresponding framework features)
Expand All @@ -100,6 +97,8 @@ $ cargo run --manifest-path=crates/apple-sys/Cargo.toml \

Continually using the same SDKs doesn't sound realistic. I agree. Don't trust apple-sys. Use the managed versions as best you can. For `CoreFoundation`, for instance, use [core-foundation-sys](https://github.com/servo/core-foundation-rs).

The [objc2](https://github.com/madsmtm/objc2) project provides human-curated bindings with safe Rust APIs for most Apple frameworks.

Then why do I use apple-sys? I created apple-sys for minor and unmanaged frameworks. apple-sys will be the last fallback.

## Contributing
Expand Down
2 changes: 1 addition & 1 deletion crates/apple-sys-prebuilt-iphoneos/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "apple-sys-prebuilt-iphoneos"
version = "0.0.0"
version = "0.26.2"
edition.workspace = true
description = "Pre-generated iOS framework bindings for apple-sys"
keywords = ["sys", "apple", "ios", "bindgen", "prebuilt"]
Expand Down
2 changes: 1 addition & 1 deletion crates/apple-sys-prebuilt-macosx/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "apple-sys-prebuilt-macosx"
version = "0.0.0"
version = "0.26.2"
edition.workspace = true
description = "Pre-generated macOS framework bindings for apple-sys"
keywords = ["sys", "apple", "macos", "bindgen", "prebuilt"]
Expand Down
6 changes: 3 additions & 3 deletions crates/apple-sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ autoexamples = false
[dependencies]
libc = "0.2"
objc2 = { version = "0.6" }
apple-sys-prebuilt-macosx = { path = "../apple-sys-prebuilt-macosx", version = "0.0.0", optional = true }
apple-sys-prebuilt-iphoneos = { path = "../apple-sys-prebuilt-iphoneos", version = "0.0.0", optional = true }
apple-sys-prebuilt-macosx = { path = "../apple-sys-prebuilt-macosx", version = "0.26.2", optional = true }
apple-sys-prebuilt-iphoneos = { path = "../apple-sys-prebuilt-iphoneos", version = "0.26.2", optional = true }

[build-dependencies]
apple-bindgen = { path = "../apple-bindgen", version = "0.3.0", default-features = false, optional = true }
Expand Down Expand Up @@ -778,7 +778,7 @@ name = "vmnet_shared"
required-features = ["vmnet", "Foundation", "prebuilt"]

[features]
default = ["bindgen"]
default = ["prebuilt"]
bindgen = ["dep:apple-bindgen", "dep:apple-sdk", "dep:rayon"]
prebuilt = ["dep:apple-sys-prebuilt-macosx", "dep:apple-sys-prebuilt-iphoneos"]
__allow_empty = []
Expand Down
81 changes: 72 additions & 9 deletions crates/apple-sys/configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,23 +123,77 @@ def test_framework_buildable(sdk_path, framework_name):
os.unlink(temp_file)


def get_sdk_path(sdk_name):
"""Get SDK path using xcrun."""
sdk_map = {
"MacOSX": "macosx",
"iPhoneOS": "iphoneos",
"iPhoneSimulator": "iphonesimulator",
}
xcrun_name = sdk_map.get(sdk_name, sdk_name.lower())
SDK_MAP = {
"MacOSX": "macosx",
"iPhoneOS": "iphoneos",
"iPhoneSimulator": "iphonesimulator",
}


def _xcrun_sdk(sdk_name, flag):
xcrun_name = SDK_MAP.get(sdk_name, sdk_name.lower())
result = subprocess.run(
["xcrun", "--sdk", xcrun_name, "--show-sdk-path"],
["xcrun", "--sdk", xcrun_name, flag],
capture_output=True, text=True
)
if result.returncode != 0:
return None
return result.stdout.rstrip()


def get_sdk_path(sdk_name):
"""Get SDK path using xcrun."""
return _xcrun_sdk(sdk_name, "--show-sdk-path")


def get_sdk_version(sdk_name):
"""Get SDK version using xcrun."""
return _xcrun_sdk(sdk_name, "--show-sdk-version")


def update_prebuilt_versions(sdk_versions):
"""Update prebuilt crate versions based on SDK versions.

Sets version to 0.{sdk_version} (e.g. SDK 26.2 -> version 0.26.2).
Updates both the prebuilt Cargo.toml files and the apple-sys dependency versions.
"""
prebuilt_map = {
"MacOSX": ("apple-sys-prebuilt-macosx", "../apple-sys-prebuilt-macosx/Cargo.toml"),
"iPhoneOS": ("apple-sys-prebuilt-iphoneos", "../apple-sys-prebuilt-iphoneos/Cargo.toml"),
}

for sdk_name, sdk_version in sdk_versions.items():
if sdk_name not in prebuilt_map:
continue
dep_name, toml_path = prebuilt_map[sdk_name]
crate_version = f"0.{sdk_version}"

# Update prebuilt Cargo.toml
if os.path.isfile(toml_path):
content = open(toml_path).read()
content = re.sub(
r'^version\s*=\s*"[^"]*"',
f'version = "{crate_version}"',
content,
count=1,
flags=re.MULTILINE,
)
with open(toml_path, "w") as f:
f.write(content)
print(f"Updated {toml_path} version to {crate_version}")

# Update apple-sys/Cargo.toml dependency version
cargo_toml = open("Cargo.toml").read()
cargo_toml = re.sub(
rf'({dep_name}\s*=\s*\{{[^}}]*version\s*=\s*")[^"]*(")',
rf'\g<1>{crate_version}\2',
cargo_toml,
)
with open("Cargo.toml", "w") as f:
f.write(cargo_toml)
print(f"Updated {dep_name} dependency to {crate_version}")


def framework_path(sdk_path):
return f"{sdk_path}/System/Library/Frameworks"

Expand Down Expand Up @@ -496,6 +550,15 @@ def main(sdk_names):
else:
print(f"Warning: SDK {sdk_name} not found, skipping")

# Get SDK versions and update prebuilt crate versions
sdk_versions = {}
for sdk_name in sdk_paths:
version = get_sdk_version(sdk_name)
if version:
sdk_versions[sdk_name] = version
print(f"SDK {sdk_name} version: {version}")
update_prebuilt_versions(sdk_versions)

framework_names = {
sdk_name: list(sorted(find_framework_names(sdk_path)))
for sdk_name, sdk_path in sdk_paths.items()
Expand Down
Loading