Skip to content

Commit

Permalink
Add support for arm64 and update mozjpeg 4.1.3 (#80)
Browse files Browse the repository at this point in the history
* Add support for arm64 and update mozjpeg 4.1.3

Windows building is broken. It has to be fixed. I recommend using vcpkg.
Mac Os X arm64 binary should be change to real arm64 binary. I don't own mac, but everything builds correctly.

* Add paths for cjpeg for 32-bit and 64-bit windows
  • Loading branch information
MateuszKrawczuk committed Jul 22, 2023
1 parent c72b1f5 commit c0587fb
Show file tree
Hide file tree
Showing 15 changed files with 94 additions and 52 deletions.
12 changes: 6 additions & 6 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,19 @@ jobs:
matrix:
node-version:
- 16
- 14
- 12
- 18
- 20
os:
- ubuntu-latest
- macos-latest
- windows-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- if: contains(matrix.os, 'ubuntu')
run: sudo apt-get install nasm
run: sudo apt-get install nasm cmake libpng-dev
- if: contains(matrix.os, 'macos')
run: brew install automake nasm
- uses: actions/setup-node@v2
run: brew install cmake nasm libpng zlib
- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: npm install
Expand Down
16 changes: 8 additions & 8 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
FROM debian:10-slim
FROM debian:12-slim

RUN apt-get update \
&& apt-get install autoconf libtool nasm libpng-dev automake pkg-config build-essential wget \
&& apt-get install cmake libtool nasm libpng-dev pkg-config build-essential wget \
-yq --no-install-suggests --no-install-recommends --force-yes

WORKDIR /src
RUN wget --no-check-certificate https://github.com/mozilla/mozjpeg/archive/v3.3.1.tar.gz -O mozjpeg-3.3.1.tar.gz
RUN tar -xzvf mozjpeg-3.3.1.tar.gz
WORKDIR /src/mozjpeg-3.3.1
RUN wget --no-check-certificate https://github.com/mozilla/mozjpeg/archive/v4.1.3.tar.gz -O mozjpeg-4.1.3.tar.gz
RUN tar -xzvf mozjpeg-4.1.3.tar.gz
WORKDIR /src/mozjpeg-4.1.3

RUN autoreconf -fiv \
&& ./configure LDFLAGS=-static libpng_LIBS='/usr/lib/x86_64-linux-gnu/libpng16.a -lz' --enable-static --disable-shared \
&& make -j8
RUN mkdir result && cd result && \
cmake .. \
&& cmake --build .
11 changes: 7 additions & 4 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@ import {fileURLToPath} from 'node:url';
import BinWrapper from 'bin-wrapper';

const pkg = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url)));
const url = `https://raw.githubusercontent.com/imagemin/mozjpeg-bin/v${pkg.version}/vendor/`;
const url = `https://github.com/imagemin/mozjpeg-bin/raw/${pkg.version}/vendor/`;

const binWrapper = new BinWrapper()
.src(`${url}macos/cjpeg`, 'darwin')
.src(`${url}linux/cjpeg`, 'linux')
.src(`${url}win/cjpeg.exe`, 'win32')
.src(`${url}macos/amd64/cjpeg`, 'darwin', 'x64')
.src(`${url}macos/arm64/cjpeg`, 'darwin', 'arm64')
.src(`${url}linux/amd64/cjpeg`, 'linux', 'x64')
.src(`${url}linux/arm64/cjpeg`, 'linux', 'arm64')
.src(`${url}win/x86/cjpeg.exe`, 'win32', 'x86')
.src(`${url}win/x64/cjpeg.exe`, 'win32', 'x64')
.dest(fileURLToPath(new URL('../vendor', import.meta.url)))
.use(process.platform === 'win32' ? 'cjpeg.exe' : 'cjpeg');

