`fromdateiso8601` was `strptime("%Y-%m-%dT%H:%M:%SZ") | mktime`, which
accepts only one of the many representations ISO 8601 permits. strptime
cannot be extended to cover the rest portably, since it has no specifier
for fractional seconds and glibc discards `%G` and `%V`.
Replace it with a parser in src/iso8601.c that handles basic and extended
representations, ordinal and week dates, fractional seconds, offsets and
date-only input. It uses integer arithmetic instead of `time_t`, so the
results no longer depend on the platform.
This is stricter than before. Impossible dates like `2015-02-30`, which
`mktime` used to normalize into March, and unpadded components like
`2015-3-5T6:00:00Z` are now errors. So is any trailing input, including
whitespace. Leading whitespace is rejected too; before, glibc skipped it
and macOS did not. A leap second now maps to the second before it rather
than the next minute. The error message has changed, and the result can
now be non-integer.
264 lines
9.4 KiB
Makefile
264 lines
9.4 KiB
Makefile
|
|
### C source files to be built and distributed.
|
|
|
|
LIBJQ_INCS = src/builtin.h src/bytecode.h src/compile.h \
|
|
src/exec_stack.h src/jq_parser.h src/jv_alloc.h src/jv_dtoa.h \
|
|
src/jv_unicode.h src/jv_utf8_tables.h src/lexer.l src/libm.h \
|
|
src/linker.h src/locfile.h src/opcode_list.h src/parser.y \
|
|
src/util.h src/iso8601.h \
|
|
src/jv_dtoa_tsd.h src/jv_thread.h src/jv_private.h \
|
|
vendor/decNumber/decContext.h vendor/decNumber/decNumber.h \
|
|
vendor/decNumber/decNumberLocal.h
|
|
|
|
LIBJQ_SRC = src/builtin.c src/bytecode.c src/compile.c src/execute.c \
|
|
src/jq_test.c src/jv.c src/jv_alloc.c src/jv_aux.c \
|
|
src/jv_dtoa.c src/jv_file.c src/jv_parse.c src/jv_print.c \
|
|
src/jv_unicode.c src/linker.c src/locfile.c src/util.c \
|
|
src/iso8601.c src/jv_dtoa_tsd.c \
|
|
vendor/decNumber/decContext.c vendor/decNumber/decNumber.c \
|
|
${LIBJQ_INCS}
|
|
|
|
### C build options
|
|
|
|
AM_CFLAGS = -Wextra -Wall -Wno-unused-parameter -Wno-unused-function \
|
|
-Woverlength-strings -Wstrict-prototypes
|
|
|
|
if WIN32
|
|
AM_CFLAGS += -municode
|
|
endif
|
|
|
|
ACLOCAL_AMFLAGS = -I config/m4
|
|
|
|
### Generating the lexer and parser
|
|
|
|
# While there is some autoconf macro support for lex/flex, it doesn't support
|
|
# header file creation so we'll use good old make
|
|
if MAINTAINER_MODE
|
|
BUILT_SOURCES = src/lexer.h src/lexer.c src/parser.h src/parser.c \
|
|
src/builtin.inc src/config_opts.inc src/version.h
|
|
src/lexer.c: src/lexer.l
|
|
$(AM_V_LEX) flex -o src/lexer.c --header-file=src/lexer.h $<
|
|
src/lexer.h: src/lexer.c
|
|
else
|
|
BUILT_SOURCES = src/builtin.inc src/config_opts.inc src/version.h
|
|
.y.c:
|
|
$(AM_V_YACC) [ "$(<D)" = "$(@D)" ] || cp $(<D)/$(@F) $@
|
|
$(AM_V_YACC) [ "$(<D)" = "$(@D)" ] || cp $(<D)/$(*F).h $*.h
|
|
$(AM_V_YACC) touch $@ $*.h
|
|
|
|
.l.c:
|
|
$(AM_V_LEX) [ "$(<D)" = "$(@D)" ] || cp $(<D)/$(@F) $@
|
|
$(AM_V_LEX) [ "$(<D)" = "$(@D)" ] || cp $(<D)/$(*F).h $*.h
|
|
$(AM_V_LEX) touch $@ $*.h
|
|
endif
|
|
|
|
# Tell YACC (Bison) autoconf macros that you want a header file created.
|
|
# If the --warnings=all fails, you probably have an old version of Bison
|
|
# macOS ships an old Bison, so update with Homebrew or MacPorts.
|
|
AM_YFLAGS = --warnings=all -Wno-yacc -d
|
|
|
|
### libjq
|
|
|
|
lib_LTLIBRARIES = libjq.la
|
|
libjq_la_SOURCES = ${LIBJQ_SRC}
|
|
libjq_la_LIBADD = -lm
|
|
libjq_la_LDFLAGS = $(onig_LDFLAGS) -export-symbols-regex '^j[qv]_' -version-info 1:4:0
|
|
|
|
if WIN32
|
|
libjq_la_LIBADD += -lshlwapi
|
|
libjq_la_LDFLAGS += -no-undefined
|
|
endif
|
|
|
|
include_HEADERS = src/jv.h src/jq.h
|
|
|
|
AM_CPPFLAGS = -I$(srcdir)/src -I$(srcdir)/vendor
|
|
|
|
### Address sanitizer (ASan)
|
|
|
|
if ENABLE_ASAN
|
|
AM_CFLAGS += -fsanitize=address
|
|
endif
|
|
|
|
### Undefined Behavior Sanitizer
|
|
|
|
if ENABLE_UBSAN
|
|
AM_CFLAGS += -fsanitize=undefined
|
|
endif
|
|
|
|
### Code coverage with gcov
|
|
|
|
if ENABLE_GCOV
|
|
AM_CFLAGS += --coverage --no-inline
|
|
endif
|
|
|
|
### Error injection for testing
|
|
|
|
if ENABLE_ERROR_INJECTION
|
|
lib_LTLIBRARIES += libinject_errors.la
|
|
libinject_errors_la_SOURCES = src/inject_errors.c
|
|
libinject_errors_la_LIBADD = -ldl
|
|
libinject_errors_la_LDFLAGS = -module
|
|
endif
|
|
|
|
### Building the jq binary
|
|
|
|
# Remake the version.h header file if, and only if, the git ID has changed
|
|
.PHONY: .FORCE
|
|
.FORCE:
|
|
generate_ver = ver="`{ $(srcdir)/scripts/version || echo '$(VERSION)' ; } | xargs printf '\043define JQ_VERSION \"%s\"\n'`"
|
|
.remake-version-h: .FORCE
|
|
@ $(generate_ver); test "x`cat src/version.h 2>/dev/null`" = "x$$ver" || touch .remake-version-h
|
|
src/version.h: .remake-version-h
|
|
mkdir -p src
|
|
$(AM_V_GEN) $(generate_ver); echo "$$ver" > $@
|
|
src/config_opts.inc:
|
|
mkdir -p src
|
|
$(AM_V_GEN) if test -x ./config.status; then \
|
|
./config.status --config; \
|
|
else echo "(unknown)"; \
|
|
fi | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' -e 's/^/"/' -e 's/$$/"/' -e 's/^/#define JQ_CONFIG /' > $@
|
|
src/main.c: src/version.h src/config_opts.inc
|
|
|
|
src/builtin.inc: $(srcdir)/src/builtin.jq
|
|
mkdir -p src
|
|
$(AM_V_GEN) od -v -A n -t o1 -- $< | \
|
|
sed -e 's/$$/ /' \
|
|
-e 's/\([0123456789]\) /\1, /g' \
|
|
-e 's/ $$//' \
|
|
-e 's/ 0/ 0/g' \
|
|
-e 's/ \([123456789]\)/ 0\1/g' > $@
|
|
src/builtin.o: src/builtin.inc
|
|
|
|
CLEANFILES = src/version.h .remake-version-h src/builtin.inc src/config_opts.inc
|
|
|
|
bin_PROGRAMS = jq
|
|
jq_SOURCES = src/main.c
|
|
jq_LDADD = libjq.la -lm
|
|
|
|
if ENABLE_ALL_STATIC
|
|
jq_LDFLAGS = -all-static
|
|
endif
|
|
|
|
### Tests (make check)
|
|
|
|
TESTS = tests/mantest tests/jqtest tests/shtest tests/utf8test tests/base64test tests/uritest
|
|
if !WIN32
|
|
TESTS += tests/optionaltest
|
|
endif
|
|
|
|
AM_TESTS_ENVIRONMENT = JQ=$(abs_builddir)/jq
|
|
if ENABLE_VALGRIND
|
|
AM_TESTS_ENVIRONMENT += ENABLE_VALGRIND=1
|
|
endif
|
|
|
|
# This is a magic make variable that causes it to treat tests/man.test as a
|
|
# DATA-type dependency for the check target. As a result, it will attempt to
|
|
# run any defined targets for tests/man.test as a dependency for check. This
|
|
# allows us to ensure that the tests are up-to-date if the manual has been updated
|
|
check_DATA = tests/man.test
|
|
|
|
### Building the man tests
|
|
|
|
# We use the examples in the manual as additional tests, to ensure they always work.
|
|
# As a result, we need to rebuild the tests if the manual has been updated.
|
|
# Making changes to the manpage without having the python deps means your
|
|
# tests won't run. If you aren't making changes to the examples, you probably
|
|
# don't care. But if you are, then you need to run the tests anyway.
|
|
tests/man.test tests/manonig.test: $(srcdir)/docs/content/manual/dev/manual.yml
|
|
if ENABLE_DOCS
|
|
$(AM_V_GEN) ( cd ${abs_srcdir}/docs && \
|
|
$(PIPENV) run python validate_manual_schema.py content/manual/dev/manual.yml && \
|
|
$(PIPENV) run python build_mantests.py )
|
|
else
|
|
@echo Changes to the manual.yml require docs to be enabled to update the manual test.
|
|
@echo As a result, the manual test is out of date.
|
|
endif
|
|
|
|
### Building the manpage
|
|
|
|
# We build the docs from the manpage yml. If no changes have been made to the
|
|
# manpage, then we'll end up using the cached version. Otherwise, we need to
|
|
# rebuild it.
|
|
man_MANS = jq.1
|
|
jq.1.prebuilt: $(srcdir)/docs/content/manual/dev/manual.yml
|
|
if ENABLE_DOCS
|
|
$(AM_V_GEN) ( cd ${abs_srcdir}/docs && \
|
|
$(PIPENV) run python validate_manual_schema.py content/manual/dev/manual.yml && \
|
|
$(PIPENV) run python build_manpage.py ) > $@
|
|
else
|
|
@echo Changes to the manual.yml require docs to be enabled to update the manpage.
|
|
@echo As a result, the manpage is out of date.
|
|
endif
|
|
|
|
jq.1: jq.1.prebuilt
|
|
$(AM_V_GEN) cp $(srcdir)/jq.1.prebuilt $@
|
|
|
|
CLEANFILES += jq.1
|
|
|
|
### Build oniguruma
|
|
|
|
if BUILD_ONIGURUMA
|
|
libjq_la_LIBADD += vendor/oniguruma/src/.libs/libonig.la
|
|
jq_LDADD += vendor/oniguruma/src/.libs/libonig.la
|
|
SUBDIRS = vendor/oniguruma
|
|
endif
|
|
|
|
AM_CFLAGS += $(onig_CFLAGS)
|
|
|
|
if WITH_ONIGURUMA
|
|
TESTS += tests/onigtest tests/manonigtest
|
|
endif
|
|
|
|
### Packaging
|
|
|
|
install-binaries: $(BUILT_SOURCES)
|
|
$(MAKE) $(AM_MAKEFLAGS) install-exec
|
|
|
|
DOC_FILES = docs/content docs/public docs/templates \
|
|
docs/Pipfile docs/Pipfile.lock docs/build_manpage.py \
|
|
docs/build_mantests.py docs/build_website.py docs/README.md \
|
|
docs/validate_manual_schema.py docs/manual_schema.yml
|
|
|
|
EXTRA_DIST = $(DOC_FILES) $(man_MANS) $(TESTS) $(TEST_LOG_COMPILER) \
|
|
jq.1.prebuilt jq.spec src/lexer.c src/lexer.h src/parser.c \
|
|
src/parser.h src/version.h src/builtin.jq scripts/version \
|
|
libjq.pc \
|
|
tests/modules/a.jq tests/modules/b/b.jq tests/modules/c/c.jq \
|
|
tests/modules/c/d.jq tests/modules/data.json \
|
|
tests/modules/deep1.jq tests/modules/deep2a.jq \
|
|
tests/modules/deep2b.jq tests/modules/deep3.jq \
|
|
tests/modules/home1/.jq tests/modules/home2/.jq/g.jq \
|
|
tests/modules/lib/jq/e/e.jq tests/modules/lib/jq/f.jq \
|
|
tests/modules/shadow1.jq tests/modules/shadow2.jq \
|
|
tests/modules/syntaxerror/syntaxerror.jq \
|
|
tests/modules/test_bind_order.jq \
|
|
tests/modules/test_bind_order0.jq \
|
|
tests/modules/test_bind_order1.jq \
|
|
tests/modules/test_bind_order2.jq \
|
|
tests/modules/cycle_a.jq tests/modules/cycle_b.jq \
|
|
tests/modules/cycle_self.jq \
|
|
tests/onig.supp tests/local.supp \
|
|
tests/setup tests/torture/input0.json \
|
|
tests/optional.test tests/man.test tests/manonig.test \
|
|
tests/jq.test tests/onig.test tests/base64.test tests/uri.test \
|
|
tests/jq-f-test.sh \
|
|
tests/no-main-program.jq tests/yes-main-program.jq
|
|
|
|
AM_DISTCHECK_CONFIGURE_FLAGS=--with-oniguruma=builtin
|
|
|
|
# README.md is expected in GitHub projects, good stuff in it, so we'll
|
|
# distribute it and install it with the package in the doc directory.
|
|
dist_doc_DATA = README.md NEWS.md COPYING AUTHORS
|
|
|
|
pkgconfigdir = $(libdir)/pkgconfig
|
|
pkgconfig_DATA = libjq.pc
|
|
|
|
RELEASE ?= 1
|
|
rpm: dist jq.spec
|
|
@echo "Packaging jq as an RPM ..."
|
|
mkdir -p rpm/SOURCES rpm/BUILD rpm/BUILDROOT rpm/RPMS rpm/SPECS
|
|
cp jq-$(VERSION).tar.gz rpm/SOURCES/
|
|
rpmbuild -tb --define "_topdir ${PWD}/rpm" --define "_prefix /usr" --define "myver $(VERSION)" --define "myrel ${RELEASE}" rpm/SOURCES/jq-$(VERSION).tar.gz
|
|
find rpm/RPMS/ -name "*.rpm" -exec mv {} ./ \;
|
|
rm -rf rpm
|