revive llvm builder utility (#154)

Pre-eliminary support for LLVM releases and resolc binary releases by streamlining the build process for all supported hosts platforms.

- Introduce the revive-llvm-builder crate with the revive-llvm builder utilty.
- Do not rely on the LLVM dependency in $PATH to decouple the system LLVM installation from the LLVM host dependency.
- Fix the emscripten build by decoupling the host and native LLVM dependencies. Thus allowing a single LLVM emscripten release that can be used on any host platform.
- An example Dockerfile building an alpine container with a fully statically linked resolc ELF binary.
- Remove the Debian builder utilities and workflow.
This commit is contained in:
Cyrill Leutwiler authored and GitHub committed 2025-01-13 15:58:27 +01:00
1 parent fde9edab10
commit 7f81f37e0c
65 files changed
+4847 -557

No files matched your search

@@ -0,0 +1,119 @@
//! The revive LLVM builder arguments.
use clap::Parser;
use revive_llvm_builder::ccache_variant::CcacheVariant;
/// The revive LLVM builder arguments.
#[derive(Debug, Parser)]
#[command(version, about)]
pub struct Arguments {
/// Target environment to build LLVM (gnu, musl, emscripten).
#[arg(long, default_value_t = revive_llvm_builder::target_env::TargetEnv::GNU)]
pub target_env: revive_llvm_builder::target_env::TargetEnv,
#[command(subcommand)]
pub subcommand: Subcommand,
}
/// The revive LLVM builder arguments.
#[derive(Debug, clap::Subcommand)]
pub enum Subcommand {
/// Clone the branch specified in `LLVM.lock`.
Clone {
/// Clone with full commits history.
#[arg(long)]
deep: bool,
},
/// Build the LLVM framework.
Build {
/// LLVM build type (`Debug`, `Release`, `RelWithDebInfo`, or `MinSizeRel`).
#[arg(long, default_value_t = revive_llvm_builder::BuildType::Release)]
build_type: revive_llvm_builder::BuildType,
/// Additional targets to build LLVM with.
#[arg(long)]
targets: Vec<String>,
/// LLVM projects to build LLVM with.
#[arg(
long,
default_values_t = vec![
revive_llvm_builder::llvm_project::LLVMProject::CLANG,
revive_llvm_builder::llvm_project::LLVMProject::LLD
]
)]
llvm_projects: Vec<revive_llvm_builder::llvm_project::LLVMProject>,
/// Whether to build LLVM with run-time type information (RTTI) enabled.
#[arg(long)]
enable_rtti: bool,
/// The default target to build LLVM with.
#[arg(long)]
default_target: Option<revive_llvm_builder::target_triple::TargetTriple>,
/// Whether to build the LLVM tests.
#[arg(long)]
enable_tests: bool,
/// Whether to build LLVM for source-based code coverage.
#[arg(long)]
enable_coverage: bool,
/// Extra arguments to pass to CMake.
/// A leading backslash will be unescaped.
#[arg(long)]
extra_args: Vec<String>,
/// Whether to use compiler cache (ccache) to speed-up builds.
#[arg(long)]
ccache_variant: Option<CcacheVariant>,
/// Whether to build with assertions enabled or not.
#[arg(long, default_value_t = true)]
enable_assertions: bool,
/// Build LLVM with sanitizer enabled (`Address`, `Memory`, `MemoryWithOrigins`, `Undefined`, `Thread`, `DataFlow`, or `Address;Undefined`).
#[arg(long)]
sanitizer: Option<revive_llvm_builder::sanitizer::Sanitizer>,
/// Whether to run LLVM unit tests under valgrind or not.
#[arg(long)]
enable_valgrind: bool,
},
/// Checkout the branch specified in `LLVM.lock`.
Checkout {
/// Remove all artifacts preventing the checkout (removes all local changes!).
#[arg(long)]
force: bool,
},
/// Clean the build artifacts.
Clean,
/// Build the LLVM compiler-rt builtins for the PolkaVM target.
Builtins {
/// LLVM build type (`Debug`, `Release`, `RelWithDebInfo`, or `MinSizeRel`).
#[arg(long, default_value_t = revive_llvm_builder::BuildType::Release)]
build_type: revive_llvm_builder::BuildType,
/// The default target to build LLVM with.
#[arg(long)]
default_target: Option<revive_llvm_builder::target_triple::TargetTriple>,
/// Extra arguments to pass to CMake.
/// A leading backslash will be unescaped.
#[arg(long)]
extra_args: Vec<String>,
/// Whether to use compiler cache (ccache) to speed-up builds.
#[arg(long)]
ccache_variant: Option<CcacheVariant>,
/// Build LLVM with sanitizer enabled (`Address`, `Memory`, `MemoryWithOrigins`, `Undefined`, `Thread`, `DataFlow`, or `Address;Undefined`).
#[arg(long)]
sanitizer: Option<revive_llvm_builder::sanitizer::Sanitizer>,
},
}
+141
View File
@@ -0,0 +1,141 @@
//! The revive LLVM builder.
pub(crate) mod arguments;
use std::collections::HashSet;
use std::path::PathBuf;
use std::str::FromStr;
use anyhow::Context;
use clap::Parser;
use self::arguments::{Arguments, Subcommand};
fn main() {
env_logger::init();
match main_inner() {
Ok(()) => std::process::exit(0),
Err(error) => {
log::error!("{error:?}");
std::process::exit(1)
}
}
}
fn main_inner() -> anyhow::Result<()> {
let arguments = Arguments::parse();
revive_llvm_builder::utils::directory_target_llvm(arguments.target_env);
match arguments.subcommand {
Subcommand::Clone { deep } => {
let lock = revive_llvm_builder::Lock::try_from(&PathBuf::from(
revive_llvm_builder::lock::LLVM_LOCK_DEFAULT_PATH,
))?;
revive_llvm_builder::clone(lock, deep, arguments.target_env)?;
}
Subcommand::Build {
build_type,
targets,
llvm_projects,
enable_rtti,
default_target,
enable_tests,
enable_coverage,
extra_args,
ccache_variant,
enable_assertions,
sanitizer,
enable_valgrind,
} => {
let mut targets = targets
.into_iter()
.map(|target| revive_llvm_builder::Platform::from_str(target.as_str()))
.collect::<Result<HashSet<revive_llvm_builder::Platform>, String>>()
.map_err(|platform| anyhow::anyhow!("Unknown platform `{}`", platform))?;
targets.insert(revive_llvm_builder::Platform::PolkaVM);
log::info!("build targets: {:?}", &targets);
let extra_args_unescaped: Vec<String> = extra_args
.iter()
.map(|argument| {
argument
.strip_prefix('\\')
.unwrap_or(argument.as_str())
.to_owned()
})
.collect();
log::debug!("extra_args: {:#?}", extra_args);
log::debug!("extra_args_unescaped: {:#?}", extra_args_unescaped);
if let Some(ccache_variant) = ccache_variant {
revive_llvm_builder::utils::check_presence(ccache_variant.to_string().as_str())?;
}
let mut projects = llvm_projects
.into_iter()
.map(|project| {
revive_llvm_builder::llvm_project::LLVMProject::from_str(
project.to_string().as_str(),
)
})
.collect::<Result<HashSet<revive_llvm_builder::llvm_project::LLVMProject>, String>>(
)
.map_err(|project| anyhow::anyhow!("Unknown LLVM project `{}`", project))?;
projects.insert(revive_llvm_builder::llvm_project::LLVMProject::LLD);
log::info!("build projects: {:?}", &projects);
revive_llvm_builder::build(
build_type,
arguments.target_env,
targets,
projects,
enable_rtti,
default_target,
enable_tests,
enable_coverage,
&extra_args_unescaped,
ccache_variant,
enable_assertions,
sanitizer,
enable_valgrind,
)?;
}
Subcommand::Checkout { force } => {
let lock = revive_llvm_builder::Lock::try_from(&PathBuf::from(
revive_llvm_builder::lock::LLVM_LOCK_DEFAULT_PATH,
))?;
revive_llvm_builder::checkout(lock, force)?;
}
Subcommand::Clean => {
revive_llvm_builder::clean()
.with_context(|| "Unable to remove target LLVM directory")?;
}
Subcommand::Builtins {
build_type,
default_target,
extra_args,
ccache_variant,
sanitizer,
} => {
revive_llvm_builder::builtins::build(
build_type,
arguments.target_env,
default_target,
&extra_args,
ccache_variant,
sanitizer,
)?;
}
}
Ok(())
}