Autodetect llvm-config for QEMU bindings generation (#1610)
* Autodetect llvm-config for QEMU bindings generation * fix ci * Fix signal handlers without ucontext pointer * ci
This commit is contained in:
parent
bbb999f4d5
commit
31f4669794
6
.github/workflows/build_and_test.yml
vendored
6
.github/workflows/build_and_test.yml
vendored
@ -145,7 +145,7 @@ jobs:
|
|||||||
# Skipping `python` as it has to be built with the `maturin` tool
|
# Skipping `python` as it has to be built with the `maturin` tool
|
||||||
# `agpl`, `nautilus` require nightly
|
# `agpl`, `nautilus` require nightly
|
||||||
# `sancov_pcguard_edges` is tested seperately
|
# `sancov_pcguard_edges` is tested seperately
|
||||||
run: cargo hack check --each-feature --clean-per-run --exclude-features=prelude,agpl,nautilus,python,sancov_pcguard_edges,arm,aarch64,i386,be,systemmode --no-dev-deps
|
run: LLVM_CONFIG=llvm-config-15 cargo hack check --each-feature --clean-per-run --exclude-features=prelude,agpl,nautilus,python,sancov_pcguard_edges,arm,aarch64,i386,be,systemmode --no-dev-deps
|
||||||
- name: Check nightly features
|
- name: Check nightly features
|
||||||
run: cargo +nightly check --features=agpl && cargo +nightly check --features=nautilus
|
run: cargo +nightly check --features=agpl && cargo +nightly check --features=nautilus
|
||||||
|
|
||||||
@ -179,7 +179,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: Swatinem/rust-cache@v2
|
- uses: Swatinem/rust-cache@v2
|
||||||
- name: Run a maturin build
|
- name: Run a maturin build
|
||||||
run: LLVM_CONFIG_PATH=llvm-config-15 cd ./bindings/pylibafl && python3 -m venv .env && . .env/bin/activate && pip install --upgrade --force-reinstall . && ./test.sh
|
run: export LLVM_CONFIG=llvm-config-15 && cd ./bindings/pylibafl && python3 -m venv .env && . .env/bin/activate && pip install --upgrade --force-reinstall . && ./test.sh
|
||||||
- name: Run python test
|
- name: Run python test
|
||||||
run: . ./bindings/pylibafl/.env/bin/activate && cd ./fuzzers/baby_fuzzer && python3 baby_fuzzer.py 2>&1 | grep "Bye"
|
run: . ./bindings/pylibafl/.env/bin/activate && cd ./fuzzers/baby_fuzzer && python3 baby_fuzzer.py 2>&1 | grep "Bye"
|
||||||
|
|
||||||
@ -270,7 +270,7 @@ jobs:
|
|||||||
run: sudo ln -s /usr/include/asm-generic /usr/include/asm
|
run: sudo ln -s /usr/include/asm-generic /usr/include/asm
|
||||||
- name: Build and run example fuzzers (Linux)
|
- name: Build and run example fuzzers (Linux)
|
||||||
if: runner.os == 'Linux'
|
if: runner.os == 'Linux'
|
||||||
run: RUN_ON_CI=1 ./scripts/test_all_fuzzers.sh
|
run: RUN_ON_CI=1 LLVM_CONFIG=llvm-config-15 ./scripts/test_all_fuzzers.sh
|
||||||
- name: Build and run example fuzzers (macOS)
|
- name: Build and run example fuzzers (macOS)
|
||||||
if: runner.os == 'macOS' # use bash v4
|
if: runner.os == 'macOS' # use bash v4
|
||||||
run: /usr/local/bin/bash -c 'RUN_ON_CI=1 ./scripts/test_all_fuzzers.sh'
|
run: /usr/local/bin/bash -c 'RUN_ON_CI=1 ./scripts/test_all_fuzzers.sh'
|
||||||
|
@ -68,7 +68,7 @@ pub struct ShutdownSignalData {
|
|||||||
/// Type for shutdown handler
|
/// Type for shutdown handler
|
||||||
#[cfg(all(unix, feature = "std"))]
|
#[cfg(all(unix, feature = "std"))]
|
||||||
pub type ShutdownFuncPtr =
|
pub type ShutdownFuncPtr =
|
||||||
unsafe fn(Signal, &mut siginfo_t, &mut ucontext_t, data: &mut ShutdownSignalData);
|
unsafe fn(Signal, &mut siginfo_t, Option<&mut ucontext_t>, data: &mut ShutdownSignalData);
|
||||||
|
|
||||||
/// Shutdown handler. `SigTerm`, `SigInterrupt`, `SigQuit` call this
|
/// Shutdown handler. `SigTerm`, `SigInterrupt`, `SigQuit` call this
|
||||||
/// We can't handle SIGKILL in the signal handler, this means that you shouldn't kill your fuzzer with `kill -9` because then the shmem segments are never freed
|
/// We can't handle SIGKILL in the signal handler, this means that you shouldn't kill your fuzzer with `kill -9` because then the shmem segments are never freed
|
||||||
@ -80,7 +80,7 @@ pub type ShutdownFuncPtr =
|
|||||||
pub unsafe fn shutdown_handler<SP>(
|
pub unsafe fn shutdown_handler<SP>(
|
||||||
signal: Signal,
|
signal: Signal,
|
||||||
_info: &mut siginfo_t,
|
_info: &mut siginfo_t,
|
||||||
_context: &mut ucontext_t,
|
_context: Option<&mut ucontext_t>,
|
||||||
data: &ShutdownSignalData,
|
data: &ShutdownSignalData,
|
||||||
) where
|
) where
|
||||||
SP: ShMemProvider,
|
SP: ShMemProvider,
|
||||||
@ -106,7 +106,7 @@ pub unsafe fn shutdown_handler<SP>(
|
|||||||
|
|
||||||
#[cfg(all(unix, feature = "std"))]
|
#[cfg(all(unix, feature = "std"))]
|
||||||
impl Handler for ShutdownSignalData {
|
impl Handler for ShutdownSignalData {
|
||||||
fn handle(&mut self, signal: Signal, info: &mut siginfo_t, context: &mut ucontext_t) {
|
fn handle(&mut self, signal: Signal, info: &mut siginfo_t, context: Option<&mut ucontext_t>) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let data = &mut SHUTDOWN_SIGHANDLER_DATA;
|
let data = &mut SHUTDOWN_SIGHANDLER_DATA;
|
||||||
if !data.shutdown_handler.is_null() {
|
if !data.shutdown_handler.is_null() {
|
||||||
|
@ -659,21 +659,30 @@ pub mod unix_signal_handler {
|
|||||||
state::{HasClientPerfMonitor, HasCorpus, HasSolutions},
|
state::{HasClientPerfMonitor, HasCorpus, HasSolutions},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) type HandlerFuncPtr =
|
pub(crate) type HandlerFuncPtr = unsafe fn(
|
||||||
unsafe fn(Signal, &mut siginfo_t, &mut ucontext_t, data: &mut InProcessExecutorHandlerData);
|
Signal,
|
||||||
|
&mut siginfo_t,
|
||||||
|
Option<&mut ucontext_t>,
|
||||||
|
data: &mut InProcessExecutorHandlerData,
|
||||||
|
);
|
||||||
|
|
||||||
/// A handler that does nothing.
|
/// A handler that does nothing.
|
||||||
/*pub fn nop_handler(
|
/*pub fn nop_handler(
|
||||||
_signal: Signal,
|
_signal: Signal,
|
||||||
_info: &mut siginfo_t,
|
_info: &mut siginfo_t,
|
||||||
_context: &mut ucontext_t,
|
_context: Option<&mut ucontext_t>,
|
||||||
_data: &mut InProcessExecutorHandlerData,
|
_data: &mut InProcessExecutorHandlerData,
|
||||||
) {
|
) {
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
impl Handler for InProcessExecutorHandlerData {
|
impl Handler for InProcessExecutorHandlerData {
|
||||||
fn handle(&mut self, signal: Signal, info: &mut siginfo_t, context: &mut ucontext_t) {
|
fn handle(
|
||||||
|
&mut self,
|
||||||
|
signal: Signal,
|
||||||
|
info: &mut siginfo_t,
|
||||||
|
context: Option<&mut ucontext_t>,
|
||||||
|
) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let data = &mut GLOBAL_STATE;
|
let data = &mut GLOBAL_STATE;
|
||||||
let in_handler = data.set_in_handler(true);
|
let in_handler = data.set_in_handler(true);
|
||||||
@ -759,7 +768,7 @@ pub mod unix_signal_handler {
|
|||||||
pub unsafe fn inproc_timeout_handler<E, EM, OF, Z>(
|
pub unsafe fn inproc_timeout_handler<E, EM, OF, Z>(
|
||||||
_signal: Signal,
|
_signal: Signal,
|
||||||
_info: &mut siginfo_t,
|
_info: &mut siginfo_t,
|
||||||
_context: &mut ucontext_t,
|
_context: Option<&mut ucontext_t>,
|
||||||
data: &mut InProcessExecutorHandlerData,
|
data: &mut InProcessExecutorHandlerData,
|
||||||
) where
|
) where
|
||||||
E: HasObservers,
|
E: HasObservers,
|
||||||
@ -809,7 +818,7 @@ pub mod unix_signal_handler {
|
|||||||
pub unsafe fn inproc_crash_handler<E, EM, OF, Z>(
|
pub unsafe fn inproc_crash_handler<E, EM, OF, Z>(
|
||||||
signal: Signal,
|
signal: Signal,
|
||||||
_info: &mut siginfo_t,
|
_info: &mut siginfo_t,
|
||||||
_context: &mut ucontext_t,
|
_context: Option<&mut ucontext_t>,
|
||||||
data: &mut InProcessExecutorHandlerData,
|
data: &mut InProcessExecutorHandlerData,
|
||||||
) where
|
) where
|
||||||
E: Executor<EM, Z> + HasObservers,
|
E: Executor<EM, Z> + HasObservers,
|
||||||
@ -840,8 +849,13 @@ pub mod unix_signal_handler {
|
|||||||
{
|
{
|
||||||
let mut writer = std::io::BufWriter::new(&mut bsod);
|
let mut writer = std::io::BufWriter::new(&mut bsod);
|
||||||
writeln!(writer, "input: {:?}", input.generate_name(0)).unwrap();
|
writeln!(writer, "input: {:?}", input.generate_name(0)).unwrap();
|
||||||
libafl_bolts::minibsod::generate_minibsod(&mut writer, signal, _info, _context)
|
libafl_bolts::minibsod::generate_minibsod(
|
||||||
.unwrap();
|
&mut writer,
|
||||||
|
signal,
|
||||||
|
_info,
|
||||||
|
_context.as_deref(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
writer.flush().unwrap();
|
writer.flush().unwrap();
|
||||||
}
|
}
|
||||||
log::error!("{}", std::str::from_utf8(&bsod).unwrap());
|
log::error!("{}", std::str::from_utf8(&bsod).unwrap());
|
||||||
@ -864,7 +878,7 @@ pub mod unix_signal_handler {
|
|||||||
let si_addr = { _info.si_addr() as usize };
|
let si_addr = { _info.si_addr() as usize };
|
||||||
|
|
||||||
log::error!(
|
log::error!(
|
||||||
"We crashed at addr 0x{si_addr:x}, but are not in the target... Bug in the fuzzer? Exiting."
|
"We crashed at addr 0x{si_addr:x}, but are not in the target... Bug in the fuzzer? Exiting."
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(all(feature = "std", unix))]
|
#[cfg(all(feature = "std", unix))]
|
||||||
@ -876,7 +890,7 @@ pub mod unix_signal_handler {
|
|||||||
&mut writer,
|
&mut writer,
|
||||||
signal,
|
signal,
|
||||||
_info,
|
_info,
|
||||||
_context,
|
_context.as_deref(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
writer.flush().unwrap();
|
writer.flush().unwrap();
|
||||||
@ -1322,8 +1336,12 @@ pub mod windows_exception_handler {
|
|||||||
|
|
||||||
/// The signature of the crash handler function
|
/// The signature of the crash handler function
|
||||||
#[cfg(all(feature = "std", unix))]
|
#[cfg(all(feature = "std", unix))]
|
||||||
pub(crate) type ForkHandlerFuncPtr =
|
pub(crate) type ForkHandlerFuncPtr = unsafe fn(
|
||||||
unsafe fn(Signal, &mut siginfo_t, &mut ucontext_t, data: &mut InProcessForkExecutorGlobalData);
|
Signal,
|
||||||
|
&mut siginfo_t,
|
||||||
|
Option<&mut ucontext_t>,
|
||||||
|
data: &mut InProcessForkExecutorGlobalData,
|
||||||
|
);
|
||||||
|
|
||||||
/// The inmem fork executor's handlers.
|
/// The inmem fork executor's handlers.
|
||||||
#[cfg(all(feature = "std", unix))]
|
#[cfg(all(feature = "std", unix))]
|
||||||
@ -1463,7 +1481,7 @@ pub(crate) static mut FORK_EXECUTOR_GLOBAL_DATA: InProcessForkExecutorGlobalData
|
|||||||
|
|
||||||
#[cfg(all(feature = "std", unix))]
|
#[cfg(all(feature = "std", unix))]
|
||||||
impl Handler for InProcessForkExecutorGlobalData {
|
impl Handler for InProcessForkExecutorGlobalData {
|
||||||
fn handle(&mut self, signal: Signal, info: &mut siginfo_t, context: &mut ucontext_t) {
|
fn handle(&mut self, signal: Signal, info: &mut siginfo_t, context: Option<&mut ucontext_t>) {
|
||||||
match signal {
|
match signal {
|
||||||
Signal::SigUser2 | Signal::SigAlarm => unsafe {
|
Signal::SigUser2 | Signal::SigAlarm => unsafe {
|
||||||
if !FORK_EXECUTOR_GLOBAL_DATA.timeout_handler.is_null() {
|
if !FORK_EXECUTOR_GLOBAL_DATA.timeout_handler.is_null() {
|
||||||
@ -2076,7 +2094,7 @@ pub mod child_signal_handlers {
|
|||||||
pub(crate) unsafe fn child_crash_handler<E>(
|
pub(crate) unsafe fn child_crash_handler<E>(
|
||||||
_signal: Signal,
|
_signal: Signal,
|
||||||
_info: &mut siginfo_t,
|
_info: &mut siginfo_t,
|
||||||
_context: &mut ucontext_t,
|
_context: Option<&mut ucontext_t>,
|
||||||
data: &mut InProcessForkExecutorGlobalData,
|
data: &mut InProcessForkExecutorGlobalData,
|
||||||
) where
|
) where
|
||||||
E: HasObservers,
|
E: HasObservers,
|
||||||
@ -2098,7 +2116,7 @@ pub mod child_signal_handlers {
|
|||||||
pub(crate) unsafe fn child_timeout_handler<E>(
|
pub(crate) unsafe fn child_timeout_handler<E>(
|
||||||
_signal: Signal,
|
_signal: Signal,
|
||||||
_info: &mut siginfo_t,
|
_info: &mut siginfo_t,
|
||||||
_context: &mut ucontext_t,
|
_context: Option<&mut ucontext_t>,
|
||||||
data: &mut InProcessForkExecutorGlobalData,
|
data: &mut InProcessForkExecutorGlobalData,
|
||||||
) where
|
) where
|
||||||
E: HasObservers,
|
E: HasObservers,
|
||||||
|
@ -1939,7 +1939,12 @@ pub struct LlmpShutdownSignalHandler {
|
|||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
impl Handler for LlmpShutdownSignalHandler {
|
impl Handler for LlmpShutdownSignalHandler {
|
||||||
fn handle(&mut self, _signal: Signal, _info: &mut siginfo_t, _context: &mut ucontext_t) {
|
fn handle(
|
||||||
|
&mut self,
|
||||||
|
_signal: Signal,
|
||||||
|
_info: &mut siginfo_t,
|
||||||
|
_context: Option<&mut ucontext_t>,
|
||||||
|
) {
|
||||||
unsafe {
|
unsafe {
|
||||||
ptr::write_volatile(&mut self.shutting_down, true);
|
ptr::write_volatile(&mut self.shutting_down, true);
|
||||||
}
|
}
|
||||||
|
@ -837,12 +837,16 @@ pub fn generate_minibsod<W: Write>(
|
|||||||
writer: &mut BufWriter<W>,
|
writer: &mut BufWriter<W>,
|
||||||
signal: Signal,
|
signal: Signal,
|
||||||
_siginfo: &siginfo_t,
|
_siginfo: &siginfo_t,
|
||||||
ucontext: &ucontext_t,
|
ucontext: Option<&ucontext_t>,
|
||||||
) -> Result<(), std::io::Error> {
|
) -> Result<(), std::io::Error> {
|
||||||
writeln!(writer, "{:━^100}", " CRASH ")?;
|
writeln!(writer, "{:━^100}", " CRASH ")?;
|
||||||
write_crash(writer, signal, ucontext)?;
|
if let Some(uctx) = ucontext {
|
||||||
writeln!(writer, "{:━^100}", " REGISTERS ")?;
|
write_crash(writer, signal, uctx)?;
|
||||||
dump_registers(writer, ucontext)?;
|
writeln!(writer, "{:━^100}", " REGISTERS ")?;
|
||||||
|
dump_registers(writer, uctx)?;
|
||||||
|
} else {
|
||||||
|
writeln!(writer, "Received signal {}", signal)?;
|
||||||
|
}
|
||||||
writeln!(writer, "{:━^100}", " BACKTRACE ")?;
|
writeln!(writer, "{:━^100}", " BACKTRACE ")?;
|
||||||
writeln!(writer, "{:?}", backtrace::Backtrace::new())?;
|
writeln!(writer, "{:?}", backtrace::Backtrace::new())?;
|
||||||
writeln!(writer, "{:━^100}", " MAPS ")?;
|
writeln!(writer, "{:━^100}", " MAPS ")?;
|
||||||
|
@ -378,7 +378,7 @@ impl Display for Signal {
|
|||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
pub trait Handler {
|
pub trait Handler {
|
||||||
/// Handle a signal
|
/// Handle a signal
|
||||||
fn handle(&mut self, signal: Signal, info: &mut siginfo_t, _context: &mut ucontext_t);
|
fn handle(&mut self, signal: Signal, info: &mut siginfo_t, _context: Option<&mut ucontext_t>);
|
||||||
/// Return a list of signals to handle
|
/// Return a list of signals to handle
|
||||||
fn signals(&self) -> Vec<Signal>;
|
fn signals(&self) -> Vec<Signal>;
|
||||||
}
|
}
|
||||||
@ -425,7 +425,7 @@ unsafe fn handle_signal(sig: c_int, info: *mut siginfo_t, void: *mut c_void) {
|
|||||||
handler.handle(
|
handler.handle(
|
||||||
*signal,
|
*signal,
|
||||||
&mut ptr::read_unaligned(info),
|
&mut ptr::read_unaligned(info),
|
||||||
&mut ptr::read_unaligned(void as *mut ucontext_t),
|
(void as *mut ucontext_t).as_mut(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +1,19 @@
|
|||||||
#![allow(clippy::missing_panics_doc)]
|
#![allow(clippy::missing_panics_doc)]
|
||||||
use std::{
|
use std::{
|
||||||
fs,
|
env, fs,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
|
process::Command,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use which::which;
|
||||||
|
|
||||||
mod bindings;
|
mod bindings;
|
||||||
mod build;
|
mod build;
|
||||||
|
|
||||||
pub use build::build;
|
pub use build::build;
|
||||||
|
|
||||||
|
const LLVM_VERSION_MAX: i32 = 33;
|
||||||
|
|
||||||
pub fn build_with_bindings(
|
pub fn build_with_bindings(
|
||||||
cpu_target: &str,
|
cpu_target: &str,
|
||||||
is_big_endian: bool,
|
is_big_endian: bool,
|
||||||
@ -25,6 +30,73 @@ pub fn build_with_bindings(
|
|||||||
.expect("Faield to write to the bindings file");
|
.expect("Faield to write to the bindings file");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For bindgen, the llvm version must be >= of the rust llvm version
|
||||||
|
fn find_llvm_config() -> Result<String, String> {
|
||||||
|
if let Ok(var) = env::var("LLVM_CONFIG") {
|
||||||
|
return Ok(var);
|
||||||
|
}
|
||||||
|
|
||||||
|
let rustc_llvm_ver = find_rustc_llvm_version().unwrap();
|
||||||
|
for version in (rustc_llvm_ver..=LLVM_VERSION_MAX).rev() {
|
||||||
|
let llvm_config_name: String = format!("llvm-config-{version}");
|
||||||
|
if which(&llvm_config_name).is_ok() {
|
||||||
|
return Ok(llvm_config_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if which("llvm-config").is_ok() {
|
||||||
|
if let Some(ver) = find_llvm_version("llvm-config".to_owned()) {
|
||||||
|
if ver >= rustc_llvm_ver {
|
||||||
|
return Ok("llvm-config".to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err("could not find llvm-config".to_owned())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn exec_llvm_config(llvm_config: String, args: &[&str]) -> String {
|
||||||
|
match Command::new(llvm_config).args(args).output() {
|
||||||
|
Ok(output) => String::from_utf8(output.stdout)
|
||||||
|
.expect("Unexpected llvm-config output")
|
||||||
|
.trim()
|
||||||
|
.to_string(),
|
||||||
|
Err(e) => panic!("Could not execute llvm-config: {e}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_llvm_version(llvm_config: String) -> Option<i32> {
|
||||||
|
let output = exec_llvm_config(llvm_config, &["--version"]);
|
||||||
|
if let Some(major) = output.split('.').collect::<Vec<&str>>().first() {
|
||||||
|
if let Ok(res) = major.parse::<i32>() {
|
||||||
|
return Some(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn exec_rustc(args: &[&str]) -> String {
|
||||||
|
let rustc = env::var("RUSTC").unwrap();
|
||||||
|
match Command::new(rustc).args(args).output() {
|
||||||
|
Ok(output) => String::from_utf8(output.stdout)
|
||||||
|
.expect("Unexpected rustc output")
|
||||||
|
.trim()
|
||||||
|
.to_string(),
|
||||||
|
Err(e) => panic!("Could not execute rustc: {e}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_rustc_llvm_version() -> Option<i32> {
|
||||||
|
let output = exec_rustc(&["--verbose", "--version"]);
|
||||||
|
let ver = output.split(':').last().unwrap().trim();
|
||||||
|
if let Some(major) = ver.split('.').collect::<Vec<&str>>().first() {
|
||||||
|
if let Ok(res) = major.parse::<i32>() {
|
||||||
|
return Some(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
//linux-user_main.c.o libqemu-x86_64-linux-user.fa.p
|
//linux-user_main.c.o libqemu-x86_64-linux-user.fa.p
|
||||||
|
|
||||||
fn qemu_bindgen_clang_args(
|
fn qemu_bindgen_clang_args(
|
||||||
@ -33,6 +105,11 @@ fn qemu_bindgen_clang_args(
|
|||||||
cpu_target: &str,
|
cpu_target: &str,
|
||||||
is_usermode: bool,
|
is_usermode: bool,
|
||||||
) -> Vec<String> {
|
) -> Vec<String> {
|
||||||
|
if env::var("LLVM_CONFIG_PATH").is_err() {
|
||||||
|
let found = find_llvm_config().expect("Cannot find a suitable llvm-config, it must be a version equal or greater than the rustc LLVM version");
|
||||||
|
env::set_var("LLVM_CONFIG_PATH", found);
|
||||||
|
}
|
||||||
|
|
||||||
// load compile commands
|
// load compile commands
|
||||||
let compile_commands_string = &fs::read_to_string(build_dir.join("compile_commands.json"))
|
let compile_commands_string = &fs::read_to_string(build_dir.join("compile_commands.json"))
|
||||||
.expect("failed to read compile commands");
|
.expect("failed to read compile commands");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user