github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-core-master/validator/build.rs (about) 1 /* 2 * Copyright 2017 Intel Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * ------------------------------------------------------------------------------ 16 */ 17 18 extern crate glob; 19 extern crate protoc_rust; 20 21 use std::error::Error; 22 use std::fs; 23 use std::io::prelude::*; 24 use std::path::Path; 25 use std::time::{Duration, UNIX_EPOCH}; 26 27 use protoc_rust::Customize; 28 29 const PROTO_FILES_DIR: &str = "../protos"; 30 const PROTOBUF_TARGET_DIR: &str = "src/proto"; 31 const GENERATED_SOURCE_HEADER: &str = r#" 32 #![cfg_attr(rustfmt, rustfmt_skip)] 33 34 /* 35 * THIS IS A GENERATED FILE: DO NOT MODIFY 36 * 37 * This is the module which contains the generated sources for the Protocol 38 * buffers messages. 39 */ 40 "#; 41 42 #[derive(Debug, Clone)] 43 struct ProtoFile { 44 module_name: String, 45 file_path: String, 46 last_modified: Duration, 47 } 48 49 fn main() { 50 // Generate protobuf files 51 let proto_src_files = glob_simple(&format!("{}/*.proto", PROTO_FILES_DIR)); 52 let last_build_time = read_last_build_time(); 53 54 let latest_change = proto_src_files.iter().fold( 55 Duration::from_secs(0), 56 |max, ref proto_file| { 57 if proto_file.last_modified > max { 58 proto_file.last_modified 59 } else { 60 max 61 } 62 }, 63 ); 64 65 if latest_change > last_build_time { 66 println!("{:?}", proto_src_files); 67 fs::create_dir_all(PROTOBUF_TARGET_DIR).unwrap(); 68 protoc_rust::run(protoc_rust::Args { 69 out_dir: PROTOBUF_TARGET_DIR, 70 input: &proto_src_files 71 .iter() 72 .map(|proto_file| proto_file.file_path.as_ref()) 73 .collect::<Vec<&str>>(), 74 includes: &["src", PROTO_FILES_DIR], 75 customize: Customize { 76 ..Default::default() 77 }, 78 }).expect("unable to run protoc"); 79 80 let mod_file_name = format!("{}/mod.rs", PROTOBUF_TARGET_DIR); 81 let mod_file_path = Path::new(&mod_file_name); 82 let mut file = match fs::File::create(&mod_file_path) { 83 Err(err) => panic!( 84 "Unable to create file {}: {}", 85 mod_file_name, 86 err.description() 87 ), 88 Ok(file) => file, 89 }; 90 91 let content = format!( 92 "{}\n{}\n", 93 GENERATED_SOURCE_HEADER, 94 proto_src_files 95 .iter() 96 .map(|proto_file| format!("pub mod {};", proto_file.module_name)) 97 .collect::<Vec<_>>() 98 .join("\n") 99 ); 100 match file.write_all(content.as_bytes()) { 101 Err(err) => panic!( 102 "Unable to write to {}: {}", 103 mod_file_name, 104 err.description() 105 ), 106 Ok(_) => println!("generated {}", mod_file_name), 107 } 108 } else { 109 println!( 110 "No proto files changed; latest modification: {}, last build: {}", 111 latest_change.as_secs(), 112 last_build_time.as_secs() 113 ); 114 } 115 } 116 117 fn glob_simple(pattern: &str) -> Vec<ProtoFile> { 118 glob::glob(pattern) 119 .expect("Search did not result in files") 120 .map(|g| protofile_info(g.expect("item").as_path())) 121 .collect() 122 } 123 124 fn protofile_info(path: &Path) -> ProtoFile { 125 let module_name = path.file_stem() 126 .expect("Unable to get file stem") 127 .to_str() 128 .expect("File name should be utf-8") 129 .to_owned(); 130 131 let file_path = path.to_str().expect("utf-8").to_owned(); 132 133 let file = fs::File::open(path).expect("Unable to open file"); 134 let last_modified = get_modified_time(file); 135 136 ProtoFile { 137 module_name, 138 file_path, 139 last_modified, 140 } 141 } 142 143 fn read_last_build_time() -> Duration { 144 let mod_file_name = format!("{}/mod.rs", PROTOBUF_TARGET_DIR); 145 match fs::File::open(Path::new(&mod_file_name)) { 146 Err(err) => { 147 println!( 148 "unable to open {}: {}; defaulting to 0", 149 mod_file_name, 150 err.description() 151 ); 152 Duration::new(0, 0) 153 } 154 Ok(file) => get_modified_time(file), 155 } 156 } 157 158 fn get_modified_time(file: fs::File) -> Duration { 159 file.metadata() 160 .expect("File should have metadata") 161 .modified() 162 .map(|sys_time| { 163 sys_time 164 .duration_since(UNIX_EPOCH) 165 .expect("System time should be after UNIX_EPOCH") 166 }) 167 .expect("File should have modified time") 168 }