Expand Down
65 changes: 52 additions & 13 deletions lib/install.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,75 @@
import os from 'node:os';
import process from 'node:process';
import {fileURLToPath} from 'node:url';
import path from 'node:path';
import fs from 'node:fs';
import {execa, $} from 'execa';
import binBuild from 'bin-build';
import bin from './index.js';

const cpuNumber = Math.max(os.cpus().length, 1);

bin.run(['-version']).then(() => {
console.log('mozjpeg pre-build test passed successfully');
}).catch(async error => {
console.warn(error.message);
console.warn('mozjpeg pre-build test failed');
console.info('compiling from source');

let cfgExtras = '';
const config = [];
const vcpkgInstall = [];

if (process.platform === 'darwin') {
cfgExtras = 'libpng_LIBS=\'/usr/local/lib/libpng16.a -lz\' --enable-static';
config.push('-DCMAKE_FIND_FRAMEWORK=LAST -DBUILD_SHARED_LIBS=OFF');
}

if (process.platform === 'win32') {
const directoryPath = '.\\vcpkg';
if (fs.existsSync(directoryPath)) {
console.log('vcpkg already downloaded');
} else {
await $`git clone https://github.com/microsoft/vcpkg.git`;
}

// Build vcpkg
await execa('.\\vcpkg\\bootstrap-vcpkg.bat');

// Install libpng and zlib
if (process.arch === 'x64') {
vcpkgInstall.push('--triplet x64-windows libpng:x64-windows-static zlib:x64-windows-static');
} else if (process.arch === 'arm64') {
vcpkgInstall.push('--triplet arm64-windows libpng:arm64-windows-static zlib:arm64-windows-static');
}

const vcpkg = [`.\\vcpkg\\vcpkg install ${vcpkgInstall.join(' ')} libpng zlib`];

await execa(`${vcpkg}`);

const currentPath = path.resolve('.', './vcpkg/scripts/buildsystems/vcpkg.cmake');
// Add vcpkg toolchain file to the configuration
config.push(`-DCMAKE_TOOLCHAIN_FILE=${currentPath}`);
}

const cfg = [
`./configure --enable-static --disable-shared --disable-dependency-tracking --with-jpeg8 ${cfgExtras}`,
`--prefix="${bin.dest()}" --bindir="${bin.dest()}" --libdir="${bin.dest()}"`,
`cmake -DCMAKE_BUILD_TYPE=Release ${config.join(' ')} .`,
].join(' ');

try {
const source = fileURLToPath(new URL('../vendor/source/mozjpeg.tar.gz', import.meta.url));
await binBuild.file(source, [
'autoreconf -fiv',
cfg,
`make -j${cpuNumber}`,
`make install -j${cpuNumber}`,
]);
if (process.platform === 'win32') {
await binBuild.file(source, [
cfg,
'cmake --build . --config Release',
`copy Release\\cjpeg.exe ${bin.dest()}\\cjpeg.exe`,
`copy Release\\turbojpeg.dll ${bin.dest()}\\turbojpeg.dll`,
`copy Release\\libpng16.dll ${bin.dest()}\\libpng16.dll`,
`copy Release\\jpeg62.dll ${bin.dest()}\\jpeg62.dll`,
`copy Release\\zlib1.dll ${bin.dest()}\\zlib1.dll`,
]);
} else {
await binBuild.file(source, [
cfg,
'cmake --build . ',
`cp cjpeg-static ${bin.dest()}/cjpeg`,
]);
}

console.log('mozjpeg built successfully');
} catch (error) {
Expand Down
14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
"exports": "./index.js",
"bin": "cli.js",
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
"node": "^16.20.0 || ^18.17.0 || >=20.0.0"
},
"scripts": {
"postinstall": "node lib/install.js",
"test": "xo && ava --timeout=120s",
"build-linux": "docker build --tag imagemin/mozjpeg docker && docker run --rm --volume $(pwd)/vendor/linux:/src/out imagemin/mozjpeg cp cjpeg /src/out"
"test": "xo && ava --timeout=180s",
"build-linux": "docker build --tag imagemin/mozjpeg docker && docker run --rm --volume $(pwd)/vendor/linux:/src/out imagemin/mozjpeg cp result/cjpeg-static /src/out/cjpeg"
},
"files": [
"index.js",
Expand All @@ -34,14 +34,14 @@
],
"dependencies": {
"bin-build": "^3.0.0",
"bin-wrapper": "^4.0.0"
"bin-wrapper": "^4.1.0"
},
"devDependencies": {
"ava": "^3.8.0",
"ava": "^4.3.3",
"bin-check": "^4.1.0",
"compare-size": "^3.0.0",
"execa": "^5.1.1",
"tempy": "^2.0.0",
"execa": "^7.1.1",
"tempy": "^3.1.0",
"xo": "^0.45.0"
},
"ava": {
Expand Down
28 changes: 14 additions & 14 deletions test/test.js
Original file line number Diff line number Diff line change
@@ -1,49 +1,49 @@
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import process from 'node:process';
import {fileURLToPath} from 'node:url';
import test from 'ava';
import execa from 'execa';
import tempy from 'tempy';
import {execa} from 'execa';
import {temporaryDirectory} from 'tempy';
import binCheck from 'bin-check';
import binBuild from 'bin-build';
import compareSize from 'compare-size';
import mozjpeg from '../index.js';

const cpuNumber = os.cpus().length;

test('rebuild the mozjpeg binaries', async t => {
const temporary = temporaryDirectory();
const config = [];
// Skip the test on Windows
if (process.platform === 'win32') {
t.pass();
return;
}

const temporary = tempy.directory();
if (process.platform === 'darwin') {
config.push('-DCMAKE_FIND_FRAMEWORK=LAST -DBUILD_SHARED_LIBS=OFF');
}

const cfg = [
'./configure --enable-static --disable-shared --disable-dependency-tracking --with-jpeg8',
`--prefix="${temporary}" --bindir="${temporary}" --libdir="${temporary}"`,
`cmake ${config.join(' ')} -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="${temporary}" .`,
].join(' ');

const source = fileURLToPath(new URL('../vendor/source/mozjpeg.tar.gz', import.meta.url));
await binBuild.file(source, [
'autoreconf -fiv',
cfg,
`make --jobs=${cpuNumber}`,
`make install --jobs=${cpuNumber}`,
'cmake --build . ',
'cmake --install . ',
]);

t.true(fs.existsSync(path.join(temporary, 'cjpeg')));
t.true(fs.existsSync(path.join(temporary, 'bin/cjpeg')));
});

test('return path to binary and verify that it is working', async t => {
t.true(await binCheck(mozjpeg, ['-version']));
});

test('minify a JPG', async t => {
const temporary = tempy.directory();
const src = fileURLToPath(new URL('./fixtures/test.jpg', import.meta.url));
const temporary = temporaryDirectory();
const src = fileURLToPath(new URL('fixtures/test.jpg', import.meta.url));
const dest = path.join(temporary, 'test.jpg');
const args = [
'-outfile',
Expand Down
Binary file added vendor/linux/amd64/cjpeg
Binary file not shown.
Binary file added vendor/linux/arm64/cjpeg
Binary file not shown.
Binary file removed vendor/linux/cjpeg
Binary file not shown.
File renamed without changes.
Binary file added vendor/macos/arm64/cjpeg
Binary file not shown.
Binary file modified vendor/source/mozjpeg.tar.gz
Binary file not shown.
Binary file removed vendor/win/cjpeg.exe
Binary file not shown.
Binary file added vendor/win/x64/cjpeg.exe
Binary file not shown.
Binary file added vendor/win/x86/cjpeg.exe
Binary file not shown.

1 comment on commit c0587fb

@Subash
Copy link

@Subash Subash commented on c0587fb Aug 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any date on when this will be released?

Please sign in to comment.