Rollup merge of #110638 - nikarh:vita, r=Mark-Simulacrum

STD support for PSVita

This PR adds std support for `armv7-sony-vita-newlibeabihf` target.

The work here is fairly similar to #95897, just for a different target platform.

This depends on the following pull requests:

rust-lang/backtrace-rs#523
rust-lang/libc#3209
This commit is contained in:
Yuki Okushi 2023-05-08 19:41:49 +09:00 committed by GitHub
commit 4df84a1e4e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 322 additions and 41 deletions

View file

@ -1938,9 +1938,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
version = "0.2.142"
version = "0.2.143"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317"
checksum = "edc207893e85c5d6be840e969b496b53d94cec8be2d501b214f50daa97fa8024"
dependencies = [
"rustc-std-workspace-core",
]

View file

@ -9,7 +9,7 @@ pub fn target() -> Target {
let pre_link_args = TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-Wl,-q"]);
Target {
llvm_target: "armv7a-vita-newlibeabihf".into(),
llvm_target: "armv7a-vita-eabihf".into(),
pointer_width: 32,
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
arch: "arm".into(),

@ -1 +1 @@
Subproject commit 8ad84ca5ad88ade697637387e7cb4d7c3cf4bde8
Subproject commit 4245978ca8169c40c088ff733825e4527f7b914c

View file

@ -15,7 +15,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
panic_unwind = { path = "../panic_unwind", optional = true }
panic_abort = { path = "../panic_abort" }
core = { path = "../core" }
libc = { version = "0.2.142", default-features = false, features = ['rustc-dep-of-std'] }
libc = { version = "0.2.143", default-features = false, features = ['rustc-dep-of-std'] }
compiler_builtins = { version = "0.1.91" }
profiler_builtins = { path = "../profiler_builtins", optional = true }
unwind = { path = "../unwind" }

View file

@ -34,6 +34,7 @@ fn main() {
|| target.contains("espidf")
|| target.contains("solid")
|| target.contains("nintendo-3ds")
|| target.contains("vita")
|| target.contains("nto")
{
// These platforms don't have any special requirements.

View file

@ -137,6 +137,8 @@ pub mod windows {}
pub mod solaris;
#[cfg(target_os = "solid_asp3")]
pub mod solid;
#[cfg(target_os = "vita")]
pub mod vita;
#[cfg(target_os = "vxworks")]
pub mod vxworks;
#[cfg(target_os = "watchos")]

View file

@ -73,6 +73,8 @@ mod platform {
pub use crate::os::redox::*;
#[cfg(target_os = "solaris")]
pub use crate::os::solaris::*;
#[cfg(target_os = "vita")]
pub use crate::os::vita::*;
#[cfg(target_os = "vxworks")]
pub use crate::os::vxworks::*;
#[cfg(target_os = "watchos")]

View file

@ -0,0 +1,95 @@
#![stable(feature = "metadata_ext", since = "1.1.0")]
use crate::fs::Metadata;
use crate::sys_common::AsInner;
/// OS-specific extensions to [`fs::Metadata`].
///
/// [`fs::Metadata`]: crate::fs::Metadata
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub trait MetadataExt {
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_dev(&self) -> u64;
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_ino(&self) -> u64;
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_mode(&self) -> u32;
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_nlink(&self) -> u64;
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_uid(&self) -> u32;
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_gid(&self) -> u32;
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_rdev(&self) -> u64;
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_size(&self) -> u64;
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_atime(&self) -> i64;
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_atime_nsec(&self) -> i64;
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_mtime(&self) -> i64;
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_mtime_nsec(&self) -> i64;
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_ctime(&self) -> i64;
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_ctime_nsec(&self) -> i64;
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_blksize(&self) -> u64;
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_blocks(&self) -> u64;
}
#[stable(feature = "metadata_ext", since = "1.1.0")]
impl MetadataExt for Metadata {
fn st_dev(&self) -> u64 {
self.as_inner().as_inner().st_dev as u64
}
fn st_ino(&self) -> u64 {
self.as_inner().as_inner().st_ino as u64
}
fn st_mode(&self) -> u32 {
self.as_inner().as_inner().st_mode as u32
}
fn st_nlink(&self) -> u64 {
self.as_inner().as_inner().st_nlink as u64
}
fn st_uid(&self) -> u32 {
self.as_inner().as_inner().st_uid as u32
}
fn st_gid(&self) -> u32 {
self.as_inner().as_inner().st_gid as u32
}
fn st_rdev(&self) -> u64 {
self.as_inner().as_inner().st_rdev as u64
}
fn st_size(&self) -> u64 {
self.as_inner().as_inner().st_size as u64
}
fn st_atime(&self) -> i64 {
self.as_inner().as_inner().st_atime as i64
}
fn st_atime_nsec(&self) -> i64 {
0
}
fn st_mtime(&self) -> i64 {
self.as_inner().as_inner().st_mtime as i64
}
fn st_mtime_nsec(&self) -> i64 {
0
}
fn st_ctime(&self) -> i64 {
self.as_inner().as_inner().st_ctime as i64
}
fn st_ctime_nsec(&self) -> i64 {
0
}
fn st_blksize(&self) -> u64 {
self.as_inner().as_inner().st_blksize as u64
}
fn st_blocks(&self) -> u64 {
self.as_inner().as_inner().st_blocks as u64
}
}

View file

@ -0,0 +1,6 @@
//! Definitions for vita
#![stable(feature = "raw_ext", since = "1.1.0")]
pub mod fs;
pub(crate) mod raw;

View file

@ -0,0 +1,70 @@
//! vita raw type definitions
#![stable(feature = "raw_ext", since = "1.1.0")]
#![deprecated(
since = "1.8.0",
note = "these type aliases are no longer supported by \
the standard library, the `libc` crate on \
crates.io should be used instead for the correct \
definitions"
)]
#![allow(deprecated)]
use crate::os::raw::c_long;
use crate::os::unix::raw::{gid_t, uid_t};
#[stable(feature = "pthread_t", since = "1.8.0")]
pub type pthread_t = libc::pthread_t;
#[stable(feature = "raw_ext", since = "1.1.0")]
pub type blkcnt_t = libc::blkcnt_t;
#[stable(feature = "raw_ext", since = "1.1.0")]
pub type blksize_t = libc::blksize_t;
#[stable(feature = "raw_ext", since = "1.1.0")]
pub type dev_t = libc::dev_t;
#[stable(feature = "raw_ext", since = "1.1.0")]
pub type ino_t = libc::ino_t;
#[stable(feature = "raw_ext", since = "1.1.0")]
pub type mode_t = libc::mode_t;
#[stable(feature = "raw_ext", since = "1.1.0")]
pub type nlink_t = libc::nlink_t;
#[stable(feature = "raw_ext", since = "1.1.0")]
pub type off_t = libc::off_t;
#[stable(feature = "raw_ext", since = "1.1.0")]
pub type time_t = libc::time_t;
#[repr(C)]
#[derive(Clone)]
#[stable(feature = "raw_ext", since = "1.1.0")]
pub struct stat {
#[stable(feature = "raw_ext", since = "1.1.0")]
pub st_dev: dev_t,
#[stable(feature = "raw_ext", since = "1.1.0")]
pub st_ino: ino_t,
#[stable(feature = "raw_ext", since = "1.1.0")]
pub st_mode: mode_t,
#[stable(feature = "raw_ext", since = "1.1.0")]
pub st_nlink: nlink_t,
#[stable(feature = "raw_ext", since = "1.1.0")]
pub st_uid: uid_t,
#[stable(feature = "raw_ext", since = "1.1.0")]
pub st_gid: gid_t,
#[stable(feature = "raw_ext", since = "1.1.0")]
pub st_rdev: dev_t,
#[stable(feature = "raw_ext", since = "1.1.0")]
pub st_size: off_t,
#[stable(feature = "raw_ext", since = "1.1.0")]
pub st_atime: time_t,
#[stable(feature = "raw_ext", since = "1.1.0")]
pub st_mtime: time_t,
#[stable(feature = "raw_ext", since = "1.1.0")]
pub st_ctime: time_t,
#[stable(feature = "raw_ext", since = "1.1.0")]
pub st_blksize: blksize_t,
#[stable(feature = "raw_ext", since = "1.1.0")]
pub st_blocks: blkcnt_t,
#[stable(feature = "raw_ext", since = "1.1.0")]
pub st_spare4: [c_long; 2usize],
}

View file

@ -59,7 +59,8 @@ unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut
target_os = "redox",
target_os = "solaris",
target_os = "espidf",
target_os = "horizon"
target_os = "horizon",
target_os = "vita",
))] {
#[inline]
unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {

View file

@ -265,7 +265,7 @@ pub fn args() -> Args {
}
}
#[cfg(target_os = "espidf")]
#[cfg(any(target_os = "espidf", target_os = "vita"))]
mod imp {
use super::Args;

View file

@ -141,6 +141,17 @@ pub mod os {
pub const EXE_EXTENSION: &str = "elf";
}
#[cfg(target_os = "vita")]
pub mod os {
pub const FAMILY: &str = "unix";
pub const OS: &str = "vita";
pub const DLL_PREFIX: &str = "lib";
pub const DLL_SUFFIX: &str = ".so";
pub const DLL_EXTENSION: &str = "so";
pub const EXE_SUFFIX: &str = ".elf";
pub const EXE_EXTENSION: &str = "elf";
}
#[cfg(all(target_os = "emscripten", target_arch = "asmjs"))]
pub mod os {
pub const FAMILY: &str = "unix";

View file

@ -75,6 +75,7 @@ const fn max_iov() -> usize {
target_os = "nto",
target_os = "openbsd",
target_os = "horizon",
target_os = "vita",
target_os = "watchos",
)))]
const fn max_iov() -> usize {
@ -93,7 +94,7 @@ pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
Ok(ret as usize)
}
#[cfg(not(any(target_os = "espidf", target_os = "horizon")))]
#[cfg(not(any(target_os = "espidf", target_os = "horizon", target_os = "vita")))]
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
let ret = cvt(unsafe {
libc::readv(
@ -105,14 +106,14 @@ pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
Ok(ret as usize)
}
#[cfg(any(target_os = "espidf", target_os = "horizon"))]
#[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita"))]
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
io::default_read_vectored(|b| self.read(b), bufs)
}
#[inline]
pub fn is_read_vectored(&self) -> bool {
cfg!(not(any(target_os = "espidf", target_os = "horizon")))
cfg!(not(any(target_os = "espidf", target_os = "horizon", target_os = "vita")))
}
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
@ -253,7 +254,7 @@ pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
Ok(ret as usize)
}
#[cfg(not(any(target_os = "espidf", target_os = "horizon")))]
#[cfg(not(any(target_os = "espidf", target_os = "horizon", target_os = "vita")))]
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
let ret = cvt(unsafe {
libc::writev(
@ -265,14 +266,14 @@ pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
Ok(ret as usize)
}
#[cfg(any(target_os = "espidf", target_os = "horizon"))]
#[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita"))]
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
io::default_write_vectored(|b| self.write(b), bufs)
}
#[inline]
pub fn is_write_vectored(&self) -> bool {
cfg!(not(any(target_os = "espidf", target_os = "horizon")))
cfg!(not(any(target_os = "espidf", target_os = "horizon", target_os = "vita")))
}
pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {

View file

@ -447,7 +447,12 @@ pub fn created(&self) -> io::Result<SystemTime> {
#[cfg(not(any(target_os = "netbsd", target_os = "nto")))]
impl FileAttr {
#[cfg(not(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon")))]
#[cfg(not(any(
target_os = "vxworks",
target_os = "espidf",
target_os = "horizon",
target_os = "vita"
)))]
pub fn modified(&self) -> io::Result<SystemTime> {
#[cfg(target_pointer_width = "32")]
cfg_has_statx! {
@ -459,7 +464,7 @@ pub fn modified(&self) -> io::Result<SystemTime> {
Ok(SystemTime::new(self.stat.st_mtime as i64, self.stat.st_mtime_nsec as i64))
}
#[cfg(any(target_os = "vxworks", target_os = "espidf"))]
#[cfg(any(target_os = "vxworks", target_os = "espidf", target_os = "vita"))]
pub fn modified(&self) -> io::Result<SystemTime> {
Ok(SystemTime::new(self.stat.st_mtime as i64, 0))
}
@ -469,7 +474,12 @@ pub fn modified(&self) -> io::Result<SystemTime> {
Ok(SystemTime::from(self.stat.st_mtim))
}
#[cfg(not(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon")))]
#[cfg(not(any(
target_os = "vxworks",
target_os = "espidf",
target_os = "horizon",
target_os = "vita"
)))]
pub fn accessed(&self) -> io::Result<SystemTime> {
#[cfg(target_pointer_width = "32")]
cfg_has_statx! {
@ -481,7 +491,7 @@ pub fn accessed(&self) -> io::Result<SystemTime> {
Ok(SystemTime::new(self.stat.st_atime as i64, self.stat.st_atime_nsec as i64))
}
#[cfg(any(target_os = "vxworks", target_os = "espidf"))]
#[cfg(any(target_os = "vxworks", target_os = "espidf", target_os = "vita"))]
pub fn accessed(&self) -> io::Result<SystemTime> {
Ok(SystemTime::new(self.stat.st_atime as i64, 0))
}
@ -866,6 +876,7 @@ pub fn file_type(&self) -> io::Result<FileType> {
target_os = "vxworks",
target_os = "espidf",
target_os = "horizon",
target_os = "vita",
target_os = "nto",
))]
pub fn ino(&self) -> u64 {

View file

@ -92,6 +92,7 @@ unsafe fn sanitize_standard_fds() {
target_os = "redox",
target_os = "l4re",
target_os = "horizon",
target_os = "vita",
)))]
'poll: {
use crate::sys::os::errno;
@ -140,6 +141,7 @@ unsafe fn sanitize_standard_fds() {
target_os = "vxworks",
target_os = "l4re",
target_os = "horizon",
target_os = "vita",
)))]
{
use crate::sys::os::errno;
@ -162,7 +164,12 @@ unsafe fn sanitize_standard_fds() {
}
unsafe fn reset_sigpipe(#[allow(unused_variables)] sigpipe: u8) {
#[cfg(not(any(target_os = "emscripten", target_os = "fuchsia", target_os = "horizon")))]
#[cfg(not(any(
target_os = "emscripten",
target_os = "fuchsia",
target_os = "horizon",
target_os = "vita"
)))]
{
// We don't want to add this as a public type to std, nor do we
// want to `include!` a file from the compiler (which would break
@ -199,7 +206,8 @@ mod sigpipe {
target_os = "espidf",
target_os = "emscripten",
target_os = "fuchsia",
target_os = "horizon"
target_os = "horizon",
target_os = "vita"
)))]
static UNIX_SIGPIPE_ATTR_SPECIFIED: crate::sync::atomic::AtomicBool =
crate::sync::atomic::AtomicBool::new(false);
@ -208,7 +216,8 @@ mod sigpipe {
target_os = "espidf",
target_os = "emscripten",
target_os = "fuchsia",
target_os = "horizon"
target_os = "horizon",
target_os = "vita",
)))]
pub(crate) fn unix_sigpipe_attr_specified() -> bool {
UNIX_SIGPIPE_ATTR_SPECIFIED.load(crate::sync::atomic::Ordering::Relaxed)
@ -402,7 +411,7 @@ pub fn abort_internal() -> ! {
}
}
#[cfg(any(target_os = "espidf", target_os = "horizon"))]
#[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita"))]
mod unsupported {
use crate::io;

View file

@ -460,7 +460,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
path.canonicalize()
}
#[cfg(any(target_os = "espidf", target_os = "horizon"))]
#[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita"))]
pub fn current_exe() -> io::Result<PathBuf> {
super::unsupported::unsupported()
}
@ -614,7 +614,8 @@ pub fn home_dir() -> Option<PathBuf> {
target_os = "redox",
target_os = "vxworks",
target_os = "espidf",
target_os = "horizon"
target_os = "horizon",
target_os = "vita",
))]
unsafe fn fallback() -> Option<OsString> {
None
@ -627,7 +628,8 @@ unsafe fn fallback() -> Option<OsString> {
target_os = "redox",
target_os = "vxworks",
target_os = "espidf",
target_os = "horizon"
target_os = "horizon",
target_os = "vita",
)))]
unsafe fn fallback() -> Option<OsString> {
let amt = match libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) {

View file

@ -14,7 +14,7 @@
} else if #[cfg(target_os = "vxworks")] {
#[path = "process_vxworks.rs"]
mod process_inner;
} else if #[cfg(any(target_os = "espidf", target_os = "horizon"))] {
} else if #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita"))] {
#[path = "process_unsupported.rs"]
mod process_inner;
} else {

View file

@ -21,7 +21,8 @@ pub fn hashmap_random_keys() -> (u64, u64) {
not(target_os = "fuchsia"),
not(target_os = "redox"),
not(target_os = "vxworks"),
not(target_os = "emscripten")
not(target_os = "emscripten"),
not(target_os = "vita"),
))]
mod imp {
use crate::fs::File;
@ -175,7 +176,7 @@ pub fn fill_bytes(v: &mut [u8]) {
}
}
#[cfg(any(target_os = "openbsd", target_os = "emscripten"))]
#[cfg(any(target_os = "openbsd", target_os = "emscripten", target_os = "vita"))]
mod imp {
use crate::sys::os::errno;

View file

@ -1,26 +1,40 @@
# armv7-sony-vita-eabihf
# armv7-sony-vita-newlibeabihf
**Tier: 3**
This tier supports the ARM Cortex A9 processor running on a PlayStation Vita console. `armv7-vita-newlibeabihf` aims to have support for `std` crate using `newlib` as a bridge.
Rust support for this target is not affiliated with Sony, and is not derived
from nor used with any official Sony SDK.
## Designated Developers
* [@amg98](https://github.com/amg98)
* [@nikarh](https://github.com/nikarh)
## Requirements
This target is cross compiled, and requires installing [VITASDK](https://vitasdk.org/) toolchain on your system.
This target is cross-compiled, and requires installing [VITASDK](https://vitasdk.org/) toolchain on your system. Dynamic linking is not supported.
`#![no_std]` crates can be built using `build-std` to build `core`, and optionally
`alloc`, and `panic_abort`.
`std` is partially supported, but mostly works. Some APIs are unimplemented
and will simply return an error, such as `std::process`. An allocator is provided
by default.
In order to support some APIs, binaries must be linked against `libc` written
for the target, using a linker for the target. These are provided by the
VITASDK toolchain.
This target generates binaries in the ELF format.
## Building
You can build Rust with support for the target by adding it to the `target`
list in `config.toml`:
Rust does not ship pre-compiled artifacts for this target. You can use `build-std` flag to build binaries with `std`:
```toml
[build]
build-stage = 1
target = ["armv7-sony-vita-newlibeabihf"]
```sh
cargo build -Z build-std=std,panic_abort --target=armv7-sony-vita-newlibeabihf --release
```
## Cross-compilation
@ -33,26 +47,81 @@ Currently there is no support to run the rustc test suite for this target.
## Building and Running Rust Programs
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:
`std` support for this target relies on newlib. In order to work, newlib must be initialized correctly. The easiest way to achieve this with VITASDK newlib implementation is by compiling your program as a staticlib with and exposing your main function from rust to `_init` function in `crt0`.
Add this to your `Cargo.toml`:
```toml
[lib]
crate-type = ["staticlib"]
[profile.release]
panic = 'abort'
lto = true
opt-level = 3
```
Your entrypoint should look roughly like this, `src/lib.rs`:
```rust,ignore,no_run
#[used]
#[export_name = "_newlib_heap_size_user"]
pub static _NEWLIB_HEAP_SIZE_USER: u32 = 100 * 1024 * 1024; // Default heap size is only 32mb, increase it to something suitable for your application
#[no_mangle]
pub extern "C" fn main() {
println!("Hello, world!");
}
```
To test your developed rust programs on PlayStation Vita, first you must correctly link and package your rust staticlib. These steps can be preformed using tools available in VITASDK, and can be automated using tools like `cargo-make`.
First, set up environment variables for `VITASDK`, and it's binaries:
```sh
export VITASDK=/opt/vitasdk
export PATH=$PATH:$VITASDK/bin
```
Use the example below as a template for your project:
```toml
[env]
TITLE = "Rust Hello World"
TITLEID = "RUST00001"
# Add other libs required by your project here
LINKER_LIBS = "-lpthread -lm -lmathneon"
# At least a "sce_sys" folder should be place there for app metadata (title, icons, description...)
# You can find sample assets for that on $VITASDK/share/gcc-arm-vita-eabi/samples/hello_world/sce_sys/
STATIC_DIR = "static" # Folder where static assets should be placed (sce_sys folder is at $STATIC_DIR/sce_sys)
CARGO_TARGET_DIR = { script = ["echo ${CARGO_TARGET_DIR:=target}"] }
RUST_TARGET_PATH = { script = ["echo $(pwd)"]}
RUST_TARGET = "armv7-sony-vita-newlibeabihf"
CARGO_OUT_DIR = "${CARGO_TARGET_DIR}/${RUST_TARGET}/release"
[tasks.xbuild]
# This is the command where you get the ELF executable file (e.g. call to cargo build)
TARGET_LINKER = "arm-vita-eabi-gcc"
TARGET_LINKER_FLAGS = "-Wl,-q"
[tasks.build]
description = "Build the project using `cargo` as a static lib."
command = "cargo"
args = ["build", "-Z", "build-std=std,panic_abort", "--target=armv7-sony-vita-newlibeabihf", "--release"]
[tasks.link]
description = "Build an ELF executable using the `vitasdk` linker."
dependencies = ["build"]
script = [
"""
${TARGET_LINKER} ${TARGET_LINKER_FLAGS} \
-L"${CARGO_OUT_DIR}" \
-l"${CARGO_MAKE_CRATE_FS_NAME}" \
${LINKER_LIBS} \
-o"${CARGO_OUT_DIR}/${CARGO_MAKE_CRATE_NAME}.elf"
"""
]
[tasks.strip]
description = "Strip the produced ELF executable."
dependencies = ["xbuild"]
dependencies = ["link"]
command = "arm-vita-eabi-strip"
args = ["-g", '${CARGO_OUT_DIR}/${CARGO_MAKE_CRATE_FS_NAME}.elf']
@ -124,4 +193,4 @@ script = [
]
```
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.
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, or you can use an [Vita3K](https://vita3k.org/) emulator.