Skip to content

Commit

Permalink
Automatically update Cargo.toml features when updating bindings (#24)
Browse files Browse the repository at this point in the history
  • Loading branch information
pheki authored Feb 25, 2024
1 parent e357f6e commit defe3aa
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 57 deletions.
6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ log-build = ["dep:env_logger"]

vitasdk-utils = []

# Stub libraries
# Automatically generated by build-util:
all-stubs = [
"SceAVConfig_stub",
"SceAppMgrForDriver_stub",
Expand Down Expand Up @@ -371,10 +371,12 @@ SceLibDbg_stub = []
SceLibG729_stub = []
SceLibJson_stub = []
SceLibKernel_stub = []
SceLibMonoBridge_stub = []
SceLibMono_stub = []
SceLibMp4Recorder_stub = []
SceLibMtp_stub = []
SceLibXml_stub = []
SceLibc_stub = []
SceLiveArea_stub = []
SceLocationExtension_stub = []
SceLocation_stub = []
Expand Down Expand Up @@ -441,6 +443,7 @@ SceRazorHud_stub = []
SceRegMgrForDriver_stub = []
SceRegMgrServiceForDriver_stub = []
SceRegistryMgr_stub = []
SceRtabi_stub = []
SceRtcForDriver_stub = []
SceRtc_stub = []
SceRudp_stub = []
Expand Down Expand Up @@ -471,6 +474,7 @@ SceSqlite_stub = []
SceSsl_stub = []
SceStdio_0931_stub = []
SceSulpha_stub = []
SceSysclibForDriver_stub = []
SceSysconForDriver_stub = []
SceSysmemForDriver_0990_stub = []
SceSysmemForDriver_stub = []
Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ Example: to find which stub is required to use `sceDisplaySetFrameBuf`, search
for it on docs.rs. You'll find `Available on crate feature SceDisplay_stub only.`
there, which means that you'll need to enable `SceDisplay_stub` to use it.

> ℹ️ **NOTE**: There are a few (currently 4) conflicting stubs, which are stubs
that define symbols that are also defined by compiler builtins or std. A list of
those features can be found [here](https://github.com/vita-rust/vitasdk-sys/blob/main/build-util/src/vita_headers_db.rs#L10).

### `vitasdk-utils`

This feature just enables some functions provided by vitasdk. Just like the
Expand Down Expand Up @@ -72,8 +76,6 @@ $ git pull
$ cd ..
```

Run `cargo run -p vitasdk-sys-build-util -- stub-libs --as-features --all-stubs-feature` and replace stub lib features in vitasdk-sys Cargo.toml with outputted ones.

Then run `cargo run -p vitasdk-sys-build-util -- bindgen`

> ℹ️ **NOTE**: The LLVM version currently used in CI is 16. Occasionally there may be slight differences in generated bindings depending on your LLVM version.
Expand Down
14 changes: 12 additions & 2 deletions build-util/src/bindgen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use std::{env, fs, io, path::Path, process};
use quote::ToTokens;
use syn::{self, visit_mut::VisitMut};

use crate::visitors::{Link, Sort};
use crate::{
visitors::{Link, Sort},
vita_headers_db::VitaDb,
};

pub fn generate(
vita_headers_include: &Path,
Expand All @@ -22,7 +25,14 @@ pub fn generate(
"Loading vita-headers metadata yaml files from \"{}\"",
db.to_string_lossy()
);
let link = Link::load(db, vitasdk_sys_manifest);
let db = VitaDb::load(db);
let link = Link::load(&db);

if is_build_rs {
db.check_missing_manifest_features(vitasdk_sys_manifest);
} else {
db.update_manifest_features(vitasdk_sys_manifest);
}

link.visit(&mut bindings);

Expand Down
35 changes: 3 additions & 32 deletions build-util/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,6 @@ Options:
-c, --conflicting Print only stub libs with conflicting symbols
--with-conflicting Include stub libs with conflicting symbols
--missing-features Print only undefined vitasdk-sys stub features
--as-features Print stub libs as cargo features
--all-stubs-feature Prepend `all-stubs` feature if `--as-features` specified
--missing-libs Print only stub libs which do not exist in `$VITASDK/arm-vita-eabi/lib`
--fail-if-any Fail if any stub lib is printed
"
Expand All @@ -99,8 +97,6 @@ Options:
Conflicting,
WithConflicting,
MissingFeatures,
AsFeatures,
AllStubsFeature,
MissingLibs,
FailIfAny,
}
Expand All @@ -119,8 +115,6 @@ Options:
"-c" | "--conflicting" => Ok(Flag::Conflicting),
"--with-conflicting" => Ok(Flag::WithConflicting),
"--missing-features" => Ok(Flag::MissingFeatures),
"--as-features" => Ok(Flag::AsFeatures),
"--all-stubs-feature" => Ok(Flag::AllStubsFeature),
"--missing-libs" => Ok(Flag::MissingLibs),
"--fail-if-any" => Ok(Flag::FailIfAny),
_ => Err(ParseFlagError),
Expand All @@ -135,7 +129,6 @@ Options:
.collect::<Result<HashSet<Flag>, ParseFlagError>>()
.ok()
.filter(|ops| !ops.contains(&Flag::Kernel) || !ops.contains(&Flag::User))
.filter(|ops| ops.contains(&Flag::AsFeatures) || !ops.contains(&Flag::AllStubsFeature))
else {
print_help();
return ExitCode::FAILURE;
Expand Down Expand Up @@ -183,31 +176,9 @@ Options:
use std::io::{self, Write};

let mut stdout = io::stdout().lock();
if options.contains(&Flag::AsFeatures) {
if options.contains(&Flag::AllStubsFeature) {
struct DisplayAsSequence<T>(T);

impl<T> std::fmt::Debug for DisplayAsSequence<T>
where
T: IntoIterator + Copy,
T::Item: std::fmt::Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// Strings are valid feature names, so debug representation only adds quotation marks
f.debug_list().entries(self.0).finish()
}
}

writeln!(stdout, "all-stubs = {:#?}", DisplayAsSequence(&stub_libs)).unwrap();
}
stub_libs
.iter()
.for_each(|stub_lib| writeln!(stdout, "{stub_lib} = []").unwrap());
} else {
stub_libs
.iter()
.for_each(|stub_lib| writeln!(stdout, "{stub_lib}").unwrap());
}
stub_libs
.iter()
.for_each(|stub_lib| writeln!(stdout, "{stub_lib}").unwrap());
}

if !stub_libs.is_empty() && options.contains(&Flag::FailIfAny) {
Expand Down
20 changes: 2 additions & 18 deletions build-util/src/visitors.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::{
collections::{BTreeMap, BTreeSet},
mem,
path::Path,
rc::Rc,
};

Expand All @@ -11,7 +10,7 @@ use syn::{
MacroDelimiter, Meta, MetaList,
};

use crate::vita_headers_db::{missing_features_filter, stub_lib_name, VitaDb};
use crate::vita_headers_db::{stub_lib_name, VitaDb};

type FeatureSet = BTreeSet<Rc<str>>;

Expand All @@ -32,7 +31,7 @@ pub struct Link {
}

impl Link {
pub fn load(db: &Path, vitasdk_sys_manifest: &Path) -> Self {
pub fn load(db: &VitaDb) -> Self {
let mut link = Link {
function: DEFINED_ELSEWHERE_FUNCTIONS
.into_iter()
Expand All @@ -45,10 +44,6 @@ impl Link {
stub_libs: BTreeSet::new(),
};

let mut db = VitaDb::load(db);

let mut predicate = missing_features_filter(vitasdk_sys_manifest);

for imports in db.imports_by_firmware.values() {
for (mod_name, mod_data) in &imports.modules {
for (lib_name, lib) in &mod_data.libraries {
Expand Down Expand Up @@ -85,20 +80,9 @@ impl Link {
}
}

let conflicting_db = db.split_conflicting();
conflicting_db.stub_lib_names().for_each(|lib_stub| {
link.stub_libs.remove(lib_stub.as_str());
});

if db.stub_lib_names().any(|s| predicate(&s)) {
panic!("Missing features in vitasdk-sys `Cargo.toml`. Please run `cargo run -p vitasdk-sys-build-util -- stub-libs --as-features --all-stubs-feature` and replace stub lib features in vitasdk-sys Cargo.toml with outputed ones.")
}

link
}
}

impl Link {
pub fn visit(&self, i: &mut syn::File) {
let mut items_by_features: BTreeMap<FeatureSet, Vec<ForeignItem>> = self
.stub_libs
Expand Down
71 changes: 69 additions & 2 deletions build-util/src/vita_headers_db.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::{
collections::{btree_map, BTreeMap, HashSet},
fmt, fs, io, mem,
collections::{btree_map, BTreeMap, BTreeSet, HashSet},
fmt, fs,
io::{self, Read, Seek, Write},
mem,
path::{Path, PathBuf},
};

Expand Down Expand Up @@ -102,6 +104,51 @@ impl VitaDb {
}
}
}

pub fn update_manifest_features(&self, vitasdk_sys_manifest: &Path) {
const FEATURES_MARKER: &str = "# Automatically generated by build-util:";

let mut manifest = fs::OpenOptions::new()
.read(true)
.write(true)
.open(vitasdk_sys_manifest)
.expect("unable to open manifest");

let marker_position = {
let mut manifest_string = String::new();
manifest
.read_to_string(&mut manifest_string)
.expect("unable to read manifest");

manifest_string
.find(FEATURES_MARKER)
.expect("features marker not found in manifest")
};

manifest
.seek(io::SeekFrom::Start(u64::try_from(marker_position).unwrap()))
.expect("unable to seek manifest");

writeln!(manifest, "{}", FEATURES_MARKER).expect("unable to write to manifest");

let stub_libs: BTreeSet<_> = self.stub_lib_names().collect();

write_all_stubs_feature(&mut manifest, &stub_libs).expect("unable to write to manifest");
write_stub_features(&mut manifest, &stub_libs).expect("unable to write to manifest");

let stream_position = manifest
.stream_position()
.expect("unable to get current stream position");
manifest
.set_len(stream_position)
.expect("unable update manifest length");
}

pub fn check_missing_manifest_features(&self, vitasdk_sys_manifest: &Path) {
let predicate = missing_features_filter(vitasdk_sys_manifest);
let missing_features: Vec<_> = self.stub_lib_names().filter(predicate).collect();
log::warn!("Missing features: {missing_features:#?}\nIf you need any of those features, please open an issue so we can update vitasdk-sys.");
}
}

pub fn missing_features_filter(vitasdk_sys_manifest: &Path) -> impl FnMut(&String) -> bool {
Expand Down Expand Up @@ -319,3 +366,23 @@ pub(crate) fn stub_lib_name<'a>(
}
}
}

fn write_all_stubs_feature(sink: &mut dyn Write, stub_libs: &BTreeSet<String>) -> io::Result<()> {
writeln!(sink, "all-stubs = [")?;

for stub_lib in stub_libs
.iter()
.filter(|stub_lib| !CONFLICTING_STUB_LIBS.contains(&stub_lib.as_str()))
{
writeln!(sink, " \"{stub_lib}\",")?;
}

writeln!(sink, "]")
}

fn write_stub_features(sink: &mut dyn Write, stub_libs: &BTreeSet<String>) -> io::Result<()> {
for stub_lib in stub_libs {
writeln!(sink, "{stub_lib} = []")?;
}
Ok(())
}
6 changes: 6 additions & 0 deletions src/bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14085,6 +14085,9 @@ extern "C" {}
#[link(name = "SceLedForDriver_stub", kind = "static")]
#[cfg(feature = "SceLedForDriver_stub")]
extern "C" {}
#[link(name = "SceLibc_stub", kind = "static")]
#[cfg(feature = "SceLibc_stub")]
extern "C" {}
#[cfg(any(feature = "SceLibc_stub", feature = "SceSysclibForDriver_stub"))]
extern "C" {
pub fn memchr(
Expand Down Expand Up @@ -17096,6 +17099,9 @@ extern "C" {
#[link(name = "SceRegMgrServiceForDriver_stub", kind = "static")]
#[cfg(feature = "SceRegMgrServiceForDriver_stub")]
extern "C" {}
#[link(name = "SceRtabi_stub", kind = "static")]
#[cfg(feature = "SceRtabi_stub")]
extern "C" {}
#[link(name = "SceRtcForDriver_stub", kind = "static")]
#[cfg(feature = "SceRtcForDriver_stub")]
extern "C" {
Expand Down

0 comments on commit defe3aa

Please sign in to comment.