1
1
extern crate regex;
2
+ extern crate serde;
3
+ #[ macro_use] extern crate serde_derive;
4
+ extern crate toml;
2
5
3
6
use regex:: { Captures , Regex } ;
4
7
5
8
use std:: collections:: HashMap ;
6
9
use std:: env;
7
10
use std:: fs:: { self , File } ;
8
- use std:: io:: { self , BufWriter , Write } ;
11
+ use std:: io:: { self , BufReader , BufWriter , Read , Write } ;
9
12
use std:: path:: { Path , PathBuf } ;
10
13
use std:: process:: Command ;
11
14
use std:: time:: { self , SystemTime } ;
12
15
16
+ #[ derive( Deserialize ) ]
17
+ struct Config {
18
+ board : String ,
19
+ calibration_pin : Option < u8 > ,
20
+ sensor_pins : Vec < u8 > ,
21
+ paths : Paths
22
+ }
23
+
24
+ #[ derive( Deserialize ) ]
25
+ struct Paths {
26
+ home : Option < PathBuf > ,
27
+ #[ serde( default ) ]
28
+ hardware : Vec < PathBuf > ,
29
+ #[ serde( default ) ]
30
+ tools : Vec < PathBuf > ,
31
+ #[ serde( default ) ]
32
+ libraries : Vec < PathBuf > ,
33
+ }
34
+
13
35
fn load_prefs_from_str ( pref_str : & str ) -> HashMap < & str , String > {
14
36
let mut prefs = HashMap :: new ( ) ;
15
37
for line in pref_str. lines ( ) {
@@ -53,16 +75,16 @@ fn write_board_file(path: &Path, prefs: &HashMap<&str, String>, name: &str, time
53
75
if * tool != "avrdude" {
54
76
panic ! ( "Only AVR boards are supported." ) ;
55
77
}
56
- let protocol: String = prefs. get ( "upload.protocol" ) . map ( Clone :: clone ) . unwrap_or_default ( ) ;
78
+ let protocol: String = prefs. get ( "upload.protocol" ) . cloned ( ) . unwrap_or_default ( ) ;
57
79
let speed: usize = prefs. get ( "upload.speed" ) . and_then ( |s| s. parse ( ) . ok ( ) ) . unwrap_or_default ( ) ;
58
80
let use_1200bps_touch: bool = prefs. get ( "upload.use_1200bps_touch" )
59
81
. and_then ( |s| s. parse ( ) . ok ( ) ) . unwrap_or_default ( ) ;
60
82
let wait_for_upload_port: bool = prefs. get ( "upload.wait_for_upload_port" )
61
83
. and_then ( |s| s. parse ( ) . ok ( ) ) . unwrap_or_default ( ) ;
62
- let mcu: String = prefs. get ( "build.mcu" ) . map ( Clone :: clone ) . unwrap_or_default ( ) ;
84
+ let mcu: String = prefs. get ( "build.mcu" ) . cloned ( ) . unwrap_or_default ( ) ;
63
85
let config_path: PathBuf = prefs. get ( "config.path" ) . map_or ( PathBuf :: new ( ) , PathBuf :: from) ;
64
86
let build_path: PathBuf = prefs. get ( "build.path" ) . map_or ( PathBuf :: new ( ) , PathBuf :: from) ;
65
- let project_name: String = prefs. get ( "build.project_name" ) . map ( Clone :: clone ) . unwrap_or_default ( ) ;
87
+ let project_name: String = prefs. get ( "build.project_name" ) . cloned ( ) . unwrap_or_default ( ) ;
66
88
67
89
let mut writer = BufWriter :: new ( File :: create ( path) . unwrap ( ) ) ;
68
90
writeln ! ( writer, r##"pub const PROTOCOL: &'static str = r#"{}"#;"## , protocol) . unwrap ( ) ;
@@ -77,51 +99,54 @@ fn write_board_file(path: &Path, prefs: &HashMap<&str, String>, name: &str, time
77
99
name, env!( "CARGO_PKG_VERSION" ) , timestamp) . unwrap ( ) ;
78
100
}
79
101
80
- fn builder_command ( compile : bool , src_path : & Path , out_path : & Path , prefs : Option < HashMap < & str , String > > ) -> Command {
102
+ fn builder_command ( compile : bool , src_path : & Path , out_path : & Path , mut extra_flags : String , mut defines : Option < HashMap < & str , String > > ) -> Command {
81
103
let mut command = Command :: new ( "arduino-builder" ) ;
82
104
command. arg ( "-libraries" ) . arg ( "libraries" )
83
105
. arg ( "-build-path" ) . arg ( out_path)
84
106
. arg ( "-warnings" ) . arg ( "all" )
85
107
. arg ( "-verbose" )
86
108
. arg ( if compile { "-compile" } else { "-dump-prefs" } ) ;
87
109
88
- if Path :: new ( "build.options.json " ) . exists ( ) {
89
- command . arg ( "-build-options-file" ) . arg ( "build.options.json" ) ;
90
- } else {
91
- if let Some ( home ) = env :: var_os ( "ARDUINO_HOME" ) . map ( PathBuf :: from ) {
92
- command . arg ( "-built-in-libraries" ) . arg ( home . join ( "libraries" ) )
93
- . arg ( "-hardware " ) . arg ( home . join ( "hardware" ) )
94
- . arg ( "-tools" ) . arg ( home. join ( "hardware/tools/avr" ) )
95
- . arg ( "-tools " ) . arg ( home. join ( "tools-builder " ) ) ;
96
- }
97
-
98
- if let Some ( board ) = env :: var_os ( "ARDUINO_BOARD" ) {
99
- command . arg ( "-fqbn" ) . arg ( board ) ;
100
- }
101
-
102
- if let Some ( hardware ) = env :: var_os ( "ARDUINO_HARDWARE" ) {
103
- for path in env :: split_paths ( & hardware ) {
104
- command. arg ( "-hardware " ) . arg ( path) ;
105
- }
106
- }
107
-
108
- if let Some ( tools ) = env :: var_os ( "ARDUINO_TOOLS" ) {
109
- for path in env :: split_paths ( & tools ) {
110
- command . arg ( "-tools" ) . arg ( path ) ;
111
- }
110
+ let mut reader = BufReader :: new ( File :: open ( "build.toml " ) . unwrap ( ) ) ;
111
+ let mut toml = String :: new ( ) ;
112
+ reader . read_to_string ( & mut toml ) . unwrap ( ) ;
113
+ let config = toml :: decode_str :: < Config > ( & toml ) . unwrap ( ) ;
114
+
115
+ command . arg ( "-fqbn " ) . arg ( & config . board ) ;
116
+ if let Some ( home ) = config . paths . home . or_else ( || env :: var_os ( "ARDUINO_HOME" ) . map ( PathBuf :: from ) ) {
117
+ command . arg ( "-built-in-libraries " ) . arg ( home. join ( "libraries " ) )
118
+ . arg ( "-hardware" ) . arg ( home . join ( "hardware" ) )
119
+ . arg ( "-tools" ) . arg ( home . join ( "hardware/tools/avr" ) )
120
+ . arg ( "-tools" ) . arg ( home . join ( "tools-builder" ) ) ;
121
+ }
122
+ for path in & config . paths . hardware {
123
+ command . arg ( "-hardware" ) . arg ( path ) ;
124
+ }
125
+ for path in & config . paths . tools {
126
+ command. arg ( "-tools " ) . arg ( path) ;
127
+ }
128
+ for path in & config . paths . libraries {
129
+ command . arg ( "-libraries" ) . arg ( path ) ;
130
+ }
131
+ if let Some ( ref mut defines ) = defines . as_mut ( ) {
132
+ if let Some ( calibration_pin ) = config . calibration_pin {
133
+ defines . insert ( "CALIBRATION_PIN" , calibration_pin . to_string ( ) ) ;
112
134
}
135
+ let sensor_pins = config. sensor_pins . iter ( )
136
+ . map ( |pin| format ! ( "{{{:#04x}, A{}}}" , pin, pin) )
137
+ . collect :: < Vec < _ > > ( )
138
+ . join ( ", " ) ;
139
+ defines. insert ( "SENSOR_PINS" , format ! ( "{{{}}}" , sensor_pins) ) ;
140
+ }
113
141
114
- if let Some ( libraries) = env:: var_os ( "ARDUINO_LIBRARIES" ) {
115
- for path in env:: split_paths ( & libraries) {
116
- command. arg ( "-libraries" ) . arg ( path) ;
117
- }
142
+ if let Some ( defines) = defines {
143
+ for ( key, value) in defines {
144
+ extra_flags. push_str ( & format ! ( " '-D{}={}'" , key, value) ) ;
118
145
}
119
146
}
120
147
121
- if let Some ( prefs) = prefs {
122
- for ( key, value) in prefs {
123
- command. arg ( "-prefs" ) . arg ( format ! ( "{}={}" , key, value) ) ;
124
- }
148
+ if !extra_flags. is_empty ( ) {
149
+ command. arg ( "-prefs" ) . arg ( format ! ( "build.extra_flags={}" , extra_flags) ) ;
125
150
}
126
151
127
152
command. arg ( src_path) ;
@@ -131,13 +156,13 @@ fn builder_command(compile: bool, src_path: &Path, out_path: &Path, prefs: Optio
131
156
132
157
pub fn main ( ) {
133
158
let timestamp = SystemTime :: now ( ) . duration_since ( time:: UNIX_EPOCH ) . unwrap ( ) . as_secs ( ) ;
134
- let out = PathBuf :: from ( env:: var_os ( "OUT_DIR" ) . unwrap ( ) ) ;
135
- let src = Path :: new ( "src/arduino/program.ino" ) ;
136
- let arduino_out = out . join ( "arduino" ) ;
137
- fs:: create_dir_all ( & arduino_out ) . unwrap ( ) ;
159
+ let out_path = PathBuf :: from ( env:: var_os ( "OUT_DIR" ) . unwrap ( ) ) ;
160
+ let src_path = Path :: new ( "src/arduino/program.ino" ) ;
161
+ let build_path = out_path . join ( "arduino" ) ;
162
+ fs:: create_dir_all ( & build_path ) . unwrap ( ) ;
138
163
139
164
// Dump preferences
140
- let output = builder_command ( false , src , & arduino_out , None ) . output ( ) . unwrap ( ) ;
165
+ let output = builder_command ( false , src_path , & build_path , String :: new ( ) , None ) . output ( ) . unwrap ( ) ;
141
166
let _ = io:: stdout ( ) . write_all ( & output. stdout ) ;
142
167
let _ = io:: stderr ( ) . write_all ( & output. stderr ) ;
143
168
if !output. status . success ( ) {
@@ -148,21 +173,19 @@ pub fn main() {
148
173
let prefs_str = String :: from_utf8_lossy ( & output. stdout ) ;
149
174
let prefs = load_prefs_from_str ( & prefs_str) ;
150
175
let expanded_prefs = expand_prefs ( & prefs) ;
151
- let name = expanded_prefs. get ( "name" ) . map ( Clone :: clone ) . unwrap_or_default ( ) ;
152
- write_board_file ( & out . join ( "board.rs" ) , & expanded_prefs, & name, timestamp) ;
176
+ let name = expanded_prefs. get ( "name" ) . cloned ( ) . unwrap_or_default ( ) ;
177
+ write_board_file ( & out_path . join ( "board.rs" ) , & expanded_prefs, & name, timestamp) ;
153
178
154
179
155
180
156
181
// Compile sketch
157
- let mut extra_prefs = HashMap :: new ( ) ;
158
- let extra_flags = format ! ( r#"{}'-DDEVICEINFO_NAME="{}"' '-DDEVICEINFO_VERSION="{}"' -DDEVICEINFO_TIMESTAMP={:#x}"# ,
159
- prefs. get( "build.extra_flags" ) . map_or_else( String :: new, |flags| format!( "{} " , flags) ) ,
160
- name,
161
- env!( "CARGO_PKG_VERSION" ) ,
162
- timestamp) ;
163
- extra_prefs. insert ( "build.extra_flags" , extra_flags) ;
164
-
165
- let output = builder_command ( true , src, & arduino_out, Some ( extra_prefs) ) . output ( ) . unwrap ( ) ;
182
+ let extra_flags = prefs. get ( "build.extra_flags" ) . cloned ( ) . unwrap_or_default ( ) ;
183
+ let mut defines = HashMap :: new ( ) ;
184
+ defines. insert ( "DEVICEINFO_NAME" , format ! ( r#""{}""# , name) ) ;
185
+ defines. insert ( "DEVICEINFO_VERSION" , format ! ( r#""{}""# , env!( "CARGO_PKG_VERSION" ) ) ) ;
186
+ defines. insert ( "DEVICEINFO_TIMESTAMP" , format ! ( "{:#x}" , timestamp) ) ;
187
+
188
+ let output = builder_command ( true , src_path, & build_path, extra_flags, Some ( defines) ) . output ( ) . unwrap ( ) ;
166
189
let _ = io:: stdout ( ) . write_all ( & output. stdout ) ;
167
190
let _ = io:: stderr ( ) . write_all ( & output. stderr ) ;
168
191
if !output. status . success ( ) {
@@ -176,6 +199,6 @@ pub fn main() {
176
199
}
177
200
}
178
201
179
- println ! ( "cargo:rerun-if-changed=src/arduino/program.ino" ) ;
180
- println ! ( "cargo:rerun-if-changed=build.options.json " ) ;
202
+ println ! ( "cargo:rerun-if-changed={}" , src_path . display ( ) ) ;
203
+ println ! ( "cargo:rerun-if-changed=build.toml " ) ;
181
204
}
0 commit comments