Skip to content

Instantly share code, notes, and snippets.

@gsidhu
Created August 26, 2025 14:02
Show Gist options
  • Select an option

  • Save gsidhu/69ad6397b98a7c67660d5cdcb17cd70f to your computer and use it in GitHub Desktop.

Select an option

Save gsidhu/69ad6397b98a7c67660d5cdcb17cd70f to your computer and use it in GitHub Desktop.
A shell script that translates the logic from the Homebrew formula to install `libev` from source on a Debian-based system like Raspberry Pi OS.
#!/bin/bash
# This script installs libev from source on Debian-based systems (like Raspberry Pi OS),
# based on the official Homebrew formula.
# Original formula: https://github.com/Homebrew/homebrew-core/blob/3f94f7aaead4364ea6905957daacefd73ca40342/Formula/lib/libev.rb
# NOTE: Translated from Ruby to Bash by Gemini Pro 2.5 with the prompt:
# "Look at this brew install script for libev on MacOS – <ORIGINAL RUBY SCRIPT>. \
# I want to install this libev package on Debian-based Raspberry Pi OS. Please create a shell script based on this."
# Tested successfully on a Raspberry Pi 5 Model B Rev 1.0 8GB running Raspberry OS (64-bit) based on Debian GNU/Linux 12 (bookworm).
# --- BEGIN INSTALL SCRIPT ---
# Exit immediately if a command exits with a non-zero status.
set -e
# --- Configuration ---
# Variables are taken directly from the Homebrew formula
VERSION="4.33"
DOWNLOAD_URL="https://dist.schmorp.de/libev/Attic/libev-${VERSION}.tar.gz"
EXPECTED_SHA256="507eb7b8d1015fbec5b935f34ebed15bf346bed04a11ab82b8eee848c4205aea"
INSTALL_PREFIX="/usr/local"
# --- Dependency Check ---
echo "--> Checking for required dependencies (build-essential, wget)..."
if ! dpkg -s build-essential wget >/dev/null 2>&1; then
echo " Dependencies missing. Please install them by running:"
echo " sudo apt-get update && sudo apt-get install build-essential wget"
exit 1
fi
echo " Dependencies are present."
# --- Workspace Setup ---
# Create a temporary directory for the build process
# The 'trap' command ensures this directory is removed when the script exits,
# even if it fails.
BUILD_DIR=$(mktemp -d)
trap 'rm -rf "$BUILD_DIR"' EXIT
cd "$BUILD_DIR"
echo "--> Created temporary build directory at: $BUILD_DIR"
# --- Download ---
echo "--> Downloading libev source code..."
wget -q -O "libev-${VERSION}.tar.gz" "$DOWNLOAD_URL"
echo " Download complete."
# --- Verify ---
echo "--> Verifying checksum of the downloaded file..."
# The double space is important for sha256sum's checking format
echo "$EXPECTED_SHA256 libev-${VERSION}.tar.gz" | sha256sum -c -
echo " Checksum OK."
# --- Build and Install ---
echo "--> Extracting source code..."
tar -xzf "libev-${VERSION}.tar.gz"
cd "libev-${VERSION}"
echo " Extraction complete."
echo "--> Configuring the build..."
# We use --prefix to install to /usr/local, the standard for manually compiled software.
# This replaces Homebrew's internal `std_configure_args`.
# The macOS-specific patch from the formula is not needed on Linux.
./configure --prefix="$INSTALL_PREFIX" \
--disable-silent-rules
echo "--> Compiling the source code (make)..."
make
echo "--> Installing the library (sudo make install)..."
sudo make install
echo " Installation complete."
# --- Post-Install Steps ---
echo "--> Performing post-install tasks..."
# Remove compatibility header to prevent conflict with libevent, as done in the formula.
if [ -f "${INSTALL_PREFIX}/include/event.h" ]; then
echo " Removing conflicting header: ${INSTALL_PREFIX}/include/event.h"
sudo rm -f "${INSTALL_PREFIX}/include/event.h"
fi
# Update the dynamic linker's cache so it can find the new library.
echo " Updating dynamic linker cache (ldconfig)..."
sudo ldconfig
echo " Post-install tasks complete."
# --- Verification Test ---
echo "--> Running verification test..."
# Change back to the parent directory to run the test
cd ..
# Create the test C file, same as in the Homebrew formula
cat <<'EOF' > test.c
/* Wait for stdin to become readable, then read and echo the first line. */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ev.h>
ev_io stdin_watcher;
static void stdin_cb (EV_P_ ev_io *watcher, int revents) {
char *buf = NULL;
size_t nbytes = 0;
getline(&buf, &nbytes, stdin);
printf("%s", buf);
free(buf);
ev_io_stop(EV_A_ watcher);
ev_break(EV_A_ EVBREAK_ALL);
}
int main() {
ev_io_init(&stdin_watcher, stdin_cb, STDIN_FILENO, EV_READ);
ev_io_start(EV_DEFAULT, &stdin_watcher);
ev_run(EV_DEFAULT, 0);
return 0;
}
EOF
echo " Compiling the test program..."
gcc test.c -I"${INSTALL_PREFIX}/include" -L"${INSTALL_PREFIX}/lib" -lev -o test
echo " Running the compiled test program..."
TEST_INPUT="hello, world from libev\n"
# We use 'echo -n' because the string already contains a newline.
# The C program reads this line and prints it back out.
TEST_OUTPUT=$(echo -n "$TEST_INPUT" | ./test)
if [ "$TEST_OUTPUT" = "$TEST_INPUT" ]; then
echo " Test PASSED!"
else
echo " Test FAILED!"
echo " Expected: '$TEST_INPUT'"
echo " Got: '$TEST_OUTPUT'"
exit 1
fi
echo ""
echo "✅ libev version ${VERSION} has been successfully installed to ${INSTALL_PREFIX}"
# --- END INSTALL SCRIPT ---
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment