Skip to content
58 changes: 39 additions & 19 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_compile_options(-Wall -Wextra -Werror -Wpedantic -Wuninitialized)


# Project information.
project(nsb
VERSION 0.1.0
Expand Down Expand Up @@ -72,15 +71,53 @@ message(STATUS "▸ Source: ${CMAKE_SOURCE_DIR}")
message(STATUS "▸ Protobuf: ${Protobuf_INCLUDE_DIRS}")
message(STATUS "▸ YAML: ${YAML_CPP_INCLUDE_DIR}")

# Set up library.
message(STATUS "Protoc Executable: ${Protobuf_PROTOC_EXECUTABLE}")

# Generate C++ protobuf files directly via protoc.
add_custom_command(
OUTPUT ${CPP_PROTO_DIR}/nsb.pb.h ${CPP_PROTO_DIR}/nsb.pb.cc
COMMAND ${Protobuf_PROTOC_EXECUTABLE}
--cpp_out=${CPP_PROTO_DIR}
--proto_path=${PROTO_DIR}
${PROTO_DIR}/nsb.proto
DEPENDS ${PROTO_DIR}/nsb.proto
COMMENT "Running cpp protocol buffer compiler on nsb.proto"
)

# Generate Python protobuf files directly via protoc.
add_custom_command(
OUTPUT ${PYTHON_DIR}/proto/nsb_pb2.py
COMMAND ${Protobuf_PROTOC_EXECUTABLE}
--python_out=${PYTHON_DIR}/proto
--proto_path=${PROTO_DIR}
${PROTO_DIR}/nsb.proto
DEPENDS ${PROTO_DIR}/nsb.proto
COMMENT "Running python protocol buffer compiler on nsb.proto"
)

# Custom target that depends on all generated proto files.
add_custom_target(nsb_proto_gen ALL
DEPENDS
${CPP_PROTO_DIR}/nsb.pb.h
${CPP_PROTO_DIR}/nsb.pb.cc
${PYTHON_DIR}/proto/nsb_pb2.py
)

# Set up library (include generated nsb.pb.cc as an explicit source).
add_library(nsb SHARED
${CPP_SRC_DIR}/nsb.cc
${CPP_SRC_DIR}/nsb_client.cc
${CPP_PROTO_DIR}/nsb.pb.cc
)

# Ensure proto files are generated before compiling nsb.
add_dependencies(nsb nsb_proto_gen)

# Link libraries.
target_link_libraries(nsb PUBLIC
${link_targets}
)

# Include directories.
target_include_directories(nsb PUBLIC
${CPP_INCLUDE_DIR}
Expand All @@ -89,23 +126,6 @@ target_include_directories(nsb PUBLIC
${YAML_CPP_INCLUDE_DIR}
)

message(STATUS "Protoc Executable: ${Protobuf_PROTOC_EXECUTABLE}")
# Generate C++ protobuf files.
protobuf_generate(
TARGET nsb
LANGUAGE cpp
IMPORT_DIRS ${PROTO_DIR}
PROTOC_OUT_DIR ${CPP_DIR}/proto
PROTOS ${PROTO_DIR}/nsb.proto
)
# Generate Python protobuf file.
protobuf_generate(
TARGET nsb
LANGUAGE python
IMPORT_DIRS ${PROTO_DIR}
PROTOC_OUT_DIR ${PYTHON_DIR}/proto
PROTOS ${PROTO_DIR}/nsb.proto
)
# Cleaning up.
set_target_properties(nsb PROPERTIES ADDITIONAL_CLEAN_FILES
"${CPP_DIR}/proto/*;${PYTHON_DIR}/proto/*;${PYTHON_DIR}/__pycache__/*"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ your code. Once this is complete, we recommend taking these steps in order:
1. **Start the Redis server.** Specify or take note of the port number that the
server is running on and make sure your configuration file points to the address
and port.
```redis-server -p 5050```
```redis-server --port 5050```

2. **Start the NSB Daemon.** If you followed the build instructions in above,
then you can start the NSB Daemon executable from either the _build_ directory
Expand Down
132 changes: 132 additions & 0 deletions arch_nsb_install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#!/bin/bash
set -e # Exit immediately on error

# If running as root, make sudo a no-op (added for testing on docker)
if [ "$(id -u)" -eq 0 ]; then
sudo() { "$@"; }
export -f sudo
fi

echo "=== NSB Installation Script (Arch Linux) ==="

# ── 1. System Packages ──────────────────────────────────────────────────────
echo "[1/7] Installing system packages..."
sudo pacman -Syu --noconfirm \
base-devel \
cmake \
pkgconf \
sqlite \
yaml-cpp \
hiredis \
python \
python-pip \
redis \
git \
wget

pip install protobuf --break-system-packages

# ── 2. Abseil ────────────────────────────────────────────────────────────────
echo "[2/7] Building & installing Abseil..."
cd ~
if [ ! -d "abseil-cpp" ]; then
git clone --depth 1 --branch 20240116.0 https://github.com/abseil/abseil-cpp.git
fi
cd abseil-cpp
mkdir -p build
cd build
cmake .. \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
-DCMAKE_CXX_STANDARD=17 \
-DCMAKE_BUILD_TYPE=Release \
-DABSL_ENABLE_INSTALL=ON \
-DBUILD_TESTING=OFF
cmake --build . -j2
sudo cmake --install .
sudo ldconfig

echo "Sanity check - Abseil:"
ls /usr/local/lib/libabsl_log* /usr/local/lib/libabsl_base* 2>/dev/null

# ── 3. Protobuf ──────────────────────────────────────────────────────────────
echo "[3/7] Building & installing Protobuf v27.5..."
cd ~
if [ ! -f "protobuf-27.5.tar.gz" ]; then
wget https://github.com/protocolbuffers/protobuf/releases/download/v27.5/protobuf-27.5.tar.gz
fi
if [ ! -d "protobuf-27.5" ]; then
tar -xvf protobuf-27.5.tar.gz
fi
cd protobuf-27.5
mkdir -p build
cd build
cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
-Dprotobuf_BUILD_SHARED_LIBS=ON \
-Dprotobuf_BUILD_TESTS=OFF \
-Dprotobuf_ABSL_PROVIDER=package \
-DCMAKE_CXX_STANDARD=17 \
-DCMAKE_INSTALL_PREFIX=/usr/local
cmake --build . -j2
sudo cmake --install .
sudo ldconfig

echo "Sanity check - Protobuf:"
which protoc
protoc --version
ls /usr/local/lib/libprotobuf.so*

# ── 4. Clone NSB ─────────────────────────────────────────────────────────────
echo "[4/7] Cloning NSB..."
cd ~
if [ ! -d "nsb" ]; then
git clone https://github.com/nsb-ucsc/nsb.git nsb
fi
cd nsb

# ── 5. Build NSB ─────────────────────────────────────────────────────────────
echo "[5/7] Building NSB..."
rm -rf build
mkdir build
cd build
cmake -DProtobuf_PROTOC_EXECUTABLE=/usr/local/bin/protoc ..
cmake --build . -j2

# ── 6. Install NSB ───────────────────────────────────────────────────────────
echo "[6/7] Installing NSB..."
sudo cmake --install .
sudo ldconfig

# ── 7. PYTHONPATH ────────────────────────────────────────────────────────────
# Detect shell rc file
case "$SHELL" in
*/zsh) RC_FILE="$HOME/.zshrc" ;;
*/bash) RC_FILE="$HOME/.bashrc" ;;
*) RC_FILE="$HOME/.profile" ;; # universal fallback
esac

