Skip to content

Commit c60f32a

Browse files
author
AMG
committed
docs: playstation vita platform
1 parent f7fb391 commit c60f32a

File tree

5 files changed

+174
-4
lines changed

5 files changed

+174
-4
lines changed

compiler/rustc_target/src/spec/armv7_sony_vita_eabihf.rs

-3
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,12 @@ pub fn target() -> Target {
2020
endian: Endian::Little,
2121
c_int_width: "32".to_string(),
2222
dynamic_linking: false,
23-
env: "newlib".to_string(),
2423
vendor: "sony".to_string(),
2524
abi: "eabihf".to_string(),
2625
linker_flavor: LinkerFlavor::Gcc,
2726
linker_is_gnu: true,
28-
no_default_libraries: false,
2927
cpu: "cortex-a9".to_string(),
3028
executables: true,
31-
families: vec!["unix".to_string()],
3229
linker: Some("arm-vita-eabi-gcc".to_string()),
3330
relocation_model: RelocModel::Static,
3431
features: "+v7,+neon".to_string(),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
use crate::abi::Endian;
2+
use crate::spec::{LinkArgs, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions};
3+
4+
/// A base target for PlayStation Vita devices using the VITASDK toolchain (using newlib).
5+
///
6+
/// Requires the VITASDK toolchain on the host system.
7+
8+
pub fn target() -> Target {
9+
let mut pre_link_args = LinkArgs::new();
10+
pre_link_args.insert(LinkerFlavor::Gcc, vec!["-Wl,-q".to_string()]);
11+
12+
Target {
13+
llvm_target: "armv7a-vita-newlibeabihf".to_string(),
14+
pointer_width: 32,
15+
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
16+
arch: "arm".to_string(),
17+
18+
options: TargetOptions {
19+
os: "vita".to_string(),
20+
endian: Endian::Little,
21+
c_int_width: "32".to_string(),
22+
dynamic_linking: false,
23+
env: "newlib".to_string(),
24+
vendor: "sony".to_string(),
25+
abi: "eabihf".to_string(),
26+
linker_flavor: LinkerFlavor::Gcc,
27+
linker_is_gnu: true,
28+
no_default_libraries: false,
29+
cpu: "cortex-a9".to_string(),
30+
executables: true,
31+
families: vec!["unix".to_string()],
32+
linker: Some("arm-vita-eabi-gcc".to_string()),
33+
relocation_model: RelocModel::Static,
34+
features: "+v7,+neon".to_string(),
35+
pre_link_args,
36+
exe_suffix: ".elf".to_string(),
37+
panic_strategy: PanicStrategy::Abort,
38+
max_atomic_width: Some(32),
39+
..Default::default()
40+
},
41+
}
42+
}

compiler/rustc_target/src/spec/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -957,6 +957,7 @@ supported_targets! {
957957
("armv6k-nintendo-3ds", armv6k_nintendo_3ds),
958958

959959
("armv7-sony-vita-eabihf", armv7_sony_vita_eabihf),
960+
("armv7-sony-vita-newlibeabihf", armv7_sony_vita_newlibeabihf),
960961

961962
("armv7-unknown-linux-uclibceabihf", armv7_unknown_linux_uclibceabihf),
962963

src/doc/rustc/src/platform-support.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,8 @@ target | std | host | notes
220220
`armv6-unknown-netbsd-eabihf` | ? | |
221221
`armv6k-nintendo-3ds` | * | | ARMv6K Nintendo 3DS, Horizon (Requires devkitARM toolchain)
222222
`armv7-apple-ios` | ✓ | | ARMv7 iOS, Cortex-a8
223-
`armv7-sony-vita-eabihf` | ? | | ARM Cortex-A9 Sony PlayStation Vita (Requires VITASDK toolchain)
223+
[`armv7-sony-vita-eabihf`](platform-support/armv7-sony-vita-eabihf.md) | ? | | ARM Cortex-A9 Sony PlayStation Vita (requires VITASDK toolchain)
224+
[`armv7-sony-vita-newlibeabihf`](platform-support/armv7-sony-vita-eabihf.md) | ? | | ARM Cortex-A9 Sony PlayStation Vita (Newlib version, requires VITASDK toolchain)
224225
`armv7-unknown-linux-uclibceabihf` | ✓ | ? | ARMv7 Linux uClibc
225226
`armv7-unknown-freebsd` | ✓ | ✓ | ARMv7 FreeBSD
226227
`armv7-unknown-netbsd-eabihf` | ✓ | ✓ |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# armv7-sony-vita-eabihf
2+
3+
**Tier: 3**
4+
5+
This tier supports the ARM Cortex A9 processor running on a PlayStation Vita console. There are two variants of this target: `armv7-vita-newlibeabihf` which aims to have support for `std` crate using `newlib` as a bridge. The second option is `armv7-vita-eabihf` whose support for `std` crate does not involve a `libc` implementation, as it uses direct kernel syscalls to implement platform-specific parts.
6+
7+
As a rule of thumb, use the first variant if you want interoperability with existing C code at the expense of having more overhead as it uses the C standard library. If this is not your case and you wish to depend only on rust crates (which I personally recommend doing) go for the second variant.
8+
9+
## Designated Developers
10+
11+
* [@amg98](https://github.com/amg98)
12+
13+
## Requirements
14+
15+
This target is cross compiled, and requires installing [VITASDK](https://vitasdk.org/) toolchain on your system.
16+
17+
## Building
18+
19+
You can build Rust with support for the target by adding it to the `target`
20+
list in `config.toml`:
21+
22+
```toml
23+
[build]
24+
build-stage = 1
25+
target = ["armv7-sony-vita-newlibeabihf"] # Or armv7-sony-vita-eabihf
26+
```
27+
28+
## Cross-compilation
29+
30+
This target can be cross-compiled from `x86_64` on either Windows, MacOS or Linux systems. Other hosts are not supported for cross-compilation.
31+
32+
## Testing
33+
34+
Currently there is no support to run the rustc test suite for this target.
35+
36+
## Building and Running Rust Programs
37+
38+
To test your developed rust programs for PlayStation Vita, first you have to prepare a proper executable for the device using the resulting ELF file you get from compilation step. The needed steps can be automated using tools like `cargo-make`. Use the example below as a template for your project:
39+
40+
```
41+
[env]
42+
TITLE = "Rust Hello World"
43+
TITLEID = "RUST00001"
44+
# At least a "sce_sys" folder should be place there for app metadata (title, icons, description...)
45+
# You can find sample assets for that on $VITASDK/share/gcc-arm-vita-eabi/samples/hello_world/sce_sys/
46+
STATIC_DIR = "static" # Folder where static assets should be placed (sce_sys folder is at $STATIC_DIR/sce_sys)
47+
CARGO_TARGET_DIR = { script = ["echo ${CARGO_TARGET_DIR:=target}"] }
48+
RUST_TARGET_PATH = { script = ["echo $(pwd)"]}
49+
RUST_TARGET = "armv7-sony-vita-eabihf" # or armv7-sony-vita-newlibeabihf
50+
CARGO_OUT_DIR = "${CARGO_TARGET_DIR}/${RUST_TARGET}/release"
51+
52+
[tasks.xbuild]
53+
# This is the command where you get the ELF executable file (e.g. call to cargo build)
54+
55+
[tasks.strip]
56+
description = "Strip the produced ELF executable."
57+
dependencies = ["xbuild"]
58+
command = "arm-vita-eabi-strip"
59+
args = ["-g", '${CARGO_OUT_DIR}/${CARGO_MAKE_CRATE_FS_NAME}.elf']
60+
61+
[tasks.velf]
62+
description = "Build an VELF executable from the obtained ELF file."
63+
dependencies = ["strip"]
64+
command = "vita-elf-create"
65+
args = ['${CARGO_OUT_DIR}/${CARGO_MAKE_CRATE_NAME}.elf', '${CARGO_OUT_DIR}/${CARGO_MAKE_CRATE_NAME}.velf']
66+
67+
[tasks.eboot-bin]
68+
description = "Build an `eboot.bin` file from the obtained VELF file."
69+
dependencies = ["velf"]
70+
command = "vita-make-fself"
71+
args = ["-s", '${CARGO_OUT_DIR}/${CARGO_MAKE_CRATE_NAME}.velf', '${CARGO_OUT_DIR}/eboot.bin']
72+
73+
[tasks.param-sfo]
74+
description = "Build the `param.sfo` manifest using with given TITLE and TITLEID."
75+
command = "vita-mksfoex"
76+
args = ["-s", 'TITLE_ID=${TITLEID}', '${TITLE}', '${CARGO_OUT_DIR}/param.sfo']
77+
78+
[tasks.manifest]
79+
description = "List all static resources into a manifest file."
80+
script = [
81+
'mkdir -p "${CARGO_OUT_DIR}"',
82+
'''
83+
if [ -d "${STATIC_DIR}" ]; then
84+
find "${STATIC_DIR}" -type f > "${CARGO_OUT_DIR}/MANIFEST"
85+
else
86+
touch "${CARGO_OUT_DIR}/MANIFEST"
87+
fi
88+
'''
89+
]
90+
91+
[tasks.vpk]
92+
description = "Build a VPK distribution of the project executable and resources."
93+
dependencies = ["eboot-bin", "param-sfo", "manifest"]
94+
script_runner = "@rust"
95+
script = [
96+
'''
97+
use std::io::BufRead;
98+
use std::fs::File;
99+
100+
fn main() {
101+
102+
let crate_name = env!("CARGO_MAKE_CRATE_NAME");
103+
let static_dir = env!("STATIC_DIR");
104+
let out_dir = std::path::PathBuf::from(env!("CARGO_OUT_DIR"));
105+
106+
let mut cmd = ::std::process::Command::new("vita-pack-vpk");
107+
cmd.arg("-s").arg(out_dir.join("param.sfo"));
108+
cmd.arg("-b").arg(out_dir.join("eboot.bin"));
109+
110+
// Add files from MANIFEST
111+
if let Ok(file) = File::open(out_dir.join("MANIFEST")) {
112+
let mut reader = ::std::io::BufReader::new(file);
113+
let mut lines = reader.lines();
114+
while let Some(Ok(line)) = lines.next() {
115+
let p1 = ::std::path::PathBuf::from(line); // path on FS
116+
let p2 = p1.strip_prefix(static_dir).unwrap(); // path in VPK
117+
cmd.arg("--add").arg(format!("{}={}", p1.display(), p2.display()));
118+
}
119+
}
120+
121+
cmd.arg(out_dir.join(format!("{}.vpk", crate_name)))
122+
.output()
123+
.expect("command failed.");
124+
}
125+
'''
126+
]
127+
```
128+
129+
After running the above script, you should be able to get a *.vpk file in the same folder your *.elf executable resides. Now you can pick it and install it on your own PlayStation Vita using, for example, [VitaShell](https://github.com/TheOfficialFloW/VitaShell/releases) or you can use an emulator. For the time being, the most mature emulator for PlayStation Vita is [Vita3K](https://vita3k.org/), although I personally recommend testing your programs in real hardware, as the emulator is quite experimental.

0 commit comments

Comments
 (0)