1
1
//@ needs-force-clang-based-tests
2
+ // This test checks that the clang defines for each target allign with the core ffi types defined in
3
+ // mod.rs. Therefore each rust target is queried and the clang defines for each target are read and
4
+ // compared to the core sizes to verify all types and sizes allign at buildtime.
5
+ //
6
+ // If this test fails because Rust adds a target that Clang does not support, this target should be
7
+ // added to SKIPPED_TARGETS.
2
8
3
9
use run_make_support:: { clang, regex, rfs, rustc} ;
4
10
11
+ // It is not possible to run the Rust test-suite on these targets.
5
12
const SKIPPED_TARGETS : & [ & str ] = & [
6
- "riscv" , //error: unknown target triple 'riscv32e-unknown-none-elf'
7
- "wasm" , //error: unknown target triple 'wasm32v1-none'
8
- "xtensa" , //error: unknown target triple 'xtensa-esp32-espidf'
13
+ "riscv32gc-unknown-linux-gnu" ,
14
+ "riscv32gc-unknown-linux-musl" ,
15
+ "riscv32im-risc0-zkvm-elf" ,
16
+ "riscv32imac-esp-espidf" ,
17
+ "riscv32imafc-esp-espidf" ,
18
+ "riscv32imafc-unknown-nuttx-elf" ,
19
+ "riscv32imc-esp-espidf" ,
20
+ "riscv32imac-unknown-nuttx-elf" ,
21
+ "riscv32imac-unknown-xous-elf" ,
22
+ "riscv32imc-unknown-nuttx-elf" ,
23
+ "riscv32e-unknown-none-elf" ,
24
+ "riscv32em-unknown-none-elf" ,
25
+ "riscv32emc-unknown-none-elf" ,
26
+ "riscv32i-unknown-none-elf" ,
27
+ "riscv32im-unknown-none-elf" ,
28
+ "riscv32imc-unknown-none-elf" ,
29
+ "riscv32ima-unknown-none-elf" ,
30
+ "riscv32imac-unknown-none-elf" ,
31
+ "riscv32imafc-unknown-none-elf" ,
32
+ "riscv64gc-unknown-freebsd" ,
33
+ "riscv64gc-unknown-fuchsia" ,
34
+ "riscv64gc-unknown-hermit" ,
35
+ "riscv64gc-unknown-linux-gnu" ,
36
+ "riscv64gc-unknown-linux-musl" ,
37
+ "riscv64gc-unknown-netbsd" ,
38
+ "riscv64gc-unknown-none-elf" ,
39
+ "riscv64gc-unknown-nuttx-elf" ,
40
+ "riscv64gc-unknown-openbsd" ,
41
+ "riscv64imac-unknown-none-elf" ,
42
+ "riscv64imac-unknown-nuttx-elf" ,
43
+ "wasm32v1-none" ,
44
+ "xtensa-esp32-espidf" ,
45
+ "xtensa-esp32-none-elf" ,
46
+ "xtensa-esp32s2-espidf" ,
47
+ "xtensa-esp32s2-none-elf" ,
48
+ "xtensa-esp32s3-espidf" ,
49
+ "xtensa-esp32s3-none-elf" ,
9
50
] ;
10
51
11
52
fn main ( ) {
@@ -16,13 +57,18 @@ fn main() {
16
57
regex_mod ( ) ;
17
58
18
59
for target in targets. lines ( ) {
19
- if SKIPPED_TARGETS . iter ( ) . any ( |prefix | target. starts_with ( prefix ) ) {
60
+ if SKIPPED_TARGETS . iter ( ) . any ( |& to_skip_target | target == to_skip_target ) {
20
61
continue ;
21
62
}
22
63
64
+ // Run Clang's preprocessor for the relevant target, printing default macro definitions.
23
65
let clang_output =
24
66
clang ( ) . args ( & [ "-E" , "-dM" , "-x" , "c" , "/dev/null" , "-target" , target] ) . run ( ) ;
25
67
68
+ if !clang_output. status ( ) . success ( ) {
69
+ continue ;
70
+ }
71
+
26
72
let defines = String :: from_utf8 ( clang_output. stdout ( ) ) . expect ( "Invalid UTF-8" ) ;
27
73
28
74
let minicore_content = rfs:: read_to_string ( & minicore_path) ;
@@ -33,13 +79,16 @@ fn main() {
33
79
#![feature(link_cfg)]
34
80
#![allow(unused)]
35
81
#![crate_type = "rlib"]
36
- {}
82
+
83
+ /* begin minicore content */
84
+ {minicore_content}
85
+ /* end minicore content */
86
+
37
87
#[path = "processed_mod.rs"]
38
88
mod ffi;
39
89
#[path = "tests.rs"]
40
90
mod tests;
41
- "# ,
42
- minicore_content
91
+ "#
43
92
) ;
44
93
45
94
rmake_content. push_str ( & format ! (
@@ -54,7 +103,7 @@ fn main() {
54
103
const CLANG_C_DOUBLE_SIZE: usize = {};
55
104
" ,
56
105
parse_size( & defines, "CHAR" ) ,
57
- parse_signed ( & defines, "CHAR" ) ,
106
+ char_is_signed ( & defines) ,
58
107
parse_size( & defines, "SHORT" ) ,
59
108
parse_size( & defines, "INT" ) ,
60
109
parse_size( & defines, "LONG" ) ,
@@ -63,20 +112,20 @@ fn main() {
63
112
parse_size( & defines, "DOUBLE" ) ,
64
113
) ) ;
65
114
66
- // Write to target-specific rmake file
67
- let mut file_name = format ! ( "{}_rmake.rs" , target. replace( "-" , "_" ) ) ;
115
+ // Generate a target-specific rmake file.
116
+ // If type misalignments occur, use the generated rmake file name to identify the failing target.
117
+ // Replace dots (.) and hyphens (-) in the target name with underscores to ensure valid filenames.
118
+ let file_name = format ! ( "{}_rmake.rs" , target. replace( "-" , "_" ) . replace( "." , "_" ) ) ;
68
119
69
- if target. starts_with ( "thumbv8m" ) {
70
- file_name = String :: from ( "thumbv8m_rmake.rs" ) ;
71
- }
72
-
73
- rfs:: create_file ( & file_name) ;
120
+ // Attempt to build the test file for the relevant target. Tests use constant evaluation,
121
+ // so running is not necessary.
74
122
rfs:: write ( & file_name, rmake_content) ;
75
123
let rustc_output = rustc ( )
76
124
. arg ( "-Zunstable-options" )
77
125
. arg ( "--emit=metadata" )
78
126
. arg ( "--target" )
79
127
. arg ( target)
128
+ . arg ( "-o-" )
80
129
. arg ( & file_name)
81
130
. run ( ) ;
82
131
rfs:: remove_file ( & file_name) ;
@@ -89,6 +138,7 @@ fn main() {
89
138
rfs:: remove_file ( "processed_mod.rs" ) ;
90
139
}
91
140
141
+ /// Get a list of available targets for 'rustc'.
92
142
fn get_target_list ( ) -> String {
93
143
let completed_process = rustc ( ) . arg ( "--print" ) . arg ( "target-list" ) . run ( ) ;
94
144
String :: from_utf8 ( completed_process. stdout ( ) ) . expect ( "error not a string" )
@@ -113,18 +163,11 @@ fn parse_size(defines: &str, type_name: &str) -> usize {
113
163
panic ! ( "Could not find size definition for type: {}" , type_name) ;
114
164
}
115
165
116
- // Helper to parse signedness from clang defines
117
- fn parse_signed ( defines : & str , type_name : & str ) -> bool {
118
- match type_name. to_uppercase ( ) . as_str ( ) {
119
- "CHAR" => {
120
- // Check if char is explicitly unsigned
121
- !defines. lines ( ) . any ( |line| line. contains ( "__CHAR_UNSIGNED__" ) )
122
- }
123
- _ => true ,
124
- }
166
+ fn char_is_signed ( defines : & str ) -> bool {
167
+ !defines. lines ( ) . any ( |line| line. contains ( "__CHAR_UNSIGNED__" ) )
125
168
}
126
169
127
- // Parse core/ffi/mod.rs to retrieve only necessary macros and type defines
170
+ /// Parse core/ffi/mod.rs to retrieve only necessary macros and type defines
128
171
fn regex_mod ( ) {
129
172
let mod_path = run_make_support:: source_root ( ) . join ( "library/core/src/ffi/mod.rs" ) ;
130
173
let mut content = rfs:: read_to_string ( & mod_path) ;
@@ -157,7 +200,7 @@ fn regex_mod() {
157
200
re = regex:: Regex :: new ( r"(?s)impl fmt::Debug for.*?\{.*?\}" ) . unwrap ( ) ;
158
201
content = re. replace_all ( & content, "" ) . to_string ( ) ;
159
202
160
- let file_name = format ! ( "processed_mod.rs" ) ;
203
+ let file_name = "processed_mod.rs" ;
161
204
162
205
rfs:: create_file ( & file_name) ;
163
206
rfs:: write ( & file_name, content) ;
0 commit comments