mirror of
https://github.com/italicsjenga/gba.git
synced 2024-12-23 10:51:30 +11:00
Simplify build process (#106)
* Simplify build process - Remove dependencies on DevkitPro - Use linker similarly to min-gba - Update cargo.toml so that dev builds will build - Update cargo config so that std builds can run without the linker for testing purposes - Update CI flow to remove xbuild dependency * Add windows toolchain install * Add windows section to toolchain install instructions
This commit is contained in:
parent
263f7909de
commit
5114f89448
|
@ -1,5 +1,3 @@
|
|||
[build]
|
||||
target = "thumbv4-none-agb.json"
|
||||
|
||||
[unstable]
|
||||
build-std = ["core"]
|
||||
[target.thumbv4t-none-eabi]
|
||||
rustflags = ["-Clink-arg=-Tlinker.ld"]
|
||||
runner = "mgba"
|
||||
|
|
26
.github/workflows/ci.yaml
vendored
26
.github/workflows/ci.yaml
vendored
|
@ -6,44 +6,40 @@ on:
|
|||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
container: devkitpro/devkitarm:latest
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
rust:
|
||||
- { toolchain: nightly }
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Add devkitARM bin to PATH
|
||||
run: echo "/opt/devkitpro/devkitARM/bin" >> $GITHUB_PATH
|
||||
- name: Install Apt Dependencies
|
||||
run: apt-get update && apt-get install -y --no-install-recommends build-essential libssl-dev
|
||||
run: sudo apt-get update && sudo apt-get install -y --no-install-recommends build-essential libssl-dev binutils-arm-none-eabi
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: ${{ matrix.rust.toolchain }}
|
||||
default: true
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- name: Install Rust Source
|
||||
run: rustup component add rust-src
|
||||
- name: Install cargo-xbuild crate
|
||||
uses: actions-rs/install@v0.1
|
||||
with:
|
||||
crate: cargo-xbuild
|
||||
version: latest
|
||||
use-tool-cache: true
|
||||
- name: Install cargo-make crate
|
||||
uses: actions-rs/install@v0.1
|
||||
with:
|
||||
crate: cargo-make
|
||||
version: latest
|
||||
use-tool-cache: true
|
||||
- name: Make Test Linux
|
||||
- name: Install gbafix crate
|
||||
uses: actions-rs/install@v0.1
|
||||
with:
|
||||
crate: gbafix
|
||||
version: latest
|
||||
use-tool-cache: true
|
||||
- uses: actions/checkout@v2
|
||||
- name: Make Test
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
toolchain: ${{ matrix.rust.toolchain }}
|
||||
command: make
|
||||
args: test linux
|
||||
args: test
|
||||
- name: Make Release
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
|
|
|
@ -22,6 +22,12 @@ gba-proc-macro = "0.5"
|
|||
embedded-hal = { version = "0.2.4", optional = true }
|
||||
nb = { version = "1.0.0", optional = true }
|
||||
|
||||
[profile.dev]
|
||||
lto = false
|
||||
panic = "abort"
|
||||
incremental = false
|
||||
codegen-units = 1
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
panic = "abort"
|
||||
|
|
|
@ -1,55 +1,70 @@
|
|||
[config]
|
||||
skip_core_tasks = true
|
||||
|
||||
[tasks.create-target-dir]
|
||||
[tasks.verify-toolchain]
|
||||
script_runner = "@duckscript"
|
||||
script = [ "mkdir ./target/" ]
|
||||
script = [
|
||||
'''
|
||||
channel = get_env CARGO_MAKE_RUST_CHANNEL
|
||||
assert_eq ${channel} nightly "Rust toolchain must be set to nightly"
|
||||
'''
|
||||
]
|
||||
|
||||
[tasks.assemble]
|
||||
dependencies = ["create-target-dir"]
|
||||
command = "arm-none-eabi-as"
|
||||
args = ["crt0.s", "-o", "target/crt0.o"]
|
||||
|
||||
[tasks.build-examples-debug]
|
||||
dependencies = ["assemble"]
|
||||
dependencies = ["verify-toolchain"]
|
||||
command = "cargo"
|
||||
args = ["build", "--examples"]
|
||||
args = ["build", "--examples", "--target=thumbv4t-none-eabi", "-Zbuild-std=core"]
|
||||
|
||||
[tasks.build-examples-release]
|
||||
dependencies = ["assemble"]
|
||||
dependencies = ["verify-toolchain"]
|
||||
command = "cargo"
|
||||
args = ["build", "--examples", "--release"]
|
||||
args = ["build", "--examples", "--release", "--target=thumbv4t-none-eabi", "-Zbuild-std=core"]
|
||||
|
||||
[tasks.pack-roms]
|
||||
script_runner = "@duckscript"
|
||||
script = [
|
||||
'''
|
||||
release_target = get_env RELEASE_TARGET
|
||||
examples_path = set ./target/thumbv4t-none-eabi/${release_target}/examples
|
||||
examples = glob_array ./examples/*.rs
|
||||
for example in ${examples}
|
||||
example = substring ${example} -3
|
||||
example = basename ${example}
|
||||
exec arm-none-eabi-objcopy -O binary ./target/thumbv4-none-agb/release/examples/${example} ./target/${example}.gba
|
||||
binary_exists = is_path_exists ${examples_path}/${example}
|
||||
|
||||
if ${binary_exists}
|
||||
echo "Packing: ${examples_path}/${example} to ${examples_path}/${example}.gba"
|
||||
exec arm-none-eabi-objcopy -O binary ${examples_path}/${example} ${examples_path}/${example}.gba
|
||||
echo "Fixing headers: ${examples_path}/${example}.gba"
|
||||
exec gbafix ${examples_path}/${example}.gba
|
||||
else
|
||||
echo "Binary does not exist: ${examples_path}/${example}"
|
||||
end
|
||||
end
|
||||
'''
|
||||
]
|
||||
|
||||
[tasks.test.linux]
|
||||
command = "cargo"
|
||||
args = ["test", "--lib", "--target", "x86_64-unknown-linux-gnu", "-Z", "build-std"]
|
||||
[tasks.pack-roms-release]
|
||||
dependencies = ["build-examples-release"]
|
||||
env = { RELEASE_TARGET = "release" }
|
||||
run_task = "pack-roms"
|
||||
|
||||
[tasks.test.windows]
|
||||
command = "cargo"
|
||||
args = ["test", "--lib", "--target", "x86_64-pc-windows-msvc", "-Z", "build-std"]
|
||||
[tasks.pack-roms-debug]
|
||||
dependencies = ["build-examples-debug"]
|
||||
env = { RELEASE_TARGET = "debug" }
|
||||
run_task = "pack-roms"
|
||||
|
||||
[tasks.test.mac]
|
||||
[tasks.test]
|
||||
dependencies = ["verify-toolchain"]
|
||||
command = "cargo"
|
||||
args = ["test", "--lib", "--target", "x86_64-apple-darwin", "-Z", "build-std"]
|
||||
args = ["test", "--lib"]
|
||||
|
||||
[tasks.justrelease]
|
||||
dependencies = ["build-examples-release", "pack-roms"]
|
||||
dependencies = ["pack-roms-release"]
|
||||
|
||||
[tasks.build-all]
|
||||
dependencies = ["build-examples-debug", "build-examples-release", "pack-roms"]
|
||||
dependencies = ["pack-roms-debug", "pack-roms-release"]
|
||||
|
||||
[tasks.default]
|
||||
alias = "build-all"
|
||||
|
|
25
README.md
25
README.md
|
@ -1,5 +1,5 @@
|
|||
[![License:Apache2](https://img.shields.io/badge/License-Apache2-green.svg)](https://www.apache.org/licenses/LICENSE-2.0)
|
||||
[![travis.ci](https://travis-ci.org/rust-console/gba.svg?branch=master)](https://travis-ci.org/rust-console/gba)
|
||||
[![ci](https://github.com/rust-console/gba/workflows/ci/badge.svg?branch=master)](https://github.com/rust-console/gba/actions?query=workflow%3Aci)
|
||||
[![crates.io](https://img.shields.io/crates/v/gba.svg)](https://crates.io/crates/gba)
|
||||
[![docs.rs](https://docs.rs/gba/badge.svg)](https://docs.rs/gba/latest/gba/)
|
||||
|
||||
|
@ -22,6 +22,29 @@ The following major GBA features are still missing from the crate:
|
|||
* Interrupt Handling
|
||||
* Serial Communication
|
||||
|
||||
## Build Dependencies
|
||||
|
||||
Install required cargo packages
|
||||
```sh
|
||||
rustup install nightly
|
||||
rustup +nightly component add rust-src
|
||||
cargo install cargo-make
|
||||
cargo install gbafix
|
||||
```
|
||||
|
||||
Install arm build tools
|
||||
* Ubuntu
|
||||
```shell
|
||||
sudo apt-get install binutils-arm-none-eabi
|
||||
```
|
||||
* OSX
|
||||
```shell
|
||||
brew install --cask gcc-arm-embedded
|
||||
```
|
||||
* Windows
|
||||
* Download the [GNU Arm Embedded Toolchain](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads)
|
||||
* Install the toolchain, make sure to select "Add path to environment variable" during install
|
||||
|
||||
## First Time Setup
|
||||
|
||||
Writing a Rust program for the GBA requires a fair amount of special setup. All
|
||||
|
|
17
build.rs
Normal file
17
build.rs
Normal file
|
@ -0,0 +1,17 @@
|
|||
fn main() {
|
||||
let out_file = "rsrt0.o";
|
||||
let out_dir = std::env::var("OUT_DIR").unwrap();
|
||||
let out_dir_file = format!("{}/{}", out_dir, out_file);
|
||||
let as_output = std::process::Command::new("arm-none-eabi-as")
|
||||
.args(&["-o", out_dir_file.as_str()])
|
||||
.arg("-mthumb-interwork")
|
||||
.arg("-mcpu=arm7tdmi")
|
||||
.arg("src/rsrt0.S")
|
||||
.output()
|
||||
.expect("failed to run arm-none-eabi-as");
|
||||
if !as_output.status.success() {
|
||||
panic!("{}", String::from_utf8_lossy(&as_output.stderr));
|
||||
}
|
||||
//
|
||||
println!("cargo:rustc-link-search={}", out_dir);
|
||||
}
|
|
@ -8,7 +8,7 @@ MEMORY {
|
|||
|
||||
SECTIONS {
|
||||
.text : {
|
||||
KEEP(target/crt0.o(.text));
|
||||
KEEP(rsrt0.o(.text));
|
||||
*(.text .text.*);
|
||||
. = ALIGN(4);
|
||||
} >rom = 0xff
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
//! pointer and execution will jump to the user interrupt handler starting at
|
||||
//! `0x0300_7FFC`, in ARM mode.
|
||||
//!
|
||||
//! Currently, the user interrupt handler is defined in `crt0.s`. It is set up
|
||||
//! Currently, the user interrupt handler is defined in `rsrt0.S`. It is set up
|
||||
//! to execute a user-specified interrupt handler after saving some registers.
|
||||
//! This handler is declared as a static function pointer on the Rust side, and
|
||||
//! can be set by using [`set_irq_handler`](irq::set_irq_handler).
|
||||
|
@ -27,7 +27,7 @@
|
|||
//! This is done by setting the corresponding IRQ flag on
|
||||
//! [`BIOS_IF`](irq::BIOS_IF) at the end of the interrupt handler.
|
||||
//! * You can change the low-level details of the interrupt handler by editing
|
||||
//! the `MainIrqHandler` routine in `crt0.s`. For example, you could declare
|
||||
//! the `MainIrqHandler` routine in `rsrt0.S`. For example, you could declare
|
||||
//! an external static variable in Rust holding a table of interrupt function
|
||||
//! pointers and jump directly into one of them in assembly, without the need
|
||||
//! to write the branching logic in Rust. However, note that the main
|
||||
|
@ -78,7 +78,7 @@
|
|||
//!
|
||||
//! ## Implementation Details
|
||||
//!
|
||||
//! This is the setup the provided user interrupt handler in `crt0.s` will do
|
||||
//! This is the setup the provided user interrupt handler in `rsrt0.S` will do
|
||||
//! when an interrupt is received, in order. It is based on the _Recommended
|
||||
//! User Interrupt Handling_ portion of the GBATEK reference.
|
||||
//!
|
||||
|
@ -136,7 +136,7 @@ pub const IE: VolAddress<IrqFlags> = unsafe { VolAddress::new(0x400_0200) };
|
|||
///
|
||||
/// The main user interrupt handler will acknowledge the interrupt that was set
|
||||
/// by writing to this register, so there is usually no need to modify it.
|
||||
/// However, if the main interrupt handler in `crt0.s` is changed, then the
|
||||
/// However, if the main interrupt handler in `rsrt0.S` is changed, then the
|
||||
/// handler must write a `1` bit to all bits that are enabled on this register
|
||||
/// when it is called.
|
||||
pub const IF: VolAddress<IrqFlags> = unsafe { VolAddress::new(0x400_0202) };
|
||||
|
@ -185,7 +185,7 @@ pub fn set_irq_handler(handler: IrqHandler) {
|
|||
|
||||
extern "C" fn default_handler(_flags: IrqFlags) {}
|
||||
|
||||
// Inner definition of the interrupt handler. It is referenced in `crt0.s`.
|
||||
// Inner definition of the interrupt handler. It is referenced in `rsrt0.S`.
|
||||
#[doc(hidden)]
|
||||
#[no_mangle]
|
||||
static mut __IRQ_HANDLER: IrqHandler = default_handler;
|
||||
|
|
|
@ -2,46 +2,8 @@
|
|||
__start:
|
||||
b .Linit
|
||||
|
||||
@ ROM header
|
||||
.byte 0x24,0xff,0xae,0x51,0x69,0x9a,0xa2,0x21,0x3d,0x84,0x82,0x0a,0x84,0xe4,0x09,0xad
|
||||
.byte 0x11,0x24,0x8b,0x98,0xc0,0x81,0x7f,0x21,0xa3,0x52,0xbe,0x19,0x93,0x09,0xce,0x20
|
||||
.byte 0x10,0x46,0x4a,0x4a,0xf8,0x27,0x31,0xec,0x58,0xc7,0xe8,0x33,0x82,0xe3,0xce,0xbf
|
||||
.byte 0x85,0xf4,0xdf,0x94,0xce,0x4b,0x09,0xc1,0x94,0x56,0x8a,0xc0,0x13,0x72,0xa7,0xfc
|
||||
.byte 0x9f,0x84,0x4d,0x73,0xa3,0xca,0x9a,0x61,0x58,0x97,0xa3,0x27,0xfc,0x03,0x98,0x76
|
||||
.byte 0x23,0x1d,0xc7,0x61,0x03,0x04,0xae,0x56,0xbf,0x38,0x84,0x00,0x40,0xa7,0x0e,0xfd
|
||||
.byte 0xff,0x52,0xfe,0x03,0x6f,0x95,0x30,0xf1,0x97,0xfb,0xc0,0x85,0x60,0xd6,0x80,0x25
|
||||
.byte 0xa9,0x63,0xbe,0x03,0x01,0x4e,0x38,0xe2,0xf9,0xa2,0x34,0xff,0xbb,0x3e,0x03,0x44
|
||||
.byte 0x78,0x00,0x90,0xcb,0x88,0x11,0x3a,0x94,0x65,0xc0,0x7c,0x63,0x87,0xf0,0x3c,0xaf
|
||||
.byte 0xd6,0x25,0xe4,0x8b,0x38,0x0a,0xac,0x72,0x21,0xd4,0xf8,0x07
|
||||
|
||||
@ game title
|
||||
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
||||
|
||||
@ game code
|
||||
.byte 0x00,0x00,0x00,0x00
|
||||
|
||||
@ maker code
|
||||
.byte 0x00,0x00
|
||||
|
||||
.byte 0x96
|
||||
|
||||
@ main unit code
|
||||
.byte 0x00
|
||||
|
||||
@ device type (0x00 retail, 0x80 debug)
|
||||
.byte 0x00
|
||||
|
||||
@ reserved
|
||||
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
||||
|
||||
@ software version
|
||||
.byte 0x00
|
||||
|
||||
@ complement check
|
||||
.byte 0x51
|
||||
|
||||
@ reserved area
|
||||
.space 2
|
||||
@ this is replaced with correct header info by `gbafix`
|
||||
.space 188
|
||||
|
||||
.Linit:
|
||||
@ Set address of user IRQ handler
|
|
@ -1,39 +0,0 @@
|
|||
{
|
||||
"abi-blacklist": [
|
||||
"stdcall",
|
||||
"fastcall",
|
||||
"vectorcall",
|
||||
"thiscall",
|
||||
"win64",
|
||||
"sysv64"
|
||||
],
|
||||
"arch": "arm",
|
||||
"atomic-cas": false,
|
||||
"cpu": "arm7tdmi",
|
||||
"data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64",
|
||||
"emit-debug-gdb-scripts": false,
|
||||
"env": "agb",
|
||||
"executables": true,
|
||||
"features": "+soft-float,+strict-align",
|
||||
"linker": "arm-none-eabi-ld",
|
||||
"linker-flavor": "ld",
|
||||
"linker-is-gnu": true,
|
||||
"llvm-target": "thumbv4-none-agb",
|
||||
"os": "none",
|
||||
"panic-strategy": "abort",
|
||||
"pre-link-args-crt": {
|
||||
"ld": [
|
||||
"crt0.o"
|
||||
]
|
||||
},
|
||||
"pre-link-args": {
|
||||
"ld": [
|
||||
"-Tlinker.ld"
|
||||
]
|
||||
},
|
||||
"relocation-model": "static",
|
||||
"target-c-int-width": "32",
|
||||
"target-endian": "little",
|
||||
"target-pointer-width": "32",
|
||||
"vendor": "nintendo"
|
||||
}
|
Loading…
Reference in a new issue