echo "[7/7] Setting PYTHONPATH..."
touch "$RC_FILE"
PROTO_PATH="$HOME/nsb/python"
if ! grep -q "nsb/python" "$RC_FILE"; then
echo "export PYTHONPATH=$PROTO_PATH:\$PYTHONPATH" >>"$RC_FILE"
fi
export PYTHONPATH=$PROTO_PATH:$PYTHONPATH

# ── 8. Redis ─────────────────────────────────────────────────────────────────
echo "Starting Redis on port 5050..."
redis-server --port 5050 --daemonize yes
redis-cli -p 5050 ping

# ── Final Test ───────────────────────────────────────────────────────────────
echo "Testing Python proto import..."
python3 - <<'EOF'
import proto.nsb_pb2 as nsb_pb2
print("NSB Python proto loaded from:", nsb_pb2.__file__)
EOF

echo ""
echo "=== Installation complete! ==="
echo "To run the daemon: cd ~/nsb/build && ./nsb_daemon ../config.yaml"
echo "Remember to run: source $RC_FILE"
32 changes: 32 additions & 0 deletions linux-setup-guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Linux Installation

## Prerequisites
Make sure you have a supported Linux distribution (using apt or pacman).

## Steps

1. **Download the install script** for your distribution:
- Arch Linux: `arch_nsb_install.sh`
- Ubuntu: `ubuntu_nsb_install.sh`

2. **Open a terminal** and navigate to the directory the script downloaded to:
```bash
cd ~/Downloads/
```

3. **Make the script executable:**
```bash
chmod +x <distro>_nsb_install.sh
```

4. **Run the script:**
```bash
./<distro>_nsb_install.sh
```

5. **Follow any on-screen instructions** that appear during installation.

