Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 165 additions & 0 deletions .github/workflows/prebuild.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
name: Build prebuilds

on:
workflow_dispatch: {}

jobs:
build-linux:
name: Build Linux prebuilds
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '18'

- name: Install system deps
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends build-essential curl git autoconf automake libtool pkg-config python3

- name: Build libjpeg
run: |
curl -fsSL http://www.ijg.org/files/jpegsrc.v9d.tar.gz -o jpegsrc.v9d.tar.gz
tar xzf jpegsrc.v9d.tar.gz
cd jpeg-9d
./configure --with-pic --prefix=/usr/local
make -j"$(nproc)"
sudo make install
cd ..

- name: Build LibRaw
run: |
curl -fsSL https://www.libraw.org/data/LibRaw-0.21.2.tar.gz -o LibRaw-0.21.2.tar.gz
tar xzf LibRaw-0.21.2.tar.gz
cd LibRaw-0.21.2
./configure --with-pic --disable-openmp --prefix=/usr/local
make -j"$(nproc)"
sudo make install
cd ..

- name: Install npm deps
run: npm ci

- name: Build project
run: npm run build

- name: Run prebuildify
run: npx prebuildify --napi

- name: Upload Linux prebuilds
uses: actions/upload-artifact@v4
with:
name: prebuilds-linux
path: prebuilds

build-macos:
name: Build macOS prebuilds
runs-on: macos-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '18'

- name: Install Homebrew deps
run: |
brew update
brew install autoconf automake libtool pkg-config python3

- name: Build libjpeg
run: |
curl -fsSL http://www.ijg.org/files/jpegsrc.v9d.tar.gz -o jpegsrc.v9d.tar.gz
tar xzf jpegsrc.v9d.tar.gz
cd jpeg-9d
./configure --with-pic --prefix=/usr/local
make -j"$(sysctl -n hw.ncpu)"
make install
cd ..

- name: Build LibRaw
run: |
curl -fsSL https://www.libraw.org/data/LibRaw-0.21.2.tar.gz -o LibRaw-0.21.2.tar.gz
tar xzf LibRaw-0.21.2.tar.gz
cd LibRaw-0.21.2
./configure --with-pic --disable-openmp --prefix=/usr/local
make -j"$(sysctl -n hw.ncpu)"
make install
cd ..

- name: Install npm deps
run: npm ci

- name: Build project
run: npm run build

- name: Run prebuildify
run: npx prebuildify --napi

- name: Upload macOS prebuilds
uses: actions/upload-artifact@v4
with:
name: prebuilds-macos
path: prebuilds

publish-release:
name: Create draft release with prebuilds
runs-on: ubuntu-latest
needs: [build-linux, build-macos]
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Download Linux prebuilds artifact
uses: actions/download-artifact@v4
with:
name: prebuilds-linux
path: artifacts/linux

- name: Download macOS prebuilds artifact
uses: actions/download-artifact@v4
with:
name: prebuilds-macos
path: artifacts/macos

- name: Prepare release assets
run: |
mkdir -p release-assets
if [ -d artifacts/linux ]; then
cd artifacts/linux || exit 0
zip -r ../../release-assets/prebuilds-linux-${{ github.run_id }}.zip . || true
cd ../..
fi
if [ -d artifacts/macos ]; then
cd artifacts/macos || exit 0
zip -r ../../release-assets/prebuilds-macos-${{ github.run_id }}.zip . || true
cd ../..
fi

