diff --git a/.cargo/config.toml b/.cargo/config.toml index 5b3856a1..9583e866 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -4,9 +4,6 @@ test-full = "test --workspace" check-full = "check --workspace" clippy-w = "clippy --verbose -- -D warnings" -[env] -PATH = { value = "external/bin", relative = true } - [target.'cfg(target_os = "linux")'] rustflags = ["-L", "native=external/lib/linux"] diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index bd6ee994..28e1d5ee 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -29,7 +29,7 @@ jobs: id: cache-binaries with: path: external/ - key: ${{ runner.os }}-binaries-v4 + key: ${{ runner.os }}-binaries-v5 restore-keys: | ${{ runner.os }}-binaries- @@ -44,7 +44,7 @@ jobs: curl -L "https://storage.googleapis.com/external_binaries/linux/bin/rust-lld.zip" -o /tmp/rust-lld.zip unzip -o /tmp/rust-lld.zip -d external/bin/linux/ # Download and extract libLLVM - curl -L "https://storage.googleapis.com/external_binaries/linux/lib/libLLVM.so.21.1-rust-1.94.zip" -o /tmp/libLLVM.zip + curl -L "https://storage.googleapis.com/external_binaries/linux/lib/libLLVM.so.21.1-rust-1.94.0-nightly.zip" -o /tmp/libLLVM.zip unzip -o /tmp/libLLVM.zip -d external/lib/linux/ # Make executables chmod +x external/bin/linux/inf-llc external/bin/linux/rust-lld diff --git a/.github/workflows/reusable-build.yml b/.github/workflows/reusable-build.yml index 43fa1986..5c40a4ce 100644 --- a/.github/workflows/reusable-build.yml +++ b/.github/workflows/reusable-build.yml @@ -43,7 +43,7 @@ jobs: id: cache-binaries with: path: external/ - key: ${{ runner.os }}-binaries-v5 + key: ${{ runner.os }}-binaries-v6 restore-keys: | ${{ runner.os }}-binaries- @@ -58,7 +58,7 @@ jobs: curl -L "https://storage.googleapis.com/external_binaries/linux/bin/rust-lld.zip" -o /tmp/rust-lld.zip unzip -o /tmp/rust-lld.zip -d external/bin/linux/ # Download and extract libLLVM - curl -L "https://storage.googleapis.com/external_binaries/linux/lib/libLLVM.so.21.1-rust-1.94.zip" -o /tmp/libLLVM.zip + curl -L "https://storage.googleapis.com/external_binaries/linux/lib/libLLVM.so.21.1-rust-1.94.0-nightly.zip" -o /tmp/libLLVM.zip unzip -o /tmp/libLLVM.zip -d external/lib/linux/ # Make executables chmod +x external/bin/linux/inf-llc external/bin/linux/rust-lld diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a854715..d627c3e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,6 +56,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Tooling +- Remove `playground-server` tool (unused, superseded by external playground infrastructure) ([#56]) - Reorganize project structure: move crates to `core/` and `tools/` directories ([#43]) - Add `inf-wasmparser` crate (fork with non-det instruction support) ([#43]) - Add `inf-wat` crate for WAT parsing ([#43]) @@ -68,6 +69,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add Codecov integration for test coverage reporting ([#57], [#58]) - Optimize local build time and refactor CI workflows ([#60]) - Add Windows development setup with cross-platform LLVM binaries +- Update libLLVM download URL to use consistent filename with `-nightly` suffix ([#56]) +- Remove unused PATH configuration from `.cargo/config.toml` ([#56]) +- Bump CI cache keys to invalidate stale binary caches ([#56]) +- Fix LLVM environment variable reference in Windows installation guide ([#56]) +- Add Linux development setup guide (`book/installation_linux.md`) ([#56]) +- Add macOS development setup guide (`book/installation_macos.md`) ([#56]) +- Add cross-platform dependency check script (`book/check_deps.sh`) ([#56]) ### Performance @@ -130,6 +138,7 @@ Initial tagged release. [#44]: https://github.com/Inferara/inference/pull/44 [#54]: https://github.com/Inferara/inference/pull/54 [#55]: https://github.com/Inferara/inference/pull/55 +[#56]: https://github.com/Inferara/inference/pull/56 [#57]: https://github.com/Inferara/inference/pull/57 [#58]: https://github.com/Inferara/inference/pull/58 [#60]: https://github.com/Inferara/inference/pull/60 diff --git a/Cargo.toml b/Cargo.toml index 87fa1c1a..3a734018 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,7 +34,6 @@ inference-wasm-codegen = { path = "./core/wasm-codegen", version = "0.0.1" } inference-tests = { path = "./tests", version = "0.0.1" } # Various supplementary tools -inference-playground-server = { path = "./tools/playground-server", version = "0.0.1" } wasm-fmt = { path = "./tools/wasm-fmt", version = "0.0.1" } wat-fmt = { path = "./tools/wat-fmt", version = "0.0.9" } inf-wast = { path = "./tools/inf-wast", version = "0.0.9" } diff --git a/README.md b/README.md index f072e29f..7fff6a1f 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,11 @@ Prebuilt `infc` binaries distributables are arranged in the following directory To build Inference from source, you'll need the required binary dependencies for your platform. +For detailed platform-specific setup instructions, see: +- [Linux Development Setup](book/installation_linux.md) +- [macOS Development Setup](book/installation_macos.md) +- [Windows Development Setup](book/installation_windows.md) + ### Required Binaries Download the following files for your platform and place them in the specified directories: @@ -86,7 +91,7 @@ Download the following files for your platform and place them in the specified d #### Linux - **inf-llc**: [Download](https://storage.googleapis.com/external_binaries/linux/bin/inf-llc.zip) → Extract to `external/bin/linux/` - **rust-lld**: [Download](https://storage.googleapis.com/external_binaries/linux/bin/rust-lld.zip) → Extract to `external/bin/linux/` -- **libLLVM**: [Download](https://storage.googleapis.com/external_binaries/linux/lib/libLLVM.so.21.1-rust-1.94.zip) → Extract to `external/lib/linux/` +- **libLLVM**: [Download](https://storage.googleapis.com/external_binaries/linux/lib/libLLVM.so.21.1-rust-1.94.0-nightly.zip) → Extract to `external/lib/linux/` #### macOS - **inf-llc**: [Download](https://storage.googleapis.com/external_binaries/macos/bin/inf-llc.zip) → Extract to `external/bin/macos/` diff --git a/book/check_deps.sh b/book/check_deps.sh new file mode 100755 index 00000000..14fa2ad4 --- /dev/null +++ b/book/check_deps.sh @@ -0,0 +1,328 @@ +#!/usr/bin/env bash +# +# Inference Dependency Check Script (Linux/macOS) +# +# Checks for required dependencies to build the Inference compiler. +# Can optionally download missing external binaries from Google Cloud Storage. +# +# Usage: +# ./check_deps.sh # Check dependencies +# ./check_deps.sh --help # Show help +# +# Required: +# - LLVM 21 installed +# - Rust nightly toolchain +# - curl and unzip (for downloading binaries) +# + +set -euo pipefail + +# --- Configuration --- +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" + +# --- Color Output --- +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +CYAN='\033[0;36m' +NC='\033[0m' + +print_found() { echo -e "${GREEN}[FOUND]${NC} $1"; } +print_missing() { echo -e "${RED}[MISSING]${NC} $1"; } +print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; } +print_info() { echo -e "${CYAN}[INFO]${NC} $1"; } + +# --- Platform Detection --- +detect_platform() { + case "$(uname -s)" in + Linux*) PLATFORM="linux" ;; + Darwin*) PLATFORM="macos" ;; + *) echo "Unsupported platform: $(uname -s)"; exit 1 ;; + esac +} + +# --- Download URLs --- +get_download_url() { + local platform="$1" binary="$2" + local base="https://storage.googleapis.com/external_binaries" + case "$platform-$binary" in + linux-inf-llc) echo "$base/linux/bin/inf-llc.zip" ;; + linux-rust-lld) echo "$base/linux/bin/rust-lld.zip" ;; + linux-libLLVM) echo "$base/linux/lib/libLLVM.so.21.1-rust-1.94.0-nightly.zip" ;; + macos-inf-llc) echo "$base/macos/bin/inf-llc.zip" ;; + macos-rust-lld) echo "$base/macos/bin/rust-lld.zip" ;; + *) echo "" ;; + esac +} + +# --- Dependency Checks --- +check_rust() { + echo "" + echo -e "${CYAN}--- Rust Toolchain ---${NC}" + if command -v rustc &> /dev/null; then + local version + version=$(rustc --version 2>/dev/null) + if [[ "$version" == *"nightly"* ]]; then + print_found "Rust: $version" + return 0 + else + print_warning "Rust installed but not nightly: $version" + echo " Run: rustup default nightly" + return 1 + fi + else + print_missing "Rust not found" + echo " Install from: https://rustup.rs/" + return 1 + fi +} + +check_cargo() { + if command -v cargo &> /dev/null; then + print_found "Cargo: $(cargo --version 2>/dev/null)" + return 0 + else + print_missing "Cargo not found" + return 1 + fi +} + +check_llvm() { + echo "" + echo -e "${CYAN}--- LLVM 21 ---${NC}" + local llvm_config="" llvm_version="" + + # Try different llvm-config names + for cmd in llvm-config-21 llvm-config; do + if command -v "$cmd" &> /dev/null; then + llvm_config="$cmd" + break + fi + done + + # Try Homebrew paths on macOS + if [[ -z "$llvm_config" && "$PLATFORM" == "macos" ]]; then + for path in "/opt/homebrew/opt/llvm@21/bin/llvm-config" \ + "/opt/homebrew/opt/llvm/bin/llvm-config" \ + "/usr/local/opt/llvm@21/bin/llvm-config" \ + "/usr/local/opt/llvm/bin/llvm-config"; do + if [[ -x "$path" ]]; then + llvm_config="$path" + break + fi + done + fi + + if [[ -n "$llvm_config" ]]; then + llvm_version=$("$llvm_config" --version 2>/dev/null || echo "") + if [[ "$llvm_version" == 21.* ]]; then + print_found "LLVM: $llvm_version (via $llvm_config)" + return 0 + elif [[ -n "$llvm_version" ]]; then + print_warning "LLVM found but version $llvm_version (need 21.x)" + return 1 + fi + fi + + print_missing "LLVM 21 not found" + if [[ "$PLATFORM" == "linux" ]]; then + echo " Install: wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && sudo ./llvm.sh 21" + else + echo " Install: brew install llvm@21" + fi + return 1 +} + +check_llvm_env() { + echo "" + echo -e "${CYAN}--- LLVM Environment ---${NC}" + if [[ -n "${LLVM_SYS_211_PREFIX:-}" ]]; then + if [[ -d "$LLVM_SYS_211_PREFIX" ]]; then + print_found "LLVM_SYS_211_PREFIX=$LLVM_SYS_211_PREFIX" + return 0 + else + print_warning "LLVM_SYS_211_PREFIX set but directory missing: $LLVM_SYS_211_PREFIX" + return 1 + fi + else + print_missing "LLVM_SYS_211_PREFIX not set" + if [[ "$PLATFORM" == "linux" ]]; then + echo " Set: export LLVM_SYS_211_PREFIX=/usr/lib/llvm-21" + else + echo " Set: export LLVM_SYS_211_PREFIX=\$(brew --prefix llvm@21)" + fi + return 1 + fi +} + +check_external_binaries() { + echo "" + echo -e "${CYAN}--- External Binaries ($PLATFORM) ---${NC}" + echo "Directory: $PROJECT_ROOT/external/" + + local bin_dir="$PROJECT_ROOT/external/bin/$PLATFORM" + local lib_dir="$PROJECT_ROOT/external/lib/$PLATFORM" + MISSING_BINARIES=() + + # Check inf-llc + if [[ -x "$bin_dir/inf-llc" ]]; then + print_found "inf-llc (in external/bin/$PLATFORM/)" + else + print_missing "inf-llc (not in external/bin/$PLATFORM/)" + MISSING_BINARIES+=("inf-llc") + fi + + # Check rust-lld + if [[ -x "$bin_dir/rust-lld" ]]; then + print_found "rust-lld (in external/bin/$PLATFORM/)" + else + print_missing "rust-lld (not in external/bin/$PLATFORM/)" + MISSING_BINARIES+=("rust-lld") + fi + + # Check libLLVM (Linux only) + if [[ "$PLATFORM" == "linux" ]]; then + if [[ -f "$lib_dir/libLLVM.so.21.1-rust-1.94.0-nightly" ]]; then + print_found "libLLVM.so (in external/lib/$PLATFORM/)" + else + print_missing "libLLVM.so (not in external/lib/$PLATFORM/)" + MISSING_BINARIES+=("libLLVM") + fi + else + print_info "libLLVM.so not required on macOS" + fi + + echo "---------------------------------" + [[ ${#MISSING_BINARIES[@]} -eq 0 ]] +} + +# --- Download Functions --- +download_binaries() { + echo "" + echo -e "${CYAN}The following binaries will be downloaded:${NC}" + for binary in "${MISSING_BINARIES[@]}"; do + echo " - $binary: $(get_download_url "$PLATFORM" "$binary")" + done + + echo "" + read -r -p "Download missing binaries? (y/N) " answer + if [[ ! "$answer" =~ ^[Yy]$ ]]; then + echo "Download cancelled." + return 1 + fi + + local bin_dir="$PROJECT_ROOT/external/bin/$PLATFORM" + local lib_dir="$PROJECT_ROOT/external/lib/$PLATFORM" + mkdir -p "$bin_dir" + [[ "$PLATFORM" == "linux" ]] && mkdir -p "$lib_dir" + + for binary in "${MISSING_BINARIES[@]}"; do + local url tmp_file="/tmp/${binary}.zip" + url=$(get_download_url "$PLATFORM" "$binary") + print_info "Downloading $binary..." + + if curl -fsSL "$url" -o "$tmp_file"; then + if [[ "$binary" == "libLLVM" ]]; then + unzip -o "$tmp_file" -d "$lib_dir/" > /dev/null + else + unzip -o "$tmp_file" -d "$bin_dir/" > /dev/null + chmod +x "$bin_dir/$binary" + fi + rm -f "$tmp_file" + print_found "Downloaded $binary" + else + print_missing "Failed to download $binary" + fi + done +} + +# --- macOS Quarantine Check --- +check_macos_quarantine() { + [[ "$PLATFORM" != "macos" ]] && return 0 + + local bin_dir="$PROJECT_ROOT/external/bin/$PLATFORM" + local quarantined=() + + for binary in inf-llc rust-lld; do + local path="$bin_dir/$binary" + if [[ -f "$path" ]] && xattr -l "$path" 2>/dev/null | grep -q "com.apple.quarantine"; then + quarantined+=("$binary") + fi + done + + if [[ ${#quarantined[@]} -gt 0 ]]; then + echo "" + print_warning "Binaries quarantined by macOS Gatekeeper:" + printf " - %s\n" "${quarantined[@]}" + echo "" + read -r -p "Remove quarantine attribute? (y/N) " answer + if [[ "$answer" =~ ^[Yy]$ ]]; then + for binary in "${quarantined[@]}"; do + xattr -d com.apple.quarantine "$bin_dir/$binary" 2>/dev/null || true + print_found "Removed quarantine from $binary" + done + fi + fi +} + +# --- Main --- +show_help() { + cat << 'EOF' +Inference Dependency Check Script + +Usage: check_deps.sh [--help] + +Checks for required dependencies to build the Inference compiler: + - Rust nightly toolchain + - LLVM 21 + - External binaries (inf-llc, rust-lld) + - libLLVM shared library (Linux only) + +Can optionally download missing external binaries. +EOF + exit 0 +} + +main() { + [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]] && show_help + + detect_platform + echo "" + echo -e "${CYAN}=== Inference Dependency Check ===${NC}" + echo "Platform: $PLATFORM" + echo "Project root: $PROJECT_ROOT" + echo "" + echo "This check is read-only. You will be prompted before any downloads or changes." + + local all_good=true + MISSING_BINARIES=() + + check_rust || all_good=false + check_cargo || all_good=false + check_llvm || all_good=false + check_llvm_env || all_good=false + check_external_binaries || all_good=false + + # Offer to download missing binaries + if [[ ${#MISSING_BINARIES[@]} -gt 0 ]]; then + download_binaries && check_external_binaries || all_good=false + fi + + check_macos_quarantine + + # Final summary + echo "" + echo "---------------------------------" + if [[ "$all_good" == "true" ]]; then + echo -e "${GREEN}SUCCESS: All dependencies are present.${NC}" + echo -e "${YELLOW}Ready to build: cargo build${NC}" + exit 0 + else + echo -e "${RED}FAILURE: Some dependencies are missing.${NC}" + echo "Please install missing dependencies and run this script again." + exit 1 + fi +} + +main "$@" diff --git a/book/installation_linux.md b/book/installation_linux.md new file mode 100644 index 00000000..812fb152 --- /dev/null +++ b/book/installation_linux.md @@ -0,0 +1,264 @@ +# Linux Development Setup Guide + +This guide walks you through setting up a complete development environment for the Inference project on Linux. + +## Prerequisites + +- Ubuntu 22.04 LTS or later (recommended), Debian 12+, or Fedora 39+ +- `curl`, `wget`, and `unzip` utilities +- `sudo` access for package installation +- At least 4GB of free disk space + +**Install prerequisites (Ubuntu/Debian):** +```bash +sudo apt update && sudo apt install -y curl wget unzip lsb-release software-properties-common gnupg build-essential pkg-config +``` + +**Install prerequisites (Fedora):** +```bash +sudo dnf install -y curl wget unzip gcc gcc-c++ make pkg-config +``` + +## Step 1: Install LLVM 21 + +LLVM 21 is required for building the Inference compiler. + +### Ubuntu/Debian + +```bash +wget https://apt.llvm.org/llvm.sh +chmod +x llvm.sh +sudo ./llvm.sh 21 + +sudo apt-get install -y llvm-21-dev libpolly-21-dev +``` + +Verify installation: +```bash +llvm-config-21 --version +``` + +### Fedora + +```bash +sudo dnf install -y llvm21-devel polly21-devel +``` + +Verify installation: +```bash +llvm-config-21 --version +``` + +**Important:** LLVM 21 is specifically required. Other versions are not compatible. + +## Step 2: Install Rust + +Inference requires the Rust nightly toolchain. + +```bash +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh +``` + +Follow the on-screen prompts (default installation is fine). Then: +```bash +source "$HOME/.cargo/env" + +rustup default nightly + +rustc --version +cargo --version +``` + +The output should show a nightly version, e.g., `rustc 1.xx.0-nightly`. + +## Step 3: Clone the Repository + +```bash +git clone https://github.com/Inferara/inference.git +cd inference +``` + +## Step 4: Download External Binaries + +The Inference compiler requires custom LLVM tools with Inference intrinsics support. + +```bash +mkdir -p external/bin/linux external/lib/linux + +curl -L "https://storage.googleapis.com/external_binaries/linux/bin/inf-llc.zip" -o /tmp/inf-llc.zip +unzip -o /tmp/inf-llc.zip -d external/bin/linux/ + +curl -L "https://storage.googleapis.com/external_binaries/linux/bin/rust-lld.zip" -o /tmp/rust-lld.zip +unzip -o /tmp/rust-lld.zip -d external/bin/linux/ + +curl -L "https://storage.googleapis.com/external_binaries/linux/lib/libLLVM.so.21.1-rust-1.94.0-nightly.zip" -o /tmp/libLLVM.zip +unzip -o /tmp/libLLVM.zip -d external/lib/linux/ + +chmod +x external/bin/linux/inf-llc external/bin/linux/rust-lld +``` + +**Important:** The `libLLVM.so` shared library is required on Linux for runtime operation. + +Alternatively, run the dependency check script: +```bash +./book/check_deps.sh +``` + +## Step 5: Configure Environment Variables + +Set the LLVM prefix environment variable for building: + +```bash +echo 'export LLVM_SYS_211_PREFIX="/usr/lib/llvm-21"' >> ~/.bashrc +source ~/.bashrc +``` + +For zsh users: +```bash +echo 'export LLVM_SYS_211_PREFIX="/usr/lib/llvm-21"' >> ~/.zshrc +source ~/.zshrc +``` + +Verify the configuration: +```bash +echo $LLVM_SYS_211_PREFIX +``` + +**Note:** The project's `.cargo/config.toml` automatically configures `LD_LIBRARY_PATH` for the vendored `libLLVM.so` during builds. + +## Step 6: Build the Project + +```bash +cargo build +``` + +First build will take several minutes as it compiles all dependencies including the LLVM bindings. + +For optimized builds: +```bash +cargo build --release +``` + +## Step 7: Verify the Build + +Run tests: +```bash +cargo test +``` + +Run the CLI: +```bash +./target/debug/infc --help +``` + +Compile a sample file: +```bash +echo 'fn main() -> i32 { return 42; }' > test.inf +./target/debug/infc test.inf --parse --codegen -o +ls -la out/ +``` + +## Troubleshooting + +### Build fails with "LLVM not found" or "llvm-sys build failed" + +1. Verify LLVM 21 is installed: + ```bash + llvm-config-21 --version + ``` + +2. Check the environment variable: + ```bash + echo $LLVM_SYS_211_PREFIX + ``` + +3. Verify the path exists: + ```bash + ls -la /usr/lib/llvm-21/ + ``` + +### Build fails with "inf-llc not found" or "rust-lld not found" + +1. Verify binaries are downloaded: + ```bash + ls -la external/bin/linux/ + ``` + +2. Check they are executable: + ```bash + file external/bin/linux/inf-llc + ``` + +3. Make them executable if needed: + ```bash + chmod +x external/bin/linux/inf-llc external/bin/linux/rust-lld + ``` + +### Runtime error "libLLVM.so: cannot open shared object file" + +The vendored libLLVM shared library is missing or not in the library path: + +1. Verify the library exists: + ```bash + ls -la external/lib/linux/ + ``` + +2. If missing, download it: + ```bash + curl -L "https://storage.googleapis.com/external_binaries/linux/lib/libLLVM.so.21.1-rust-1.94.0-nightly.zip" -o /tmp/libLLVM.zip + unzip -o /tmp/libLLVM.zip -d external/lib/linux/ + ``` + +3. Rebuild to copy to target directory: + ```bash + cargo clean && cargo build + ``` + +### Linker errors with "undefined reference to polly_*" + +Install the Polly development package: +```bash +sudo apt-get install -y libpolly-21-dev +``` + +### Tests fail with "Permission denied" + +Ensure binaries have execute permissions: +```bash +chmod +x external/bin/linux/* +chmod +x target/debug/bin/* 2>/dev/null || true +``` + +### Slow compilation + +- First build is expected to take 10-15 minutes (LLVM bindings) +- Subsequent builds use incremental compilation +- Use `cargo build --release` only when needed + +## Environment Variables Reference + +| Variable | Value | Purpose | +|----------|-------|---------| +| `LLVM_SYS_211_PREFIX` | `/usr/lib/llvm-21` | Points llvm-sys crate to LLVM installation | +| `LD_LIBRARY_PATH` | (auto-configured) | Set by `.cargo/config.toml` for vendored libLLVM | + +## Additional Resources + +- [Rust Book](https://doc.rust-lang.org/book/) +- [LLVM APT Repository](https://apt.llvm.org/) +- [Inkwell Documentation](https://thedan64.github.io/inkwell/) +- [LLVM Documentation](https://llvm.org/docs/) + +## Getting Help + +If you encounter issues not covered in this guide: +1. Check existing [GitHub issues](https://github.com/Inferara/inference/issues) +2. Run `cargo build --verbose` for detailed error messages +3. Run `./book/check_deps.sh` to verify your setup +4. Open a new issue with your error output and environment details: + ```bash + uname -a + lsb_release -a 2>/dev/null || cat /etc/os-release + llvm-config-21 --version + rustc --version + ``` diff --git a/book/installation_macos.md b/book/installation_macos.md new file mode 100644 index 00000000..9bed5d26 --- /dev/null +++ b/book/installation_macos.md @@ -0,0 +1,283 @@ +# macOS Development Setup Guide + +This guide walks you through setting up a complete development environment for the Inference project on macOS. + +## Prerequisites + +- macOS 13 (Ventura) or later +- Apple Silicon (M1/M2/M3) or Intel processor +- Administrator access for installing software +- At least 4GB of free disk space + +## Step 1: Install Xcode Command Line Tools + +```bash +xcode-select --install +``` + +Follow the on-screen prompts to complete installation. This provides essential build tools including `git`, `make`, and compilers. + +## Step 2: Install Homebrew + +Homebrew is the recommended package manager for macOS. + +```bash +/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" +``` + +After installation, add Homebrew to your PATH. + +**Apple Silicon (M1/M2/M3):** +```bash +echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile +eval "$(/opt/homebrew/bin/brew shellenv)" +``` + +**Intel Mac:** +```bash +echo 'eval "$(/usr/local/bin/brew shellenv)"' >> ~/.zprofile +eval "$(/usr/local/bin/brew shellenv)" +``` + +Verify installation: +```bash +brew --version +``` + +## Step 3: Install LLVM 21 + +Install LLVM 21 via Homebrew: + +```bash +brew install llvm@21 +``` + +If `llvm@21` is not available, install the latest LLVM: +```bash +brew install llvm +``` + +Verify installation: +```bash +$(brew --prefix llvm@21 2>/dev/null || brew --prefix llvm)/bin/llvm-config --version +``` + +**Note:** Homebrew's LLVM is "keg-only" and not symlinked to `/usr/local/bin` by default. + +## Step 4: Install Rust + +Install Rust using rustup: + +```bash +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh +``` + +Follow the on-screen prompts (default installation is fine). Then: +```bash +source "$HOME/.cargo/env" + +rustup default nightly + +rustc --version +cargo --version +``` + +The output should show a nightly version. + +## Step 5: Clone the Repository + +```bash +git clone https://github.com/Inferara/inference.git +cd inference +``` + +## Step 6: Download External Binaries + +The Inference compiler requires custom LLVM tools with Inference intrinsics support. + +**Important:** Unlike Linux, macOS does NOT require the `libLLVM.so` shared library. + +```bash +mkdir -p external/bin/macos + +curl -L "https://storage.googleapis.com/external_binaries/macos/bin/inf-llc.zip" -o /tmp/inf-llc.zip +unzip -o /tmp/inf-llc.zip -d external/bin/macos/ + +curl -L "https://storage.googleapis.com/external_binaries/macos/bin/rust-lld.zip" -o /tmp/rust-lld.zip +unzip -o /tmp/rust-lld.zip -d external/bin/macos/ + +chmod +x external/bin/macos/inf-llc external/bin/macos/rust-lld +``` + +Alternatively, run the dependency check script: +```bash +./book/check_deps.sh +``` + +## Step 7: Configure Environment Variables + +Set the LLVM prefix environment variable. The path differs based on your Mac and LLVM installation: + +```bash +LLVM_PREFIX=$(brew --prefix llvm@21 2>/dev/null || brew --prefix llvm) +echo "export LLVM_SYS_211_PREFIX=\"$LLVM_PREFIX\"" >> ~/.zshrc +source ~/.zshrc +``` + +Verify: +```bash +echo $LLVM_SYS_211_PREFIX +``` + +**Apple Silicon:** `/opt/homebrew/opt/llvm@21` or `/opt/homebrew/opt/llvm` +**Intel Mac:** `/usr/local/opt/llvm@21` or `/usr/local/opt/llvm` + +## Step 8: Build the Project + +```bash +cargo build +``` + +First build will take several minutes. + +For optimized builds: +```bash +cargo build --release +``` + +## Step 9: Verify the Build + +Run tests: +```bash +cargo test +``` + +Run the CLI: +```bash +./target/debug/infc --help +``` + +Compile a sample file: +```bash +echo 'fn main() -> i32 { return 42; }' > test.inf +./target/debug/infc test.inf --parse --codegen -o +ls -la out/ +``` + +## Troubleshooting + +### Build fails with "LLVM not found" + +1. Verify LLVM is installed: + ```bash + brew list llvm@21 || brew list llvm + ``` + +2. Check the environment variable: + ```bash + echo $LLVM_SYS_211_PREFIX + ls -la $LLVM_SYS_211_PREFIX + ``` + +3. Reconfigure if needed: + ```bash + export LLVM_SYS_211_PREFIX=$(brew --prefix llvm@21 2>/dev/null || brew --prefix llvm) + ``` + +### Build fails with "inf-llc not found" + +1. Verify binaries exist: + ```bash + ls -la external/bin/macos/ + ``` + +2. Check they are executable and not quarantined: + ```bash + file external/bin/macos/inf-llc + xattr -l external/bin/macos/inf-llc + ``` + +3. Remove quarantine attribute if present: + ```bash + xattr -d com.apple.quarantine external/bin/macos/inf-llc + xattr -d com.apple.quarantine external/bin/macos/rust-lld + ``` + +### "inf-llc cannot be opened because it is from an unidentified developer" + +This is macOS Gatekeeper blocking the binary. + +**Option 1 (Recommended):** Remove quarantine attribute: +```bash +xattr -d com.apple.quarantine external/bin/macos/inf-llc +xattr -d com.apple.quarantine external/bin/macos/rust-lld +``` + +**Option 2:** Allow in System Settings: +1. Go to System Settings > Privacy & Security +2. Scroll down to see the blocked application message +3. Click "Allow Anyway" +4. Try running the build again + +**Security Note:** Gatekeeper is an important security mechanism. Only remove quarantine for binaries from trusted sources. + +### Linker errors on Apple Silicon + +Ensure binaries match your architecture: +```bash +file external/bin/macos/inf-llc +``` + +Should show `arm64` for Apple Silicon or `x86_64` for Intel. + +### Homebrew LLVM not found in PATH + +Homebrew LLVM is keg-only. Use the full prefix path: +```bash +$(brew --prefix llvm@21)/bin/llvm-config --version +``` + +## Apple Silicon vs Intel + +The Inference project supports both Apple Silicon (M1/M2/M3) and Intel Macs. + +| Aspect | Apple Silicon | Intel | +|--------|---------------|-------| +| Homebrew prefix | `/opt/homebrew` | `/usr/local` | +| LLVM path | `/opt/homebrew/opt/llvm@21` | `/usr/local/opt/llvm@21` | +| Binary architecture | `arm64` | `x86_64` | + +### Verifying Architecture + +```bash +uname -m +``` +- `arm64` = Apple Silicon +- `x86_64` = Intel + +## Environment Variables Reference + +| Variable | Apple Silicon Value | Intel Value | Purpose | +|----------|---------------------|-------------|---------| +| `LLVM_SYS_211_PREFIX` | `/opt/homebrew/opt/llvm@21` | `/usr/local/opt/llvm@21` | LLVM installation path | + +## Additional Resources + +- [Rust Book](https://doc.rust-lang.org/book/) +- [Homebrew Documentation](https://docs.brew.sh/) +- [Inkwell Documentation](https://thedan64.github.io/inkwell/) +- [LLVM Documentation](https://llvm.org/docs/) + +## Getting Help + +If you encounter issues not covered in this guide: +1. Check existing [GitHub issues](https://github.com/Inferara/inference/issues) +2. Run `cargo build --verbose` for detailed error messages +3. Run `./book/check_deps.sh` to verify your setup +4. Open a new issue with your error output and environment details: + ```bash + uname -a + sw_vers + brew --prefix llvm@21 || brew --prefix llvm + rustc --version + ``` diff --git a/book/installation_windows.md b/book/installation_windows.md index 8084785c..a41db2b2 100644 --- a/book/installation_windows.md +++ b/book/installation_windows.md @@ -97,7 +97,7 @@ rustflags = [ ] [env] -LLVM_SYS_210_PREFIX = "C:\\msys64\\ucrt64" +LLVM_SYS_211_PREFIX = "C:\\msys64\\ucrt64" ``` This configuration: diff --git a/core/wasm-codegen/build.rs b/core/wasm-codegen/build.rs index a2220bbd..03f95736 100644 --- a/core/wasm-codegen/build.rs +++ b/core/wasm-codegen/build.rs @@ -173,7 +173,7 @@ fn get_download_url(platform: &str, binary: &str) -> String { .to_string() } ("linux", "libLLVM") => { - "https://storage.googleapis.com/external_binaries/linux/lib/libLLVM.so.21.1-rust-1.94.zip".to_string() + "https://storage.googleapis.com/external_binaries/linux/lib/libLLVM.so.21.1-rust-1.94.0-nightly.zip".to_string() } ("windows", "inf-llc") => { "https://storage.googleapis.com/external_binaries/windows/bin/inf-llc.zip" diff --git a/tools/playground-server/Cargo.toml b/tools/playground-server/Cargo.toml deleted file mode 100644 index c2dbe4b7..00000000 --- a/tools/playground-server/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "inference-playground-server" -version = { workspace = true } -edition = { workspace = true } -license = { workspace = true } -homepage = { workspace = true } -repository = { workspace = true } - -[dependencies] -actix-web = "4" -actix-cors = "0.7.0" -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" -inference.workspace = true -wat-fmt.workspace = true -wasm-fmt.workspace = true diff --git a/tools/playground-server/src/main.rs b/tools/playground-server/src/main.rs deleted file mode 100644 index 72ba8ab7..00000000 --- a/tools/playground-server/src/main.rs +++ /dev/null @@ -1,111 +0,0 @@ -use actix_cors::Cors; -use actix_web::{post, web, App, HttpResponse, HttpServer, Responder}; -use serde::{Deserialize, Serialize}; - -#[derive(Deserialize)] -struct CompileRequest { - code: String, -} - -#[derive(Deserialize, Serialize)] -struct Response { - wat: String, - wasm: Vec, - wasm_str: String, - v: String, - errors: Vec, -} - -fn parse_inf_file(_: &str) -> Response { - // let mut wasm = vec![]; - let v = String::new(); - let errors = vec![]; - - // let wat = match compile_to_wat(input) { - // Ok(w) => w, - // Err(e) => { - // errors.push(e.to_string()); - // return Response { - // wat: String::new(), - // wasm: vec![], - // wasm_str: String::new(), - // v: String::new(), - // errors, - // }; - // } - // }; - - // if !wat.is_empty() { - // wat_to_wasm(&wat) - // .map(|w| wasm = w) - // .unwrap_or_else(|e| errors.push(e.to_string())); - - // wasm_to_v("playground", &wasm) - // .map(|v_str| v = v_str) - // .unwrap_or_else(|e| errors.push(e.to_string())); - - // let wat = wat_format(&wat); - // let wasm_str = wasm_format(&wasm); - // Response { - // wat, - // wasm, - // wasm_str, - // v, - // errors, - // } - // } else { - Response { - wat: String::new(), - wasm: vec![], - wasm_str: String::new(), - v, - errors, - } - // } -} - -#[post("/compile")] -async fn compile_code(payload: web::Json) -> impl Responder { - let code = &payload.code; - let compiled_result = parse_inf_file(code); - HttpResponse::Ok().json(compiled_result) -} - -#[actix_web::main] -async fn main() -> std::io::Result<()> { - HttpServer::new(|| { - App::new() - .wrap( - Cors::default() - .allowed_origin("http://localhost:3000") - .allowed_methods(vec!["POST", "GET"]) - .allowed_headers(vec!["Content-Type"]) - .supports_credentials(), - ) - .service(compile_code) - }) - .bind(("127.0.0.1", 8080))? - .run() - .await -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn test_parse_inf_file() { - let input = r#" - fn main() { - let x: i32 = 10; - let y: i32 = 20; - let z: i32 = x + y; - } - "#; - parse_inf_file(input); - // assert_eq!(result.errors.len(), 0); - // assert_eq!(result.wat.len(), 0); - // assert_eq!(result.v.len(), 0); - // assert_eq!(result.wasm.len(), 0); - } -}