kornelski / pngquant

Lossy PNG compressor — pngquant command based on libimagequant library
https://pngquant.org
Other
5.25k stars 486 forks source link

Configure: Enable FULLY static builds #368

Open bdkjones opened 4 years ago

bdkjones commented 4 years ago

The INSTALL documentation lists a procedure for ensuring that pngquant statically links to libpng (put the source for libpng as subfolder of pngquant's source, configure it with the static flag, then make it.)

However, zlib is still linked dynamically, no matter what the hell I try to do to change that. It would be very handy to have baked-in support for statically linking zlib as well.

I tried this, but had no luck: https://stackoverflow.com/questions/35582138/compile-a-static-version-of-pngquant

bdkjones commented 4 years ago

Ok, finally noticed that the patch at the SO link above used zlib.a instead of libz.a, which is why it failed. Here is the new, patched Configure file.

To ensure a fully static build, you need only follow the existing directions in INSTALL: download libpng and libz. Build each project, then drop their source folders inside pngquant's source folder. Run ./configure on pngQuant and you'll see both libraries are now linked statically.

#!/usr/bin/env bash

CONFIG="config.mk"
PREFIX="/usr/local"

DEBUG=
LIQSRCDIR=./lib
LIQCONFIGURE=(--quiet)
SSE=auto
OPENMP=
LIBPNG_DIR=.
LCMS2=auto
EXTRA_CFLAGS=
EXTRA_LDFLAGS=

# make gcc default compiler unless CC is already set
CC=${CC:-gcc}
SKIP_CC_CHECK=0

help() {
    printf "%4s %s\n" "" "$1"
}

for i in "$@"; do
    case $i in
    --help|-h)
        echo
        help "--prefix=<dir>                installation directory [$PREFIX]"
        help "--extra-cflags=<flags>        append to CFLAGS"
        help "--extra-ldflags=<flags>       append to LDFLAGS"
        echo
        help "--enable-debug"
        help "--enable-sse/--disable-sse    enable/disable SSE instructions"
        echo
        help "--with-libimagequant=<dir>    external libimagequant (lib/ default)"
        help "--with-openmp=static          compile with multicore support"
        help "--with-lcms2/--without-lcms2  compile with color profile support"
if [[ "$OSTYPE" =~ "darwin" ]]; then
        help "--with-cocoa/--without-cocoa  use Cocoa framework to read images"
fi
        help "--with-libpng=<dir>           search for libpng in directory"
        help "--with-zlib=<dir>             search for zlib in directory"
        echo
        help "CC=<compiler>                 use given compiler command"
        help "CFLAGS=<flags>                pass options to the compiler"
        help "LDFLAGS=<flags>               pass options to the linker"
        echo
        exit 0
        ;;
    # Can be set before or after configure. Latter overrides former.
    CC=*)
        CC=${i#*=}
        SKIP_CC_CHECK=1
        LIQCONFIGURE+=("$i")
        ;;
    CFLAGS=*)
        CFLAGS=${i#*=}
        LIQCONFIGURE+=("$i")
        ;;
    LDFLAGS=*)
        LDFLAGS=${i#*=}
        LIQCONFIGURE+=("$i")
        ;;
    --enable-debug)
        DEBUG=1
        LIQCONFIGURE+=("$i")
        ;;
    --enable-sse)
        SSE=1
        LIQCONFIGURE+=("$i")
        ;;
    --disable-sse)
        SSE=0
        LIQCONFIGURE+=("$i")
        ;;
    --with-openmp)
        OPENMP=1
        LIQCONFIGURE+=("$i")
        ;;
    --with-openmp=static)
        OPENMP=static
        LIQCONFIGURE+=("$i")
        ;;
    --with-lcms2)
        LCMS2=1
        ;;
    --without-lcms2)
        LCMS2=0
        ;;
    --with-cocoa)
        LCMS2=auto
        ;;
    --without-cocoa)
        LCMS2=auto
        ;;
    --with-libpng=*)
        LIBPNG_DIR=${i#*=}
        ;;
    --with-libimagequant=*)
        LIQSRCDIR=${i#*=}
        ;;
    --with-libimagequant)
        LIQSRCDIR=""
        ;;
    --with-zlib=*)
        ZLIB_DIR=${i#*=}
        ;;
    --prefix=*)
        PREFIX=${i#*=}
        LIQCONFIGURE+=("$i")
        ;;
    # can be used multiple times or in quotes to set multiple flags
    --extra-cflags=*)
        EXTRA_CFLAGS="$EXTRA_CFLAGS ${i#*=}"
        LIQCONFIGURE+=("$i")
        ;;
    --extra-ldflags=*)
        EXTRA_LDFLAGS="$EXTRA_LDFLAGS ${i#*=}"
        LIQCONFIGURE+=("$i")
        ;;
    *)
        echo "warning: unknown switch ${i%%=*} (see $0 --help for the list)"
        ;;
    esac
done

# If someone runs sudo make install as very first command, and configure later,
# $CONFIG cannot be overwritten, and must be deleted before continuing.
if [[ -f "$CONFIG" && ! -w "$CONFIG" ]]; then
    echo "Cannot overwrite file $CONFIG! Please delete it."
    exit 1
fi

cflags() {
    CFLAGS="$CFLAGS $1"
}

lflags() {
    LDFLAGS="$LDFLAGS $1"
}

status() {
    printf "%10s: %s\n" "$1" "$2"
}

# Append to CFLAGS if compiler supports flag, with optional prerequisite.
# Fails on errors and warnings.
conditional_cflags() {
    if [ -z "$(echo | "$CC" -xc -S -o /dev/null $2 $1 - 2>&1)" ]; then
        cflags "$1"
    fi
}

# returns first matching file in directory
find_f() {
    echo $(find "$1" -not -path '*/.git/*' -not -type d -name "$2" -print -quit 2> /dev/null)
}

# returns first matching file in directory (no symlinks)
find_h() {
    echo $(find "$1" -not -path '*/.*/*' -type f -name "$2" -print -quit 2> /dev/null)
}

find_pkgconfig() {
    local LIBNAME=$1
    PKG_CONFIG=${PKG_CONFIG:-pkg-config}
    if $PKG_CONFIG --exists "$LIBNAME" &> /dev/null; then
        cflags "$($PKG_CONFIG --cflags "$LIBNAME")"
        lflags "$($PKG_CONFIG --libs "$LIBNAME")"
        LIBRARY_FOUND_VERSION=$($PKG_CONFIG --modversion "$LIBNAME")
        status "$LIBNAME" "shared ($LIBRARY_FOUND_VERSION)"
        return 0
    fi
    if ! type "$PKG_CONFIG" &> /dev/null; then
        echo "warning: pkg-config is not installed, can't search for libraries. Please install pkg-config."
    fi
    return 1
}

find_static() {
    local LIBNAME=$1
    local HEADERPATTERN=$2
    local STATICPATTERN=$3

    local HPATH=$(find_h . "$HEADERPATTERN")
    if [ -n "$HPATH" ]; then
        local APATH=$(find_f . "$STATICPATTERN")
        if [ -n "$APATH" ]; then
            LIBRARY_FOUND_HEADER=$HPATH
            cflags "-I${HPATH%/*}"
            lflags "${APATH}"
            status "$LIBNAME" "static ($APATH)"
            return 0
        fi
    fi
    return 1
}

find_dynamic() {
    local LIBNAME=$1
    local HEADERPATTERN=$2
    local DYNAMICPATTERN=$3
    local HEADERDIR=$4
    local LIBDIR=$5

    local HPATH=$(find_h "$HEADERDIR" "$HEADERPATTERN")
    if [ -n "$HPATH" ]; then
        local SOPATH=$(find_f "$LIBDIR" "$DYNAMICPATTERN")
        if [ -n "$SOPATH" ]; then
            LIBRARY_FOUND_HEADER=$HPATH
            cflags "-I${HPATH%/*}"
            lflags "-L${SOPATH%/*} -l$DYNAMICLIBNAME"
            status "$LIBNAME" "shared ... $SOPATH"
            return 0
        fi
    fi
    return 1
}

