Skip to content

Commit a5fe464

Browse files
author
bors-servo
authored
Auto merge of servo#16762 - upsuper:buildtime-pseudo, r=emilio
Generate atom files at build-time The commits here basically do the following things: 1. move all generated files for gecko into "gecko/generated" so that we can copy all of them around 2. make regen_atoms.py generate file to the out dir rather than in-tree 3. make the build script invoke regen_atoms.py when bindgen feature is enabled <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/16762) <!-- Reviewable:end -->
2 parents 34d3357 + ff76ec8 commit a5fe464

File tree

14 files changed

+129
-111
lines changed

14 files changed

+129
-111
lines changed

components/style/binding_tools/regen_atoms.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,9 @@ def type(self):
9797
def collect_atoms(objdir):
9898
atoms = []
9999
for source in SOURCES:
100-
with open(os.path.join(objdir, source.FILE)) as f:
100+
path = os.path.abspath(os.path.join(objdir, source.FILE))
101+
print("cargo:rerun-if-changed={}".format(path))
102+
with open(path) as f:
101103
for line in f.readlines():
102104
result = re.match(source.PATTERN, line)
103105
if result:
@@ -255,15 +257,14 @@ def write_pseudo_element_helper(atoms, target_filename):
255257
f.write("}\n")
256258

257259

258-
def generate_atoms(dist):
259-
style_path = os.path.dirname(os.path.dirname(__file__))
260+
def generate_atoms(dist, out):
260261
atoms = collect_atoms(dist)
261-
write_atom_macro(atoms, os.path.join(style_path, "gecko_string_cache/atom_macro.rs"))
262-
write_pseudo_element_helper(atoms, os.path.join(style_path, "gecko/generated/gecko_pseudo_element_helper.rs"))
262+
write_atom_macro(atoms, os.path.join(out, "atom_macro.rs"))
263+
write_pseudo_element_helper(atoms, os.path.join(out, "pseudo_element_helper.rs"))
263264

264265

265266
if __name__ == "__main__":
266-
if len(sys.argv) != 2:
267-
print("Usage: {} objdir".format(sys.argv[0]))
267+
if len(sys.argv) != 3:
268+
print("Usage: {} dist out".format(sys.argv[0]))
268269
exit(2)
269-
generate_atoms(os.path.join(sys.argv[1], "dist"))
270+
generate_atoms(sys.argv[1], sys.argv[2])

components/style/build.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
* License, v. 2.0. If a copy of the MPL was not distributed with this
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

5-
#[cfg(feature = "gecko")]
65
#[macro_use]
76
extern crate lazy_static;
87
#[cfg(feature = "bindgen")]
@@ -53,6 +52,10 @@ fn find_python() -> String {
5352
}.to_owned()
5453
}
5554

55+
lazy_static! {
56+
pub static ref PYTHON: String = env::var("PYTHON").ok().unwrap_or_else(find_python);
57+
}
58+
5659
fn generate_properties() {
5760
for entry in WalkDir::new("properties") {
5861
let entry = entry.unwrap();
@@ -64,10 +67,9 @@ fn generate_properties() {
6467
}
6568
}
6669

67-
let python = env::var("PYTHON").ok().unwrap_or_else(find_python);
6870
let script = Path::new(file!()).parent().unwrap().join("properties").join("build.py");
6971
let product = if cfg!(feature = "gecko") { "gecko" } else { "servo" };
70-
let status = Command::new(python)
72+
let status = Command::new(&*PYTHON)
7173
.arg(&script)
7274
.arg(product)
7375
.arg("style-crate")

components/style/build_gecko.rs

Lines changed: 101 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,25 @@
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

55
mod common {
6-
use std::env;
7-
use std::path::PathBuf;
6+
use std::{env, fs, io};
7+
use std::path::{Path, PathBuf};
88

99
lazy_static! {
1010
pub static ref OUTDIR_PATH: PathBuf = PathBuf::from(env::var("OUT_DIR").unwrap()).join("gecko");
1111
}
1212

13-
pub const STRUCTS_DEBUG_FILE: &'static str = "structs_debug.rs";
14-
pub const STRUCTS_RELEASE_FILE: &'static str = "structs_release.rs";
15-
pub const BINDINGS_FILE: &'static str = "bindings.rs";
16-
17-
#[derive(Clone, Copy, PartialEq)]
18-
pub enum BuildType {
19-
Debug,
20-
Release,
21-
}
22-
23-
pub fn structs_file(build_type: BuildType) -> &'static str {
24-
match build_type {
25-
BuildType::Debug => STRUCTS_DEBUG_FILE,
26-
BuildType::Release => STRUCTS_RELEASE_FILE
13+
/// Copy contents of one directory into another.
14+
/// It currently only does a shallow copy.
15+
pub fn copy_dir<P, Q, F>(from: P, to: Q, callback: F) -> io::Result<()>
16+
where P: AsRef<Path>, Q: AsRef<Path>, F: Fn(&Path) {
17+
let to = to.as_ref();
18+
for entry in from.as_ref().read_dir()? {
19+
let entry = entry?;
20+
let path = entry.path();
21+
callback(&path);
22+
fs::copy(&path, to.join(entry.file_name()))?;
2723
}
24+
Ok(())
2825
}
2926
}
3027

@@ -39,9 +36,28 @@ mod bindings {
3936
use std::fs::{self, File};
4037
use std::io::{Read, Write};
4138
use std::path::{Path, PathBuf};
39+
use std::process::{Command, exit};
4240
use std::sync::Mutex;
4341
use std::time::SystemTime;
4442
use super::common::*;
43+
use super::super::PYTHON;
44+
45+
const STRUCTS_DEBUG_FILE: &'static str = "structs_debug.rs";
46+
const STRUCTS_RELEASE_FILE: &'static str = "structs_release.rs";
47+
const BINDINGS_FILE: &'static str = "bindings.rs";
48+
49+
#[derive(Clone, Copy, PartialEq)]
50+
enum BuildType {
51+
Debug,
52+
Release,
53+
}
54+
55+
fn structs_file(build_type: BuildType) -> &'static str {
56+
match build_type {
57+
BuildType::Debug => STRUCTS_DEBUG_FILE,
58+
BuildType::Release => STRUCTS_RELEASE_FILE
59+
}
60+
}
4561

4662
lazy_static! {
4763
static ref INCLUDE_RE: Regex = Regex::new(r#"#include\s*"(.+?)""#).unwrap();
@@ -60,11 +76,6 @@ mod bindings {
6076
pub static ref LAST_MODIFIED: Mutex<SystemTime> =
6177
Mutex::new(get_modified_time(&env::current_exe().unwrap())
6278
.expect("Failed to get modified time of executable"));
63-
static ref BINDING_DISTDIR_PATH: PathBuf = {
64-
let path = DISTDIR_PATH.join("rust_bindings/style");
65-
fs::create_dir_all(&path).expect("Fail to create bindings dir in dist");
66-
path
67-
};
6879
}
6980

7081
fn get_modified_time(file: &Path) -> Option<SystemTime> {
@@ -237,8 +248,6 @@ mod bindings {
237248
}
238249
let bytes = result.into_bytes();
239250
File::create(&out_file).unwrap().write_all(&bytes).expect("Unable to write output");
240-
File::create(&BINDING_DISTDIR_PATH.join(file)).unwrap()
241-
.write_all(&bytes).expect("Unable to write output to binding dist");
242251
}
243252

244253
fn get_arc_types() -> Vec<String> {
@@ -276,7 +285,7 @@ mod bindings {
276285
}
277286
}
278287

279-
pub fn generate_structs(build_type: BuildType) {
288+
fn generate_structs(build_type: BuildType) {
280289
let mut builder = Builder::get_initial_builder(build_type)
281290
.enable_cxx_namespaces()
282291
.with_codegen_config(CodegenConfig {
@@ -565,7 +574,7 @@ mod bindings {
565574
write_binding_file(builder, structs_file(build_type), &fixups);
566575
}
567576

568-
pub fn setup_logging() {
577+
fn setup_logging() -> bool {
569578
use log;
570579

571580
struct BuildLogger {
@@ -594,20 +603,23 @@ mod bindings {
594603
}
595604
}
596605

597-
log::set_logger(|log_level| {
598-
log_level.set(log::LogLevelFilter::Debug);
599-
Box::new(BuildLogger {
600-
file: env::var("STYLO_BUILD_LOG").ok().and_then(|path| {
601-
fs::File::create(path).ok().map(Mutex::new)
602-
}),
603-
filter: env::var("STYLO_BUILD_FILTER").ok()
604-
.unwrap_or_else(|| "bindgen".to_owned()),
606+
if let Ok(path) = env::var("STYLO_BUILD_LOG") {
607+
log::set_logger(|log_level| {
608+
log_level.set(log::LogLevelFilter::Debug);
609+
Box::new(BuildLogger {
610+
file: fs::File::create(path).ok().map(Mutex::new),
611+
filter: env::var("STYLO_BUILD_FILTER").ok()
612+
.unwrap_or_else(|| "bindgen".to_owned()),
613+
})
605614
})
606-
})
607-
.expect("Failed to set logger.");
615+
.expect("Failed to set logger.");
616+
true
617+
} else {
618+
false
619+
}
608620
}
609621

610-
pub fn generate_bindings() {
622+
fn generate_bindings() {
611623
let mut builder = Builder::get_initial_builder(BuildType::Release)
612624
.disable_name_namespacing()
613625
.with_codegen_config(CodegenConfig {
@@ -816,52 +828,70 @@ mod bindings {
816828
}
817829
write_binding_file(builder, BINDINGS_FILE, &Vec::new());
818830
}
819-
}
820831

821-
#[cfg(not(feature = "bindgen"))]
822-
mod bindings {
823-
use std::fs;
824-
use std::path::{Path, PathBuf};
825-
use super::common::*;
826-
827-
lazy_static! {
828-
static ref BINDINGS_PATH: PathBuf = Path::new(file!()).parent().unwrap().join("gecko_bindings");
832+
fn generate_atoms() {
833+
let script = Path::new(file!()).parent().unwrap().join("binding_tools").join("regen_atoms.py");
834+
println!("cargo:rerun-if-changed={}", script.display());
835+
let status = Command::new(&*PYTHON)
836+
.arg(&script)
837+
.arg(DISTDIR_PATH.as_os_str())
838+
.arg(OUTDIR_PATH.as_os_str())
839+
.status()
840+
.unwrap();
841+
if !status.success() {
842+
exit(1);
843+
}
829844
}
830845

831-
pub fn setup_logging() {}
846+
pub fn generate() {
847+
use std::thread;
848+
macro_rules! run_tasks {
849+
($($task:expr,)+) => {
850+
if setup_logging() {
851+
$($task;)+
852+
} else {
853+
let threads = vec![$( thread::spawn(|| $task) ),+];
854+
for thread in threads.into_iter() {
855+
thread.join().unwrap();
856+
}
857+
}
858+
}
859+
}
860+
run_tasks! {
861+
generate_structs(BuildType::Debug),
862+
generate_structs(BuildType::Release),
863+
generate_bindings(),
864+
generate_atoms(),
865+
}
832866

833-
pub fn generate_structs(build_type: BuildType) {
834-
let file = structs_file(build_type);
835-
let source = BINDINGS_PATH.join(file);
836-
println!("cargo:rerun-if-changed={}", source.display());
837-
fs::copy(source, OUTDIR_PATH.join(file)).unwrap();
867+
// Copy all generated files to dist for the binding package
868+
let path = DISTDIR_PATH.join("rust_bindings/style");
869+
if path.exists() {
870+
fs::remove_dir_all(&path).expect("Fail to remove binding dir in dist");
871+
}
872+
fs::create_dir_all(&path).expect("Fail to create bindings dir in dist");
873+
copy_dir(&*OUTDIR_PATH, &path, |_| {}).expect("Fail to copy generated files to dist dir");
838874
}
875+
}
876+
877+
#[cfg(not(feature = "bindgen"))]
878+
mod bindings {
879+
use std::path::Path;
880+
use super::common::*;
839881

840-
pub fn generate_bindings() {
841-
let source = BINDINGS_PATH.join(BINDINGS_FILE);
842-
println!("cargo:rerun-if-changed={}", source.display());
843-
fs::copy(source, OUTDIR_PATH.join(BINDINGS_FILE)).unwrap();
882+
pub fn generate() {
883+
let dir = Path::new(file!()).parent().unwrap().join("gecko/generated");
884+
println!("cargo:rerun-if-changed={}", dir.display());
885+
copy_dir(&dir, &*OUTDIR_PATH, |path| {
886+
println!("cargo:rerun-if-changed={}", path.display());
887+
}).expect("Fail to copy generated files to out dir");
844888
}
845889
}
846890

847891
pub fn generate() {
848892
use self::common::*;
849-
use std::{env, fs, thread};
893+
use std::fs;
850894
println!("cargo:rerun-if-changed=build_gecko.rs");
851895
fs::create_dir_all(&*OUTDIR_PATH).unwrap();
852-
bindings::setup_logging();
853-
if env::var("STYLO_BUILD_LOG").is_ok() {
854-
bindings::generate_structs(BuildType::Debug);
855-
bindings::generate_structs(BuildType::Release);
856-
bindings::generate_bindings();
857-
} else {
858-
let threads = vec![
859-
thread::spawn(|| bindings::generate_structs(BuildType::Debug)),
860-
thread::spawn(|| bindings::generate_structs(BuildType::Release)),
861-
thread::spawn(|| bindings::generate_bindings()),
862-
];
863-
for t in threads.into_iter() {
864-
t.join().unwrap();
865-
}
866-
}
896+
bindings::generate();
867897
}

components/style/gecko/selector_parser.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ impl PseudoElement {
165165
}}
166166
}
167167

168-
include!("generated/gecko_pseudo_element_helper.rs");
168+
include!(concat!(env!("OUT_DIR"), "/gecko/pseudo_element_helper.rs"));
169169

170170
None
171171
}
@@ -190,7 +190,7 @@ impl PseudoElement {
190190
}}
191191
}
192192

193-
include!("generated/gecko_pseudo_element_helper.rs");
193+
include!(concat!(env!("OUT_DIR"), "/gecko/pseudo_element_helper.rs"));
194194

195195
None
196196
}
@@ -492,7 +492,7 @@ impl SelectorImpl {
492492
}}
493493
}
494494

495-
include!("generated/gecko_pseudo_element_helper.rs")
495+
include!(concat!(env!("OUT_DIR"), "/gecko/pseudo_element_helper.rs"));
496496
}
497497

498498
#[inline]

components/style/gecko_string_cache/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ use std::slice;
2525

2626
#[macro_use]
2727
#[allow(improper_ctypes, non_camel_case_types, missing_docs)]
28-
pub mod atom_macro;
28+
pub mod atom_macro {
29+
include!(concat!(env!("OUT_DIR"), "/gecko/atom_macro.rs"));
30+
}
31+
2932
#[macro_use]
3033
pub mod namespace;
3134

0 commit comments

Comments
 (0)