@@ -13,8 +13,8 @@ use crate::ffi_items::FfiItems;
1313use crate :: template:: { CTestTemplate , RustTestTemplate } ;
1414use crate :: translator:: translate_primitive_type;
1515use 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,
1818} ;
1919
2020/// 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>;
3535#[ derive( Default ) ]
3636#[ expect( missing_debug_implementations) ]
3737pub struct TestGenerator {
38- pub ( crate ) headers : Vec < String > ,
38+ pub ( crate ) headers : Vec < ( BoxStr , Vec < BoxStr > ) > ,
3939 pub ( crate ) target : Option < String > ,
4040 pub ( crate ) includes : Vec < PathBuf > ,
4141 out_dir : Option < PathBuf > ,
4242 pub ( crate ) flags : Vec < String > ,
43- pub ( crate ) defines : Vec < ( String , Option < String > ) > ,
43+ pub ( crate ) global_defines : Vec < ( String , Option < String > ) > ,
4444 cfg : Vec < ( String , Option < String > ) > ,
4545 mapped_names : Vec < MappedName > ,
46+ /// The programming language to generate tests in.
47+ pub ( crate ) language : Language ,
4648 pub ( crate ) skips : Vec < Skip > ,
4749 pub ( crate ) verbose_skip : bool ,
4850 pub ( crate ) volatile_items : Vec < VolatileItem > ,
@@ -100,7 +102,53 @@ impl TestGenerator {
100102 /// .header("bar.h");
101103 /// ```
102104 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;
104152 self
105153 }
106154
@@ -585,7 +633,7 @@ impl TestGenerator {
585633
586634 /// Set a `-D` flag for the C compiler being called.
587635 ///
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
589637 /// files are included or what APIs are exposed from header files.
590638 ///
591639 /// # Examples
@@ -598,7 +646,7 @@ impl TestGenerator {
598646 /// .define("_WIN32_WINNT", Some("0x8000"));
599647 /// ```
600648 pub fn define ( & mut self , k : & str , v : Option < & str > ) -> & mut Self {
601- self . defines
649+ self . global_defines
602650 . push ( ( k. to_string ( ) , v. map ( std:: string:: ToString :: to_string) ) ) ;
603651 self
604652 }
@@ -999,7 +1047,7 @@ impl TestGenerator {
9991047 ensure_trailing_newline ( & mut c_file) ;
10001048
10011049 // 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 ( ) ) ;
10031051 File :: create ( & c_output_path)
10041052 . map_err ( GenerationError :: OsError ) ?
10051053 . write_all ( c_file. as_bytes ( ) )
0 commit comments