Rust-for-Arduboy/run.py

259 lines
7.6 KiB
Python
Raw Normal View History

2023-10-11 14:55:18 +02:00
import sys
import os
import tomllib
import subprocess
import platform
# Global Params
param1 = ""
param2 = ""
2023-10-11 17:42:27 +02:00
fx_mode = False
project_list = []
parameter_validation_check = False
project = []
2023-10-11 14:55:18 +02:00
# Functions
def get_args():
global param1
global param2
global fx_mode
2023-10-11 17:42:27 +02:00
if len(sys.argv) == 1:
2023-10-11 14:55:18 +02:00
help()
2023-10-11 17:42:27 +02:00
if len(sys.argv) > 1:
2023-10-11 14:55:18 +02:00
param1 = sys.argv[1]
2023-10-11 17:42:27 +02:00
if len(sys.argv) > 2:
2023-10-11 14:55:18 +02:00
param2 = sys.argv[2]
2023-10-11 17:42:27 +02:00
fx_mode = True
2023-10-11 14:55:18 +02:00
def help():
print("Usage build and upload Project:")
print(" run.py list Get a list of all Projects")
print(" run.py new <Project-Name> Create a new game in the Project folder")
print(" run.py <Project-Name> For uploading a game")
print("")
print("Usage FX-Data build and upload:")
print(" run.py fxbuild <Project-Name> Build your fxdata")
print(" run.py fxupload <Project-Name> Upload your fxdata")
print(" run.py fxall <Project-Name> Build and Upload your fxdata")
print(" and the game in one step")
sys.exit()
2023-10-11 17:42:27 +02:00
2023-10-11 14:55:18 +02:00
def get_projects():
global project_list
with open("Cargo.toml", "rb") as f:
data = tomllib.load(f)
2023-10-11 17:42:27 +02:00
path = data["workspace"]["members"]
2023-10-11 14:55:18 +02:00
for p in path:
name = p.split("/")[-1]
2023-10-11 17:42:27 +02:00
if name == "arduboy-rust":
2023-10-11 14:55:18 +02:00
continue
2023-10-11 17:42:27 +02:00
project = [name, p]
2023-10-11 14:55:18 +02:00
project_list.append(project)
2023-10-11 17:42:27 +02:00
2023-10-11 14:55:18 +02:00
def validate_args():
global parameter_validation_check
global project
if fx_mode:
for p in project_list:
2023-10-11 17:42:27 +02:00
if param2 in p:
parameter_validation_check = True
2023-10-11 14:55:18 +02:00
project = p
else:
for p in project_list:
2023-10-11 17:42:27 +02:00
if param1 in p:
parameter_validation_check = True
2023-10-11 14:55:18 +02:00
project = p
if not parameter_validation_check:
help()
2023-10-11 17:42:27 +02:00
2023-10-11 14:55:18 +02:00
def execute_options():
2023-10-11 17:42:27 +02:00
if param1 == "list":
group = ""
2023-10-11 14:55:18 +02:00
for p in project_list:
2023-10-11 17:42:27 +02:00
if not group == p[1].split("/")[-2]:
group = p[1].split("/")[-2]
2023-10-11 14:55:18 +02:00
print(f"\n{group}:")
print(f" {p[0]}")
print("")
2023-10-12 09:54:42 +02:00
sys.exit(0)
2023-10-11 17:42:27 +02:00
if param1 == "new":
2023-10-11 14:55:18 +02:00
create_new_project()
2023-10-12 09:54:42 +02:00
sys.exit(0)
2023-10-11 17:42:27 +02:00
if param1 == "doc":
if platform.system() == "Linux":
cmd = "cargo doc -p arduboy-rust; rm -r ./docs/doc/; cp -r ./target/arduboy/doc ./docs/"
process = subprocess.Popen(cmd, stdout=subprocess.PIPE)
elif platform.system() == "Windows":
cmd = 'cargo doc -p arduboy-rust; rm -r ./docs/doc/; cp -r ./target/arduboy/doc ./docs/'
process = subprocess.Popen(["powershell", "-Command", cmd], stdout=subprocess.PIPE)
else:
2023-10-12 09:54:42 +02:00
sys.exit(1)
2023-10-11 17:42:27 +02:00
for c in iter(lambda: process.stdout.read(1), b""):
sys.stdout.buffer.write(c)
if process.returncode != 0:
2023-10-12 09:54:42 +02:00
sys.exit(1)
2023-10-11 17:42:27 +02:00
2023-10-11 14:55:18 +02:00
def _dumps_value(value):
if isinstance(value, bool):
return "true" if value else "false"
elif isinstance(value, (int, float)):
return str(value)
elif isinstance(value, str):
return f'"{value}"'
elif isinstance(value, list):
return f"[{', '.join(_dumps_value(v) for v in value)}]"
else:
raise TypeError(f"{type(value).__name__} {value!r} is not supported")
2023-10-11 17:42:27 +02:00
2023-10-11 14:55:18 +02:00
def dumps(toml_dict, table=""):
toml = []
for key, value in toml_dict.items():
if isinstance(value, dict):
table_key = f"{table}.{key}" if table else key
toml.append(f"\n[{table_key}]\n{dumps(value, table_key)}")
else:
toml.append(f"{key} = {_dumps_value(value)}")
return "\n".join(toml)
2023-10-11 17:42:27 +02:00
2023-10-11 14:55:18 +02:00
def create_new_project():
2023-10-11 17:42:27 +02:00
project_name = param2.replace("-", "_")
2023-10-11 14:55:18 +02:00
for p in project_list:
2023-10-11 17:42:27 +02:00
if p[0] == project_name:
2023-10-12 09:54:42 +02:00
sys.exit(1)
2023-10-11 17:42:27 +02:00
error_code = os.system(f'cargo new --vcs=none --lib ./Project/{project_name}')
if error_code > 0:
2023-10-12 09:54:42 +02:00
sys.exit(1)
2023-10-11 14:55:18 +02:00
# Edit main Cargo.toml
with open("Cargo.toml", "rb") as f:
data = tomllib.load(f)
data["workspace"]["members"].append(f"Project/{project_name}")
2023-10-11 17:42:27 +02:00
with open("Cargo.toml", "w") as f:
2023-10-11 14:55:18 +02:00
f.write(dumps(data))
# Edit new project Cargo.toml
with open(f"Project/{project_name}/Cargo.toml", "rb") as f:
data = tomllib.load(f)
2023-10-11 17:42:27 +02:00
newdata = {}
newdata["package"] = data["package"]
newdata["lib"] = {'crate-type': ["staticlib"]}
newdata["dependencies"] = {"arduboy-rust": {"path": "../../arduboy-rust"}}
with open(f"Project/{project_name}/Cargo.toml", "w") as f:
2023-10-11 14:55:18 +02:00
f.write(dumps(newdata))
# Edit lib.rs
2023-10-11 17:42:27 +02:00
with open(f"Project/{project_name}/src/lib.rs", "w") as f:
2023-10-11 14:55:18 +02:00
f.write('''#![no_std]
#![allow(non_upper_case_globals)]
//Include the Arduboy Library
#[allow(unused_imports)]
use arduboy_rust::prelude::*;
#[allow(dead_code)]
const arduboy: Arduboy2 = Arduboy2::new();
// Progmem data
// dynamic ram variables
// The setup() function runs once when you turn your Arduboy on
#[no_mangle]
pub unsafe extern "C" fn setup() {
// put your setup code here, to run once:
}
// The loop() function repeats forever after setup() is done
#[no_mangle]
#[export_name = "loop"]
pub unsafe extern "C" fn loop_() {
// put your main code here, to run repeatedly:
}''')
2023-10-11 18:05:53 +02:00
with open(f"Project/{project_name}/config.toml", "w") as f:
data = '''Libraries = [
"Arduboy2",
#"ArduboyTones",
#"ArduboyFX",
#"ArdVoice",
#"Serial",
"EEPROM",
"Arduino",
]'''
f.writelines(data)
2023-10-11 14:55:18 +02:00
2023-10-11 17:42:27 +02:00
2023-10-11 14:55:18 +02:00
def generate_import_h():
with open(f"{project[1]}/config.toml", "rb") as f:
data = tomllib.load(f)
2023-10-11 17:42:27 +02:00
strings = ["#pragma once\n"]
2023-10-11 14:55:18 +02:00
for lib in data["Libraries"]:
strings.append(f"#define {lib}_Library ;\n")
f = open("arduboy-rust/Wrapper-Project/src/imports.h", "w")
f.writelines(strings)
f.close()
2023-10-11 17:42:27 +02:00
2023-10-11 14:55:18 +02:00
def upload_to_arduboy():
if not fx_mode:
2023-10-11 17:42:27 +02:00
game_name = param1
2023-10-11 14:55:18 +02:00
else:
2023-10-11 17:42:27 +02:00
game_name = param2
if platform.system() == "Linux":
cmd = f"cargo build -p {game_name} --release; cp ./target/arduboy/release/lib{game_name}.a ./arduboy-rust/Wrapper-Project/lib/libgame.a; cd arduboy-rust/Wrapper-Project/; pio run -v -t upload; cp ./.pio/build/arduboy/firmware.hex ./build/{game_name}.hex; pio run -t clean; rm ./lib/libgame.a; cd ../../"
2023-10-11 14:55:18 +02:00
process = subprocess.Popen(cmd, stdout=subprocess.PIPE)
2023-10-11 17:42:27 +02:00
elif platform.system() == "Windows":
cmd = f'cargo build -p {game_name} --release; cp ./target/arduboy/release/lib{game_name}.a ./arduboy-rust/Wrapper-Project/lib/libgame.a; cd arduboy-rust/Wrapper-Project/; pio run -v -t upload; cp ./.pio/build/arduboy/firmware.hex ./build/{game_name}.hex; pio run -t clean; rm lib/libgame.a; cd ../../'
2023-10-11 14:55:18 +02:00
process = subprocess.Popen(["powershell", "-Command", cmd], stdout=subprocess.PIPE)
else:
2023-10-12 09:54:42 +02:00
sys.exit(1)
2023-10-11 17:42:27 +02:00
for c in iter(lambda: process.stdout.read(1), b""):
2023-10-11 14:55:18 +02:00
sys.stdout.buffer.write(c)
if process.returncode != 0:
2023-10-12 09:54:42 +02:00
sys.exit(1)
2023-10-11 14:55:18 +02:00
2023-10-11 17:42:27 +02:00
2023-10-11 14:55:18 +02:00
def fx_build():
2023-10-11 17:42:27 +02:00
error_code = os.system(f'python ./Tools/Arduboy-Python-Utilities/fxdata-build.py ./{project[1]}/fxdata/fxdata.txt')
if error_code > 0:
2023-10-12 09:54:42 +02:00
sys.exit(1)
2023-10-11 14:55:18 +02:00
2023-10-11 17:42:27 +02:00
2023-10-11 14:55:18 +02:00
def fx_upload():
2023-10-11 17:42:27 +02:00
error_code = os.system(f'python ./Tools/Arduboy-Python-Utilities/fxdata-upload.py ./{project[1]}/fxdata/fxdata.bin')
if error_code > 0:
2023-10-12 09:54:42 +02:00
sys.exit(1)
2023-10-11 14:55:18 +02:00
2023-10-11 17:42:27 +02:00
2023-10-11 14:55:18 +02:00
def fx_commands():
print("")
2023-10-11 17:42:27 +02:00
if param1 == "fxbuild":
2023-10-11 14:55:18 +02:00
fx_build()
2023-10-11 17:42:27 +02:00
elif param1 == "fxupload":
2023-10-11 14:55:18 +02:00
fx_upload()
2023-10-11 17:42:27 +02:00
elif param1 == "fxall":
2023-10-11 14:55:18 +02:00
fx_build()
fx_upload()
upload_to_arduboy()
# Execute Script
get_args()
get_projects()
execute_options()
validate_args()
generate_import_h()
if fx_mode:
fx_commands()
else:
upload_to_arduboy()