find_library() {
    local LIBNAME=$1
    local DYNAMICLIBNAME=$2
    local HEADERPATTERN=$3
    local STATICPATTERN=$4
    local DYNAMICPATTERN=$5

    # other functions will overwrite it
    LIBRARY_FOUND_HEADER=
    LIBRARY_FOUND_VERSION=
    LIBRARY_FOUND_BUILD=

    if [ "imagequant" = "$LIBNAME" -a -n "$LIQSRCDIR" -a -f "$LIQSRCDIR"/"$HEADERPATTERN" ]; then
        status "$LIBNAME" "build static"
        cflags "-I$LIQSRCDIR"
        lflags "$LIQSRCDIR/libimagequant.a"
        LIBRARY_FOUND_HEADER="$LIQSRCDIR"/"$HEADERPATTERN"
        LIBRARY_FOUND_BUILD="$LIQSRCDIR"
        return 0;
    fi

    # try static in current directory first
    if find_static "$LIBNAME" "$HEADERPATTERN" "$STATICPATTERN"; then
        return 0;
    fi

    # try shared
    if find_pkgconfig "$LIBNAME"; then
        return 0
    fi

    for i in "${DIRS[@]}"; do
        DIR=($i)
        if find_dynamic "$LIBNAME" "$HEADERPATTERN" "$DYNAMICPATTERN" "${DIR[0]}" "${DIR[1]}"; then
            return 0
        fi
    done
    return 1
}

