Open bdkjones opened 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"
Ugh, zlib vs libz name seems to vary between platforms.
Does 9d8f9685f2422a55a391d270c54c8f0ad5d6e9dd work for you?
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.
It searches for libz. first, and then searches for zlib.
I just tested on 2.x branch. All works out of the box.
Steps:
End result:
Which is good for me!
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
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.
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.
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.
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!
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 :-)
The
INSTALL
documentation lists a procedure for ensuring that pngquant statically links tolibpng
(put the source for libpng as subfolder of pngquant's source,configure
it with the static flag, thenmake
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