Skip to content

Commit

Permalink
Add basic iOS Platform Implementation (#111)
Browse files Browse the repository at this point in the history
* Add basic ios platform implementation

* Add working Camera and PhotoLibrary permission request on iOS
  • Loading branch information
enfipy authored Jul 22, 2022
1 parent 75cf43a commit 44294da
Show file tree
Hide file tree
Showing 27 changed files with 409 additions and 74 deletions.
9 changes: 4 additions & 5 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,16 @@

## Changelog

> This section is optional. If this was a trivial fix, or has no externally-visible impact, you can delete this section.
> This section is optional. If this was a trivial fix or has no externally-visible impact, you can delete this section.
- What changed as a result of this PR?
- If applicable, organize changes under "Added", "Changed", or "Fixed" sub-headings
- Stick to one or two sentences. If more detail is needed for a particular change, consider adding it to the "Solution" section
- 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!
- If applicable, organize changes under "Added", "Changed", or "Fixed" sub-headings.
- Stick to one or two sentences. If more detail is needed for a particular change, consider adding it to the "Solution" section.

## Migration Guide

> This section is optional. If there are no breaking changes, you can delete this section.
- 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
- Simply adding new functionality is not a breaking change.
- Fixing behavior that was definitely a bug, rather than a questionable design choice is not a breaking change.
- Fixing behavior that was definitely a bug rather than a questionable design choice is not a breaking change.
1 change: 1 addition & 0 deletions .github/scripts/publish_crates.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# Legends say that the order of the crates should be kept.
crates=(
platform/android
platform/ios
plugins/admob
crossbundle/tools
crossbundle/cli
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ jobs:
build-and-publish-release:
name: Build and publish Github release
runs-on: ${{ matrix.os }}
if: false
strategy:
fail-fast: false
matrix:
Expand Down
14 changes: 10 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,31 @@ authors = ["DodoRare Team <[email protected]>"]
description = "Cross-Platform Rust Toolkit for Games 🏹"
repository = "https://github.com/dodorare/crossbow"
license = "Apache-2.0"
keywords = ["build", "android", "apple", "ios", "tools"]
keywords = ["build", "android", "ios", "tools"]
readme = "README.md"
exclude = [".github/**/*"]

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

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

[target.'cfg(target_os = "ios")'.dependencies]
crossbow-ios = { path = "platform/ios", version = "0.1.6", optional = true }

[patch.crates-io]
winit = { git = "https://github.com/rust-windowing/winit", rev = "f93f2c158bf527ed56ab2b6f5272214f0c1d9f7d" }
bevy = { git = "https://github.com/dodorare/bevy", rev = "d51104020004d34db1aa3a9a5795834d7814ae55" }
miniquad = { git = "https://github.com/not-fl3/miniquad", rev = "d67ffe6950cf73df307e2d23aaa4726f14399985" }

[features]
default = ["android"]
default = ["android", "ios"]
android = ["crossbow-android"]
ios = ["crossbow-ios"]

[workspace]
members = [
Expand Down
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,20 @@

## What is Crossbow?

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.
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.

## Why Crossbow?

> 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?
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*.
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*.

## Design Goals

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

## 🛠 Installation

Expand All @@ -41,14 +41,16 @@ Crossbundle crates:

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

Crossbow Plugins:

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

Expand Down
2 changes: 1 addition & 1 deletion crossbundle/cli/src/commands/build/apple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ impl AppleBuildCommand {
config.status("Copying binary to app folder")?;
std::fs::copy(&bin_path, &app_path.join(&name)).unwrap();
config.status_message("Generating", "Info.plist")?;
apple::save_apple_plist(&app_path, properties, false).unwrap();
apple::save_info_plist(&app_path, properties, false).unwrap();
if self.identity.is_some() {
config.status("Starting code signing process")?;
apple::copy_profile(
Expand Down
2 changes: 2 additions & 0 deletions crossbundle/cli/src/commands/build/build_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ impl BuildContext {
pub fn gen_info_plist(&self, package_name: &str) -> Result<InfoPlist> {
if let Some(info_plist_path) = &self.apple_config.info_plist_path {
Ok(apple::read_info_plist(info_plist_path)?)
} else if let Some(info_plist) = &self.apple_config.info_plist {
Ok(info_plist.clone())
} else {
Ok(apple::gen_minimal_info_plist(
package_name,
Expand Down
16 changes: 8 additions & 8 deletions crossbundle/cli/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,25 @@ pub enum Error {
TeamIdentifierNotProvided,
/// Invalid cargo metadata values
InvalidCargoMetadata,
/// Invalid metadata in manifest
/// Invalid metadata in manifest: {0:?}
InvalidMetadata(anyhow::Error),
/// IO error
/// IO error: {0:?}
Io(#[from] std::io::Error),
/// Clap error
/// Clap error: {0:?}
Clap(#[from] clap::Error),
/// Anyhow error
/// Anyhow error: {0:?}
AnyhowError(#[from] anyhow::Error),
/// Crossbundle Tools error
/// Crossbundle Tools error: {0:?}
CrossbundleTools(#[from] crossbundle_tools::error::Error),
/// AndroidManifest error
/// AndroidManifest error: {0:?}
AndroidManifest(#[from] android_manifest::error::Error),
/// FsExtra error
/// FsExtra error: {0:?}
FsExtra(#[from] fs_extra::error::Error),
/// Path {0:?} doesn't exist
PathNotFound(std::path::PathBuf),
/// Home dir not found
HomeDirNotFound,
/// Failed to download jar file
/// Failed to download jar file: {0:?}
DownloadFailed(ureq::Error),
/// Failed to create jar file in specified path `{path}` cause of `{cause}`
JarFileCreationFailed {
Expand Down
7 changes: 7 additions & 0 deletions crossbundle/cli/src/types/android_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,19 @@ pub const MIN_SDK_VERSION: u32 = 19;

#[derive(Debug, Clone, Deserialize, Serialize, Default)]
pub struct AndroidConfig {
/// Application name.
pub app_name: Option<String>,
/// Application version name.
pub version_name: Option<String>,
/// Application version code.
pub version_code: Option<u32>,
/// Minimum SDK version supported.
pub min_sdk_version: Option<u32>,
/// Target SDK version.
pub target_sdk_version: Option<u32>,
/// Maximum SDK version supported.
pub max_sdk_version: Option<u32>,
/// Icon name in resources.
pub icon: Option<String>,

/// Path to AndroidManifest.xml file.
Expand Down
10 changes: 9 additions & 1 deletion crossbundle/cli/src/types/apple_config.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
use crossbundle_tools::types::*;
use crossbundle_tools::types::{apple_bundle::prelude::*, AppleTarget};
use serde::{Deserialize, Serialize};
use std::path::PathBuf;

#[derive(Debug, Clone, Deserialize, Serialize, Default)]
pub struct AppleConfig {
/// Application Name.
pub app_name: Option<String>,
/// Application version name.
pub version_name: Option<String>,
/// Application version code.
pub version_code: Option<u32>,
/// Icon name in resources.
pub icon: Option<String>,

/// Path to Info.plist file.
pub info_plist_path: Option<PathBuf>,

/// Apple Info.plist configuration.
pub info_plist: Option<InfoPlist>,
/// Apple build targets.
pub build_targets: Option<Vec<AppleTarget>>,
/// Apple resources directory path relatively to project path.
Expand Down
4 changes: 2 additions & 2 deletions crossbundle/tools/src/commands/apple/save_plist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::fs::File;
use std::path::Path;

/// Saves given InfoPlist in new `Info.plist` file.
pub fn save_apple_plist(out_dir: &Path, properties: &InfoPlist, binary: bool) -> Result<()> {
pub fn save_info_plist(out_dir: &Path, properties: &InfoPlist, binary: bool) -> Result<()> {
// Create Info.plist file
let file_path = out_dir.join("Info.plist");
let file = File::create(file_path)?;
Expand Down Expand Up @@ -104,7 +104,7 @@ mod tests {
},
..Default::default()
};
save_apple_plist(dir.path(), &properties, false).unwrap();
save_info_plist(dir.path(), &properties, false).unwrap();
let file_path = dir.path().join("Info.plist");
let result = std::fs::read_to_string(&file_path).unwrap();
assert_eq!(result, PLIST_TEST_EXAMPLE.replace(" ", "\t"));
Expand Down
22 changes: 11 additions & 11 deletions crossbundle/tools/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ pub enum AndroidError {
FailedToFindAndroidManifest(String),
/// Unable to find NDK file
UnableToFindNDKFile,
/// AndroidTools error
/// AndroidTools error: {0:?}
AndroidTools(#[from] android_tools::error::Error),
/// AndroidManifest error
/// AndroidManifest error: {0:?}
AndroidManifest(#[from] android_manifest::error::Error),
}

Expand All @@ -61,7 +61,7 @@ pub enum AppleError {
ZipCommandFailed,
/// Codesign allocate not found
CodesignAllocateNotFound,
/// Simctl error
/// Simctl error: {0:?}
Simctl(simctl::Error),
/// Target dir does not exists
TargetNotFound,
Expand All @@ -71,7 +71,7 @@ pub enum AppleError {
AssetsNotFound,
/// Failed to find Info.plist in path: {0}
FailedToFindInfoPlist(String),
/// Plist data error
/// Plist data error: {0:?}
Plist(#[from] plist::Error),
}

Expand Down Expand Up @@ -115,19 +115,19 @@ pub enum Error {
/// Failed to choose shell string color.
/// Argument for --color must be auto, always, or never, but found `{}`
FailedToChooseShellStringColor(String),
/// IO error
/// IO error: {0:?}
Io(#[from] std::io::Error),
/// FS Extra error
/// FS Extra error: {0:?}
FsExtra(#[from] fs_extra::error::Error),
/// Zip error
/// Zip error: {0:?}
Zip(#[from] zip::result::ZipError),
/// Android error
/// Android error: {0:?}
Android(#[from] AndroidError),
/// Apple error
/// Apple error: {0:?}
Apple(#[from] AppleError),
/// Anyhow error
/// Anyhow error: {0:?}
AnyhowError(#[from] anyhow::Error),
/// Other error
/// Other error: {0:?}
OtherError(#[from] Box<dyn std::error::Error>),
}

Expand Down
2 changes: 1 addition & 1 deletion crossbundle/tools/tests/apple_full.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ fn test_apple_full() {

// Generate Info.plist
let properties = get_minimal_info_plist(&name);
save_apple_plist(&app_dir, &properties, false).unwrap();
save_info_plist(&app_dir, &properties, false).unwrap();

// Sign bundle
codesign(&app_dir, true, None, None).unwrap();
Expand Down
18 changes: 15 additions & 3 deletions examples/macroquad-permissions/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ edition = "2021"

[dependencies]
crossbow = { version = "0.1.6", path = "../../" }
crossbow-admob = { version = "0.1.6", path = "../../plugins/admob" }
log = "0.4"
anyhow = "1.0"
macroquad = "0.3.7"
async-executor = "1.4.1"
futures-lite = "1.12.0"

[target.'cfg(target_os = "android")'.dependencies]
crossbow-admob = { version = "0.1.6", path = "../../plugins/admob" }

[package.metadata.android]
app_name = "Macroquad_Permissions"
target_sdk_version = 30
Expand Down Expand Up @@ -45,10 +47,20 @@ name = "android.permission.CAMERA"

[package.metadata.apple]
app_name = "Macroquad_Permissions"
target_sdk_version = 30
version_code = 1
icon = "ic_launcher"
icon = "icon"

build_targets = ["aarch64-apple-ios", "x86_64-apple-ios"]
assets = "assets"
res = "res/apple"

[package.metadata.apple.info_plist]
CFBundleIdentifier = "dodorare.macroquad-permissions"
CFBundleVersion = "1.0"
CFBundleShortVersionString = "1.0"
CFBundleExecutable = "macroquad-permissions"
UILaunchStoryboardName = "LaunchScreen"
CFBundleName = "Macroquad_Permissions"
# Permissions
NSCameraUsageDescription = "Macroquad_Permissions requires access to your phone's camera."
NSPhotoLibraryUsageDescription = "Macroquad_Permissions requires access to your phone's photo library."
Loading

0 comments on commit 44294da

Please sign in to comment.