44//!
55//! Also see the docs in `asm.rs`.
66
7- use std:: collections:: BTreeMap ;
8- use std:: env:: current_dir;
9- use std:: fs:: { self , File } ;
10- use std:: path:: Path ;
11- use std:: process:: { Command , Stdio } ;
12-
13- fn toolchain ( ) -> String {
14- fs:: read_to_string ( "cortex-m/asm-toolchain" )
15- . unwrap ( )
16- . trim ( )
17- . to_string ( )
18- }
19-
20- fn rustc ( ) -> Command {
21- let mut cmd = Command :: new ( "rustc" ) ;
22- cmd. arg ( format ! ( "+{}" , toolchain( ) ) ) ;
23- cmd. arg ( "--edition=2024" ) ;
24- cmd
25- }
26-
27- fn assemble_really ( target : & str , cfgs : & [ & str ] , plugin_lto : bool ) {
28- let mut cmd = rustc ( ) ;
29-
30- // Set the codegen target.
31- cmd. arg ( "--target" ) . arg ( target) ;
32- // Set all the `--cfg` directives for the target.
33- cmd. args ( cfgs. iter ( ) . map ( |cfg| format ! ( "--cfg={}" , cfg) ) ) ;
34-
35- // We want some level of debuginfo to allow unwinding through the functions.
36- cmd. arg ( "-g" ) ;
37- // We always optimize the assembly shims. There's not really any reason not to.
38- cmd. arg ( "-O" ) ;
39-
40- // We use LTO on the archive to ensure the (unused) panic handler is removed, preventing
41- // a linker error when the archives are linked into final crates with two panic handlers.
42- cmd. arg ( "-Clto=yes" ) ;
43-
44- // rustc will usually add frame pointers by default to aid with debugging, but that is a high
45- // overhead for the tiny assembly routines.
46- cmd. arg ( "-Cforce-frame-pointers=no" ) ;
47-
48- // We don't want any system-specific paths to show up since we ship the result to other users.
49- // Add `--remap-path-prefix $(pwd)=.`.
50- let mut dir = current_dir ( )
51- . unwrap ( )
52- . join ( "cortex-m" )
53- . as_os_str ( )
54- . to_os_string ( ) ;
55- dir. push ( "=." ) ;
56- cmd. arg ( "--remap-path-prefix" ) . arg ( dir) ;
57-
58- // We let rustc build a single object file, not a staticlib, since the latter pulls in loads of
59- // code that will never be used (`compiler_builtins` and `core::fmt`, etc.). We build the static
60- // archive by hand after compiling.
61- cmd. arg ( "--emit=obj" ) ;
62-
63- if plugin_lto {
64- // Make artifacts compatible with Linker-Plugin LTO (and incompatible with everything else).
65- cmd. arg ( "-Clinker-plugin-lto" ) ;
66- }
67-
68- let file_stub = if plugin_lto {
69- format ! ( "{}-lto" , target)
70- } else {
71- target. to_string ( )
72- } ;
73-
74- let obj_file = format ! ( "bin/{}.o" , file_stub) ;
75-
76- // Pass output and input file.
77- cmd. arg ( "-o" ) . arg ( & obj_file) ;
78- cmd. arg ( "asm/lib.rs" ) ;
79- cmd. current_dir ( "cortex-m" ) ;
80-
81- println ! ( "{:?}" , cmd) ;
82- let status = cmd. status ( ) . unwrap ( ) ;
83- assert ! ( status. success( ) ) ;
84-
85- let full_obj_file_path = Path :: new ( "cortex-m" ) . join ( & obj_file) ;
86-
87- // Archive `target.o` -> `bin/target.a`.
88- let mut builder =
89- ar:: Builder :: new ( File :: create ( format ! ( "cortex-m/bin/{}.a" , file_stub) ) . unwrap ( ) ) ;
90-
91- // Use `append`, not `append_path`, to avoid adding any filesystem metadata (modification times,
92- // etc.).
93- let file = fs:: read ( & full_obj_file_path) . unwrap ( ) ;
94- builder
95- . append (
96- & ar:: Header :: new ( obj_file. as_bytes ( ) . to_vec ( ) , file. len ( ) as u64 ) ,
97- & * file,
98- )
99- . unwrap ( ) ;
100-
101- fs:: remove_file ( & full_obj_file_path) . unwrap ( ) ;
102- }
103-
104- fn assemble ( target : & str , cfgs : & [ & str ] ) {
105- assemble_really ( target, cfgs, false ) ;
106- assemble_really ( target, cfgs, true ) ;
107- }
108-
109- // `--target` -> `--cfg` list (mirrors what `build.rs` does).
110- static TARGETS : & [ ( & str , & [ & str ] ) ] = & [
111- ( "thumbv6m-none-eabi" , & [ ] ) ,
112- ( "thumbv7m-none-eabi" , & [ "armv7m" ] ) ,
113- ( "thumbv7em-none-eabi" , & [ "armv7m" , "armv7em" ] ) ,
114- ( "thumbv7em-none-eabihf" , & [ "armv7m" , "armv7em" , "has_fpu" ] ) ,
115- ( "thumbv8m.base-none-eabi" , & [ "armv8m" , "armv8m_base" ] ) ,
116- (
117- "thumbv8m.main-none-eabi" ,
118- & [ "armv7m" , "armv8m" , "armv8m_main" ] ,
119- ) ,
120- (
121- "thumbv8m.main-none-eabihf" ,
122- & [ "armv7m" , "armv8m" , "armv8m_main" , "has_fpu" ] ,
123- ) ,
124- ] ;
7+ use std:: process:: Command ;
1258
1269pub fn install_targets ( targets : & mut dyn Iterator < Item = & str > , toolchain : Option < & str > ) {
12710 let mut rustup = Command :: new ( "rustup" ) ;
@@ -135,90 +18,6 @@ pub fn install_targets(targets: &mut dyn Iterator<Item = &str>, toolchain: Optio
13518 assert ! ( status. success( ) , "rustup command failed: {:?}" , rustup) ;
13619}
13720
138- pub fn assemble_blobs ( ) {
139- let mut cmd = rustc ( ) ;
140- cmd. arg ( "-V" ) ;
141- cmd. stdout ( Stdio :: null ( ) ) ;
142- let status = cmd. status ( ) . unwrap ( ) ;
143- let toolchain = toolchain ( ) ;
144-
145- if !status. success ( ) {
146- println ! (
147- "asm toolchain {} does not seem to be installed. installing it now." ,
148- toolchain
149- ) ;
150-
151- let mut rustup = Command :: new ( "rustup" ) ;
152- let status = rustup. arg ( "install" ) . arg ( & toolchain) . status ( ) . unwrap ( ) ;
153- assert ! ( status. success( ) , "rustup command failed: {:?}" , rustup) ;
154- }
155-
156- install_targets (
157- & mut TARGETS . iter ( ) . map ( |( target, _) | * target) ,
158- Some ( & * toolchain) ,
159- ) ;
160-
161- for ( target, cfgs) in TARGETS {
162- println ! ( "building artifacts for {}" , target) ;
163- assemble ( target, cfgs) ;
164- }
165- }
166-
167- pub fn check_blobs ( ) {
168- // Load each `.a` file in `bin` into memory.
169- let mut files_before = BTreeMap :: new ( ) ;
170- for entry in fs:: read_dir ( "cortex-m/bin" ) . unwrap ( ) {
171- let entry = entry. unwrap ( ) ;
172- if entry. path ( ) . extension ( ) . unwrap ( ) == "a" {
173- files_before. insert (
174- entry
175- . path ( )
176- . file_name ( )
177- . unwrap ( )
178- . to_str ( )
179- . unwrap ( )
180- . to_string ( ) ,
181- fs:: read ( entry. path ( ) ) . unwrap ( ) ,
182- ) ;
183- }
184- }
185-
186- assemble_blobs ( ) ;
187-
188- let mut files_after = BTreeMap :: new ( ) ;
189- for entry in fs:: read_dir ( "cortex-m/bin" ) . unwrap ( ) {
190- let entry = entry. unwrap ( ) ;
191- if entry. path ( ) . extension ( ) . unwrap ( ) == "a" {
192- files_after. insert (
193- entry
194- . path ( )
195- . file_name ( )
196- . unwrap ( )
197- . to_str ( )
198- . unwrap ( )
199- . to_string ( ) ,
200- fs:: read ( entry. path ( ) ) . unwrap ( ) ,
201- ) ;
202- }
203- }
204-
205- // Ensure they contain the same files.
206- let before = files_before. keys ( ) . collect :: < Vec < _ > > ( ) ;
207- let after = files_after. keys ( ) . collect :: < Vec < _ > > ( ) ;
208- assert_eq ! ( before, after) ;
209-
210- for ( ( file, before) , ( _, after) ) in files_before. iter ( ) . zip ( files_after. iter ( ) ) {
211- if before != after {
212- panic ! (
213- "{} is not up-to-date, please run `cargo xtask assemble`" ,
214- file
215- ) ;
216- }
217- }
218-
219- println ! ( "Blobs identical." ) ;
220- }
221-
22221// Check that serde and PartialOrd works with VectActive
22322pub fn check_host_side ( ) {
22423 use cortex_m:: peripheral:: scb:: VectActive ;
0 commit comments