const ARCH_LIST: &'static str = "$ARCH_LIST$";
const APP_ID: &'static str = "$APP_ID$";
const PACKAGE: &'static str = "$PACKAGE$";
const SDK_PATH: &'static str = "$SDK_PATH$";
const MIN_SDK: &'static str = "$MIN_SDK$";
const TARGET_SDK: &'static str = "$TARGET_SDK$";
const NDK_PATH: &'static str = "$NDK_PATH$";
const DEPENDENCIES: &'static str = "$DEPENDENCIES$";
const APP_NAME: &'static str = "$APP_NAME$";
const VERSION: &'static str = "$VERSION$";
const VERSION_CODE: &'static str = "$VERSION_CODE$";
const ACTIVITY_NAME: &'static str = "$ACTIVITY_NAME$";
const ACTIVITIES: &'static str = "$ACTIVITIES$";
const PROJECT_NAME: &'static str = "$PROJECT_NAME$";
const PROFILE: &'static str = "$PROFILE$";
#[derive(thiserror::Error, Debug)]
pub enum Errors {
#[error("io error")]
IoError(#[from] std::io::Error),
#[error("string parse error")]
StringParseError(#[from] std::convert::Infallible),
#[error("Toml parse error")]
TomlParseError(#[from] toml::de::Error),
#[error("json parse error")]
JsonParseError(#[from] serde_json::error::Error),
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
pub struct ActivityInfo {
pub name: String,
pub is_launcher: bool,
}
pub fn instantiate_for(
dir: &str,
dependencies: &str,
arch_list: &str,
app_id: &str,
min_sdk: &str,
target_sdk: &str,
sdk_dir: &str,
ndk_dir: &str,
package: &str,
app_name: &str,
version: &str,
version_code: &str,
lib_content: &str,
activities: Vec<ActivityInfo>,
release_profile: bool,
) -> Result<(), Errors> {
std::fs::create_dir_all(dir)?;
std::fs::write(
format!("{}/build.gradle", dir),
std::include_str!("./templates/main_build.gradle"),
)?;
{
use std::{
fs::File,
io::Write,
};
let app_gradle_dir = format!("{}/gradle/wrapper/", dir);
std::fs::create_dir_all(&app_gradle_dir)?;
let wrapper_dir = format!("{}/gradle-wrapper.jar", app_gradle_dir);
let wrapper_content =
std::include_bytes!("./templates/gradle/wrapper/gradle-wrapper.jar");
let mut file = File::create(wrapper_dir)?;
file.write_all(wrapper_content)?;
}
std::fs::write(
format!("{}/gradle/wrapper/gradle-wrapper.properties", dir),
std::include_str!("./templates/gradle/wrapper/gradle-wrapper.properties"),
)?;
std::fs::write(
&format!("{}/gradlew", dir),
std::include_str!("./templates/gradlew"),
)?;
std::fs::write(
format!("{}/settings.gradle", dir),
std::include_str!("./templates/settings.gradle").replace(PROJECT_NAME, package),
)?;
std::fs::write(
format!("{}/gradle.properties", dir),
std::include_str!("./templates/gradle.properties"),
)?;
{
let main_gradle = format!("{}/gradlew", dir);
let main_gradle_content = std::include_str!("./templates/gradlew");
std::fs::write(&main_gradle, &main_gradle_content)?;
std::fs::set_permissions(
&main_gradle,
std::os::unix::fs::PermissionsExt::from_mode(0o700),
)?
}
std::fs::write(
format!("{}/local.properties", dir),
std::include_str!("./templates/local.properties")
.replace(SDK_PATH, sdk_dir)
.replace(NDK_PATH, ndk_dir),
)?;
{
let module_path = "rust";
let rust_dir = format!("{}/{}/src", dir, module_path);
std::fs::create_dir_all(&rust_dir)?;
std::fs::write(format!("{}/lib.rs", rust_dir), lib_content)?;
std::fs::write(
format!("{}/{}/Cargo.toml", dir, module_path),
std::include_str!("./templates/cargo.toml")
.replace(DEPENDENCIES, dependencies),
)?;
}
{
let app_gradle_dir = format!("{}/app/", dir);
std::fs::create_dir_all(&app_gradle_dir)?;
std::fs::write(
format!("{}/build.gradle", app_gradle_dir),
std::include_str!("./templates/app_build.gradle")
.replace(ARCH_LIST, arch_list)
.replace(APP_ID, app_id)
.replace(MIN_SDK, min_sdk)
.replace(TARGET_SDK, target_sdk)
.replace(VERSION, version)
.replace(VERSION_CODE, version_code)
.replace(PROFILE, match release_profile {
true => "release",
false => "debug",
}),
)?;
}
{
let activities_xml = activities
.iter()
.map(|a| {
match a.is_launcher {
true => {
format!(
"<activity android:name=\"{}.{}\">
<intent-filter>
<action android:name=\"android.intent.action.MAIN\" />
<category android:name=\"android.intent.category.LAUNCHER\" />
</intent-filter>
</activity>",
uni_components::APPLICATION_PACKAGE,
a.name,
)
},
false => {
format!(
"<activity android:name=\"{}.{}\"/>",
uni_components::APPLICATION_PACKAGE,
a.name
)
},
}
})
.collect::<Vec<_>>()
.join("\n");
let app_main_dir = format!("{}/app/src/main/", dir);
std::fs::create_dir_all(&app_main_dir)?;
std::fs::write(
format!("{}/AndroidManifest.xml", app_main_dir),
std::include_str!("./templates/manifest.xml")
.replace(PACKAGE, package)
.replace(APP_NAME, app_name)
.replace(ACTIVITIES, &activities_xml),
)?;
}
{
let app_values_dir = format!("{}/app/src/main/res/values/", dir);
std::fs::create_dir_all(&app_values_dir)?;
std::fs::write(
format!("{}/styles.xml", app_values_dir),
std::include_str!("./templates/styles.xml"),
)?;
}
{
let package_dir = package.clone().replace(".", "/");
let package_dir = format!("{}/app/src/main/java/{}/", dir, package_dir);
std::fs::create_dir_all(&package_dir)?;
std::fs::write(
format!("{}/Application.kt", package_dir),
std::include_str!("./templates/application.kt").replace(PACKAGE, package),
)?;
for activity in activities.iter() {
std::fs::write(
format!("{}/app/src/main/java/{}.kt", dir, activity.name),
std::include_str!("./templates/activity.kt")
.replace(PACKAGE, uni_components::APPLICATION_PACKAGE)
.replace(ACTIVITY_NAME, &activity.name),
)?;
}
}
return Ok(());
}