Skip to content

Implement glib_build_tools::compile_schemas #1721

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 76 additions & 1 deletion glib-build-tools/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@

#![doc = include_str!("../README.md")]

use std::{env, path::Path, process::Command};
use gio::glib;
use std::{
env,
path::{Path, PathBuf},
process::Command,
};

// rustdoc-stripper-ignore-next
/// Call to run `glib-compile-resources` to generate compiled gresources to embed
Expand Down Expand Up @@ -57,3 +62,73 @@ pub fn compile_resources<P: AsRef<Path>>(source_dirs: &[P], gresource: &str, tar
println!("cargo:rerun-if-changed={dep}");
}
}

// rustdoc-stripper-ignore-next
/// Call to run `glib-compile-schemas` to generate compiled gschemas from `.gschema.xml` schemas
/// files from specified directories and store `gschemas.compiled` into `glib-2.0` schema cache
/// directory.
///
/// If `target_dir` is `None`, the default schema cache directory is used:
/// - Unix: `$HOME/.local/share/glib-2.0/schemas/`
/// - Windows: `C:/ProgramData/glib-2.0/schemas/`
///
/// ```no_run
/// glib_build_tools::compile_schemas(
/// &["schemas"],
/// None
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please document the default target_dir.

/// );
/// ```
pub fn compile_schemas(schemas_dir: &[&str], target_dir: Option<&str>) {
let target_dir = match target_dir {
Some(base) => PathBuf::from(base),
None => {
let prefix = if cfg!(windows) {
PathBuf::from("C:/ProgramData")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why a hardcoded path on windows?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked everywhere, but I couldn’t find any information on where the target directory is on Windows. The paths are based on the gtk-rs.org documentation.

https://gtk-rs.org/gtk4-rs/stable/latest/book/settings.html
https://man.archlinux.org/man/core/glib2/glib-compile-schemas.1.en

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should also be g_get_user_data_dir() on Windows too or not?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also there's the extra complication that on Windows IIRC these things are relative to the executable (or library?) path. This needs some further investigation in any case.

} else {
glib::user_data_dir()
};

Path::new(&prefix).join("glib-2.0").join("schemas")
}
};

// Ensure target_dir exists
std::fs::create_dir_all(&target_dir).expect("Failed to create target directory");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Installing things as part of build.rs is an anti-pattern and unexpected. You should not place (or modify) anything outside of OUT_DIR, see https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts


// Recursively copy all files with .gschema.xml extension from schema_dir to target_dir
for schema_dir in schemas_dir {
let entries = Path::new(schema_dir)
.read_dir()
.expect("Failed to read schema directory")
.flatten();

for entry in entries {
let path = entry.path();
let file_name = path.file_name().unwrap().to_str().unwrap();

if path.is_file() && file_name.ends_with(".gschema.xml") {
let target_path = target_dir.join(path.file_name().unwrap());
std::fs::copy(&path, &target_path).expect("Failed to copy schema file");
}
}
}

let mut command = Command::new("glib-compile-schemas");
command.arg("--strict");
command.arg(target_dir);

let output = command
.output()
.expect("Failed to execute glib-compile-schemas");

assert!(
output.status.success(),
"glib-compile-schemas failed with exit status {} and stderr:\n{}",
output.status,
String::from_utf8_lossy(&output.stderr)
);

for schema_dir in schemas_dir {
println!("cargo:rerun-if-changed={}", schema_dir);
}
}
Loading