Skip to content

Commit 44294da

Browse files
authored
Add basic iOS Platform Implementation (#111)
* Add basic ios platform implementation * Add working Camera and PhotoLibrary permission request on iOS
1 parent 75cf43a commit 44294da

File tree

27 files changed

+409
-74
lines changed

27 files changed

+409
-74
lines changed

.github/pull_request_template.md

+4-5
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,16 @@
99

1010
## Changelog
1111

12-
> This section is optional. If this was a trivial fix, or has no externally-visible impact, you can delete this section.
12+
> This section is optional. If this was a trivial fix or has no externally-visible impact, you can delete this section.
1313
1414
- What changed as a result of this PR?
15-
- If applicable, organize changes under "Added", "Changed", or "Fixed" sub-headings
16-
- Stick to one or two sentences. If more detail is needed for a particular change, consider adding it to the "Solution" section
17-
- If you can't summarize the work, your change may be unreasonably large / unrelated. Consider splitting your PR to make it easier to review and merge!
15+
- If applicable, organize changes under "Added", "Changed", or "Fixed" sub-headings.
16+
- Stick to one or two sentences. If more detail is needed for a particular change, consider adding it to the "Solution" section.
1817

1918
## Migration Guide
2019

2120
> This section is optional. If there are no breaking changes, you can delete this section.
2221
2322
- If this PR is a breaking change (relative to the last release of Crossbow), describe how a user might need to migrate their code to support these changes
2423
- Simply adding new functionality is not a breaking change.
25-
- Fixing behavior that was definitely a bug, rather than a questionable design choice is not a breaking change.
24+
- Fixing behavior that was definitely a bug rather than a questionable design choice is not a breaking change.

.github/scripts/publish_crates.sh

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
# Legends say that the order of the crates should be kept.
55
crates=(
66
platform/android
7+
platform/ios
78
plugins/admob
89
crossbundle/tools
910
crossbundle/cli

.github/workflows/publish.yml

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ jobs:
1616
build-and-publish-release:
1717
name: Build and publish Github release
1818
runs-on: ${{ matrix.os }}
19+
if: false
1920
strategy:
2021
fail-fast: false
2122
matrix:

Cargo.toml

+10-4
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,31 @@ authors = ["DodoRare Team <support@dodorare.com>"]
66
description = "Cross-Platform Rust Toolkit for Games 🏹"
77
repository = "https://github.com/dodorare/crossbow"
88
license = "Apache-2.0"
9-
keywords = ["build", "android", "apple", "ios", "tools"]
9+
keywords = ["build", "android", "ios", "tools"]
1010
readme = "README.md"
1111
exclude = [".github/**/*"]
1212

1313
[dependencies]
14-
# Platform-specific dependencies
15-
crossbow-android = { path = "platform/android", version = "0.1.6", optional = true }
14+
thiserror = "1.0"
15+
displaydoc = "0.2"
16+
anyhow = "1.0"
1617

1718
[target.'cfg(target_os = "android")'.dependencies]
19+
crossbow-android = { path = "platform/android", version = "0.1.6", optional = true }
1820
ndk-glue = "0.6.2"
1921

22+
[target.'cfg(target_os = "ios")'.dependencies]
23+
crossbow-ios = { path = "platform/ios", version = "0.1.6", optional = true }
24+
2025
[patch.crates-io]
2126
winit = { git = "https://github.com/rust-windowing/winit", rev = "f93f2c158bf527ed56ab2b6f5272214f0c1d9f7d" }
2227
bevy = { git = "https://github.com/dodorare/bevy", rev = "d51104020004d34db1aa3a9a5795834d7814ae55" }
2328
miniquad = { git = "https://github.com/not-fl3/miniquad", rev = "d67ffe6950cf73df307e2d23aaa4726f14399985" }
2429

2530
[features]
26-
default = ["android"]
31+
default = ["android", "ios"]
2732
android = ["crossbow-android"]
33+
ios = ["crossbow-ios"]
2834

2935
[workspace]
3036
members = [

README.md

+7-5
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,20 @@
1010

1111
## What is Crossbow?
1212

13-
The `crossbow` project aims to provide a complete toolkit for cross-platform game development in Rust - from project creation to publishing. In addition, the project simplifies the creation, packaging, and signing of Android and iOS applications. We want to make most of our tools - engine agnostic to help rust game developers integrate them into their engines or games.
13+
The `crossbow` project aims to provide a complete toolkit for cross-platform game development in *Rust* - from project creation to publishing. In addition, the project simplifies the creation, packaging, and signing of **Android** and **iOS** applications. We want to make most of our tools - engine agnostic to help rust game developers integrate them into their engines or games.
1414

1515
## Why Crossbow?
1616

1717
> There are already [cargo-apk](https://github.com/rust-windowing/android-ndk-rs/tree/master/cargo-apk), [cargo-mobile](https://github.com/BrainiumLLC/cargo-mobile), [cargo-xcode](https://gitlab.com/kornelski/cargo-xcode), etc. - why do I need another packaging tool?
1818
19-
Project `crossbow` is not only a packaging tool for Android and iOS - it's a toolkit. With `crossbundle-tools` you can customize and create new commands; with `crossbundle` you can create native **.apk/.aab** without any *Java* or setup *Gradle* project with fancy **Crossbow Android plugins** (iOS in near future); with `crossbow-android` you can write your own Android plugins in *Java/Kotlin*.
19+
Project `crossbow` is not only a packaging tool for **Android** and iOS - it's a toolkit. With `crossbundle-tools` you can customize and create new commands; with `crossbundle` you can create native **.apk/.aab** without any *Java* or setup *Gradle* project with fancy **Crossbow Android plugins** (**iOS** in near future); with `crossbow-android` you can write your own Android plugins in *Java/Kotlin*.
2020

2121
## Design Goals
2222

2323
* **Customizable**: Create new commands with available tools.
2424
* **Simple**: Easy to start but flexible for strong devs.
2525
* **Capable**: It's possible to build plain **.apk/.aab** or **.app/.ipa**; or with help of *Gradle/XCode*.
26-
* **Rust**: Don't leave your *Rust* code - almost everything can be configured from **Cargo.toml**.
26+
* **Rust**: Don't leave your *Rust* code - almost everything can be configured from `Cargo.toml`.
2727

2828
## 🛠 Installation
2929

@@ -41,14 +41,16 @@ Crossbundle crates:
4141

4242
| Name | Description | Status |
4343
| ---- | ----------- | ------ |
44-
| [crossbundle](./crossbundle/cli) | Command-line tool for building applications. ||
44+
| [crossbundle](./crossbundle/cli) | Command-line tool for building and running applications. ||
4545
| [crossbundle-tools](./crossbundle/tools) | Toolkit used in `crossbundle` to build/pack/sign bundles. ||
4646

4747
Crossbow Plugins:
4848

4949
| Name | Description | Status |
5050
| ---- | ----------- | ------ |
51-
| [crossbow-admob](./crossbow/admob) | Google AdMob Plugin for Android. | 🆗 |
51+
| [crossbow-android](./platform/android) | Crossbow Android Platform implementation. | 🆗 |
52+
| [crossbow-ios](./platform/ios) | Crossbow iOS Platform implementation. | 🛠 |
53+
| [crossbow-admob](./crossbow/admob) | Google AdMob Plugin for Android (iOS in future). | 🆗 |
5254
| [crossbow-play-billing](./crossbow/play-billing) | Google Play Billing for Android. | 📝 |
5355
| [crossbow-play-games-sdk](./crossbow/play-games-sdk) | Google Play Games Sdk for Android. | 📝 |
5456

crossbundle/cli/src/commands/build/apple.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ impl AppleBuildCommand {
120120
config.status("Copying binary to app folder")?;
121121
std::fs::copy(&bin_path, &app_path.join(&name)).unwrap();
122122
config.status_message("Generating", "Info.plist")?;
123-
apple::save_apple_plist(&app_path, properties, false).unwrap();
123+
apple::save_info_plist(&app_path, properties, false).unwrap();
124124
if self.identity.is_some() {
125125
config.status("Starting code signing process")?;
126126
apple::copy_profile(

crossbundle/cli/src/commands/build/build_context.rs

+2
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ impl BuildContext {
162162
pub fn gen_info_plist(&self, package_name: &str) -> Result<InfoPlist> {
163163
if let Some(info_plist_path) = &self.apple_config.info_plist_path {
164164
Ok(apple::read_info_plist(info_plist_path)?)
165+
} else if let Some(info_plist) = &self.apple_config.info_plist {
166+
Ok(info_plist.clone())
165167
} else {
166168
Ok(apple::gen_minimal_info_plist(
167169
package_name,

crossbundle/cli/src/error.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,25 @@ pub enum Error {
1414
TeamIdentifierNotProvided,
1515
/// Invalid cargo metadata values
1616
InvalidCargoMetadata,
17-
/// Invalid metadata in manifest
17+
/// Invalid metadata in manifest: {0:?}
1818
InvalidMetadata(anyhow::Error),
19-
/// IO error
19+
/// IO error: {0:?}
2020
Io(#[from] std::io::Error),
21-
/// Clap error
21+
/// Clap error: {0:?}
2222
Clap(#[from] clap::Error),
23-
/// Anyhow error
23+
/// Anyhow error: {0:?}
2424
AnyhowError(#[from] anyhow::Error),
25-
/// Crossbundle Tools error
25+
/// Crossbundle Tools error: {0:?}
2626
CrossbundleTools(#[from] crossbundle_tools::error::Error),
27-
/// AndroidManifest error
27+
/// AndroidManifest error: {0:?}
2828
AndroidManifest(#[from] android_manifest::error::Error),
29-
/// FsExtra error
29+
/// FsExtra error: {0:?}
3030
FsExtra(#[from] fs_extra::error::Error),
3131
/// Path {0:?} doesn't exist
3232
PathNotFound(std::path::PathBuf),
3333
/// Home dir not found
3434
HomeDirNotFound,
35-
/// Failed to download jar file
35+
/// Failed to download jar file: {0:?}
3636
DownloadFailed(ureq::Error),
3737
/// Failed to create jar file in specified path `{path}` cause of `{cause}`
3838
JarFileCreationFailed {

crossbundle/cli/src/types/android_config.rs

+7
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,19 @@ pub const MIN_SDK_VERSION: u32 = 19;
99

1010
#[derive(Debug, Clone, Deserialize, Serialize, Default)]
1111
pub struct AndroidConfig {
12+
/// Application name.
1213
pub app_name: Option<String>,
14+
/// Application version name.
1315
pub version_name: Option<String>,
16+
/// Application version code.
1417
pub version_code: Option<u32>,
18+
/// Minimum SDK version supported.
1519
pub min_sdk_version: Option<u32>,
20+
/// Target SDK version.
1621
pub target_sdk_version: Option<u32>,
22+
/// Maximum SDK version supported.
1723
pub max_sdk_version: Option<u32>,
24+
/// Icon name in resources.
1825
pub icon: Option<String>,
1926

2027
/// Path to AndroidManifest.xml file.

crossbundle/cli/src/types/apple_config.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,23 @@
1-
use crossbundle_tools::types::*;
1+
use crossbundle_tools::types::{apple_bundle::prelude::*, AppleTarget};
22
use serde::{Deserialize, Serialize};
33
use std::path::PathBuf;
44

55
#[derive(Debug, Clone, Deserialize, Serialize, Default)]
66
pub struct AppleConfig {
7+
/// Application Name.
78
pub app_name: Option<String>,
9+
/// Application version name.
810
pub version_name: Option<String>,
11+
/// Application version code.
912
pub version_code: Option<u32>,
13+
/// Icon name in resources.
1014
pub icon: Option<String>,
15+
16+
/// Path to Info.plist file.
1117
pub info_plist_path: Option<PathBuf>,
1218

19+
/// Apple Info.plist configuration.
20+
pub info_plist: Option<InfoPlist>,
1321
/// Apple build targets.
1422
pub build_targets: Option<Vec<AppleTarget>>,
1523
/// Apple resources directory path relatively to project path.

crossbundle/tools/src/commands/apple/save_plist.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::fs::File;
44
use std::path::Path;
55

66
/// Saves given InfoPlist in new `Info.plist` file.
7-
pub fn save_apple_plist(out_dir: &Path, properties: &InfoPlist, binary: bool) -> Result<()> {
7+
pub fn save_info_plist(out_dir: &Path, properties: &InfoPlist, binary: bool) -> Result<()> {
88
// Create Info.plist file
99
let file_path = out_dir.join("Info.plist");
1010
let file = File::create(file_path)?;
@@ -104,7 +104,7 @@ mod tests {
104104
},
105105
..Default::default()
106106
};
107-
save_apple_plist(dir.path(), &properties, false).unwrap();
107+
save_info_plist(dir.path(), &properties, false).unwrap();
108108
let file_path = dir.path().join("Info.plist");
109109
let result = std::fs::read_to_string(&file_path).unwrap();
110110
assert_eq!(result, PLIST_TEST_EXAMPLE.replace(" ", "\t"));

crossbundle/tools/src/error.rs

+11-11
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ pub enum AndroidError {
4242
FailedToFindAndroidManifest(String),
4343
/// Unable to find NDK file
4444
UnableToFindNDKFile,
45-
/// AndroidTools error
45+
/// AndroidTools error: {0:?}
4646
AndroidTools(#[from] android_tools::error::Error),
47-
/// AndroidManifest error
47+
/// AndroidManifest error: {0:?}
4848
AndroidManifest(#[from] android_manifest::error::Error),
4949
}
5050

@@ -61,7 +61,7 @@ pub enum AppleError {
6161
ZipCommandFailed,
6262
/// Codesign allocate not found
6363
CodesignAllocateNotFound,
64-
/// Simctl error
64+
/// Simctl error: {0:?}
6565
Simctl(simctl::Error),
6666
/// Target dir does not exists
6767
TargetNotFound,
@@ -71,7 +71,7 @@ pub enum AppleError {
7171
AssetsNotFound,
7272
/// Failed to find Info.plist in path: {0}
7373
FailedToFindInfoPlist(String),
74-
/// Plist data error
74+
/// Plist data error: {0:?}
7575
Plist(#[from] plist::Error),
7676
}
7777

@@ -115,19 +115,19 @@ pub enum Error {
115115
/// Failed to choose shell string color.
116116
/// Argument for --color must be auto, always, or never, but found `{}`
117117
FailedToChooseShellStringColor(String),
118-
/// IO error
118+
/// IO error: {0:?}
119119
Io(#[from] std::io::Error),
120-
/// FS Extra error
120+
/// FS Extra error: {0:?}
121121
FsExtra(#[from] fs_extra::error::Error),
122-
/// Zip error
122+
/// Zip error: {0:?}
123123
Zip(#[from] zip::result::ZipError),
124-
/// Android error
124+
/// Android error: {0:?}
125125
Android(#[from] AndroidError),
126-
/// Apple error
126+
/// Apple error: {0:?}
127127
Apple(#[from] AppleError),
128-
/// Anyhow error
128+
/// Anyhow error: {0:?}
129129
AnyhowError(#[from] anyhow::Error),
130-
/// Other error
130+
/// Other error: {0:?}
131131
OtherError(#[from] Box<dyn std::error::Error>),
132132
}
133133

crossbundle/tools/tests/apple_full.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ fn test_apple_full() {
9393

9494
// Generate Info.plist
9595
let properties = get_minimal_info_plist(&name);
96-
save_apple_plist(&app_dir, &properties, false).unwrap();
96+
save_info_plist(&app_dir, &properties, false).unwrap();
9797

9898
// Sign bundle
9999
codesign(&app_dir, true, None, None).unwrap();

examples/macroquad-permissions/Cargo.toml

+15-3
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ edition = "2021"
66

77
[dependencies]
88
crossbow = { version = "0.1.6", path = "../../" }
9-
crossbow-admob = { version = "0.1.6", path = "../../plugins/admob" }
109
log = "0.4"
1110
anyhow = "1.0"
1211
macroquad = "0.3.7"
1312
async-executor = "1.4.1"
1413
futures-lite = "1.12.0"
1514

15+
[target.'cfg(target_os = "android")'.dependencies]
16+
crossbow-admob = { version = "0.1.6", path = "../../plugins/admob" }
17+
1618
[package.metadata.android]
1719
app_name = "Macroquad_Permissions"
1820
target_sdk_version = 30
@@ -45,10 +47,20 @@ name = "android.permission.CAMERA"
4547

4648
[package.metadata.apple]
4749
app_name = "Macroquad_Permissions"
48-
target_sdk_version = 30
4950
version_code = 1
50-
icon = "ic_launcher"
51+
icon = "icon"
5152

5253
build_targets = ["aarch64-apple-ios", "x86_64-apple-ios"]
5354
assets = "assets"
5455
res = "res/apple"
56+
57+
[package.metadata.apple.info_plist]
58+
CFBundleIdentifier = "dodorare.macroquad-permissions"
59+
CFBundleVersion = "1.0"
60+
CFBundleShortVersionString = "1.0"
61+
CFBundleExecutable = "macroquad-permissions"
62+
UILaunchStoryboardName = "LaunchScreen"
63+
CFBundleName = "Macroquad_Permissions"
64+
# Permissions
65+
NSCameraUsageDescription = "Macroquad_Permissions requires access to your phone's camera."
66+
NSPhotoLibraryUsageDescription = "Macroquad_Permissions requires access to your phone's photo library."

0 commit comments

Comments
 (0)