# returns full png.h version string
pngh_string() {
    echo "$(grep -m1 "define PNG_LIBPNG_VER_STRING" "$1" | \
            grep -Eo '"[^"]+"' | grep -Eo '[^"]+')"
}

# returns major minor version numbers from png.h
pngh_majmin() {
    local MAJ=$(grep -m1 "define PNG_LIBPNG_VER_MAJOR" "$1" | grep -Eo "[0-9]+")
    local MIN=$(grep -m1 "define PNG_LIBPNG_VER_MINOR" "$1" | grep -Eo "[0-9]+")
    echo "${MAJ}${MIN}"
}

# returns full zlib.h version string
zlibh_string() {
    echo "$(grep -m1 "define ZLIB_VERSION" "$1" | \
            grep -Eo '"[^"]+"' | grep -Eo '[^"]+')"
}

# returns major minor version numbers from png.h
zlibh_majmin() {
    local MAJ=$(grep -m1 "define ZLIB_VER_MAJOR" "$1" | grep -Eo "[0-9]+")
    local MIN=$(grep -m1 "define ZLIB_VER_MINOR" "$1" | grep -Eo "[0-9]+")
    echo "${MAJ}${MIN}"
}

error() {
    status "$1" "error ... $2"
    echo
    exit 1
}

echo

# /tmp, because mingw has problems opening /dev/null and gives false negative
if ! echo "int main(){}" | "$CC" -xc -std=c99 -o pngquant-gcccheck - > /dev/null; then
    rm -f pngquant-gcccheck
    if [ "$SKIP_CC_CHECK" -eq 1 ]; then
        status "Compiler" "$CC failed to compile anything (make sure it's installed and supports C99)"
    else
        error "Compiler" "$CC failed to compile anything (make sure it's installed and supports C99)"
    fi
fi
rm -f pngquant-gcccheck

status "Compiler" "$CC"

# init flags
CFLAGS=${CFLAGS:--fno-math-errno -funroll-loops -fomit-frame-pointer -Wall}
cflags "-std=c99 -I."

# DEBUG
if [ -z "$DEBUG" ]; then
    cflags "-O3 -DNDEBUG"
    status "Debug" "no"
else
    cflags "-O1 -g -DDEBUG"
    status "Debug" "yes"
fi

# SSE
if [ "$SSE" = 'auto' ]; then
    SSE=0
    if type uname > /dev/null; then
        if [[ "$(uname -m)" =~ "amd64" || "$(uname -m)" =~ "x86_64" ||
              "$(grep -E -m1 "^flags" /proc/cpuinfo)" =~ "sse" ]]; then
            SSE=1
        fi
    fi
fi

if [ "$SSE" -eq 1 ]; then
    status "SSE" "yes"
    cflags "-DUSE_SSE=1"
    cflags "-msse"
    # Silence a later ICC warning due to -msse working slightly different.
    conditional_cflags "-wd10121"
    # Must be set explicitly for GCC on x86_32. Other compilers imply it.
    conditional_cflags "-mfpmath=sse" "-msse"
elif [ "$SSE" -eq 0 ]; then
    status "SSE" "no"
    cflags "-DUSE_SSE=0"
fi

# OpenMP
if [ -n "$OPENMP" ]; then
    if [ "static" = "$OPENMP" ]; then
        OPENMPFLAGS="-static-libgcc -Bstatic -fopenmp -Bdynamic"
    else
        OPENMPFLAGS="-fopenmp"
    fi
    if [[ "$("$CC" -xc -E $OPENMPFLAGS <(echo "#ifdef _OPENMP
           #include <omp.h>
           #endif") 2>&1)" =~ "omp_get_thread_num" ]]; then
        cflags "$OPENMPFLAGS"
        lflags "$OPENMPFLAGS"
        status "OpenMP" "yes"
    else
        error "OpenMP" "not supported by compiler (please install a compiler that supports OpenMP (e.g. gcc) and specify it with the CC= argument)"
    fi
else
    # silence warnings about omp pragmas
    cflags "-Wno-unknown-pragmas"
    conditional_cflags "-wd3180" # ICC
    status "OpenMP" "no"
fi

# Cocoa
if [[ "$OSTYPE" =~ "darwin" ]]; then
    cflags "-mmacosx-version-min=10.7"
    lflags "-mmacosx-version-min=10.7"
fi

# pairs of possible *.h and lib*.so locations
DIRS=()

if command -v >/dev/null libpng-config; then
    DIRS+=("$(libpng-config --prefix) $(libpng-config --libdir)")
fi

if [ -n $"LIQSRCDIR" ]; then
    DIRS+=("$LIQSRCDIR" "$LIQSRCDIR") # local libimagequant
fi

DIRS+=(
      "/usr/local/include /usr/local/lib"
      "/usr/include /usr/lib64"
      "/usr/include /usr/lib"
      "/opt/local/include /opt/local/lib" # macports
      )

if [[ "$OSTYPE" =~ "darwin" ]]; then
    SOLIBSUFFIX=dylib

    # Search Developer SDK paths, since Apple seems to have dropped the standard Unixy ones
    XCODE_CMD="xcode-select"
    XCODE_PATH=$($XCODE_CMD -p)
    DIRS+=("$XCODE_PATH/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/include $XCODE_PATH/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/lib")
    DIRS+=("$XCODE_PATH/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk/usr/include $XCODE_PATH/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk/usr/lib")
elif [[ "$OSTYPE" =~ "msys" ]]; then
    SOLIBSUFFIX=dll
else
    SOLIBSUFFIX=so
fi

# libimagequant
if [ "./lib" = "$LIQSRCDIR" -a -d ".git" -a ! -f "lib/Cargo.toml" ]; then
    git submodule init && git submodule update;
fi

if find_library "imagequant" "imagequant" "libimagequant.h" "libimagequant.a" "libimagequant.$SOLIBSUFFIX*"; then
    if [ -n "$LIBRARY_FOUND_VERSION" ]; then
        VERSION=$LIBRARY_FOUND_VERSION
    elif [ -n "$LIBRARY_FOUND_HEADER" ]; then
        VERSION=$(grep LIQ_VERSION_STRING "$LIBRARY_FOUND_HEADER" | grep -Eo "2\.[0-9.]+")
    else
        VERSION=unknown
    fi

    if [ -n "$LIBRARY_FOUND_BUILD" ]; then
        STATICLIBDEPS="$LIBRARY_FOUND_BUILD/libimagequant.h $LIBRARY_FOUND_BUILD/libimagequant.a"
        LIQSRCDIR="$LIBRARY_FOUND_BUILD"
    fi
else
    if [ -n "$LIQSRCDIR" -a ! -f "$LIQSRCDIR"/libimagequant.h ]; then
        echo "If you're using git, do clone with --recursive, or download from https://github.com/ImageOptim/libimagequant"
        error "imagequant" "libimagequant.h not found in $LIQSRCDIR/"
    else
        error "imagequant" "not found. Get it from https://github.com/ImageOptim/libimagequant and build it in ./lib/"
    fi
fi

# libpng
# try if given flags are enough
HAS_LIBPNG=0
if echo "#include \"png.h\"
    int main(){
    return !png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
}" | "$CC" -xc -std=c99 -o /dev/null $CFLAGS $LDFLAGS - &> /dev/null; then
    status "libpng" "custom flags"
    HAS_LIBPNG=1
fi

if [ "$HAS_LIBPNG" -eq 0 ]; then
    # try static in the given directory
    PNGH=$(find_h "$LIBPNG_DIR" "png.h")
    if [ -n "$PNGH" ]; then
        PNGH_STRING=$(pngh_string "$PNGH")
        PNGH_MAJMIN=$(pngh_majmin "$PNGH")
        if [[ -n "$PNGH_STRING" && -n "$PNGH_MAJMIN" ]]; then
            LIBPNGA=$(find_f "$LIBPNG_DIR" "libpng${PNGH_MAJMIN}.a")
            if [ -z "$LIBPNGA" ]; then
                LIBPNGA=$(find_f "$LIBPNG_DIR" "libpng.a")
            fi
            if [ -n "$LIBPNGA" ]; then
                cflags "-I${PNGH%/*}"
                lflags "${LIBPNGA}"
                status "libpng" "static (${PNGH_STRING})"
                HAS_LIBPNG=1
            fi
        fi
    fi
fi
# try shared
if [ "$HAS_LIBPNG" -eq 0 ]; then
    if find_pkgconfig libpng; then
        HAS_LIBPNG=1
    else
        for i in "${DIRS[@]}"; do
            DIR=($i)
            PNGH=$(find_h "${DIR[0]}" "png.h")
            if [ -n "$PNGH" ]; then
                PNGH_STRING=$(pngh_string "$PNGH")
                PNGH_MAJMIN=$(pngh_majmin "$PNGH")
                if [[ -n "$PNGH_STRING" && -n "$PNGH_MAJMIN" ]]; then
                    LIBPNGSO=$(find_f "${DIR[1]}" "libpng${PNGH_MAJMIN}.$SOLIBSUFFIX*")
                    if [ -n "$LIBPNGSO" ]; then
                        cflags "-I${PNGH%/*}"
                        lflags "-L${LIBPNGSO%/*} -lpng${PNGH_MAJMIN}"
                        status "libpng" "shared (${PNGH_STRING})"
                        HAS_LIBPNG=1
                        break
                    fi
                fi
            fi
        done
    fi
fi
if [ "$HAS_LIBPNG" -eq 0 ]; then
    if [[ "$OSTYPE" =~ "darwin" ]]; then
        LIBPNG_CMD='`brew install libpng`'
    else
        LIBPNG_CMD='`apt-get install libpng16-dev` or `apt-get install libpng-dev` or `yum install libpng-devel`'
    fi
    error "libpng" "not found (try: $LIBPNG_CMD)"
fi

# try if given flags are enough for zlib
HAS_ZLIB=0
if echo "#include \"zlib.h\"
    int main(){
    uLong test = zlibCompileFlags();
    return 0;
}" | "$CC" -xc -std=c99 -o /dev/null $CFLAGS $LDFLAGS - &> /dev/null; then
    status "zlib" "custom flags"
    HAS_ZLIB=1
fi

if [ "$HAS_ZLIB" -eq 0 ]; then
    # try static in the given directory
    ZLIBH=$(find_h "$ZLIB_DIR" "zlib.h")
    if [ -n "$ZLIBH" ]; then
        ZLIBH_STRING=$(zlibh_string "$ZLIBH")
        ZLIBH_MAJMIN=$(zlibh_majmin "$ZLIBH")
        if [[ -n "$ZLIBH_STRING" && -n "$ZLIBH_MAJMIN" ]]; then
            ZLIBA=$(find_f "$ZLIB_DIR" "libz${ZLIBH_MAJMIN}.a")
            if [ -z "$ZLIBA" ]; then
                ZLIBA=$(find_f "$ZLIB_DIR" "libz.a")
            fi
            if [ -n "$ZLIBA" ]; then
                cflags "-I${ZLIBH%/*}"
                lflags "${ZLIBA}"
                status "zlib" "static (${ZLIBH_STRING})"
                HAS_ZLIB=1
            fi
        fi
    fi
fi
# zlib
if ! find_library "zlib" "z" "zlib.h" "libz.a" "zlib.$SOLIBSUFFIX*"; then
    error "zlib" "not found (please install zlib-devel package)"
fi

# lcms2
if [ "$LCMS2" != 0 ]; then
    if find_library "lcms2" "lcms2" "lcms2.h" "liblcms2.a" "liblcms2.$SOLIBSUFFIX*"; then
        cflags "-DUSE_LCMS=1"
    else
        if [ "$LCMS2" = 'auto' ]; then
            status "lcms2" "no"
        else
            error "lcms2" "not found (please install libcms2-devel package)"
        fi
    fi
else
    status "lcms2" "no"
fi

echo

# As of GCC 4.5, 387 fp math is significantly slower in C99 mode without this.
# Note: CPUs without SSE2 use 387 for doubles, even when SSE fp math is set.
conditional_cflags "-fexcess-precision=fast"

# Intel C++ Compiler

# ICC does usually only produce fast(er) code when it can optimize to the full
# capabilites of the (Intel) CPU. This is equivalent to -march=native for GCC.
conditional_cflags "-xHOST"

# Disable unsafe fp optimizations and enforce fp precision as set in the source.
conditional_cflags "-fp-model source"

# Silence a gold linker warning about string misalignment.
conditional_cflags "-falign-stack=maintain-16-byte"

lflags "-lm" # Ubuntu requires this library last, issue #38

if [ -n "$EXTRA_CFLAGS" ]; then
    cflags "$EXTRA_CFLAGS"
fi

if [ -n "$EXTRA_LDFLAGS" ]; then
    lflags "$EXTRA_LDFLAGS"
fi

# Overwrite previous configuration.
echo "
# auto-generated by configure
PREFIX = $PREFIX
VERSION = $VERSION
CC = $CC
CFLAGS = $CFLAGS
LDFLAGS = $LDFLAGS
SOLIBSUFFIX = $SOLIBSUFFIX
STATICLIBDEPS = $STATICLIBDEPS
LIQSRCDIR = $LIQSRCDIR
LIQCONFIGUREFLAGS = $(printf "'%s' " "${LIQCONFIGURE[@]}")
" > "$CONFIG"
kornelski commented 4 years ago

Ugh, zlib vs libz name seems to vary between platforms.

kornelski commented 4 years ago

Does 9d8f9685f2422a55a391d270c54c8f0ad5d6e9dd work for you?

bdkjones commented 4 years ago

I don’t think so—it doesn’t look like anything has actually changed in that commit? It’s still missing “libz.a” in the list of names to search for.

-Bryan

On Nov 21, 2020, at 09:53, Kornel notifications@github.com wrote:

 Does 9d8f968 work for you?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe.

kornelski commented 4 years ago

It searches for libz. first, and then searches for zlib.

dpanic commented 1 year ago

I just tested on 2.x branch. All works out of the box.

Steps:

End result: image

Which is good for me!

kornelski commented 1 year ago

The latest version on the main branch:

cargo build --release --features=lcms2-static,png-static,z-static

or 100% static:

rustup target add x86_64-unknown-linux-musl
# install musl build utils if needed
cargo build --release --features=lcms2-static,png-static,z-static --target=x86_64-unknown-linux-musl
dpanic commented 1 year ago

The latest version on the main branch:

cargo build --release --features=lcms2-static,png-static,z-static

or 100% static:

rustup target add x86_64-unknown-linux-musl
# install musl build utils if needed
cargo build --release --features=lcms2-static,png-static,z-static --target=x86_64-unknown-linux-musl

Amazing. Thank you!

Will this work for target Darwin and Windows as well?

And is latest 3.x stable enough for usage? I saw on your website that stable is 2.x branch.

kornelski commented 1 year ago

MUSL target is specifically for the Linux kernel only. Darwin does not support 100% static executables — you're required to use libSystem. I don't know what Windows supports in theory, but in practice Rust just has msvc and gnu targets that require some runtime libraries. In all cases you can have static 3rd party deps like zlib/png/lcms2.

kornelski commented 1 year ago

I've updated the site. The current status is:

dpanic commented 1 year ago

MUSL target is specifically for the Linux kernel only. Darwin does not support 100% static executables — you're required to use libSystem. I don't know what Windows supports in theory, but in practice Rust just has msvc and gnu targets that require some runtime libraries. In all cases you can have static 3rd party deps like zlib/png/lcms2.

Thank you for clarification!

dpanic commented 1 year ago

I've updated the site. The current status is:

  • libimagequant 4.x in Rust is now stable production ready. Use it if you can. The 2.x C version is in maintenance mode and isn't getting new features.
  • pngquant v3 is a combination of 2.x CLI executable and 4.x Rust library. It's technically fine and stable, but it's a bit of a Frankenstein multi-language executable. I suspect it's annoying to package in distros, so I'm not pushing for it.
  • pngquant v4, a pure-Rust rewrite from scratch is a work in progress. There's a branch for it, but it's not feature-complete.

I am waiting for v4 than. I am using statically built for Linux v2. And v2 for Windows and MacOS which I downloaded from your website. I am developing desktop app which is multi OS, and it's written in Go Lang.

I know that it would be better to create Go Lang bindings for libpngquant, but I don't have time now for that. I am willing to pay "price" for fork-exec :-)