1# ################################################################ 2# Copyright (c) 2015-present, Yann Collet, Facebook, Inc. 3# All rights reserved. 4# 5# This source code is licensed under both the BSD-style license (found in the 6# LICENSE file in the root directory of this source tree) and the GPLv2 (found 7# in the COPYING file in the root directory of this source tree). 8# ########################################################################## 9# zstd : Command Line Utility, supporting gzip-like arguments 10# zstd32 : Same as zstd, but forced to compile in 32-bits mode 11# zstd_nolegacy : zstd without support of decompression of legacy versions 12# zstd-small : minimal zstd without dictionary builder and benchmark 13# zstd-compress : compressor-only version of zstd 14# zstd-decompress : decompressor-only version of zstd 15# ########################################################################## 16 17ZSTDDIR = ../lib 18 19# Version numbers 20LIBVER_SRC := $(ZSTDDIR)/zstd.h 21LIBVER_MAJOR_SCRIPT:=`sed -n '/define ZSTD_VERSION_MAJOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < $(LIBVER_SRC)` 22LIBVER_MINOR_SCRIPT:=`sed -n '/define ZSTD_VERSION_MINOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < $(LIBVER_SRC)` 23LIBVER_PATCH_SCRIPT:=`sed -n '/define ZSTD_VERSION_RELEASE/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < $(LIBVER_SRC)` 24LIBVER_SCRIPT:= $(LIBVER_MAJOR_SCRIPT).$(LIBVER_MINOR_SCRIPT).$(LIBVER_PATCH_SCRIPT) 25LIBVER_MAJOR := $(shell echo $(LIBVER_MAJOR_SCRIPT)) 26LIBVER_MINOR := $(shell echo $(LIBVER_MINOR_SCRIPT)) 27LIBVER_PATCH := $(shell echo $(LIBVER_PATCH_SCRIPT)) 28LIBVER := $(shell echo $(LIBVER_SCRIPT)) 29 30ZSTD_VERSION = $(LIBVER) 31 32HAVE_COLORNEVER = $(shell echo a | grep --color=never a > /dev/null 2> /dev/null && echo 1 || echo 0) 33GREP_OPTIONS ?= 34ifeq ($HAVE_COLORNEVER, 1) 35GREP_OPTIONS += --color=never 36endif 37GREP = grep $(GREP_OPTIONS) 38 39ifeq ($(shell $(CC) -v 2>&1 | $(GREP) -c "gcc version "), 1) 40ALIGN_LOOP = -falign-loops=32 41else 42ALIGN_LOOP = 43endif 44 45CPPFLAGS+= -I$(ZSTDDIR) -I$(ZSTDDIR)/common -I$(ZSTDDIR)/compress \ 46 -I$(ZSTDDIR)/dictBuilder \ 47 -DXXH_NAMESPACE=ZSTD_ 48ifeq ($(OS),Windows_NT) # MinGW assumed 49CPPFLAGS += -D__USE_MINGW_ANSI_STDIO # compatibility with %zu formatting 50endif 51CFLAGS ?= -O3 52DEBUGFLAGS+=-Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \ 53 -Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \ 54 -Wstrict-prototypes -Wundef -Wpointer-arith \ 55 -Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \ 56 -Wredundant-decls -Wmissing-prototypes -Wc++-compat 57CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS) 58FLAGS = $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) 59 60 61ZSTDCOMMON_FILES := $(ZSTDDIR)/common/*.c 62ZSTDCOMP_FILES := $(ZSTDDIR)/compress/*.c 63ZSTDDECOMP_FILES := $(ZSTDDIR)/decompress/*.c 64ZSTD_FILES := $(ZSTDDECOMP_FILES) $(ZSTDCOMMON_FILES) $(ZSTDCOMP_FILES) 65ZDICT_FILES := $(ZSTDDIR)/dictBuilder/*.c 66ZSTDDECOMP_O = $(ZSTDDIR)/decompress/zstd_decompress.o 67 68ZSTD_LEGACY_SUPPORT ?= 5 69ZSTDLEGACY_FILES := 70ifneq ($(ZSTD_LEGACY_SUPPORT), 0) 71ifeq ($(shell test $(ZSTD_LEGACY_SUPPORT) -lt 8; echo $$?), 0) 72 ZSTDLEGACY_FILES += $(shell ls $(ZSTDDIR)/legacy/*.c | $(GREP) 'v0[$(ZSTD_LEGACY_SUPPORT)-7]') 73endif 74 CPPFLAGS += -I$(ZSTDDIR)/legacy 75else 76endif 77 78# Sort files in alphabetical order for reproducible builds 79ZSTDLIB_FILES := $(sort $(wildcard $(ZSTD_FILES)) $(wildcard $(ZSTDLEGACY_FILES)) $(wildcard $(ZDICT_FILES))) 80 81# Define *.exe as extension for Windows systems 82ifneq (,$(filter Windows%,$(OS))) 83EXT =.exe 84RES64_FILE = windres/zstd64.res 85RES32_FILE = windres/zstd32.res 86ifneq (,$(filter x86_64%,$(shell $(CC) -dumpmachine))) 87 RES_FILE = $(RES64_FILE) 88else 89 RES_FILE = $(RES32_FILE) 90endif 91else 92EXT = 93endif 94 95VOID = /dev/null 96 97# thread detection 98NO_THREAD_MSG := ==> no threads, building without multithreading support 99HAVE_PTHREAD := $(shell printf '\#include <pthread.h>\nint main(void) { return 0; }' > have_pthread.c && $(CC) $(FLAGS) -o have_pthread$(EXT) have_pthread.c -pthread 2> $(VOID) && rm have_pthread$(EXT) && echo 1 || echo 0; rm have_pthread.c) 100HAVE_THREAD := $(shell [ "$(HAVE_PTHREAD)" -eq "1" -o -n "$(filter Windows%,$(OS))" ] && echo 1 || echo 0) 101ifeq ($(HAVE_THREAD), 1) 102THREAD_MSG := ==> building with threading support 103THREAD_CPP := -DZSTD_MULTITHREAD 104THREAD_LD := -pthread 105else 106THREAD_MSG := $(NO_THREAD_MSG) 107endif 108 109# zlib detection 110NO_ZLIB_MSG := ==> no zlib, building zstd without .gz support 111HAVE_ZLIB := $(shell printf '\#include <zlib.h>\nint main(void) { return 0; }' > have_zlib.c && $(CC) $(FLAGS) -o have_zlib$(EXT) have_zlib.c -lz 2> $(VOID) && rm have_zlib$(EXT) && echo 1 || echo 0; rm have_zlib.c) 112ifeq ($(HAVE_ZLIB), 1) 113ZLIB_MSG := ==> building zstd with .gz compression support 114ZLIBCPP = -DZSTD_GZCOMPRESS -DZSTD_GZDECOMPRESS 115ZLIBLD = -lz 116else 117ZLIB_MSG := $(NO_ZLIB_MSG) 118endif 119 120# lzma detection 121NO_LZMA_MSG := ==> no liblzma, building zstd without .xz/.lzma support 122HAVE_LZMA := $(shell printf '\#include <lzma.h>\nint main(void) { return 0; }' > have_lzma.c && $(CC) $(FLAGS) -o have_lzma$(EXT) have_lzma.c -llzma 2> $(VOID) && rm have_lzma$(EXT) && echo 1 || echo 0; rm have_lzma.c) 123ifeq ($(HAVE_LZMA), 1) 124LZMA_MSG := ==> building zstd with .xz/.lzma compression support 125LZMACPP = -DZSTD_LZMACOMPRESS -DZSTD_LZMADECOMPRESS 126LZMALD = -llzma 127else 128LZMA_MSG := $(NO_LZMA_MSG) 129endif 130 131# lz4 detection 132NO_LZ4_MSG := ==> no liblz4, building zstd without .lz4 support 133HAVE_LZ4 := $(shell printf '\#include <lz4frame.h>\n\#include <lz4.h>\nint main(void) { return 0; }' > have_lz4.c && $(CC) $(FLAGS) -o have_lz4$(EXT) have_lz4.c -llz4 2> $(VOID) && rm have_lz4$(EXT) && echo 1 || echo 0; rm have_lz4.c) 134ifeq ($(HAVE_LZ4), 1) 135LZ4_MSG := ==> building zstd with .lz4 compression support 136LZ4CPP = -DZSTD_LZ4COMPRESS -DZSTD_LZ4DECOMPRESS 137LZ4LD = -llz4 138else 139LZ4_MSG := $(NO_LZ4_MSG) 140endif 141 142# explicit backtrace enable/disable for Linux & Darwin 143ifeq ($(BACKTRACE), 0) 144DEBUGFLAGS += -DBACKTRACE_ENABLE=0 145endif 146ifeq (,$(filter Windows%, $(OS))) 147ifeq ($(BACKTRACE), 1) 148DEBUGFLAGS += -DBACKTRACE_ENABLE=1 149DEBUGFLAGS_LD += -rdynamic 150endif 151endif 152 153 154.PHONY: default 155default: zstd-release 156 157.PHONY: all 158all: zstd 159 160.PHONY: allVariants 161allVariants: zstd zstd-compress zstd-decompress zstd-small zstd-nolegacy 162 163$(ZSTDDECOMP_O): CFLAGS += $(ALIGN_LOOP) 164 165zstd : CPPFLAGS += $(THREAD_CPP) $(ZLIBCPP) $(LZMACPP) $(LZ4CPP) 166zstd : LDFLAGS += $(THREAD_LD) $(ZLIBLD) $(LZMALD) $(LZ4LD) $(DEBUGFLAGS_LD) 167zstd : CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT) 168zstd : $(ZSTDLIB_FILES) zstdcli.o util.o timefn.o fileio.o benchfn.o benchzstd.o datagen.o dibio.o 169 @echo "$(THREAD_MSG)" 170 @echo "$(ZLIB_MSG)" 171 @echo "$(LZMA_MSG)" 172 @echo "$(LZ4_MSG)" 173ifneq (,$(filter Windows%,$(OS))) 174 windres/generate_res.bat 175endif 176 $(CC) $(FLAGS) $^ $(RES_FILE) -o $@$(EXT) $(LDFLAGS) 177 178.PHONY: zstd-release 179zstd-release: DEBUGFLAGS := -DBACKTRACE_ENABLE=0 180zstd-release: DEBUGFLAGS_LD := 181zstd-release: zstd 182 183zstd32 : CPPFLAGS += $(THREAD_CPP) 184zstd32 : LDFLAGS += $(THREAD_LD) 185zstd32 : CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT) 186zstd32 : $(ZSTDLIB_FILES) zstdcli.c util.c timefn.c fileio.c benchfn.c benchzstd.c datagen.c dibio.c 187ifneq (,$(filter Windows%,$(OS))) 188 windres/generate_res.bat 189endif 190 $(CC) -m32 $(FLAGS) $^ $(RES32_FILE) -o $@$(EXT) 191 192zstd-nolegacy : $(ZSTD_FILES) $(ZDICT_FILES) zstdcli.o util.o fileio.c benchfn.o benchzstd.o timefn.o datagen.o dibio.o 193 $(CC) $(FLAGS) $^ -o $@$(EXT) $(LDFLAGS) 194 195zstd-nomt : THREAD_CPP := 196zstd-nomt : THREAD_LD := 197zstd-nomt : THREAD_MSG := - multi-threading disabled 198zstd-nomt : zstd 199 200zstd-nogz : ZLIBCPP := 201zstd-nogz : ZLIBLD := 202zstd-nogz : ZLIB_MSG := - gzip support is disabled 203zstd-nogz : zstd 204 205zstd-noxz : LZMACPP := 206zstd-noxz : LZMALD := 207zstd-noxz : LZMA_MSG := - xz/lzma support is disabled 208zstd-noxz : zstd 209 210 211zstd-pgo : 212 $(MAKE) clean 213 $(MAKE) zstd MOREFLAGS=-fprofile-generate 214 ./zstd -b19i1 $(PROFILE_WITH) 215 ./zstd -b16i1 $(PROFILE_WITH) 216 ./zstd -b9i2 $(PROFILE_WITH) 217 ./zstd -b $(PROFILE_WITH) 218 ./zstd -b7i2 $(PROFILE_WITH) 219 ./zstd -b5 $(PROFILE_WITH) 220 $(RM) zstd *.o $(ZSTDDECOMP_O) $(ZSTDDIR)/compress/*.o 221 $(MAKE) zstd MOREFLAGS=-fprofile-use 222 223# minimal target, with only zstd compression and decompression. no bench. no legacy. 224zstd-small: CFLAGS = -Os -s 225zstd-frugal zstd-small: $(ZSTD_FILES) zstdcli.c util.c timefn.c fileio.c 226 $(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT $^ -o $@$(EXT) 227 228zstd-decompress: $(ZSTDCOMMON_FILES) $(ZSTDDECOMP_FILES) zstdcli.c util.c timefn.c fileio.c 229 $(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT -DZSTD_NOCOMPRESS $^ -o $@$(EXT) 230 231zstd-compress: $(ZSTDCOMMON_FILES) $(ZSTDCOMP_FILES) zstdcli.c util.c timefn.c fileio.c 232 $(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT -DZSTD_NODECOMPRESS $^ -o $@$(EXT) 233 234zstdmt: zstd 235 ln -sf zstd zstdmt 236 237.PHONY: generate_res 238generate_res: 239 windres/generate_res.bat 240 241.PHONY: clean 242clean: 243 $(MAKE) -C $(ZSTDDIR) clean 244 @$(RM) $(ZSTDDIR)/decompress/*.o $(ZSTDDIR)/decompress/zstd_decompress.gcda 245 @$(RM) core *.o tmp* result* *.gcda dictionary *.zst \ 246 zstd$(EXT) zstd32$(EXT) zstd-compress$(EXT) zstd-decompress$(EXT) \ 247 zstd-small$(EXT) zstd-frugal$(EXT) zstd-nolegacy$(EXT) zstd4$(EXT) \ 248 *.gcda default.profraw have_zlib$(EXT) 249 @echo Cleaning completed 250 251MD2ROFF = ronn 252MD2ROFF_FLAGS = --roff --warnings --manual="User Commands" --organization="zstd $(ZSTD_VERSION)" 253 254zstd.1: zstd.1.md ../lib/zstd.h 255 cat $< | $(MD2ROFF) $(MD2ROFF_FLAGS) | sed -n '/^\.\\\".*/!p' > $@ 256 257zstdgrep.1: zstdgrep.1.md ../lib/zstd.h 258 cat $< | $(MD2ROFF) $(MD2ROFF_FLAGS) | sed -n '/^\.\\\".*/!p' > $@ 259 260zstdless.1: zstdless.1.md ../lib/zstd.h 261 cat $< | $(MD2ROFF) $(MD2ROFF_FLAGS) | sed -n '/^\.\\\".*/!p' > $@ 262 263.PHONY: man 264man: zstd.1 zstdgrep.1 zstdless.1 265 266.PHONY: clean-man 267clean-man: 268 $(RM) zstd.1 269 $(RM) zstdgrep.1 270 $(RM) zstdless.1 271 272.PHONY: preview-man 273preview-man: clean-man man 274 man ./zstd.1 275 man ./zstdgrep.1 276 man ./zstdless.1 277 278#----------------------------------------------------------------------------- 279# make install is validated only for Linux, macOS, BSD, Hurd and Solaris targets 280#----------------------------------------------------------------------------- 281ifneq (,$(filter $(shell uname),Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD NetBSD DragonFly SunOS Haiku)) 282 283HAVE_COLORNEVER = $(shell echo a | egrep --color=never a > /dev/null 2> /dev/null && echo 1 || echo 0) 284EGREP_OPTIONS ?= 285ifeq ($HAVE_COLORNEVER, 1) 286EGREP_OPTIONS += --color=never 287endif 288EGREP = egrep $(EGREP_OPTIONS) 289 290# Print a two column output of targets and their description. To add a target description, put a 291# comment in the Makefile with the format "## <TARGET>: <DESCRIPTION>". For example: 292# 293## list: Print all targets and their descriptions (if provided) 294.PHONY: list 295list: 296 @TARGETS=$$($(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null \ 297 | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' \ 298 | $(EGREP) -v -e '^[^[:alnum:]]' | sort); \ 299 { \ 300 printf "Target Name\tDescription\n"; \ 301 printf "%0.s-" {1..16}; printf "\t"; printf "%0.s-" {1..40}; printf "\n"; \ 302 for target in $$TARGETS; do \ 303 line=$$($(EGREP) "^##[[:space:]]+$$target:" $(lastword $(MAKEFILE_LIST))); \ 304 description=$$(echo $$line | awk '{i=index($$0,":"); print substr($$0,i+1)}' | xargs); \ 305 printf "$$target\t$$description\n"; \ 306 done \ 307 } | column -t -s $$'\t' 308 309 310DESTDIR ?= 311# directory variables : GNU conventions prefer lowercase 312# see https://www.gnu.org/prep/standards/html_node/Makefile-Conventions.html 313# support both lower and uppercase (BSD), use uppercase in script 314prefix ?= /usr/local 315PREFIX ?= $(prefix) 316exec_prefix ?= $(PREFIX) 317bindir ?= $(exec_prefix)/bin 318BINDIR ?= $(bindir) 319datarootdir ?= $(PREFIX)/share 320mandir ?= $(datarootdir)/man 321man1dir ?= $(mandir)/man1 322 323ifneq (,$(filter $(shell uname),OpenBSD FreeBSD NetBSD DragonFly SunOS)) 324MANDIR ?= $(PREFIX)/man 325MAN1DIR ?= $(MANDIR)/man1 326else 327MAN1DIR ?= $(man1dir) 328endif 329 330ifneq (,$(filter $(shell uname),SunOS)) 331INSTALL ?= ginstall 332else 333INSTALL ?= install 334endif 335 336INSTALL_PROGRAM ?= $(INSTALL) 337INSTALL_SCRIPT ?= $(INSTALL_PROGRAM) 338INSTALL_DATA ?= $(INSTALL) -m 644 339INSTALL_MAN ?= $(INSTALL_DATA) 340 341.PHONY: install 342install: zstd 343 @echo Installing binaries 344 @$(INSTALL) -d -m 755 $(DESTDIR)$(BINDIR)/ $(DESTDIR)$(MAN1DIR)/ 345 @$(INSTALL_PROGRAM) zstd $(DESTDIR)$(BINDIR)/zstd 346 @ln -sf zstd $(DESTDIR)$(BINDIR)/zstdcat 347 @ln -sf zstd $(DESTDIR)$(BINDIR)/unzstd 348 @ln -sf zstd $(DESTDIR)$(BINDIR)/zstdmt 349 @$(INSTALL_SCRIPT) zstdless $(DESTDIR)$(BINDIR)/zstdless 350 @$(INSTALL_SCRIPT) zstdgrep $(DESTDIR)$(BINDIR)/zstdgrep 351 @echo Installing man pages 352 @$(INSTALL_MAN) zstd.1 $(DESTDIR)$(MAN1DIR)/zstd.1 353 @ln -sf zstd.1 $(DESTDIR)$(MAN1DIR)/zstdcat.1 354 @ln -sf zstd.1 $(DESTDIR)$(MAN1DIR)/unzstd.1 355 @$(INSTALL_MAN) zstdgrep.1 $(DESTDIR)$(MAN1DIR)/zstdgrep.1 356 @$(INSTALL_MAN) zstdless.1 $(DESTDIR)$(MAN1DIR)/zstdless.1 357 @echo zstd installation completed 358 359.PHONY: uninstall 360uninstall: 361 @$(RM) $(DESTDIR)$(BINDIR)/zstdgrep 362 @$(RM) $(DESTDIR)$(BINDIR)/zstdless 363 @$(RM) $(DESTDIR)$(BINDIR)/zstdcat 364 @$(RM) $(DESTDIR)$(BINDIR)/unzstd 365 @$(RM) $(DESTDIR)$(BINDIR)/zstdmt 366 @$(RM) $(DESTDIR)$(BINDIR)/zstd 367 @$(RM) $(DESTDIR)$(MAN1DIR)/zstdless.1 368 @$(RM) $(DESTDIR)$(MAN1DIR)/zstdgrep.1 369 @$(RM) $(DESTDIR)$(MAN1DIR)/zstdcat.1 370 @$(RM) $(DESTDIR)$(MAN1DIR)/unzstd.1 371 @$(RM) $(DESTDIR)$(MAN1DIR)/zstd.1 372 @echo zstd programs successfully uninstalled 373 374endif 375