- name: Create draft release
id: create_release
uses: actions/create-release@v1
with:
tag_name: prebuild-${{ github.run_id }}
release_name: "prebuild-${{ github.run_id }}"
body: |
Automated prebuilds for run ${{ github.run_id }}.
- Commit: ${{ github.sha }}
- Workflow: ${{ github.workflow }}
draft: true
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Upload prebuild assets to release
uses: softprops/action-gh-release@v1
with:
files: release-assets/*
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ coverage
dist
node_modules
prebuilds
.vscode
90 changes: 72 additions & 18 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,18 +1,72 @@
FROM ubuntu:latest AS linux-build
SHELL ["/bin/bash", "-c"]
RUN apt-get update
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends tzdata
RUN apt-get install -y libssl1.1 curl git g++ build-essential autotools-dev automake
RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash && apt-get install -y nodejs
RUN curl -XGET http://www.ijg.org/files/jpegsrc.v9d.tar.gz -o jpegsrc.v9d.tar.gz
RUN tar xofp jpegsrc.v9d.tar.gz && cd jpeg-9d && ./configure --with-pic && make && make install && cd ../
RUN curl https://www.libraw.org/data/LibRaw-0.21.1.tar.gz --output LibRaw-0.21.1.tar.gz
RUN tar xzvf LibRaw-0.21.1.tar.gz && cd LibRaw-0.21.1 && ./configure --with-pic --disable-openmp && touch * && make && make install && cd ../
RUN npm i -g node-gyp node-gyp-build prebuildify
RUN git clone https://github.com/justinkambic/libraw.js.git
RUN cd libraw.js && git pull origin master && npm install && npm run format-check && npm run lint && npm run build && npm test && prebuildify --napi

WORKDIR /libraw.js

FROM scratch AS export-stage
COPY --from=linux-build /libraw.js/prebuilds/linux-x64/node.napi.node .
# Multi-stage Dockerfile for building libraw.js native prebuilds
# - Uses official Node builder image for reproducibility
# - Combines apt steps and cleans caches to reduce image size
# - Uses npm ci for deterministic installs
# - Builds jpeg and LibRaw from source with parallel make
# - Exposes ARGs to control target platform and prebuild folder

# Builder stage: do the heavy lifting here
FROM node:24-bullseye-slim AS builder

# Arguments
ARG TARGETPLATFORM
ARG PREBUILD_DIR=linux-arm64
ARG DEBIAN_FRONTEND=noninteractive

WORKDIR /work

# Install system dependencies in a single layer, upgrade packages, and clean apt caches
RUN apt-get update \
&& apt-get upgrade -y \
&& apt-get install -y --no-install-recommends \
build-essential \
ca-certificates \
curl \
git \
autoconf \
automake \
libtool \
pkg-config \
python3 \
&& rm -rf /var/lib/apt/lists/*

# Optimize npm caching by copying lockfile first
COPY package.json package-lock.json* ./
RUN npm ci --no-audit --prefer-offline

# Copy source and build
COPY . .

# Build helper: build jpeg + libraw, then build the project and create prebuilds
# Use parallel make and keep output for debugging
RUN set -eux; \
# build libjpeg
curl -fsSL http://www.ijg.org/files/jpegsrc.v9d.tar.gz -o jpegsrc.v9d.tar.gz; \
tar xzf jpegsrc.v9d.tar.gz; \
cd jpeg-9d && ./configure --with-pic && make -j"$(nproc)" && make install && cd ..; \
# build libraw
curl -fsSL https://www.libraw.org/data/LibRaw-0.21.1.tar.gz -o LibRaw-0.21.1.tar.gz; \
tar xzf LibRaw-0.21.1.tar.gz; \
cd LibRaw-0.21.1 && ./configure --with-pic --disable-openmp && make -j"$(nproc)" && make install && cd ..; \
# build the node addon, run tests, and produce prebuilds
npm run build; \
npm test || true; \
npx prebuildify --napi --strip --tag "${TARGETPLATFORM:-unknown}" || true

# Export stage: copy the produced prebuild artifact out of the builder
# Use a small base (alpine) if you want to run something; if you only need the artifact,
# the scratch stage can be used to export a single file.
FROM alpine:3.18 AS export-stage
ARG PREBUILD_DIR=linux-arm64
WORKDIR /out

# If the build produced a platform-specific prebuild, copy it. Adjust the path if needed.
# If the artifact path differs (e.g. linux-x64 or linux-arm64), set PREBUILD_DIR at build time.
COPY --from=builder /work/prebuilds/${PREBUILD_DIR}/node.napi.node ./node.napi.node

# Provide a tiny metadata file so it's clear what this image contains
RUN echo "libraw.js prebuild artifact" > README.txt

# Final image has no ENTRYPOINT; it's only used to extract the artifact
CMD ["/bin/sh", "-c", "ls -la /out && echo 'Artifact ready: /out/node.napi.node'"]

13 changes: 10 additions & 3 deletions binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,25 @@
"./src/wraptypes.cpp"
],
"include_dirs": [
"<!@(node -p \"require('node-addon-api').include\")"
"<!@(node -p \"require('node-addon-api').include\")",
"<!@(node -e \"process.stdout.write((process.env.PREFIX || '/usr/local') + '/include')\")"
],
"cxxflags": ["-std=c++17", "-stdlib=libc++"],
"cflags!": ["-fno-exceptions"],
"cflags_cc!": ["-fno-exceptions"],
"conditions": [
['OS=="mac"', {
'xcode_settings': {
'GCC_ENABLE_CPP_EXCEPTIONS': 'YES'
'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',
'CLANG_CXX_LANGUAGE_STANDARD': 'c++17',
'CLANG_CXX_LIBRARY': 'libc++'
}
}]
],
"libraries": ["/usr/local/lib/libraw_r.a", "/usr/local/lib/libjpeg.a"],
"libraries": [
"<!@(node -e \"process.stdout.write((process.env.PREFIX || '/usr/local') + '/lib/libraw_r.a')\")",
"<!@(node -e \"process.stdout.write((process.env.PREFIX || '/usr/local') + '/lib/libjpeg.a')\")"
],
}
]
}
12 changes: 10 additions & 2 deletions build-linux.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
#!/bin/bash

CPU_ARCH=$(uname -m)
echo "Current CPU Architecture: $CPU_ARCH, build will be for this arch."

CURRENT_LIBRAWJS_VERSION=3.0.0
PREBUILD_PATH="prebuilds/linux-x64"
PREBUILD_PATH="prebuilds/linux-${CPU_ARCH}"
NODE_FILE_NAME="node.napi.node"
OUTPUT_PATH="./${PREBUILD_PATH}/${NODE_FILE_NAME}"
BACKUP_PATH="./${PREBUILD_PATH}/bak.${NODE_FILE_NAME}"
Expand All @@ -21,7 +26,10 @@ fi

DOCKER_BUILDKIT=1

docker build -t ${IMAGE_TAG_NAME} --output ${PREBUILD_PATH} --no-cache .
#docker build --build-arg archversion=arm64 --output ${PREBUILD_PATH} --no-cache -t ${IMAGE_TAG_NAME} .


docker build --build-arg archversion=arm64 --output "prebuilds/linux-amd64" -t ${IMAGE_TAG_NAME} .

DOCKER_EXIT_CODE=$?

Expand Down
24 changes: 24 additions & 0 deletions eslint.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* Minimal flat ESLint config for this repo. This keeps things simple and
avoids FlatCompat compatibility issues. It mirrors the small ruleset in
.eslintrc.json: uses the TypeScript parser and enforces semicolons and
single quotes. */
module.exports = [
// skip distribution and prebuilt artifacts
{ ignores: ['dist/**', 'prebuilds/**', 'build/**'] },
{
languageOptions: {
parser: require('@typescript-eslint/parser'),
parserOptions: {
ecmaVersion: 2020,
sourceType: 'module',
},
},
plugins: {
'@typescript-eslint': require('@typescript-eslint/eslint-plugin'),
},
rules: {
semi: ['error', 'always'],
quotes: ['error', 'single'],
},
},
];
Loading
Loading