@@ -13,8 +13,8 @@ use crate::ffi_items::FfiItems;
13
13
use crate :: template:: { CTestTemplate , RustTestTemplate } ;
14
14
use crate :: translator:: translate_primitive_type;
15
15
use crate :: {
16
- Const , Field , MapInput , Parameter , Result , Static , Struct , TranslationError , Type , Union ,
17
- VolatileItemKind , expand, get_build_target,
16
+ BoxStr , Const , Field , Language , MapInput , Parameter , Result , Static , Struct , TranslationError ,
17
+ Type , Union , VolatileItemKind , expand, get_build_target,
18
18
} ;
19
19
20
20
/// A function that takes a mappable input and returns its mapping as `Some`, otherwise
@@ -35,14 +35,16 @@ type CEnum = Box<dyn Fn(&str) -> bool>;
35
35
#[ derive( Default ) ]
36
36
#[ expect( missing_debug_implementations) ]
37
37
pub struct TestGenerator {
38
- pub ( crate ) headers : Vec < String > ,
38
+ pub ( crate ) headers : Vec < ( BoxStr , Vec < BoxStr > ) > ,
39
39
pub ( crate ) target : Option < String > ,
40
40
pub ( crate ) includes : Vec < PathBuf > ,
41
41
out_dir : Option < PathBuf > ,
42
42
pub ( crate ) flags : Vec < String > ,
43
- pub ( crate ) defines : Vec < ( String , Option < String > ) > ,
43
+ pub ( crate ) global_defines : Vec < ( String , Option < String > ) > ,
44
44
cfg : Vec < ( String , Option < String > ) > ,
45
45
mapped_names : Vec < MappedName > ,
46
+ /// The programming language to generate tests in.
47
+ pub ( crate ) language : Language ,
46
48
pub ( crate ) skips : Vec < Skip > ,
47
49
pub ( crate ) verbose_skip : bool ,
48
50
pub ( crate ) volatile_items : Vec < VolatileItem > ,
@@ -100,7 +102,53 @@ impl TestGenerator {
100
102
/// .header("bar.h");
101
103
/// ```
102
104
pub fn header ( & mut self , header : & str ) -> & mut Self {
103
- self . headers . push ( header. to_string ( ) ) ;
105
+ self . headers . push ( ( header. into ( ) , vec ! [ ] ) ) ;
106
+ self
107
+ }
108
+
109
+ /// Add a header to be included as part of the generated C file, as well as defines for it.
110
+ ///
111
+ /// The generated C test will be compiled by a C compiler, and this can be
112
+ /// used to ensure that all the necessary header files are included to test
113
+ /// all FFI definitions. The defines are only set for the inclusion of that header file, and are
114
+ /// undefined immediately after.
115
+ ///
116
+ /// # Examples
117
+ ///
118
+ /// ```no_run
119
+ /// use ctest::TestGenerator;
120
+ ///
121
+ /// let mut cfg = TestGenerator::new();
122
+ /// cfg.header_with_defines("foo.h", Vec::<String>::new())
123
+ /// .header_with_defines("bar.h", vec!["DEBUG", "DEPRECATED"]);
124
+ /// ```
125
+ pub fn header_with_defines (
126
+ & mut self ,
127
+ header : & str ,
128
+ defines : impl IntoIterator < Item = impl AsRef < str > > ,
129
+ ) -> & mut Self {
130
+ self . headers . push ( (
131
+ header. into ( ) ,
132
+ defines. into_iter ( ) . map ( |d| d. as_ref ( ) . into ( ) ) . collect ( ) ,
133
+ ) ) ;
134
+ self
135
+ }
136
+
137
+ /// Sets the programming language, by default it is C.
138
+ ///
139
+ /// This determines what compiler is chosen to compile the C/C++ tests, as well as adding
140
+ /// external linkage to the tests if set to C++, so that they can be used in Rust.
141
+ ///
142
+ /// # Examples
143
+ ///
144
+ /// ```no_run
145
+ /// use ctest::{TestGenerator, Language};
146
+ ///
147
+ /// let mut cfg = TestGenerator::new();
148
+ /// cfg.language(Language::CXX);
149
+ /// ```
150
+ pub fn language ( & mut self , language : Language ) -> & mut Self {
151
+ self . language = language;
104
152
self
105
153
}
106
154
@@ -585,7 +633,7 @@ impl TestGenerator {
585
633
586
634
/// Set a `-D` flag for the C compiler being called.
587
635
///
588
- /// This can be used to define various variables to configure how header
636
+ /// This can be used to define various global variables to configure how header
589
637
/// files are included or what APIs are exposed from header files.
590
638
///
591
639
/// # Examples
@@ -598,7 +646,7 @@ impl TestGenerator {
598
646
/// .define("_WIN32_WINNT", Some("0x8000"));
599
647
/// ```
600
648
pub fn define ( & mut self , k : & str , v : Option < & str > ) -> & mut Self {
601
- self . defines
649
+ self . global_defines
602
650
. push ( ( k. to_string ( ) , v. map ( std:: string:: ToString :: to_string) ) ) ;
603
651
self
604
652
}
@@ -999,7 +1047,7 @@ impl TestGenerator {
999
1047
ensure_trailing_newline ( & mut c_file) ;
1000
1048
1001
1049
// Generate the C/Cxx side of the tests.
1002
- let c_output_path = output_file_path. with_extension ( "c" ) ;
1050
+ let c_output_path = output_file_path. with_extension ( self . language . extension ( ) ) ;
1003
1051
File :: create ( & c_output_path)
1004
1052
. map_err ( GenerationError :: OsError ) ?
1005
1053
. write_all ( c_file. as_bytes ( ) )
0 commit comments