Add function to choose what Qt modules to link to
parent
0fb6e84077
commit
7c8bb6a535
130
src/build.rs
130
src/build.rs
|
@ -1,11 +1,11 @@
|
||||||
extern crate cc;
|
extern crate cc;
|
||||||
|
|
||||||
|
use super::{generate_bindings, read_bindings_file, Config};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use serde_xml_rs::deserialize;
|
use serde_xml_rs::deserialize;
|
||||||
|
use std::io::{self, Write};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::io::{self, Write};
|
|
||||||
use super::{Config, generate_bindings, read_bindings_file};
|
|
||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
|
@ -22,7 +22,8 @@ struct QResource {
|
||||||
/// Parse the qrc file, panic if it fails.
|
/// Parse the qrc file, panic if it fails.
|
||||||
fn read_qrc(qrc: &Path) -> RCC {
|
fn read_qrc(qrc: &Path) -> RCC {
|
||||||
let bytes = ::std::fs::read(qrc).expect(&format!("Could not read {}", qrc.display()));
|
let bytes = ::std::fs::read(qrc).expect(&format!("Could not read {}", qrc.display()));
|
||||||
let mut rcc: RCC = deserialize(&bytes[..]).expect(&format!("could not parse {}", qrc.display()));
|
let mut rcc: RCC =
|
||||||
|
deserialize(&bytes[..]).expect(&format!("could not parse {}", qrc.display()));
|
||||||
for qresource in &mut rcc.qresource {
|
for qresource in &mut rcc.qresource {
|
||||||
for file in &mut qresource.file {
|
for file in &mut qresource.file {
|
||||||
let mut p = qrc.parent().unwrap().to_path_buf();
|
let mut p = qrc.parent().unwrap().to_path_buf();
|
||||||
|
@ -50,18 +51,14 @@ fn qrc_to_input_list<'a>(qrc: &'a Path, rcc: &'a RCC) -> Vec<&'a Path> {
|
||||||
fn run(cmd: &str, command: &mut Command) -> Vec<u8> {
|
fn run(cmd: &str, command: &mut Command) -> Vec<u8> {
|
||||||
eprintln!("running: {:?}", command);
|
eprintln!("running: {:?}", command);
|
||||||
match command.output() {
|
match command.output() {
|
||||||
Err(e) => {
|
Err(e) => eprintln!(
|
||||||
eprintln!(
|
"Could not run {}. Make sure {} is in your path: {}",
|
||||||
"Could not run {}. Make sure {} is in your path: {}",
|
cmd, cmd, e
|
||||||
cmd,
|
),
|
||||||
cmd,
|
|
||||||
e
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Ok(output) => {
|
Ok(output) => {
|
||||||
io::stderr().write(&output.stderr).expect(
|
io::stderr()
|
||||||
"Could not write to stderr.",
|
.write(&output.stderr)
|
||||||
);
|
.expect("Could not write to stderr.");
|
||||||
if output.status.success() {
|
if output.status.success() {
|
||||||
return output.stdout;
|
return output.stdout;
|
||||||
}
|
}
|
||||||
|
@ -95,17 +92,16 @@ fn parse_qt_version(qt_version: &str) -> Version {
|
||||||
let re = Regex::new(r"(\d)\.(\d{1,2})(\.(\d{1,2}))").unwrap();
|
let re = Regex::new(r"(\d)\.(\d{1,2})(\.(\d{1,2}))").unwrap();
|
||||||
match re.captures(&qt_version) {
|
match re.captures(&qt_version) {
|
||||||
None => panic!("Cannot parse Qt version number {}", qt_version),
|
None => panic!("Cannot parse Qt version number {}", qt_version),
|
||||||
Some(cap) => {
|
Some(cap) => Version {
|
||||||
Version {
|
major: cap[1].parse::<u8>().unwrap(),
|
||||||
major: cap[1].parse::<u8>().unwrap(),
|
minor: cap[2].parse::<u8>().unwrap(),
|
||||||
minor: cap[2].parse::<u8>().unwrap(),
|
patch: cap
|
||||||
patch: cap.get(4)
|
.get(4)
|
||||||
.map(|m| m.as_str())
|
.map(|m| m.as_str())
|
||||||
.unwrap_or("0")
|
.unwrap_or("0")
|
||||||
.parse::<u8>()
|
.parse::<u8>()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
}
|
},
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,20 +122,49 @@ fn parse_qt_version(qt_version: &str) -> Version {
|
||||||
pub fn require_qt_version(major: u8, minor: u8, patch: u8) {
|
pub fn require_qt_version(major: u8, minor: u8, patch: u8) {
|
||||||
let qt_version = qmake_query("QT_VERSION");
|
let qt_version = qmake_query("QT_VERSION");
|
||||||
let version = parse_qt_version(&qt_version);
|
let version = parse_qt_version(&qt_version);
|
||||||
if version.major < major ||
|
if version.major < major
|
||||||
(version.major == major &&
|
|| (version.major == major
|
||||||
(version.minor < minor || (version.minor == minor && version.patch < patch)))
|
&& (version.minor < minor || (version.minor == minor && version.patch < patch)))
|
||||||
{
|
{
|
||||||
panic!(
|
panic!(
|
||||||
"Please use a version of Qt >= {}.{}.{}, not {}",
|
"Please use a version of Qt >= {}.{}.{}, not {}",
|
||||||
major,
|
major, minor, patch, qt_version
|
||||||
minor,
|
|
||||||
patch,
|
|
||||||
qt_version
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum QtModule {
|
||||||
|
Core,
|
||||||
|
Gui,
|
||||||
|
Multimedia,
|
||||||
|
MultimediaWidgets,
|
||||||
|
Network,
|
||||||
|
Qml,
|
||||||
|
Quick,
|
||||||
|
QuickTest,
|
||||||
|
Sql,
|
||||||
|
Test,
|
||||||
|
Widgets,
|
||||||
|
|
||||||
|
Concurrent,
|
||||||
|
DBus,
|
||||||
|
Help,
|
||||||
|
Location,
|
||||||
|
OpenGL,
|
||||||
|
Positioning,
|
||||||
|
PrintSupport,
|
||||||
|
Svg,
|
||||||
|
WebChannel,
|
||||||
|
WebEngine,
|
||||||
|
WaylandCompositor,
|
||||||
|
X11Extras,
|
||||||
|
Xml,
|
||||||
|
XmlPatterns,
|
||||||
|
|
||||||
|
Charts,
|
||||||
|
}
|
||||||
|
|
||||||
/// A builder for binding generation and compilation of a Qt application.
|
/// A builder for binding generation and compilation of a Qt application.
|
||||||
///
|
///
|
||||||
/// Pass options into this `Build` and then run `build` to generate binddings
|
/// Pass options into this `Build` and then run `build` to generate binddings
|
||||||
|
@ -153,6 +178,7 @@ pub struct Build {
|
||||||
qrc: Vec<PathBuf>,
|
qrc: Vec<PathBuf>,
|
||||||
h: Vec<PathBuf>,
|
h: Vec<PathBuf>,
|
||||||
cpp: Vec<PathBuf>,
|
cpp: Vec<PathBuf>,
|
||||||
|
modules: Vec<QtModule>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Build {
|
impl Build {
|
||||||
|
@ -177,10 +203,10 @@ impl Build {
|
||||||
pub fn new<P: AsRef<Path>>(out_dir: P) -> Build {
|
pub fn new<P: AsRef<Path>>(out_dir: P) -> Build {
|
||||||
let qt_include_path = qmake_query("QT_INSTALL_HEADERS");
|
let qt_include_path = qmake_query("QT_INSTALL_HEADERS");
|
||||||
let mut build = cc::Build::new();
|
let mut build = cc::Build::new();
|
||||||
build.cpp(true).include(out_dir.as_ref()).include(
|
build
|
||||||
qt_include_path
|
.cpp(true)
|
||||||
.trim(),
|
.include(out_dir.as_ref())
|
||||||
);
|
.include(qt_include_path.trim());
|
||||||
Build {
|
Build {
|
||||||
qt_library_path: qmake_query("QT_INSTALL_LIBS").trim().into(),
|
qt_library_path: qmake_query("QT_INSTALL_LIBS").trim().into(),
|
||||||
out_dir: out_dir.as_ref().to_path_buf(),
|
out_dir: out_dir.as_ref().to_path_buf(),
|
||||||
|
@ -189,6 +215,7 @@ impl Build {
|
||||||
qrc: Vec::new(),
|
qrc: Vec::new(),
|
||||||
h: Vec::new(),
|
h: Vec::new(),
|
||||||
cpp: Vec::new(),
|
cpp: Vec::new(),
|
||||||
|
modules: vec![QtModule::Core],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Add a bindings file to be processed.
|
/// Add a bindings file to be processed.
|
||||||
|
@ -217,6 +244,11 @@ impl Build {
|
||||||
self.cpp.push(path.as_ref().to_path_buf());
|
self.cpp.push(path.as_ref().to_path_buf());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
/// Add a Qt module to be linked to the executable
|
||||||
|
pub fn module(&mut self, module: QtModule) -> &mut Build {
|
||||||
|
self.modules.push(module);
|
||||||
|
self
|
||||||
|
}
|
||||||
/// Compile the static library.
|
/// Compile the static library.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
|
@ -249,10 +281,9 @@ impl Build {
|
||||||
print_cpp_link_stdlib();
|
print_cpp_link_stdlib();
|
||||||
}
|
}
|
||||||
println!("cargo:rustc-link-search={}", self.qt_library_path.display());
|
println!("cargo:rustc-link-search={}", self.qt_library_path.display());
|
||||||
println!("cargo:rustc-link-lib=Qt5Core");
|
for module in &self.modules {
|
||||||
println!("cargo:rustc-link-lib=Qt5Network");
|
println!("cargo:rustc-link-lib=Qt5{:?}", module);
|
||||||
println!("cargo:rustc-link-lib=Qt5Gui");
|
}
|
||||||
println!("cargo:rustc-link-lib=Qt5Qml");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,9 +293,7 @@ fn print_cpp_link_stdlib() {
|
||||||
let target = ::std::env::var("TARGET").unwrap();
|
let target = ::std::env::var("TARGET").unwrap();
|
||||||
let stdlib = if target.contains("msvc") {
|
let stdlib = if target.contains("msvc") {
|
||||||
None
|
None
|
||||||
} else if target.contains("apple")
|
} else if target.contains("apple") || target.contains("freebsd") || target.contains("openbsd") {
|
||||||
|| target.contains("freebsd")
|
|
||||||
|| target.contains("openbsd") {
|
|
||||||
Some("c++")
|
Some("c++")
|
||||||
} else {
|
} else {
|
||||||
Some("stdc++")
|
Some("stdc++")
|
||||||
|
@ -299,9 +328,10 @@ fn are_outputs_up_to_date(paths: &[&Path], input: SystemTime) -> bool {
|
||||||
fn get_youngest_mtime(paths: &[&Path]) -> Result<SystemTime, String> {
|
fn get_youngest_mtime(paths: &[&Path]) -> Result<SystemTime, String> {
|
||||||
let mut max = UNIX_EPOCH;
|
let mut max = UNIX_EPOCH;
|
||||||
for path in paths {
|
for path in paths {
|
||||||
let mt = path.metadata().and_then(|m| m.modified()).map_err(|e| {
|
let mt = path
|
||||||
format!("Error reading file {}: {}.", path.display(), e)
|
.metadata()
|
||||||
})?;
|
.and_then(|m| m.modified())
|
||||||
|
.map_err(|e| format!("Error reading file {}: {}.", path.display(), e))?;
|
||||||
if mt > max {
|
if mt > max {
|
||||||
max = mt;
|
max = mt;
|
||||||
}
|
}
|
||||||
|
@ -344,9 +374,8 @@ fn handle_binding(
|
||||||
h: &mut Vec<PathBuf>,
|
h: &mut Vec<PathBuf>,
|
||||||
cpp: &mut Vec<PathBuf>,
|
cpp: &mut Vec<PathBuf>,
|
||||||
) {
|
) {
|
||||||
let mut config = read_bindings_file(&bindings_json).unwrap_or_else(|e| {
|
let mut config = read_bindings_file(&bindings_json)
|
||||||
panic!("Could not parse {}: {}", bindings_json.display(), e)
|
.unwrap_or_else(|e| panic!("Could not parse {}: {}", bindings_json.display(), e));
|
||||||
});
|
|
||||||
let bindings_cpp = out_dir.join(&config.cpp_file);
|
let bindings_cpp = out_dir.join(&config.cpp_file);
|
||||||
let mut bindings_h = bindings_cpp.clone();
|
let mut bindings_h = bindings_cpp.clone();
|
||||||
bindings_h.set_extension("h");
|
bindings_h.set_extension("h");
|
||||||
|
@ -356,8 +385,7 @@ fn handle_binding(
|
||||||
if should_run(
|
if should_run(
|
||||||
&[&bindings_json],
|
&[&bindings_json],
|
||||||
&[&bindings_h, &bindings_cpp, &interface_rs],
|
&[&bindings_h, &bindings_cpp, &interface_rs],
|
||||||
)
|
) {
|
||||||
{
|
|
||||||
generate_bindings(&config).unwrap();
|
generate_bindings(&config).unwrap();
|
||||||
}
|
}
|
||||||
h.push(bindings_h);
|
h.push(bindings_h);
|
||||||
|
|
Loading…
Reference in New Issue