diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 00000000..1ca5289f --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,44 @@ +name: CI + +on: + push: + branches: + - main + - master + pull_request: + branches: + - main + - master + workflow_dispatch: + +jobs: + + build: + name: Build + strategy: + matrix: + runs-on: + - macos-14 + - ubuntu-22.04 + fail-fast: false + runs-on: ${{ matrix.runs-on }} + steps: + - name: Check out repo + uses: actions/checkout@v4 + + - name: Install Go + uses: actions/setup-go@v5 + with: + cache: false + go-version: "1.23" + + - name: Build + run: go build + + - name: Test + run: go test -v + + - name: Build examples + run: | + cd examples + go build diff --git a/.github/workflows/deps.yaml b/.github/workflows/deps.yaml new file mode 100644 index 00000000..206f1720 --- /dev/null +++ b/.github/workflows/deps.yaml @@ -0,0 +1,101 @@ +name: Build dependencies + +on: + push: + branches: + - main + - master + paths: + - 'deps/**' + pull_request: + branches: + - main + - master + paths: + - 'deps/**' + workflow_dispatch: + +jobs: + linux: + name: Linux + runs-on: ubuntu-22.04 + steps: + - name: Check out repo + uses: actions/checkout@v4 + + - name: Install build tools + run: | + sudo apt-get update + sudo apt-get install nasm + + - name: Build deps + run: | + export MAKEFLAGS="-j$(nproc)" + ./deps/build-deps-linux.sh + + - run: | + git status + git diff + + - name: Install Go + uses: actions/setup-go@v5 + with: + cache: false + go-version: "1.23" + + - name: Build and test lilliput with the new deps + run: | + go build + go test -v + + - name: Compress deps + run: tar -czf deps.tar.gz deps/linux + + - name: Upload deps artifact + uses: actions/upload-artifact@v4 + with: + name: deps-linux.tar.gz + path: deps.tar.gz + + macos: + name: macOS + runs-on: macos-14 + steps: + - name: Check out repo + uses: actions/checkout@v4 + + - name: Install build tools + run: | + brew install autoconf + brew install automake + brew install coreutils # for ffmpeg build + brew install libtool + + - name: Build deps + run: | + export MAKEFLAGS="-j$(nproc)" + ./deps/build-deps-osx.sh + + - run: | + git status + git diff + + - name: Install Go + uses: actions/setup-go@v5 + with: + cache: false + go-version: "1.23" + + - name: Build and test lilliput with the new deps + run: | + go build + go test -v + + - name: Compress deps + run: tar -czf deps.tar.gz deps/osx + + - name: Upload deps artifact + uses: actions/upload-artifact@v4 + with: + name: deps-macos.tar.gz + path: deps.tar.gz diff --git a/deps/build-deps-linux.sh b/deps/build-deps-linux.sh index 0e7849ad..f0abf4e8 100755 --- a/deps/build-deps-linux.sh +++ b/deps/build-deps-linux.sh @@ -91,9 +91,10 @@ mkdir -p $BASEDIR/opencv tar -xzf $SRCDIR/opencv-3.2.0.tar.gz -C $BASEDIR/opencv --strip-components 1 cd $BASEDIR/opencv patch -p1 < $SRCDIR/0001-export-exif-orientation.patch +patch -p1 < $BASEDIR/patches/0001-remove-invalid-flow-control.patch mkdir -p $BUILDDIR/opencv cd $BUILDDIR/opencv -cmake $BASEDIR/opencv -DWITH_JPEG=ON -DWITH_PNG=ON -DWITH_WEBP=ON -DWITH_JASPER=OFF -DWITH_TIFF=OFF -DWITH_OPENEXR=OFF -DWITH_OPENCL=OFF -DBUILD_JPEG=OFF -DBUILD_PNG=OFF -DBUILD_ZLIB=OFF -DENABLE_SSE41=ON -DENABLE_SSE42=ON -DBUILD_SHARED_LIBS=OFF -DBUILD_DOCS=OFF -DBUILD_PERF_TESTS=OFF -DBUILD_TESTS=OFF -DBUILD_opencv_photo=OFF -DBUILD_opencv_video=OFF -DBUILD_opencv_videoio=OFF -DBUILD_opencv_highgui=OFF -DBUILD_opencv_ml=off -DBUILD_opencv_flann=off -DCMAKE_LIBRARY_PATH=$PREFIX/LIB -DCMAKE_INCLUDE_PATH=$PREFIX/INCLUDE -DCMAKE_INSTALL_PREFIX=$PREFIX +cmake $BASEDIR/opencv -DWITH_JPEG=ON -DWITH_PNG=ON -DWITH_WEBP=ON -DWITH_JASPER=OFF -DWITH_TIFF=OFF -DWITH_OPENEXR=OFF -DWITH_OPENCL=OFF -DBUILD_JPEG=OFF -DBUILD_PNG=OFF -DBUILD_ZLIB=OFF -DENABLE_SSE41=ON -DENABLE_SSE42=ON -DBUILD_SHARED_LIBS=OFF -DBUILD_DOCS=OFF -DBUILD_PERF_TESTS=OFF -DBUILD_TESTS=OFF -DBUILD_opencv_photo=OFF -DBUILD_opencv_video=OFF -DBUILD_opencv_videoio=OFF -DBUILD_opencv_highgui=OFF -DBUILD_opencv_ml=off -DBUILD_opencv_flann=off -DBUILD_opencv_java=OFF -DBUILD_opencv_python=OFF -DCMAKE_LIBRARY_PATH=$PREFIX/LIB -DCMAKE_INCLUDE_PATH=$PREFIX/INCLUDE -DCMAKE_INSTALL_PREFIX=$PREFIX make make install @@ -116,9 +117,21 @@ $BASEDIR/ffmpeg/configure --prefix=$PREFIX --disable-doc --disable-programs --di make make install +rm -rf $BASEDIR/linux/$ARCH/bin +rm -f $BASEDIR/linux/$ARCH/**/*.cmake + # Since go modules don't currently download symlinked files # (see https://github.com/golang/go/issues/39417) # we replace symlinks with copies of the target. # We use a `find -exec` with a separate file because POSIX sh # is that much more limited than bash. find "$PREFIX" -type l -exec "${BASEDIR}/copy-symlink-target.sh" {} \; + +rm -rf $BASEDIR/linux/$ARCH/bin +rm -f $BASEDIR/linux/$ARCH/**/*.cmake + +if [ -n "$CI" ]; then + echo "CI detected, cleaning up build artifacts" + rm -rf "$SRCDIR" + rm -rf "$BUILDDIR" +fi diff --git a/deps/build-deps-osx.sh b/deps/build-deps-osx.sh index 7443ef9d..a0223248 100755 --- a/deps/build-deps-osx.sh +++ b/deps/build-deps-osx.sh @@ -319,7 +319,9 @@ cmake $BASEDIR/opencv \ -DWITH_APPLE_VISION=OFF \ -DWITH_COREIMAGE=OFF \ -DWITH_CAROTENE=OFF \ - -DWITH_VIDEOTOOLBOX=ON + -DWITH_VIDEOTOOLBOX=ON \ + -DBUILD_opencv_java=OFF \ + -DBUILD_opencv_python=OFF # Remove iOS-specific build files sed -i '' "s|;$BASEDIR/opencv/modules/imgcodecs/include/opencv2/imgcodecs/ios.h||" $BASEDIR/build/opencv/CMakeCache.txt @@ -349,6 +351,9 @@ $BASEDIR/ffmpeg/configure --prefix=$PREFIX --disable-doc --disable-programs --di make make install +rm -rf $BASEDIR/osx/$ARCH/bin +rm -f $BASEDIR/osx/$ARCH/**/*.cmake + # Since go modules don't currently download symlinked files # (see https://github.com/golang/go/issues/39417) # we replace symlinks with copies of the target. @@ -356,3 +361,9 @@ make install # is that much more limited than bash. find "$PREFIX" -type l -exec "${BASEDIR}/copy-symlink-target.sh" {} \; echo "Done!" + +if [ -n "$CI" ]; then + echo "CI detected, cleaning up build artifacts" + rm -rf "$SRCDIR" + rm -rf "$BUILDDIR" +fi diff --git a/deps/patches/0001-remove-invalid-flow-control.patch b/deps/patches/0001-remove-invalid-flow-control.patch new file mode 100644 index 00000000..5401ee34 --- /dev/null +++ b/deps/patches/0001-remove-invalid-flow-control.patch @@ -0,0 +1,13 @@ +diff --git a/cmake/OpenCVCompilerOptions.cmake b/cmake/OpenCVCompilerOptions.cmake +index 5bb0479..3d07b1c 100644 +--- a/cmake/OpenCVCompilerOptions.cmake ++++ b/cmake/OpenCVCompilerOptions.cmake +@@ -18,8 +18,6 @@ if(ENABLE_CCACHE AND NOT CMAKE_COMPILER_IS_CCACHE) + message(STATUS "Unable to compile program with enabled ccache, reverting...") + set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${__OLD_RULE_LAUNCH_COMPILE}") + endif() +- else() +- message(STATUS "Looking for ccache - not found") + endif() + endif() + endif() diff --git a/examples/go.mod b/examples/go.mod new file mode 100644 index 00000000..a7bb4c6d --- /dev/null +++ b/examples/go.mod @@ -0,0 +1,7 @@ +module example + +go 1.23.2 + +require github.com/discord/lilliput v0.0.0-20241012171911-37dccacf7c50 // indirect + +replace github.com/discord/lilliput => .. diff --git a/examples/go.sum b/examples/go.sum new file mode 100644 index 00000000..903ac075 --- /dev/null +++ b/examples/go.sum @@ -0,0 +1,2 @@ +github.com/discord/lilliput v0.0.0-20241012171911-37dccacf7c50 h1:5tSOh98txNCq1k4SwG4ZYCBjKjNg3fXHfdjOv8t4kBk= +github.com/discord/lilliput v0.0.0-20241012171911-37dccacf7c50/go.mod h1:0euuUBAD72MAYRm2ElLaG1h0nBR+CgpfnKc/U6y/uE8= diff --git a/webp_test.go b/webp_test.go index 4a4b663a..931e1134 100644 --- a/webp_test.go +++ b/webp_test.go @@ -235,7 +235,7 @@ func testNewWebpEncoderWithAnimatedWebPSource(t *testing.T) { resizeMethod: ImageOpsResize, }, { - name: "Animated WebP - Supported", + name: "Animated WebP - Resize #1", inputPath: "testdata/ferry_sunset.webp", outputPath: "testdata/out/ferry_sunset_out_resize.webp", width: 266, @@ -244,7 +244,7 @@ func testNewWebpEncoderWithAnimatedWebPSource(t *testing.T) { resizeMethod: ImageOpsResize, }, { - name: "Animated WebP - Supported", + name: "Animated WebP - Resize #2", inputPath: "testdata/animated-webp-supported.webp", outputPath: "testdata/out/animated-webp-supported_out_resize.webp", width: 400, @@ -253,7 +253,7 @@ func testNewWebpEncoderWithAnimatedWebPSource(t *testing.T) { resizeMethod: ImageOpsResize, }, { - name: "Animated WebP - Supported", + name: "Animated WebP - Fit #1", inputPath: "testdata/animated-webp-supported.webp", outputPath: "testdata/out/animated-webp-supported_out_fit.webp", width: 400, @@ -262,7 +262,7 @@ func testNewWebpEncoderWithAnimatedWebPSource(t *testing.T) { resizeMethod: ImageOpsFit, }, { - name: "Animated WebP - Supported", + name: "Animated WebP - No resize", inputPath: "testdata/animated-webp-supported.webp", outputPath: "testdata/out/animated-webp-supported_out_no_resize.webp", width: 0, @@ -271,7 +271,7 @@ func testNewWebpEncoderWithAnimatedWebPSource(t *testing.T) { resizeMethod: ImageOpsNoResize, }, { - name: "Animated WebP - Supported", + name: "Animated WebP - Fit #2", inputPath: "testdata/animated-webp-supported.webp", outputPath: "testdata/out/animated-webp-supported_out.webp", width: 200, @@ -341,11 +341,12 @@ func testNewWebpEncoderWithAnimatedWebPSource(t *testing.T) { DisableAnimatedOutput: tc.disableAnimatedOutput, } - ops := NewImageOps(50000) + ops := NewImageOps(2000) var newDst []byte newDst, err = ops.Transform(decoder, options, dstBuf) if err != nil { decoder.Close() + ops.Close() t.Errorf("Transform() error for %s: %v", tc.inputPath, err) return } @@ -353,6 +354,7 @@ func testNewWebpEncoderWithAnimatedWebPSource(t *testing.T) { // verify length of newDst if len(newDst) == 0 { decoder.Close() + ops.Close() t.Errorf("Transform() returned empty data for %s", tc.inputPath) } @@ -362,6 +364,7 @@ func testNewWebpEncoderWithAnimatedWebPSource(t *testing.T) { if _, err := os.Stat("testdata/out"); os.IsNotExist(err) { if err = os.Mkdir("testdata/out", 0755); err != nil { decoder.Close() + ops.Close() t.Errorf("Failed to create output directory: %v", err) return } @@ -369,10 +372,12 @@ func testNewWebpEncoderWithAnimatedWebPSource(t *testing.T) { if err = os.WriteFile(tc.outputPath, newDst, 0644); err != nil { decoder.Close() + ops.Close() t.Errorf("Failed to write %s: %v", tc.outputPath, err) } } decoder.Close() + ops.Close() }) } } @@ -429,11 +434,12 @@ func testNewWebpEncoderWithAnimatedGIFSource(t *testing.T) { EncodeTimeout: time.Second * 300, } - ops := NewImageOps(50000) + ops := NewImageOps(2000) var newDst []byte newDst, err = ops.Transform(decoder, options, dstBuf) if err != nil { decoder.Close() + ops.Close() t.Errorf("Transform() error for %s: %v", tc.inputPath, err) return } @@ -441,6 +447,7 @@ func testNewWebpEncoderWithAnimatedGIFSource(t *testing.T) { // verify length of newDst if len(newDst) == 0 { decoder.Close() + ops.Close() t.Errorf("Transform() returned empty data for %s", tc.inputPath) } @@ -450,6 +457,7 @@ func testNewWebpEncoderWithAnimatedGIFSource(t *testing.T) { if _, err := os.Stat("testdata/out"); os.IsNotExist(err) { if err = os.Mkdir("testdata/out", 0755); err != nil { decoder.Close() + ops.Close() t.Errorf("Failed to create output directory: %v", err) return } @@ -457,10 +465,12 @@ func testNewWebpEncoderWithAnimatedGIFSource(t *testing.T) { if err = os.WriteFile(tc.outputPath, newDst, 0644); err != nil { decoder.Close() + ops.Close() t.Errorf("Failed to write %s: %v", tc.outputPath, err) } } decoder.Close() + ops.Close() }) } }