6. **Reload your shell** after installation completes:
```bash
source ~/.bashrc
```
135 changes: 135 additions & 0 deletions ubuntu_nsb_install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
#!/bin/bash
set -e # Exit immediately on error

# If running as root (e.g. Docker), make sudo a no-op
if [ "$(id -u)" -eq 0 ]; then
sudo() { "$@"; }
export -f sudo
fi

echo "=== NSB Installation Script (Ubuntu) ==="

# ── 1. System Packages ──────────────────────────────────────────────────────
echo "[1/7] Installing system packages..."
sudo apt update
sudo apt install -y \
build-essential \
cmake \
pkg-config \
libsqlite3-dev \
libyaml-cpp-dev \
libhiredis-dev \
python3 \
python3-pip \
redis-server \
git \
wget

pip install protobuf --break-system-packages

# ── 2. Abseil ────────────────────────────────────────────────────────────────
echo "[2/7] Building & installing Abseil..."
cd ~
if [ ! -d "abseil-cpp" ]; then
git clone --depth 1 --branch 20240116.0 https://github.com/abseil/abseil-cpp.git
fi
cd abseil-cpp
mkdir -p build
cd build
cmake .. \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
-DCMAKE_CXX_STANDARD=17 \
-DCMAKE_BUILD_TYPE=Release \
-DABSL_ENABLE_INSTALL=ON \
-DBUILD_TESTING=OFF
cmake --build . -j2
sudo cmake --install .
sudo ldconfig

echo "Sanity check - Abseil:"
ls /usr/local/lib/libabsl_log* /usr/local/lib/libabsl_base* 2>/dev/null

# ── 3. Protobuf ──────────────────────────────────────────────────────────────
echo "[3/7] Building & installing Protobuf v27.5..."
cd ~
if [ ! -f "protobuf-27.5.tar.gz" ]; then
wget https://github.com/protocolbuffers/protobuf/releases/download/v27.5/protobuf-27.5.tar.gz
fi
if [ ! -d "protobuf-27.5" ]; then
tar -xvf protobuf-27.5.tar.gz
fi
cd protobuf-27.5
mkdir -p build
cd build
cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
-Dprotobuf_BUILD_SHARED_LIBS=ON \
-Dprotobuf_BUILD_TESTS=OFF \
-Dprotobuf_ABSL_PROVIDER=package \
-DCMAKE_CXX_STANDARD=17 \
-DCMAKE_INSTALL_PREFIX=/usr/local
cmake --build . -j2
sudo cmake --install .
sudo ldconfig

echo "Sanity check - Protobuf:"
which protoc
protoc --version
ls /usr/local/lib/libprotobuf.so*

# ── 4. Clone NSB ─────────────────────────────────────────────────────────────
echo "[4/7] Cloning NSB..."
cd ~
if [ ! -d "nsb" ]; then
git clone https://github.com/nsb-ucsc/nsb.git nsb
fi
cd nsb

# ── 5. Build NSB ─────────────────────────────────────────────────────────────
echo "[5/7] Building NSB..."
rm -rf build
mkdir build
cd build
cmake -DProtobuf_PROTOC_EXECUTABLE=/usr/local/bin/protoc ..
cmake --build . -j2

# ── 6. Install NSB ───────────────────────────────────────────────────────────
echo "[6/7] Installing NSB..."
sudo cmake --install .
sudo ldconfig

# ── 7. PYTHONPATH ────────────────────────────────────────────────────────────
# Detect shell rc file
case "$SHELL" in
*/zsh) RC_FILE="$HOME/.zshrc" ;;
*/bash) RC_FILE="$HOME/.bashrc" ;;
*) RC_FILE="$HOME/.profile" ;;
esac

echo "[7/7] Setting PYTHONPATH..."
touch "$RC_FILE"
PROTO_PATH="$HOME/nsb/python"
if ! grep -q "nsb/python" "$RC_FILE"; then
echo "export PYTHONPATH=$PROTO_PATH:\$PYTHONPATH" >>"$RC_FILE"
fi
export PYTHONPATH=$PROTO_PATH:$PYTHONPATH

source $RC_FILE

# ── 8. Redis ─────────────────────────────────────────────────────────────────
echo "Starting Redis on port 5050..."
redis-server --port 5050 --daemonize yes
redis-cli -p 5050 ping

# ── Final Test ───────────────────────────────────────────────────────────────
echo "Testing Python proto import..."
python3 - <<'EOF'
import proto.nsb_pb2 as nsb_pb2
print("NSB Python proto loaded from:", nsb_pb2.__file__)
EOF

echo ""
echo "=== Installation complete! ==="
echo "To run the daemon: cd ~/nsb/build && ./nsb_daemon ../config.yaml"
echo "Remember to run: source $RC_FILE"