diff --git a/plugins/bntl_utils/cli/src/create.rs b/plugins/bntl_utils/cli/src/create.rs index c83f4f8f66..c6d9332f12 100644 --- a/plugins/bntl_utils/cli/src/create.rs +++ b/plugins/bntl_utils/cli/src/create.rs @@ -19,6 +19,9 @@ pub struct CreateArgs { pub include_directories: Vec, #[clap(long)] pub dry_run: bool, + /// A list of additional compiler options to pass to the compiler when parsing C header files. + #[arg(last = true, allow_hyphen_values = true, num_args = 0..)] + compiler_options: Vec, } impl CreateArgs { @@ -41,7 +44,8 @@ impl CreateArgs { std::fs::create_dir_all(&output_path).expect("Failed to create output directory"); let processor = TypeLibProcessor::new(&self.name, &self.platform) - .with_include_directories(self.include_directories.clone()); + .with_include_directories(self.include_directories.clone()) + .with_compiler_options(self.compiler_options.clone()); // TODO: Need progress indicator here, when downloading files. let resolved_input = self.input.resolve().expect("Failed to resolve input"); diff --git a/plugins/bntl_utils/src/command/create.rs b/plugins/bntl_utils/src/command/create.rs index 8fc37159e6..01a4adb563 100644 --- a/plugins/bntl_utils/src/command/create.rs +++ b/plugins/bntl_utils/src/command/create.rs @@ -124,6 +124,23 @@ impl PlatformField { } } +pub struct CompilerOptionsField; + +impl CompilerOptionsField { + pub fn field() -> FormInputField { + FormInputField::MultilineText { + prompt: "Compiler options".to_string(), + default: None, + value: None, + } + } + + pub fn from_form(form: &Form) -> Option { + let field = form.get_field_with_name("Compiler options")?; + field.try_value_string() + } +} + pub struct CreateFromDirectory; impl CreateFromDirectory { @@ -134,6 +151,8 @@ impl CreateFromDirectory { form.add_field(PlatformField::field()); form.add_field(NameField::field()); form.add_field(OutputDirectoryField::field()); + form.add_field(CompilerOptionsField::field()); + if !form.prompt() { return; } @@ -141,13 +160,15 @@ impl CreateFromDirectory { let platform_name = PlatformField::from_form(&form).unwrap(); let default_name = NameField::from_form(&form).unwrap(); let output_dir = OutputDirectoryField::from_form(&form).unwrap(); + let flags = CompilerOptionsField::from_form(&form).unwrap(); let Some(default_platform) = Platform::by_name(&platform_name) else { tracing::error!("Invalid platform name: {}", platform_name); return; }; - let processor = TypeLibProcessor::new(&default_name, &default_platform.name()); + let processor = TypeLibProcessor::new(&default_name, &default_platform.name()) + .with_compiler_options(split_args(flags.as_str())); let background_task = BackgroundTask::new("Processing started...", true); new_processing_state_background_thread(background_task.clone(), processor.state()); @@ -274,3 +295,22 @@ impl ProjectCommand for CreateFromProject { true } } + +fn split_args(input: &str) -> Vec { + let mut args = Vec::new(); + let mut cur = String::new(); + let mut in_quote = false; + let mut has_token = false; + + for c in input.chars() { + match c { + '"' => { in_quote = !in_quote; has_token = true; } + c if c.is_whitespace() && !in_quote => { + if has_token { args.push(std::mem::take(&mut cur)); has_token = false; } + } + c => { cur.push(c); has_token = true; } + } + } + if has_token { args.push(cur); } + args +} diff --git a/plugins/bntl_utils/src/process.rs b/plugins/bntl_utils/src/process.rs index 5c9651a473..7c9d962566 100644 --- a/plugins/bntl_utils/src/process.rs +++ b/plugins/bntl_utils/src/process.rs @@ -434,6 +434,8 @@ pub struct TypeLibProcessor { include_directories: Vec, /// Whether to process existing type libraries when processing a binary file. process_existing_type_libraries: bool, + /// The compiler flags to use when processing header files. + compiler_options: Vec, } impl TypeLibProcessor { @@ -448,6 +450,7 @@ impl TypeLibProcessor { default_platform_name: default_platform_name.to_owned(), include_directories: Vec::new(), process_existing_type_libraries: false, + compiler_options: Vec::new(), } } @@ -461,6 +464,11 @@ impl TypeLibProcessor { self } + pub fn with_compiler_options(mut self, options: Vec) -> Self { + self.compiler_options = options; + self + } + /// Whether to process existing type libraries when processing a binary file. /// /// If you open `mymodule.dll` and it imports functions from `kernel32.dll`, any import found @@ -988,7 +996,7 @@ impl TypeLibProcessor { &file_name, &platform, &platform_type_container, - &[], + &self.compiler_options, &include_dirs, "", )