Skip to main content
Glama

microsandbox

by microsandbox
build_libkrun.sh14.5 kB
#!/bin/sh # build_libkrun.sh # --------------- # This script automates the building of libkrun and libkrunfw libraries, # which are essential components for running micro virtual machines. # # Usage: # ./build_libkrun.sh [options] # # Options: # --no-cleanup, --no-clean Skip cleanup of build directories and VMs after completion # --force-build, --force Force rebuild even if libraries are already built # # Requirements: # - git # - make # - Rust/Cargo (for libkrun) # - Python with packages in ~/.local/lib/python3.*/site-packages (for libkrunfw) # - On macOS: krunvm must be installed (brew tap slp/krun && brew install krunvm) # - On Linux: patchelf must be installed # # The script performs the following tasks: # 1. Creates build directory if needed # 2. Clones libkrunfw from Github # 3. Clones libkrun from GitHub # 4. Builds both libraries in the build directory # 5. Creates non-versioned variants of libraries # 6. Handles cleanup (including VM deletion on macOS) unless --no-cleanup is specified # # Library Build Paths: # Libraries are built and placed in the ./build directory: # Linux: # - ./build/libkrun.so.$ABI_VERSION (versioned) # - ./build/libkrun.so (symlink to versioned) # - ./build/libkrunfw.so.$ABI_VERSION (versioned) # - ./build/libkrunfw.so (symlink to versioned) # macOS: # - ./build/libkrun.$ABI_VERSION.dylib (versioned) # - ./build/libkrun.dylib (symlink to versioned) # - ./build/libkrunfw.$ABI_VERSION.dylib (versioned) # - ./build/libkrunfw.dylib (symlink to versioned) # Note: $ABI_VERSION is determined from each library's Makefile # # Error Handling: # - The script checks for errors after each critical operation # - Exits with status code 1 on any failure # - Performs cleanup on exit unless --no-cleanup is specified # - On macOS, cleanup includes deleting libkrunfw-builder and libkrun-builder VMs # # Platform Support: # - Linux: Full support # - macOS: Requires krunvm, handles platform-specific paths and library extensions # - Other platforms are not supported # # Examples: # # Standard build # ./build_libkrun.sh # # # Build without cleaning up build directory and VMs # ./build_libkrun.sh --no-cleanup # # # Force rebuild even if libraries exist # ./build_libkrun.sh --force-build # # # Combine options # ./build_libkrun.sh --no-cleanup --force-build # Color variables RED="\033[1;31m" GREEN="\033[1;32m" YELLOW="\033[1;33m" RESET="\033[0m" # Package requirements per distribution DEBIAN_PACKAGES="patchelf bc libelf-dev gcc flex bison git python3 curl" FEDORA_PACKAGES="patchelf bc elfutils-libelf-devel gcc flex bison git python3 curl" ARCH_PACKAGES="patchelf bc libelf gcc flex bison git python3 curl" SUSE_PACKAGES="patchelf bc libelf-devel gcc flex bison git python3 curl" # Function to detect Linux distribution detect_linux_distro() { if [ -f /etc/os-release ]; then . /etc/os-release echo "$ID" elif [ -f /etc/debian_version ]; then echo "debian" elif [ -f /etc/fedora-release ]; then echo "fedora" elif [ -f /etc/arch-release ]; then echo "arch" else echo "unknown" fi } # Function to check for required packages check_linux_packages() { local distro=$(detect_linux_distro) local missing_packages="" local install_command="" local packages="" case $distro in debian|ubuntu) install_command="apt-get install -y" packages=$DEBIAN_PACKAGES # Use dpkg-query and an exact status check to verify that the package is fully installed for pkg in $packages; do status=$(dpkg-query -W -f='${Status}' "$pkg" 2>/dev/null || echo "not installed") if [ "$status" != "install ok installed" ]; then missing_packages="$missing_packages $pkg" fi done ;; fedora|rhel|centos) install_command="dnf install -y" packages=$FEDORA_PACKAGES # Check if rpm command exists and packages are installed for pkg in $packages; do if ! rpm -q "$pkg" >/dev/null 2>&1; then missing_packages="$missing_packages $pkg" fi done ;; arch) install_command="pacman -S --noconfirm" packages=$ARCH_PACKAGES # Check if pacman command exists and packages are installed for pkg in $packages; do if ! pacman -Qi "$pkg" >/dev/null 2>&1; then missing_packages="$missing_packages $pkg" fi done ;; suse|opensuse|sles) install_command="zypper install -y" packages=$SUSE_PACKAGES # Check if rpm command exists and packages are installed for pkg in $packages; do if ! rpm -q "$pkg" >/dev/null 2>&1; then missing_packages="$missing_packages $pkg" fi done ;; *) warn "Unable to detect Linux distribution. Please ensure required packages are installed manually:" info "Required packages: patchelf, bc, libelf-dev/elfutils-libelf-devel, gcc, flex, bison" return ;; esac if [ -n "$missing_packages" ]; then error "Missing required packages:$missing_packages" info "You can install them using:" info "sudo $install_command$missing_packages" exit 1 fi } # Function to check for required packages check_python_dependencies() { # Check if python3 is installed if ! command -v python3 >/dev/null 2>&1; then error "python3 is not installed. Please install python3." exit 1 fi # Check if pip is available using python3 -m pip if ! python3 -m pip --version >/dev/null 2>&1; then error "pip is not installed. Please install pip for python3 (e.g., apt-get install python3-pip)." exit 1 fi # Check if pyelftools is installed (you import it as 'elftools') if ! python3 -c "import elftools" >/dev/null 2>&1; then error "pyelftools module is not installed. Please run: pip3 install pyelftools" exit 1 fi } # Logging functions info() { printf "${GREEN}:: %s${RESET}\n" "$1" } warn() { printf "${YELLOW}:: %s${RESET}\n" "$1" } error() { printf "${RED}:: %s${RESET}\n" "$1" } # Store the original working directory ORIGINAL_DIR="$(pwd)" # Ensure PATH includes common binary locations export PATH="/usr/local/bin:/usr/bin:/bin:$PATH" # Set up variables BUILD_DIR="$ORIGINAL_DIR/build" LIBKRUNFW_REPO="https://github.com/microsandbox/libkrunfw.git" LIBKRUN_REPO="https://github.com/microsandbox/libkrun.git" NO_CLEANUP=false FORCE_BUILD=false # Parse command line arguments for arg in "$@" do case $arg in --no-clean|--no-cleanup) NO_CLEANUP=true shift ;; --force|--force-build) FORCE_BUILD=true shift ;; esac done # Determine the OS type OS_TYPE="$(uname -s)" # Check if krunvm is installed on macOS, if applicable if [ "$OS_TYPE" = "Darwin" ]; then if ! which krunvm >/dev/null 2>&1; then printf "${RED}krunvm command not found. Please install it using: brew tap slp/krun && brew install krunvm${RESET}\n" exit 1 fi fi # Check for required packages and Python dependencies on Linux if [ "$OS_TYPE" = "Linux" ]; then check_linux_packages check_python_dependencies fi # Function to handle cleanup cleanup() { if [ "$NO_CLEANUP" = true ]; then info "Skipping cleanup as requested." return fi warn "Cleaning up..." cd "$ORIGINAL_DIR" || { error "Failed to change back to original directory"; exit 1; } rm -rf "$BUILD_DIR" if [ "$OS_TYPE" = "Darwin" ]; then warn "Deleting libkrunfw-builder VM..." krunvm delete libkrunfw-builder warn "Deleting libkrun-builder VM..." krunvm delete libkrun-builder fi info "Cleanup complete." } # Trap EXIT signal to run cleanup trap cleanup EXIT # Function to check command success check_success() { if [ $? -ne 0 ]; then error "Error occurred: $1" exit 1 fi } # Common function to check for existing installations check_existing_lib() { if [ "$FORCE_BUILD" = true ]; then info "Force build enabled. Skipping check for existing $1." return 0 fi local lib_name="$1" # Get ABI version from the appropriate Makefile local abi_version=$(get_abi_version "$BUILD_DIR/$lib_name/Makefile") case "$OS_TYPE" in Linux) lib_path="$BUILD_DIR/$lib_name.so.$abi_version" ;; Darwin) lib_path="$BUILD_DIR/$lib_name.$abi_version.dylib" ;; *) error "Unsupported OS: $OS_TYPE" exit 1 ;; esac if [ -f "$lib_path" ]; then info "$lib_name already exists in $lib_path. Skipping build." return 1 fi return 0 } # Function to create build directory create_build_directory() { cd "$ORIGINAL_DIR" || { error "Failed to change to original directory"; exit 1; } if [ -d "$BUILD_DIR" ]; then info "Build directory already exists. Skipping creation..." else info "Creating build directory..." mkdir -p "$BUILD_DIR" check_success "Failed to create build directory" fi } # Common function to clone repositories clone_repo() { cd "$BUILD_DIR" || { error "Failed to change to build directory"; exit 1; } local repo_url="$1" local repo_name="$2" shift 2 # Remove the first two arguments, leaving any additional args if [ -d "$repo_name" ]; then info "$repo_name directory already exists. Skipping cloning..." else info "Cloning $repo_name repository..." git clone "$repo_url" "$@" # Pass any remaining arguments to git clone check_success "Failed to clone $repo_name repository" fi } # Function to extract ABI version from Makefile get_abi_version() { local makefile="$1" local abi_version=$(grep "^ABI_VERSION.*=" "$makefile" | cut -d'=' -f2 | tr -d ' ') if [ -z "$abi_version" ]; then error "Could not determine ABI version from $makefile" exit 1 fi echo "$abi_version" } # Function to extract FULL_VERSION from Makefile get_full_version() { local makefile="$1" local full_version=$(grep "^FULL_VERSION.*=" "$makefile" | cut -d'=' -f2 | tr -d ' ') if [ -z "$full_version" ]; then error "Could not determine FULL_VERSION from $makefile" exit 1 fi echo "$full_version" } # Function to build and copy libkrunfw build_libkrunfw() { cd "$BUILD_DIR/libkrunfw" || { error "Failed to change to libkrunfw directory"; exit 1; } local abi_version=$(get_abi_version "Makefile") info "Detected libkrunfw ABI version: $abi_version" info "Building libkrunfw..." export PYTHONPATH="$HOME/.local/lib/python3.*/site-packages:$PYTHONPATH" case "$OS_TYPE" in Darwin) # On macOS, we need sudo to allow krunvm set xattr on the volume sudo make PYTHONPATH="$PYTHONPATH" ;; *) make PYTHONPATH="$PYTHONPATH" ;; esac check_success "Failed to build libkrunfw" # Copy the library to build directory and create symlink info "Copying libkrunfw to build directory..." cd "$BUILD_DIR" || { error "Failed to change to build directory"; exit 1; } case "$OS_TYPE" in Linux) cp libkrunfw/libkrunfw.so.$abi_version.* "libkrunfw.so.$abi_version" patchelf --set-rpath '$ORIGIN' "libkrunfw.so.$abi_version" ln -sf "libkrunfw.so.$abi_version" "libkrunfw.so" ;; Darwin) cp libkrunfw/libkrunfw.$abi_version.dylib "libkrunfw.$abi_version.dylib" install_name_tool -id "@rpath/libkrunfw.$abi_version.dylib" "libkrunfw.$abi_version.dylib" ln -sf "libkrunfw.$abi_version.dylib" "libkrunfw.dylib" ;; *) error "Unsupported OS: $OS_TYPE" exit 1 ;; esac check_success "Failed to copy libkrunfw" } # Function to build and copy libkrun build_libkrun() { cd "$BUILD_DIR/libkrun" || { error "Failed to change to libkrun directory"; exit 1; } local abi_version=$(get_abi_version "Makefile") local full_version=$(get_full_version "Makefile") info "Detected libkrun ABI version: $abi_version" info "Detected libkrun FULL version: $full_version" info "Building libkrun..." # Update library path to use our build directory export LIBRARY_PATH="$BUILD_DIR:$LIBRARY_PATH" export PATH="$HOME/.cargo/bin:$PATH" case "$OS_TYPE" in Darwin) sudo make LIBRARY_PATH="$LIBRARY_PATH" PATH="$PATH" ;; *) make LIBRARY_PATH="$LIBRARY_PATH" PATH="$PATH" ;; esac check_success "Failed to build libkrun" # Copy and rename the library to build directory and create symlink info "Copying libkrun to build directory..." cd "$BUILD_DIR" || { error "Failed to change to build directory"; exit 1; } case "$OS_TYPE" in Linux) cp libkrun/target/release/libkrun.so.$full_version "libkrun.so.$abi_version" patchelf --set-rpath '$ORIGIN' "libkrun.so.$abi_version" patchelf --set-needed "libkrunfw.so.4" "libkrun.so.$abi_version" ln -sf "libkrun.so.$abi_version" "libkrun.so" ;; Darwin) cp libkrun/target/release/libkrun.$full_version.dylib "libkrun.$abi_version.dylib" install_name_tool -id "@rpath/libkrun.$abi_version.dylib" "libkrun.$abi_version.dylib" install_name_tool -change "libkrunfw.4.dylib" "@rpath/libkrunfw.4.dylib" "libkrun.$abi_version.dylib" ln -sf "libkrun.$abi_version.dylib" "libkrun.dylib" ;; *) error "Unsupported OS: $OS_TYPE" exit 1 ;; esac check_success "Failed to copy libkrun" } # Main script execution check_existing_lib "libkrunfw" if [ $? -eq 0 ]; then create_build_directory clone_repo "$LIBKRUNFW_REPO" "libkrunfw" --single-branch --branch develop build_libkrunfw fi check_existing_lib "libkrun" if [ $? -eq 0 ]; then create_build_directory clone_repo "$LIBKRUN_REPO" "libkrun" --single-branch --branch develop build_libkrun fi # Finished info "Setup complete."

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/microsandbox/microsandbox'

If you have feedback or need assistance with the MCP directory API, please join our Discord server