diff --git a/.gitignore b/.gitignore index 56e78a02..e70c5446 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,11 @@ ms_print.* /references/ECMA-262 5.1 edition June 2011.pdf /references/ECMA-262.pdf /tests/octane/octane +/src-tools/from-xml +/src-tools/js-yaml +/src-tools/node_modules +/src-tools/lib/extdeps +/src-tools/lib/extdeps/from-xml.js +/src-tools/lib/extdeps/js-yaml.js +/src-tools/package-lock.json +/src-tools/duktool.js diff --git a/Makefile b/Makefile index 7de2fb30..6e03abab 100644 --- a/Makefile +++ b/Makefile @@ -39,6 +39,7 @@ NODE := $(shell { command -v nodejs || command -v node; } 2>/dev/null) WGET := $(shell command -v wget 2>/dev/null) JAVA := $(shell command -v java 2>/dev/null) VALGRIND := $(shell command -v valgrind 2>/dev/null) +#PYTHON := $(shell { command -v python3 || command -v python; } 2>/dev/null) PYTHON := $(shell { command -v python2 || command -v python; } 2>/dev/null) DOCKER := docker SCAN_BUILD := scan-build-7 @@ -153,7 +154,7 @@ CCOPTS_SHARED += -I./extras/print-alert CCOPTS_SHARED += -I./extras/console CCOPTS_SHARED += -I./extras/logging CCOPTS_SHARED += -I./extras/module-duktape -#CCOPTS_SHARED += -m32 # force 32-bit compilation on a 64-bit host +#CCOPTS_SHARED += -m32 # force 32-bit compilation on a 64-bit host #CCOPTS_SHARED += -mx32 # force X32 compilation on a 64-bit host #CCOPTS_SHARED += -fstack-usage # enable manually, then e.g. $ make clean duk; python util/pretty_stack_usage.py duktape.su @@ -249,6 +250,7 @@ clean: @rm -rf oprofile_data/ @rm -f /tmp/duk-test-eval-file-temp.js # used by tests/api/test-eval-file.js @rm -f a.out + @cd src-tools; make clean .PHONY: cleanall cleanall: clean @@ -257,6 +259,7 @@ cleanall: clean @rm -f "references/ECMA-262 5th edition December 2009.pdf" @rm -f "references/ECMA-262 5.1 edition June 2011.pdf" @rm -f "references/ECMA-262.pdf" + @cd src-tools; make cleanall # External dependencies. deps: @@ -274,63 +277,72 @@ build: dist: @mkdir -p $@ +# Duktape configurations. +prep: + @mkdir -p prep + # Targets for tooling. build/duktool.js: | build make -C src-tools cp src-tools/duktool.js $@ # Targets for preparing different Duktape configurations. -prep: - @mkdir -p prep -prep/nondebug: prep +.PHONY: prep-duktool +prep-duktool: src-tools/duktool.js +src-tools/duktool.js: + @cd src-tools && make + @touch $@ +.PHONY: configure-deps +configure-deps: prep-duktool +prep/nondebug: configure-deps | prep @rm -rf ./prep/nondebug $(PYTHON) tools/configure.py --output-directory ./prep/nondebug --source-directory src-input --config-metadata config $(CONFIGOPTS_NONDEBUG) --line-directives -prep/nondebug-scanbuild: prep +prep/nondebug-scanbuild: configure-deps | prep @rm -rf ./prep/nondebug-scanbuild $(PYTHON) tools/configure.py --output-directory ./prep/nondebug-scanbuild --source-directory src-input --config-metadata config $(CONFIGOPTS_NONDEBUG_SCANBUILD) --separate-sources --line-directives -prep/nondebug-perf: prep +prep/nondebug-perf: configure-deps | prep @rm -rf ./prep/nondebug-perf $(PYTHON) tools/configure.py --output-directory ./prep/nondebug-perf --source-directory src-input --config-metadata config $(CONFIGOPTS_NONDEBUG_PERF) --line-directives -prep/nondebug-size: prep +prep/nondebug-size: configure-deps | prep @rm -rf ./prep/nondebug-size $(PYTHON) tools/configure.py --output-directory ./prep/nondebug-size --source-directory src-input --config-metadata config $(CONFIGOPTS_NONDEBUG_SIZE) --line-directives -prep/nondebug-rom: prep +prep/nondebug-rom: configure-deps | prep @rm -rf ./prep/nondebug-rom $(PYTHON) tools/configure.py --output-directory ./prep/nondebug-rom --source-directory src-input --config-metadata config $(CONFIGOPTS_NONDEBUG_ROM) --line-directives -prep/debug: prep +prep/debug: configure-deps | prep @rm -rf ./prep/debug $(PYTHON) tools/configure.py --output-directory ./prep/debug --source-directory src-input --config-metadata config $(CONFIGOPTS_DEBUG) --line-directives -prep/fuzz: prep +prep/fuzz: | prep @rm -rf ./prep/fuzz $(PYTHON) tools/configure.py --output-directory ./prep/fuzz --source-directory src-input --config-metadata config $(CONFIGOPTS_FUZZ) --line-directives -prep/debug-scanbuild: prep +prep/debug-scanbuild: configure-deps | prep @rm -rf ./prep/debug-scanbuild $(PYTHON) tools/configure.py --output-directory ./prep/debug-scanbuild --source-directory src-input --config-metadata config $(CONFIGOPTS_DEBUG_SCANBUILD) --separate-sources --line-directives -prep/debug-rom: prep +prep/debug-rom: configure-deps | prep @rm -rf ./prep/debug-rom $(PYTHON) tools/configure.py --output-directory ./prep/debug-rom --source-directory src-input --config-metadata config $(CONFIGOPTS_DEBUG_ROM) --line-directives -prep/emduk: prep +prep/emduk: configure-deps | prep @rm -rf ./prep/emduk $(PYTHON) tools/configure.py --output-directory ./prep/emduk --source-directory src-input --config-metadata config $(CONFIGOPTS_EMDUK) --line-directives -prep/dukweb: prep +prep/dukweb: configure-deps | prep @rm -rf ./prep/dukweb $(PYTHON) tools/configure.py --output-directory ./prep/dukweb --source-directory src-input --config-metadata config $(CONFIGOPTS_DUKWEB) --line-directives -prep/duklow-nondebug: prep +prep/duklow-nondebug: configure-deps | prep @rm -rf ./prep/duklow-nondebug $(PYTHON) tools/configure.py --output-directory ./prep/duklow-nondebug --source-directory src-input --config-metadata config $(CONFIGOPTS_NONDEBUG_DUKLOW) --line-directives -prep/duklow-debug: prep +prep/duklow-debug: configure-deps | prep @rm -rf ./prep/duklow-debug $(PYTHON) tools/configure.py --output-directory ./prep/duklow-debug --source-directory src-input --config-metadata config $(CONFIGOPTS_DEBUG_DUKLOW) --line-directives -prep/duklow-nondebug-rom: prep +prep/duklow-nondebug-rom: configure-deps | prep @rm -rf ./prep/duklow-nondebug-rom $(PYTHON) tools/configure.py --output-directory ./prep/duklow-nondebug-rom --source-directory src-input --config-metadata config $(CONFIGOPTS_NONDEBUG_DUKLOW_ROM) --line-directives -prep/duklow-debug-rom: prep +prep/duklow-debug-rom: configure-deps | prep @rm -rf ./prep/duklow-debug-rom $(PYTHON) tools/configure.py --output-directory ./prep/duklow-debug-rom --source-directory src-input --config-metadata config $(CONFIGOPTS_DEBUG_DUKLOW_ROM) --line-directives -prep/duklow-nondebug-norefc: prep +prep/duklow-nondebug-norefc: configure-deps | prep @rm -rf ./prep/duklow-nondebug-norefc $(PYTHON) tools/configure.py --output-directory ./prep/duklow-nondebug-norefc --source-directory src-input --config-metadata config $(CONFIGOPTS_NONDEBUG_DUKLOW_NOREFC) --line-directives -prep/duklow-debug-norefc: prep +prep/duklow-debug-norefc: configure-deps | prep @rm -rf ./prep/duklow-debug-norefc $(PYTHON) tools/configure.py --output-directory ./prep/duklow-debug-norefc --source-directory src-input --config-metadata config $(CONFIGOPTS_DEBUG_DUKLOW_NOREFC) --line-directives @@ -351,11 +363,11 @@ DUK_SOURCE_DEPS=$(DUKTAPE_CMDLINE_SOURCES) $(LINENOISE_SOURCES) $(LINENOISE_HEAD duk: build/duk # Convenience target. cp $< $@ -build/duk: prep/nondebug $(DUK_SOURCE_DEPS) | build +build/duk: $(DUK_SOURCE_DEPS) | build prep/nondebug $(CC) -o $@ -Iprep/nondebug $(CCOPTS_NONDEBUG) prep/nondebug/duktape.c $(DUKTAPE_CMDLINE_SOURCES) $(LINENOISE_SOURCES) $(CCLIBS) @ls -l $@ -@size $@ -build/duk-pgo: prep/nondebug $(DUK_SOURCE_DEPS) | build +build/duk-pgo: $(DUK_SOURCE_DEPS) | build prep/nondebug @echo "Compiling with -fprofile-generate..." @rm -f *.gcda $(CC) -o $@ -Iprep/nondebug $(CCOPTS_NONDEBUG) -fprofile-generate prep/nondebug/duktape.c $(DUKTAPE_CMDLINE_SOURCES) $(LINENOISE_SOURCES) $(CCLIBS) @@ -369,31 +381,31 @@ build/duk-pgo: prep/nondebug $(DUK_SOURCE_DEPS) | build $(CC) -o $@ -Iprep/nondebug $(CCOPTS_NONDEBUG) -fprofile-use prep/nondebug/duktape.c $(DUKTAPE_CMDLINE_SOURCES) $(LINENOISE_SOURCES) $(CCLIBS) @ls -l $@ -@size $@ -build/duk-perf: prep/nondebug-perf $(DUK_SOURCE_DEPS) | build +build/duk-perf: $(DUK_SOURCE_DEPS) | build prep/nondebug-perf $(CC) -o $@ -Iprep/nondebug-perf $(CCOPTS_NONDEBUG) prep/nondebug-perf/duktape.c $(DUKTAPE_CMDLINE_SOURCES) $(LINENOISE_SOURCES) $(CCLIBS) @ls -l $@ -@size $@ -build/duk-size: prep/nondebug-size $(DUK_SOURCE_DEPS) | build +build/duk-size: $(DUK_SOURCE_DEPS) | build prep/nondebug-size $(CC) -o $@ -Iprep/nondebug-size $(CCOPTS_NONDEBUG) prep/nondebug-size/duktape.c $(DUKTAPE_CMDLINE_SOURCES) $(LINENOISE_SOURCES) $(CCLIBS) @ls -l $@ -@size $@ -build/duk-rom: prep/nondebug-rom $(DUK_SOURCE_DEPS) | build +build/duk-rom: $(DUK_SOURCE_DEPS) | build prep/nondebug-rom $(CC) -o $@ -Iprep/nondebug-rom $(CCOPTS_NONDEBUG) prep/nondebug-rom/duktape.c $(DUKTAPE_CMDLINE_SOURCES) $(LINENOISE_SOURCES) $(CCLIBS) @ls -l $@ -@size $@ -build/dukd: prep/debug $(DUK_SOURCE_DEPS) | build +build/dukd: $(DUK_SOURCE_DEPS) | build prep/debug $(CC) -o $@ -Iprep/debug $(CCOPTS_DEBUG) prep/debug/duktape.c $(DUKTAPE_CMDLINE_SOURCES) $(LINENOISE_SOURCES) $(CCLIBS) @ls -l $@ -@size $@ -build/dukd-rom: prep/debug-rom $(DUK_SOURCE_DEPS) | build +build/dukd-rom: $(DUK_SOURCE_DEPS) | build prep/debug-rom $(CC) -o $@ -Iprep/debug-rom $(CCOPTS_DEBUG) prep/debug-rom/duktape.c $(DUKTAPE_CMDLINE_SOURCES) $(LINENOISE_SOURCES) $(CCLIBS) @ls -l $@ -@size $@ -build/duk.O2: prep/nondebug $(DUK_SOURCE_DEPS) | build +build/duk.O2: $(DUK_SOURCE_DEPS) | build prep/nondebug $(CC) -o $@ -Iprep/nondebug $(CCOPTS_NONDEBUG) -O2 prep/nondebug/duktape.c $(DUKTAPE_CMDLINE_SOURCES) $(LINENOISE_SOURCES) $(CCLIBS) @ls -l $@ -@size $@ -build/duk-pgo.O2: prep/nondebug $(DUK_SOURCE_DEPS) | build +build/duk-pgo.O2: $(DUK_SOURCE_DEPS) | build prep/nondebug @echo "Compiling with -fprofile-generate..." @rm -f *.gcda $(CC) -o $@ -Iprep/nondebug $(CCOPTS_NONDEBUG) -O2 -fprofile-generate prep/nondebug/duktape.c $(DUKTAPE_CMDLINE_SOURCES) $(LINENOISE_SOURCES) $(CCLIBS) @@ -407,11 +419,11 @@ build/duk-pgo.O2: prep/nondebug $(DUK_SOURCE_DEPS) | build $(CC) -o $@ -Iprep/nondebug $(CCOPTS_NONDEBUG) -O2 -fprofile-use prep/nondebug/duktape.c $(DUKTAPE_CMDLINE_SOURCES) $(LINENOISE_SOURCES) $(CCLIBS) @ls -l $@ -@size $@ -build/duk-perf.O2: prep/nondebug-perf $(DUK_SOURCE_DEPS) | build +build/duk-perf.O2: $(DUK_SOURCE_DEPS) | build prep/nondebug-perf $(CC) -o $@ -Iprep/nondebug-perf $(CCOPTS_NONDEBUG) -O2 prep/nondebug-perf/duktape.c $(DUKTAPE_CMDLINE_SOURCES) $(LINENOISE_SOURCES) $(CCLIBS) @ls -l $@ -@size $@ -build/duk-perf-pgo.O2: prep/nondebug-perf $(DUK_SOURCE_DEPS) | build +build/duk-perf-pgo.O2: $(DUK_SOURCE_DEPS) | build prep/nondebug-perf @echo "Compiling with -fprofile-generate..." @rm -f *.gcda $(CC) -o $@ -Iprep/nondebug-perf $(CCOPTS_NONDEBUG) -O2 -fprofile-generate prep/nondebug-perf/duktape.c $(DUKTAPE_CMDLINE_SOURCES) $(LINENOISE_SOURCES) $(CCLIBS) @@ -423,59 +435,59 @@ build/duk-perf-pgo.O2: prep/nondebug-perf $(DUK_SOURCE_DEPS) | build @rm -f $@ @echo "Recompiling with -fprofile-use..." $(CC) -o $@ -Iprep/nondebug-perf $(CCOPTS_NONDEBUG) -O2 -fprofile-use prep/nondebug-perf/duktape.c $(DUKTAPE_CMDLINE_SOURCES) $(LINENOISE_SOURCES) $(CCLIBS) -build/duk.O3: prep/nondebug $(DUKTAPE_CMDLINE_SOURCES) $(LINENOISE_SOURCES) | deps/linenoise +build/duk.O3: $(DUKTAPE_CMDLINE_SOURCES) $(LINENOISE_SOURCES) | deps/linenoise prep/nondebug $(CC) -o $@ -Iprep/nondebug $(CCOPTS_NONDEBUG) -O3 prep/nondebug/duktape.c $(DUKTAPE_CMDLINE_SOURCES) $(LINENOISE_SOURCES) $(CCLIBS) @ls -l $@ -@size $@ -build/duk-perf.O3: prep/nondebug-perf $(DUK_SOURCE_DEPS) | build +build/duk-perf.O3: $(DUK_SOURCE_DEPS) | build prep/nondebug-perf $(CC) -o $@ -Iprep/nondebug-perf $(CCOPTS_NONDEBUG) -O3 prep/nondebug-perf/duktape.c $(DUKTAPE_CMDLINE_SOURCES) $(LINENOISE_SOURCES) $(CCLIBS) @ls -l $@ -@size $@ -build/duk.O4: prep/nondebug $(DUK_SOURCE_DEPS) | build +build/duk.O4: $(DUK_SOURCE_DEPS) | build prep/nondebug $(CC) -o $@ -Iprep/nondebug $(CCOPTS_NONDEBUG) -O4 prep/nondebug/duktape.c $(DUKTAPE_CMDLINE_SOURCES) $(LINENOISE_SOURCES) $(CCLIBS) @ls -l $@ -@size $@ -build/duk-perf.O4: prep/nondebug-perf $(DUK_SOURCE_DEPS) | build +build/duk-perf.O4: $(DUK_SOURCE_DEPS) | build prep/nondebug-perf $(CC) -o $@ -Iprep/nondebug-perf $(CCOPTS_NONDEBUG) -O4 prep/nondebug-perf/duktape.c $(DUKTAPE_CMDLINE_SOURCES) $(LINENOISE_SOURCES) $(CCLIBS) @ls -l $@ -@size $@ -build/duk-clang: prep/nondebug $(DUK_SOURCE_DEPS) | build +build/duk-clang: $(DUK_SOURCE_DEPS) | build prep/nondebug @# Use -Wcast-align to trigger issues like: https://github.com/svaarala/duktape/issues/270 @# Use -Wshift-sign-overflow to trigger issues like: https://github.com/svaarala/duktape/issues/812 @# -Weverything $(CLANG) -o $@ -Wcast-align -Wshift-sign-overflow -Iprep/nondebug $(CLANG_CCOPTS_NONDEBUG) prep/nondebug/duktape.c $(DUKTAPE_CMDLINE_SOURCES) $(LINENOISE_SOURCES) $(CCLIBS) @ls -l $@ -@size $@ -build/duk-sanitize-clang: prep/nondebug $(DUK_SOURCE_DEPS) | build +build/duk-sanitize-clang: $(DUK_SOURCE_DEPS) | build prep/nondebug $(CLANG) -o $@ -Wcast-align -Wshift-sign-overflow -fsanitize=undefined -Iprep/nondebug $(CLANG_CCOPTS_NONDEBUG) prep/nondebug/duktape.c $(DUKTAPE_CMDLINE_SOURCES) $(LINENOISE_SOURCES) $(CCLIBS) @ls -l $@ -@size $@ -build/duk-fuzzilli: prep/fuzz $(DUK_SOURCE_DEPS) | build +build/duk-fuzzilli: $(DUK_SOURCE_DEPS) | build prep/fuzz # Target for fuzzilli. Adds in the appropriate debug flags, without doing the debug prints. $(CLANG) -O3 -o $@ -Wall -Wextra -Wcast-align -Wshift-sign-overflow -fsanitize=undefined -fsanitize-coverage=trace-pc-guard -Iprep/fuzz $(CLANG_CCOPTS_DEBUG) prep/fuzz/duktape.c $(DUKTAPE_CMDLINE_SOURCES) $(LINENOISE_SOURCES) $(CCLIBS) @ls -l $@ -@size $@ -build/duk-perf-clang: prep/nondebug-perf $(DUK_SOURCE_DEPS) | build +build/duk-perf-clang: $(DUK_SOURCE_DEPS) | build prep/nondebug-perf $(CLANG) -o $@ -Wcast-align -Wshift-sign-overflow -Iprep/nondebug-perf $(CLANG_CCOPTS_NONDEBUG) prep/nondebug-perf/duktape.c $(DUKTAPE_CMDLINE_SOURCES) $(LINENOISE_SOURCES) $(CCLIBS) @ls -l $@ -@size $@ -build/duk-g++: prep/nondebug $(DUK_SOURCE_DEPS) | build +build/duk-g++: $(DUK_SOURCE_DEPS) | build prep/nondebug $(GXX) -o $@ -Iprep/nondebug $(GXXOPTS_NONDEBUG) prep/nondebug/duktape.c $(DUKTAPE_CMDLINE_SOURCES) $(CCLIBS) @ls -l $@ -@size $@ -build/duk-perf-g++: prep/nondebug-perf $(DUK_SOURCE_DEPS) | build +build/duk-perf-g++: $(DUK_SOURCE_DEPS) | build prep/nondebug-perf $(GXX) -o $@ -Iprep/nondebug-perf $(GXXOPTS_NONDEBUG) prep/nondebug-perf/duktape.c $(DUKTAPE_CMDLINE_SOURCES) $(CCLIBS) @ls -l $@ -@size $@ -build/dukd-g++: prep/debug $(DUK_SOURCE_DEPS) | build +build/dukd-g++: $(DUK_SOURCE_DEPS) | build prep/debug $(GXX) -o $@ -Iprep/debug $(GXXOPTS_DEBUG) prep/debug/duktape.c $(DUKTAPE_CMDLINE_SOURCES) $(CCLIBS) @ls -l $@ -@size $@ .PHONY: dukscanbuild -build/dukscanbuild: prep/nondebug-scanbuild $(DUK_SOURCE_DEPS) | build tmp +build/dukscanbuild: $(DUK_SOURCE_DEPS) | build tmp prep/nondebug-scanbuild $(SCAN_BUILD) $(GCC) -otmp/duk.scanbuild -Iprep/nondebug-scanbuild $(CCOPTS_NONDEBUG) prep/nondebug-scanbuild/*.c $(DUKTAPE_CMDLINE_SOURCES) $(LINENOISE_SOURCES) $(CCLIBS) .PHONY: dukdscanbuild -build/dukdscanbuild: prep/debug-scanbuild $(DUK_SOURCE_DEPS) | build tmp +build/dukdscanbuild: $(DUK_SOURCE_DEPS) | build tmp prep/debug-scanbuild $(SCAN_BUILD) $(GCC) -otmp/dukd.scanbuild -Iprep/debug-scanbuild $(CCOPTS_DEBUG) prep/debug-scanbuild/*.c $(DUKTAPE_CMDLINE_SOURCES) $(LINENOISE_SOURCES) $(CCLIBS) # Command line with a simple pool allocator, for low memory testing. # The pool sizes only make sense with -m32, so force that. This forces @@ -486,7 +498,7 @@ DUKTAPE_CMDLINE_LOWMEM_SOURCES=\ extras/alloc-pool/duk_alloc_pool.c DUK_LOWMEM_SOURCE_DEPS=$(DUKTAPE_CMDLINE_LOWMEM_SOURCES) $(LINENOISE_SOURCES) $(LINENOISE_HEADERS) -build/duk-low: prep/duklow-nondebug $(DUK_LOWMEM_SOURCE_DEPS) | build +build/duk-low: $(DUK_LOWMEM_SOURCE_DEPS) | build prep/duklow-nondebug $(CC) -o $@ \ -Iextras/alloc-pool/ -Iprep/duklow-nondebug \ $(CCOPTS_NONDEBUG) $(CCOPTS_DUKLOW) \ @@ -495,7 +507,7 @@ build/duk-low: prep/duklow-nondebug $(DUK_LOWMEM_SOURCE_DEPS) | build @echo "*** SUCCESS:" @ls -l $@ -@size $@ -build/dukd-low: prep/duklow-debug $(DUK_LOWMEM_SOURCE_DEPS) | build +build/dukd-low: $(DUK_LOWMEM_SOURCE_DEPS) | build prep/duklow-debug $(CC) -o $@ \ -Iextras/alloc-pool/ -Iprep/duklow-debug \ $(CCOPTS_DEBUG) $(CCOPTS_DUKLOW) \ @@ -504,7 +516,7 @@ build/dukd-low: prep/duklow-debug $(DUK_LOWMEM_SOURCE_DEPS) | build @echo "*** SUCCESS:" @ls -l $@ -@size $@ -build/duk-low-rom: prep/duklow-nondebug-rom $(DUK_LOWMEM_SOURCE_DEPS) | build +build/duk-low-rom: $(DUK_LOWMEM_SOURCE_DEPS) | build prep/duklow-nondebug-rom $(CC) -o $@ \ -Iextras/alloc-pool/ -Iprep/duklow-nondebug-rom \ $(CCOPTS_NONDEBUG) $(CCOPTS_DUKLOW) \ @@ -513,7 +525,7 @@ build/duk-low-rom: prep/duklow-nondebug-rom $(DUK_LOWMEM_SOURCE_DEPS) | build @echo "*** SUCCESS:" @ls -l $@ -@size $@ -build/dukd-low-rom: prep/duklow-debug-rom $(DUK_LOWMEM_SOURCE_DEPS) | build +build/dukd-low-rom: $(DUK_LOWMEM_SOURCE_DEPS) | build prep/duklow-debug-rom $(CC) -o $@ \ -Iextras/alloc-pool/ -Iprep/duklow-debug-rom \ $(CCOPTS_DEBUG) $(CCOPTS_DUKLOW) \ @@ -522,7 +534,7 @@ build/dukd-low-rom: prep/duklow-debug-rom $(DUK_LOWMEM_SOURCE_DEPS) | build @echo "*** SUCCESS:" @ls -l $@ -@size $@ -build/duk-low-norefc: prep/duklow-nondebug-norefc $(DUK_LOWMEM_SOURCE_DEPS) | build +build/duk-low-norefc: $(DUK_LOWMEM_SOURCE_DEPS) | build prep/duklow-nondebug-norefc $(CC) -o $@ \ -Iextras/alloc-pool/ -Iprep/duklow-nondebug-norefc \ $(CCOPTS_NONDEBUG) $(CCOPTS_DUKLOW) \ @@ -531,7 +543,7 @@ build/duk-low-norefc: prep/duklow-nondebug-norefc $(DUK_LOWMEM_SOURCE_DEPS) | bu @echo "*** SUCCESS:" @ls -l $@ -@size $@ -build/dukd-low-norefc: prep/duklow-debug-norefc $(DUK_LOWMEM_SOURCE_DEPS) | build +build/dukd-low-norefc: $(DUK_LOWMEM_SOURCE_DEPS) | build prep/duklow-debug-norefc $(CC) -o $@ \ -Iextras/alloc-pool/ -Iprep/duklow-debug-norefc \ $(CCOPTS_DEBUG) $(CCOPTS_DUKLOW) \ @@ -547,7 +559,7 @@ build/dukd-low-norefc: prep/duklow-debug-norefc $(DUK_LOWMEM_SOURCE_DEPS) | buil build/emduk: emduk.js | build cat util/emduk_wrapper.sh | sed "s|WORKDIR|$(shell pwd)|" > $@ chmod ugo+x $@ -build/emduk.js: prep/emduk examples/cmdline/duk_cmdline.c extras/print-alert/duk_print_alert.c | build tmp +build/emduk.js: examples/cmdline/duk_cmdline.c extras/print-alert/duk_print_alert.c | build tmp prep/emduk $(EMCC) $(EMCCOPTS) -Iprep/emduk -Iexamples/cmdline -Iextras/print-alert \ $(EMDUKOPTS) \ prep/emduk/duktape.c examples/cmdline/duk_cmdline.c extras/print-alert/duk_print_alert.c \ @@ -558,13 +570,13 @@ build/emduk.js: prep/emduk examples/cmdline/duk_cmdline.c extras/print-alert/duk # This is a prototype of running Duktape in a web environment with Emscripten, # and providing an eval() facility from both sides. This is a placeholder now # and doesn't do anything useful yet. -build/dukweb.js: prep/dukweb dukweb/dukweb_extra.js dukweb/dukweb.c | build +build/dukweb.js: dukweb/dukweb_extra.js dukweb/dukweb.c | build prep/dukweb @rm -f build/dukweb.js build/dukweb.asm $(EMCC) $(EMCCOPTS_DUKVM_WASM) $(EMCCOPTS_DUKWEB_EXPORT) --post-js dukweb/dukweb_extra.js \ -Iprep/dukweb prep/dukweb/duktape.c dukweb/dukweb.c -o $@ @wc build/dukweb.js build/dukweb.wasm -build/literal_intern_test: prep/nondebug misc/literal_intern_test.c | build +build/literal_intern_test: misc/literal_intern_test.c | build prep/nondebug $(CC) -o $@ -std=c99 -O2 -fstrict-aliasing -Wall -Wextra \ -Iprep/nondebug prep/nondebug/duktape.c misc/literal_intern_test.c -lm .PHONY: literalinterntest @@ -652,8 +664,8 @@ apitest: runtestsdeps build/libduktape.so.1.0.0 | tmp @echo "### apitest" "$(NODE)" runtests/runtests.js $(RUNTESTSOPTS) --num-threads 1 --log-file=tmp/duk-api-test.log tests/api/ -# Configure.py test. -configuretest: +# Configure tests. +configuretest: configure-deps @echo "### configuretest" bash tests/configure/test_minimal.sh @@ -997,8 +1009,9 @@ doc/%.html: doc/%.txt rst2html $< $@ # Source distributable for end users. -dist/source: | codepolicycheck dist - $(PYTHON) util/dist.py +dist/source: prep-duktool | codepolicycheck dist + $(PYTHON) util/dist.py --output-directory $@ + cp src-tools/duktool.js $@/tools/ dist/duktape-$(DUK_VERSION_FORMATTED).tar: dist/source | dist rm -rf dist/duktape-$(DUK_VERSION_FORMATTED) dist/duktape-$(DUK_VERSION_FORMATTED).* mkdir dist/duktape-$(DUK_VERSION_FORMATTED) && cp -r dist/source/* dist/duktape-$(DUK_VERSION_FORMATTED)/ diff --git a/README.md b/README.md index 0b21fab8..06785997 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,8 @@ For example, to enable fastint support (example for Linux): # src-custom/ will now contain: duktape.c, duktape.h, duk_config.h. -You can download and install duktape using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager: +You can download and install Duktape using the +[vcpkg](https://github.com/Microsoft/vcpkg) dependency manager: $ git clone https://github.com/Microsoft/vcpkg.git $ cd vcpkg @@ -94,7 +95,10 @@ You can download and install duktape using the [vcpkg](https://github.com/Micros $ ./vcpkg integrate install $ vcpkg install duktape -The duktape port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. +The Duktape port in vcpkg is kept up to date by Microsoft team members +and community contributors. If the version is out of date, please +[create an issue or pull request](https://github.com/Microsoft/vcpkg) on +the vcpkg repository. You can also clone this repository, make modifications, and build a source distributable on Linux, macOS, and Windows using `python util/dist.py`. @@ -107,16 +111,19 @@ If you intend to change Duktape internals and want to rebuild the source distributable in Linux, macOS, or Windows: # Linux; can often install from packages or using 'pip' + # Install Node.js >= 14.x $ sudo apt-get install python python-yaml $ python util/dist.py # macOS # Install Python 2.7.x + # Install Node.js >= 14.x $ pip install PyYAML $ python util/dist.py # Windows ; Install Python 2.7.x from python.org, and add it to PATH + ; Install Node.js >= 14.x > pip install PyYAML > python util\dist.py diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 3389b536..00000000 --- a/appveyor.yml +++ /dev/null @@ -1,171 +0,0 @@ -version: "{build}" - -clone_depth: 5 - -platform: - - x64 - - x86 - -configuration: - - Release - -matrix: - fast_finish: true - -install: - - cmd: python -m pip install PyYAML - -build_script: - # C:\projects\duktape - # https://en.wikipedia.org/wiki/Microsoft_Visual_Studio#History - #- cmd: set - #- cmd: dir "C:\Program Files\" - #- cmd: dir "C:\Program Files (x86)\" - - # Make dist, ensure it works on Windows too. - - - cmd: cd C:\projects\duktape - - cmd: mkdir dist - - cmd: python util\dist.py - - # Prep a few variants of headers and sources. - - - cmd: python tools\configure.py --line-directives --output-directory prep-nondll --source-directory src-input --config-metadata config - - cmd: dir prep-nondll - - cmd: python tools\configure.py --line-directives --output-directory prep-dll --source-directory src-input --config-metadata config --dll - - cmd: dir prep-dll - - cmd: python tools\configure.py --line-directives --output-directory prep-cpp --source-directory src-input --config-metadata config -DDUK_USE_CPP_EXCEPTIONS - - cmd: dir prep-cpp - - # --- Visual Studio 2015 --- - - # PATH doesn't include any 'cl' by default, not sure how to do this correctly. - # https://msdn.microsoft.com/en-us/library/f2ccy3wt.aspx - # Multi-line commands are run line-by-line (?). - - cmd: set VCPATH="\Program Files (x86)\Microsoft Visual Studio 14.0\VC" - - cmd: set VCPLATFORM=NONE - - cmd: set VCNAME=vs2015 - - cmd: if "%PLATFORM%"=="x86" ( set VCPLATFORM=x86 ) - - cmd: if "%PLATFORM%"=="x64" ( set VCPLATFORM=x86_amd64 ) - - cmd: echo PLATFORM=%PLATFORM%, VCPLATFORM=%VCPLATFORM% - - cmd: "%VCPATH%\\vcvarsall %VCPLATFORM%" - - cmd: cl - - # Normal build. - - cmd: cl /W3 /O2 /DDUK_CMDLINE_PRINTALERT_SUPPORT /DDUK_CMDLINE_PRINTALERT_SUPPORT /Iprep-nondll /Iexamples\cmdline /Iextras\print-alert prep-nondll\duktape.c examples\cmdline\duk_cmdline.c extras\print-alert\duk_print_alert.c /Feduk-%VCNAME%-%PLATFORM%.exe - - # DLL build. - - cmd: cl /W3 /O2 /Iprep-dll /LD /Feduktape-%VCNAME%-%PLATFORM% prep-dll\duktape.c - - cmd: cl /W3 /O2 /DDUK_CMDLINE_PRINTALERT_SUPPORT /Iprep-dll /Iexamples\cmdline /Iextras\print-alert examples\cmdline\duk_cmdline.c extras\print-alert\duk_print_alert.c /Feduk-dll-%VCNAME%-%PLATFORM%.exe duktape-%VCNAME%-%PLATFORM%.lib - - # Build as C++, catches some static variable issues specific to C++. - # Also test C++ exceptions on Windows. - # /TP forces files to be interpreted as C++ despite their extension. - # /EHsc enables exception unwind support. - - cmd: cl /TP /EHsc /W3 /O2 /DDUK_CMDLINE_PRINTALERT_SUPPORT /Iprep-cpp /Iexamples\cmdline /Iextras\print-alert prep-cpp\duktape.c examples\cmdline\duk_cmdline.c extras\print-alert\duk_print_alert.c /Feduk-cxx-%VCNAME%-%PLATFORM%.exe - - # --- Visual Studio 2013 --- - - - cmd: set VCPATH="\Program Files (x86)\Microsoft Visual Studio 12.0\VC" - - cmd: set VCPLATFORM=NONE - - cmd: set VCNAME=vs2013 - - cmd: if "%PLATFORM%"=="x86" ( set VCPLATFORM=x86 ) - - cmd: if "%PLATFORM%"=="x64" ( set VCPLATFORM=x86_amd64 ) - - cmd: echo PLATFORM=%PLATFORM%, VCPLATFORM=%VCPLATFORM% - - cmd: "%VCPATH%\\vcvarsall %VCPLATFORM%" - - cmd: cl - - - cmd: cl /W3 /O2 /DDUK_CMDLINE_PRINTALERT_SUPPORT /Iprep-nondll /Iexamples\cmdline /Iextras\print-alert prep-nondll\duktape.c examples\cmdline\duk_cmdline.c extras\print-alert\duk_print_alert.c /Feduk-%VCNAME%-%PLATFORM%.exe - - cmd: cl /W3 /O2 /Iprep-dll /LD /Feduktape-%VCNAME%-%PLATFORM% prep-dll\duktape.c - - cmd: cl /W3 /O2 /DDUK_CMDLINE_PRINTALERT_SUPPORT /Iprep-dll /Iexamples\cmdline /Iextras\print-alert examples\cmdline\duk_cmdline.c extras\print-alert\duk_print_alert.c /Feduk-dll-%VCNAME%-%PLATFORM%.exe duktape-%VCNAME%-%PLATFORM%.lib - - cmd: cl /TP /EHsc /W3 /O2 /DDUK_CMDLINE_PRINTALERT_SUPPORT /Iprep-cpp /Iexamples\cmdline /Iextras\print-alert prep-cpp\duktape.c examples\cmdline\duk_cmdline.c extras\print-alert\duk_print_alert.c /Feduk-cxx-%VCNAME%-%PLATFORM%.exe - - # --- Visual Studio 2012 --- - - # Use VS2012 (11.0) to catch https://github.com/svaarala/duktape/pull/595. - - cmd: set VCPATH="\Program Files (x86)\Microsoft Visual Studio 11.0\VC" - - cmd: set VCPLATFORM=NONE - - cmd: set VCNAME=vs2012 - - cmd: if "%PLATFORM%"=="x86" ( set VCPLATFORM=x86 ) - - cmd: if "%PLATFORM%"=="x64" ( set VCPLATFORM=x86_amd64 ) - - cmd: echo PLATFORM=%PLATFORM%, VCPLATFORM=%VCPLATFORM% - - cmd: "%VCPATH%\\vcvarsall %VCPLATFORM%" - - cmd: cl - - - cmd: cl /W3 /O2 /DDUK_CMDLINE_PRINTALERT_SUPPORT /Iprep-nondll /Iexamples\cmdline /Iextras\print-alert prep-nondll\duktape.c examples\cmdline\duk_cmdline.c extras\print-alert\duk_print_alert.c /Feduk-%VCNAME%-%PLATFORM%.exe - - cmd: cl /W3 /O2 /Iprep-dll /LD /Feduktape-%VCNAME%-%PLATFORM% prep-dll\duktape.c - - cmd: cl /W3 /O2 /DDUK_CMDLINE_PRINTALERT_SUPPORT /Iprep-dll /Iexamples\cmdline /Iextras\print-alert examples\cmdline\duk_cmdline.c extras\print-alert\duk_print_alert.c /Feduk-dll-%VCNAME%-%PLATFORM%.exe duktape-%VCNAME%-%PLATFORM%.lib - - cmd: cl /TP /EHsc /W3 /O2 /DDUK_CMDLINE_PRINTALERT_SUPPORT /Iprep-cpp /Iexamples\cmdline /Iextras\print-alert prep-cpp\duktape.c examples\cmdline\duk_cmdline.c extras\print-alert\duk_print_alert.c /Feduk-cxx-%VCNAME%-%PLATFORM%.exe - - # --- Visual Studio 2010 --- - - - cmd: set VCPATH="\Program Files (x86)\Microsoft Visual Studio 10.0\VC" - - cmd: set VCPLATFORM=NONE - - cmd: set VCNAME=vs2010 - - cmd: if "%PLATFORM%"=="x86" ( set VCPLATFORM=x86 ) - - cmd: if "%PLATFORM%"=="x64" ( set VCPLATFORM=x86_amd64 ) - - cmd: echo PLATFORM=%PLATFORM%, VCPLATFORM=%VCPLATFORM% - - cmd: "%VCPATH%\\vcvarsall %VCPLATFORM%" - - cmd: cl - - - cmd: cl /W3 /O2 /DDUK_CMDLINE_PRINTALERT_SUPPORT /Iprep-nondll /Iexamples\cmdline /Iextras\print-alert prep-nondll\duktape.c examples\cmdline\duk_cmdline.c extras\print-alert\duk_print_alert.c /Feduk-%VCNAME%-%PLATFORM%.exe - - cmd: cl /W3 /O2 /Iprep-dll /LD /Feduktape-%VCNAME%-%PLATFORM% prep-dll\duktape.c - - cmd: cl /W3 /O2 /DDUK_CMDLINE_PRINTALERT_SUPPORT /Iprep-dll /Iexamples\cmdline /Iextras\print-alert examples\cmdline\duk_cmdline.c extras\print-alert\duk_print_alert.c /Feduk-dll-%VCNAME%-%PLATFORM%.exe duktape-%VCNAME%-%PLATFORM%.lib - - cmd: cl /TP /EHsc /W3 /O2 /DDUK_CMDLINE_PRINTALERT_SUPPORT /Iprep-cpp /Iexamples\cmdline /Iextras\print-alert prep-cpp\duktape.c examples\cmdline\duk_cmdline.c extras\print-alert\duk_print_alert.c /Feduk-cxx-%VCNAME%-%PLATFORM%.exe - - # --- Visual Studio 2008 --- - - - cmd: set VCPATH="\Program Files (x86)\Microsoft Visual Studio 9.0\VC" - - cmd: set VCPLATFORM=NONE - - cmd: set VCNAME=vs2008 - - cmd: if "%PLATFORM%"=="x86" ( set VCPLATFORM=x86 ) - - cmd: if "%PLATFORM%"=="x64" ( set VCPLATFORM=x86_amd64 ) - - cmd: echo PLATFORM=%PLATFORM%, VCPLATFORM=%VCPLATFORM% - - cmd: "%VCPATH%\\vcvarsall %VCPLATFORM%" - - cmd: cl - - - cmd: cl /W3 /O2 /DDUK_CMDLINE_PRINTALERT_SUPPORT /Iprep-nondll /Iexamples\cmdline /Iextras\print-alert prep-nondll\duktape.c examples\cmdline\duk_cmdline.c extras\print-alert\duk_print_alert.c /Feduk-%VCNAME%-%PLATFORM%.exe - - cmd: cl /W3 /O2 /Iprep-dll /LD /Feduktape-%VCNAME%-%PLATFORM% prep-dll\duktape.c - - cmd: cl /W3 /O2 /DDUK_CMDLINE_PRINTALERT_SUPPORT /Iprep-dll /Iexamples\cmdline /Iextras\print-alert examples\cmdline\duk_cmdline.c extras\print-alert\duk_print_alert.c /Feduk-dll-%VCNAME%-%PLATFORM%.exe duktape-%VCNAME%-%PLATFORM%.lib - - cmd: cl /TP /EHsc /W3 /O2 /DDUK_CMDLINE_PRINTALERT_SUPPORT /Iprep-cpp /Iexamples\cmdline /Iextras\print-alert prep-cpp\duktape.c examples\cmdline\duk_cmdline.c extras\print-alert\duk_print_alert.c /Feduk-cxx-%VCNAME%-%PLATFORM%.exe - -test_script: - - cmd: echo --- VS2015 - - cmd: duk-vs2015-%PLATFORM%.exe -e "print(Duktape.env); print('Hello world!');" - - cmd: duk-vs2015-%PLATFORM%.exe -e "print(Date.now(), performance.now(), performance.now());" - - cmd: duk-dll-vs2015-%PLATFORM%.exe -e "print(Duktape.env); print('Hello world!');" - - cmd: duk-cxx-vs2015-%PLATFORM%.exe -e "print(Duktape.env); print('Hello world!');" - - - cmd: echo --- VS2013 - - cmd: duk-vs2013-%PLATFORM%.exe -e "print(Duktape.env); print('Hello world!');" - - cmd: duk-dll-vs2013-%PLATFORM%.exe -e "print(Duktape.env); print('Hello world!');" - - cmd: duk-cxx-vs2013-%PLATFORM%.exe -e "print(Duktape.env); print('Hello world!');" - - - cmd: echo --- VS2012 - - cmd: duk-vs2012-%PLATFORM%.exe -e "print(Duktape.env); print('Hello world!');" - - cmd: duk-dll-vs2012-%PLATFORM%.exe -e "print(Duktape.env); print('Hello world!');" - - cmd: duk-cxx-vs2012-%PLATFORM%.exe -e "print(Duktape.env); print('Hello world!');" - - - cmd: echo --- VS2010 - - cmd: duk-vs2010-%PLATFORM%.exe -e "print(Duktape.env); print('Hello world!');" - - cmd: duk-dll-vs2010-%PLATFORM%.exe -e "print(Duktape.env); print('Hello world!');" - - cmd: duk-cxx-vs2010-%PLATFORM%.exe -e "print(Duktape.env); print('Hello world!');" - - - cmd: echo --- VS2008 - - cmd: duk-vs2008-%PLATFORM%.exe -e "print(Duktape.env); print('Hello world!');" - - cmd: duk-dll-vs2008-%PLATFORM%.exe -e "print(Duktape.env); print('Hello world!');" - - cmd: duk-cxx-vs2008-%PLATFORM%.exe -e "print(Duktape.env); print('Hello world!');" - -after_build: - # Show what was built. - - cmd: dir - -artifacts: - - path: duk-*.exe - name: Duk command line binary - - path: duktape-*.dll - name: Duktape DLL - - path: duktape-*.exp - name: Duktape EXP - - path: duktape-*.lib - name: Duktape LIB diff --git a/dist-files/README.rst b/dist-files/README.rst index 6e018685..95600356 100644 --- a/dist-files/README.rst +++ b/dist-files/README.rst @@ -122,7 +122,7 @@ implementations, with no included code, of the following algorithms: Lua string hash (MIT license), djb2 hash, Murmurhash2 (MIT license), Adi Shamir's three-op hash algorithm, xoroshiro128+ PRNG (public domain), SplitMix64 PRNG (public domain), and CommonJS module loading specification -(MIT license). +(MIT license). Duktape tooling relies on js-yaml (MIT license). Have fun! diff --git a/tests/configure/test_minimal.sh b/tests/configure/test_minimal.sh index fc0e6299..c1c6572e 100644 --- a/tests/configure/test_minimal.sh +++ b/tests/configure/test_minimal.sh @@ -12,7 +12,6 @@ reinit() { fi rm -rf /tmp/duk-configure-test - mkdir /tmp/duk-configure-test } # Test for command line -D with macro arguments, GH-2013 / GH-2014. diff --git a/tools/configure.py b/tools/configure.py index bc081f06..beb063ac 100644 --- a/tools/configure.py +++ b/tools/configure.py @@ -1,195 +1,69 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python # -# Prepare a duk_config.h and combined/separate sources for compilation, -# given user supplied config options, built-in metadata, Unicode tables, etc. -# -# This is intended to be the main tool application build scripts would use -# before their build step, so convenient, versions, Python compatibility, -# etc all matter. -# -# When obsoleting options, leave the option definitions behind (with -# help=optparse.SUPPRESS_HELP) and give useful suggestions when obsolete -# options are used. This makes it easier for users to fix their build -# scripts. +# Compatibility stub which now executes JS-based tooling. # - -import logging -import sys -logging.basicConfig(level=logging.INFO, stream=sys.stdout, format='%(name)-21s %(levelname)-7s %(message)s') -logger = logging.getLogger('configure.py') -logger.setLevel(logging.INFO) +# Should be Python2 and Python3 compatible. import os -import re -import shutil -import glob +import sys +import time +import subprocess import optparse -import tarfile -import json +import yaml import tempfile -import subprocess -import atexit -def import_warning(module, aptPackage, pipPackage): - sys.stderr.write('\n') - sys.stderr.write('*** NOTE: Could not "import %s". Install it using e.g.:\n' % module) - sys.stderr.write('\n') - sys.stderr.write(' # Linux\n') - sys.stderr.write(' $ sudo apt-get install %s\n' % aptPackage) - sys.stderr.write('\n') - sys.stderr.write(' # Windows\n') - sys.stderr.write(' > pip install %s\n' % pipPackage) - -try: - import yaml -except ImportError: - import_warning('yaml', 'python-yaml', 'PyYAML') - sys.exit(1) - -import genconfig - -# Helpers - -def exec_get_stdout(cmd, input=None, default=None, print_stdout=False): +def detect_nodejs(): try: - proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - ret = proc.communicate(input=input) - if print_stdout: - sys.stdout.write(ret[0]) - sys.stdout.flush() - if proc.returncode != 0: - sys.stdout.write(ret[1]) # print stderr on error - sys.stdout.flush() - if default is not None: - logger.info('WARNING: command %r failed, return default' % cmd) - return default - raise Exception('command failed, return code %d: %r' % (proc.returncode, cmd)) - return ret[0] + cmd = [ 'nodejs', '-e', 'console.log("test")' ] + res = subprocess.check_output(cmd) + if res[:4] == 'test'.encode('utf-8'): + return 'nodejs' except: - if default is not None: - logger.info('WARNING: command %r failed, return default' % cmd) - return default - raise - -def exec_print_stdout(cmd, input=None): - ret = exec_get_stdout(cmd, input=input, print_stdout=True) - -def mkdir(path): - os.mkdir(path) - -def copy_file(src, dst): - with open(src, 'rb') as f_in: - with open(dst, 'wb') as f_out: - f_out.write(f_in.read()) - -def copy_files(filelist, srcdir, dstdir): - for i in filelist: - copy_file(os.path.join(srcdir, i), os.path.join(dstdir, i)) - -def copy_and_replace(src, dst, rules): - # Read and write separately to allow in-place replacement - keys = sorted(rules.keys()) - res = [] - with open(src, 'rb') as f_in: - for line in f_in: - for k in keys: - line = line.replace(k, rules[k]) - res.append(line) - with open(dst, 'wb') as f_out: - f_out.write(''.join(res)) - -def copy_and_cquote(src, dst): - with open(src, 'rb') as f_in: - with open(dst, 'wb') as f_out: - f_out.write('/*\n') - for line in f_in: - line = line.decode('utf-8') - f_out.write(' * ') - for c in line: - if (ord(c) >= 0x20 and ord(c) <= 0x7e) or (c in '\x0a'): - f_out.write(c.encode('ascii')) - else: - f_out.write('\\u%04x' % ord(c)) - f_out.write(' */\n') - -def read_file(src, strip_last_nl=False): - with open(src, 'rb') as f: - data = f.read() - if len(data) > 0 and data[-1] == '\n': - data = data[:-1] - return data - -def delete_matching_files(dirpath, cb): - for fn in os.listdir(dirpath): - if os.path.isfile(os.path.join(dirpath, fn)) and cb(fn): - logger.debug('Deleting %r' % os.path.join(dirpath, fn)) - os.unlink(os.path.join(dirpath, fn)) - -def create_targz(dstfile, filelist): - # https://docs.python.org/2/library/tarfile.html#examples - - def _add(tf, fn): # recursive add - logger.debug('Adding to tar: ' + fn) - if os.path.isdir(fn): - for i in sorted(os.listdir(fn)): - _add(tf, os.path.join(fn, i)) - elif os.path.isfile(fn): - tf.add(fn) - else: - raise Exception('invalid file: %r' % fn) - - with tarfile.open(dstfile, 'w:gz') as tf: - for fn in filelist: - _add(tf, fn) - -def cstring(x): - return '"' + x + '"' # good enough for now - -# DUK_VERSION is grepped from duktape.h.in: it is needed for the -# public API and we want to avoid defining it in two places. -def get_duk_version(apiheader_filename): - r = re.compile(r'^#define\s+DUK_VERSION\s+(.*?)L?\s*$') - with open(apiheader_filename, 'rb') as f: - for line in f: - m = r.match(line) - if m is not None: - duk_version = int(m.group(1)) - duk_major = duk_version / 10000 - duk_minor = (duk_version % 10000) / 100 - duk_patch = duk_version % 100 - duk_version_formatted = '%d.%d.%d' % (duk_major, duk_minor, duk_patch) - return duk_version, duk_major, duk_minor, duk_patch, duk_version_formatted + pass - raise Exception('cannot figure out duktape version') + try: + cmd = [ 'node', '-e', 'console.log("test")' ] + res = subprocess.check_output(cmd) + if res[:4] == 'test'.encode('utf-8'): + return 'node' + except: + pass -# Option parsing + return None def main(): + sys.stderr.write('\n') + sys.stderr.write('****************************************************************************\n') + sys.stderr.write('*** Duktape python tooling is obsolete, migrate to JS-based tooling! ***\n') + sys.stderr.write('*** This tool now internally invokes the JS-based tooling. ***\n') + sys.stderr.write('*** Minimum Node.js version is 14.x. ***\n') + sys.stderr.write('****************************************************************************\n') + sys.stderr.write('\n') + time.sleep(2) + parser = optparse.OptionParser( usage='Usage: %prog [options]', - description='Prepare Duktape source files and a duk_config.h configuration header for compilation. ' + \ - 'Source files can be combined (amalgamated) or kept separate. ' + \ - 'See http://wiki.duktape.org/Configuring.html for examples.' + description='Compatibility stub for JS-based tooling' ) # Forced options from multiple sources are gathered into a shared list # so that the override order remains the same as on the command line. force_options_yaml = [] def add_force_option_yaml(option, opt, value, parser): - # XXX: check that YAML parses force_options_yaml.append(value) def add_force_option_file(option, opt, value, parser): - # XXX: check that YAML parses with open(value, 'rb') as f: force_options_yaml.append(f.read()) def add_force_option_define(option, opt, value, parser): - tmp = value.split('=') - if len(tmp) == 1: - doc = { tmp[0]: True } - elif len(tmp) == 2: - doc = { tmp[0]: tmp[1] } + defname, eq, defval = value.partition('=') + if not eq: + doc = { defname: True } else: - raise Exception('invalid option value: %r' % value) + defname, paren, defargs = defname.partition('(') + if not paren: + doc = { defname: defval } + else: + doc = { defname: { 'verbatim': '#define %s%s%s %s' % (defname, paren, defargs, defval) } } force_options_yaml.append(yaml.safe_dump(doc)) def add_force_option_undefine(option, opt, value, parser): tmp = value.split('=') @@ -209,6 +83,10 @@ def main(): line = line[:-1] fixup_header_lines.append(line) + # Log level options. + parser.add_option('--quiet', dest='quiet', action='store_true', default=False, help='Suppress info messages (show warnings)') + parser.add_option('--verbose', dest='verbose', action='store_true', default=False, help='Show verbose debug messages') + # Options for configure.py tool itself. parser.add_option('--source-directory', dest='source_directory', default=None, help='Directory with raw input sources (defaulted based on configure.py script path)') parser.add_option('--output-directory', dest='output_directory', default=None, help='Directory for output files (created automatically if it doesn\'t exist, reused if safe)') @@ -233,12 +111,34 @@ def main(): parser.add_option('--unicode-data', dest='unicode_data', default=None, help='Provide custom UnicodeData.txt') parser.add_option('--special-casing', dest='special_casing', default=None, help='Provide custom SpecialCasing.txt') - # Options forwarded to genconfig.py. - genconfig.add_genconfig_optparse_options(parser) + # Options for genconfig.py. + parser.add_option('--config-metadata', dest='config_metadata', default=None, help='metadata directory (defaulted based on configure.py script path)') + parser.add_option('--platform', dest='platform', default=None, help='platform (default is autodetect)') + parser.add_option('--compiler', dest='compiler', default=None, help='compiler (default is autodetect)') + parser.add_option('--architecture', dest='architecture', default=None, help='architecture (default is autodetec)') + parser.add_option('--c99-types-only', dest='c99_types_only', action='store_true', default=False, help='assume C99 types, no legacy type detection') + parser.add_option('--dll', dest='dll', action='store_true', default=False, help='dll build of Duktape, affects symbol visibility macros especially on Windows') + parser.add_option('--support-feature-options', dest='support_feature_options', action='store_true', default=False, help=optparse.SUPPRESS_HELP) + parser.add_option('--emit-legacy-feature-check', dest='emit_legacy_feature_check', action='store_true', default=False, help='emit preprocessor checks to reject legacy feature options (DUK_OPT_xxx)') + parser.add_option('--emit-config-sanity-check', dest='emit_config_sanity_check', action='store_true', default=False, help='emit preprocessor checks for config option consistency (DUK_USE_xxx)') + parser.add_option('--omit-removed-config-options', dest='omit_removed_config_options', action='store_true', default=False, help='omit removed config options from generated headers') + parser.add_option('--omit-deprecated-config-options', dest='omit_deprecated_config_options', action='store_true', default=False, help='omit deprecated config options from generated headers') + parser.add_option('--omit-unused-config-options', dest='omit_unused_config_options', action='store_true', default=False, help='omit unused config options from generated headers') + parser.add_option('--add-active-defines-macro', dest='add_active_defines_macro', action='store_true', default=False, help='add DUK_ACTIVE_DEFINES macro, for development only') + parser.add_option('--define', type='string', metavar='OPTION', dest='force_options_yaml', action='callback', callback=add_force_option_define, default=force_options_yaml, help='force #define option using a C compiler like syntax, e.g. "--define DUK_USE_DEEP_C_STACK" or "--define DUK_USE_TRACEBACK_DEPTH=10"') + parser.add_option('-D', type='string', metavar='OPTION', dest='force_options_yaml', action='callback', callback=add_force_option_define, default=force_options_yaml, help='synonym for --define, e.g. "-DDUK_USE_DEEP_C_STACK" or "-DDUK_USE_TRACEBACK_DEPTH=10"') + parser.add_option('--undefine', type='string', metavar='OPTION', dest='force_options_yaml', action='callback', callback=add_force_option_undefine, default=force_options_yaml, help='force #undef option using a C compiler like syntax, e.g. "--undefine DUK_USE_DEEP_C_STACK"') + parser.add_option('-U', type='string', metavar='OPTION', dest='force_options_yaml', action='callback', callback=add_force_option_undefine, default=force_options_yaml, help='synonym for --undefine, e.g. "-UDUK_USE_DEEP_C_STACK"') + parser.add_option('--option-yaml', type='string', metavar='YAML', dest='force_options_yaml', action='callback', callback=add_force_option_yaml, default=force_options_yaml, help='force option(s) using inline YAML (e.g. --option-yaml "DUK_USE_DEEP_C_STACK: true")') + parser.add_option('--option-file', type='string', metavar='FILENAME', dest='force_options_yaml', action='callback', callback=add_force_option_file, default=force_options_yaml, help='YAML file(s) providing config option overrides') + parser.add_option('--fixup-file', type='string', metavar='FILENAME', dest='fixup_header_lines', action='callback', callback=add_fixup_header_file, default=fixup_header_lines, help='C header snippet file(s) to be appended to generated header, useful for manual option fixups') + parser.add_option('--fixup-line', type='string', metavar='LINE', dest='fixup_header_lines', action='callback', callback=add_fixup_header_line, default=fixup_header_lines, help='C header fixup line to be appended to generated header (e.g. --fixup-line "#define DUK_USE_FASTINT")') + parser.add_option('--sanity-warning', dest='sanity_strict', action='store_false', default=True, help='emit a warning instead of #error for option sanity check issues') + parser.add_option('--use-cpp-warning', dest='use_cpp_warning', action='store_true', default=False, help='emit a (non-portable) #warning when appropriate') + parser.add_option('--nodejs-command', dest='nodejs_command', default=None, help='Force Node.js command name') - # Log level options. - parser.add_option('--quiet', dest='quiet', action='store_true', default=False, help='Suppress info messages (show warnings)') - parser.add_option('--verbose', dest='verbose', action='store_true', default=False, help='Show verbose debug messages') + entry_cwd = os.getcwd() + script_path = sys.path[0] # http://stackoverflow.com/questions/4934806/how-can-i-find-scripts-directory-with-python (opts, args) = parser.parse_args() if len(args) > 0: @@ -247,745 +147,76 @@ def main(): if opts.obsolete_builtin_metadata is not None: raise Exception('--user-builtin-metadata has been removed, use --builtin-file instead') - # Log level. - forward_loglevel = [] - if opts.quiet: - logger.setLevel(logging.WARNING) - forward_loglevel = [ '--quiet' ] - elif opts.verbose: - logger.setLevel(logging.DEBUG) - forward_loglevel = [ '--verbose' ] - - # Figure out directories, git info, etc - - entry_cwd = os.getcwd() - script_path = sys.path[0] # http://stackoverflow.com/questions/4934806/how-can-i-find-scripts-directory-with-python - - def default_from_script_path(optname, orig, alternatives): - if orig is not None: - orig = os.path.abspath(orig) - if os.path.exists(orig): - logger.debug(optname + ' ' + orig) - return orig - else: - raise Exception('invalid argument to ' + optname) - for alt in alternatives: - cand = os.path.abspath(os.path.join(script_path, '..', alt)) - if os.path.exists(cand): - logger.debug('default ' + optname + ' to ' + cand) - return cand - raise Exception('no ' + optname + ' and cannot default based on script path') - - if opts.output_directory is None: - raise Exception('missing --output-directory') - opts.output_directory = os.path.abspath(opts.output_directory) - outdir = opts.output_directory - - opts.source_directory = default_from_script_path('--source-directory', opts.source_directory, [ 'src-input' ]) - srcdir = opts.source_directory - - opts.config_metadata = default_from_script_path('--config-metadata', opts.config_metadata, [ 'config' ]) - - opts.license_file = default_from_script_path('--license-file', opts.license_file, [ 'LICENSE.txt' ]) - license_file = opts.license_file - - opts.authors_file = default_from_script_path('--authors-file', opts.authors_file, [ 'AUTHORS.rst' ]) - authors_file = opts.authors_file - - duk_dist_meta = None - if opts.duk_dist_meta is not None: - with open(opts.duk_dist_meta, 'rb') as f: - duk_dist_meta = json.loads(f.read()) - - duk_version, duk_major, duk_minor, duk_patch, duk_version_formatted = \ - get_duk_version(os.path.join(srcdir, 'duktape.h.in')) - - git_commit = None - git_branch = None - git_describe = None - - if duk_dist_meta is not None: - git_commit = duk_dist_meta['git_commit'] - git_branch = duk_dist_meta['git_branch'] - git_describe = duk_dist_meta['git_describe'] - - if opts.git_commit is not None: - git_commit = opts.git_commit - if opts.git_describe is not None: - git_describe = opts.git_describe - if opts.git_branch is not None: - git_branch = opts.git_branch - - if git_commit is None: - logger.debug('Git commit not specified, autodetect from current directory') - git_commit = exec_get_stdout([ 'git', 'rev-parse', 'HEAD' ], default='external').strip() - if git_describe is None: - logger.debug('Git describe not specified, autodetect from current directory') - git_describe = exec_get_stdout([ 'git', 'describe', '--always', '--dirty' ], default='external').strip() - if git_branch is None: - logger.debug('Git branch not specified, autodetect from current directory') - git_branch = exec_get_stdout([ 'git', 'rev-parse', '--abbrev-ref', 'HEAD' ], default='external').strip() - - git_commit = str(git_commit) - git_describe = str(git_describe) - git_branch = str(git_branch) - - git_commit_cstring = cstring(git_commit) - git_describe_cstring = cstring(git_describe) - git_branch_cstring = cstring(git_branch) - - if opts.unicode_data is None: - unicode_data = os.path.join(srcdir, 'UnicodeData.txt') - else: - unicode_data = opts.unicode_data - if opts.special_casing is None: - special_casing = os.path.join(srcdir, 'SpecialCasing.txt') + if opts.nodejs_command is None: + nodejs_command = detect_nodejs() else: - special_casing = opts.special_casing - - logger.info('Configuring Duktape version %s, commit %s, describe %s, branch %s' % \ - (duk_version_formatted, git_commit, git_describe, git_branch)) - logger.info(' - source input directory: ' + opts.source_directory) - logger.info(' - license file: ' + opts.license_file) - logger.info(' - authors file: ' + opts.authors_file) - logger.info(' - config metadata directory: ' + opts.config_metadata) - logger.info(' - output directory: ' + opts.output_directory) - - # Create output directory. If the directory already exists, reuse it but - # only when it's safe to do so, i.e. it contains only known output files. - allow_outdir_reuse = True - outdir_whitelist = [ 'duk_config.h', 'duktape.c', 'duktape.h', 'duk_source_meta.json' ] - if os.path.exists(outdir): - if not allow_outdir_reuse: - raise Exception('configure target directory %s already exists, please delete it first' % repr(outdir)) - for fn in os.listdir(outdir): - if fn == '.' or fn == '..' or (fn in outdir_whitelist and os.path.isfile(os.path.join(outdir, fn))): - continue - else: - raise Exception('configure target directory %s already exists, cannot reuse because it contains unknown files such as %s' % (repr(outdir), repr(fn))) - logger.info('Reusing output directory (already exists but contains only safe, known files)') - for fn in outdir_whitelist: - if os.path.isfile(os.path.join(outdir, fn)): - os.unlink(os.path.join(outdir, fn)) - else: - logger.debug('Output directory doesn\'t exist, create it') - os.mkdir(outdir) - - # Temporary directory. - tempdir = tempfile.mkdtemp(prefix='tmp-duk-prepare-') - atexit.register(shutil.rmtree, tempdir) - mkdir(os.path.join(tempdir, 'src')) - logger.debug('Using temporary directory %r' % tempdir) - - # Separate sources are mostly copied as is at present. - copy_files([ - 'duk_alloc_default.c', - 'duk_api_internal.h', - 'duk_api_stack.c', - 'duk_api_heap.c', - 'duk_api_buffer.c', - 'duk_api_call.c', - 'duk_api_codec.c', - 'duk_api_compile.c', - 'duk_api_bytecode.c', - 'duk_api_inspect.c', - 'duk_api_memory.c', - 'duk_api_object.c', - 'duk_api_random.c', - 'duk_api_string.c', - 'duk_api_time.c', - 'duk_api_debug.c', - 'duk_bi_array.c', - 'duk_bi_boolean.c', - 'duk_bi_buffer.c', - 'duk_bi_cbor.c', - 'duk_bi_date.c', - 'duk_bi_date_unix.c', - 'duk_bi_date_windows.c', - 'duk_bi_duktape.c', - 'duk_bi_encoding.c', - 'duk_bi_error.c', - 'duk_bi_function.c', - 'duk_bi_global.c', - 'duk_bi_json.c', - 'duk_bi_math.c', - 'duk_bi_number.c', - 'duk_bi_object.c', - 'duk_bi_performance.c', - 'duk_bi_pointer.c', - 'duk_bi_protos.h', - 'duk_bi_reflect.c', - 'duk_bi_regexp.c', - 'duk_bi_string.c', - 'duk_bi_promise.c', - 'duk_bi_proxy.c', - 'duk_bi_symbol.c', - 'duk_bi_thread.c', - 'duk_bi_thrower.c', - 'duk_dblunion.h', - 'duk_debug_fixedbuffer.c', - 'duk_debug.h', - 'duk_debug_macros.c', - 'duk_debug_vsnprintf.c', - 'duk_debugger.c', - 'duk_debugger.h', - 'duk_error_augment.c', - 'duk_error.h', - 'duk_error_longjmp.c', - 'duk_error_macros.c', - 'duk_error_misc.c', - 'duk_error_throw.c', - 'duk_fltunion.h', - 'duk_forwdecl.h', - 'duk_harray.h', - 'duk_hboundfunc.h', - 'duk_hbuffer_alloc.c', - 'duk_hbuffer_assert.c', - 'duk_hbuffer.h', - 'duk_hbuffer_ops.c', - 'duk_hbufobj.h', - 'duk_hbufobj_misc.c', - 'duk_hcompfunc.h', - 'duk_heap_alloc.c', - 'duk_heap.h', - 'duk_heap_hashstring.c', - 'duk_heaphdr.h', - 'duk_heaphdr_assert.c', - 'duk_heap_finalize.c', - 'duk_heap_markandsweep.c', - 'duk_heap_memory.c', - 'duk_heap_misc.c', - 'duk_heap_refcount.c', - 'duk_heap_stringcache.c', - 'duk_heap_stringtable.c', - 'duk_hnatfunc.h', - 'duk_hobject_alloc.c', - 'duk_hobject_assert.c', - 'duk_hobject_class.c', - 'duk_hobject_enum.c', - 'duk_hobject.h', - 'duk_hobject_misc.c', - 'duk_hobject_pc2line.c', - 'duk_hobject_props.c', - 'duk_hproxy.h', - 'duk_hstring.h', - 'duk_hstring_assert.c', - 'duk_hstring_misc.c', - 'duk_hthread_alloc.c', - 'duk_hthread_builtins.c', - 'duk_hthread.h', - 'duk_hthread_misc.c', - 'duk_hthread_stacks.c', - 'duk_henv.h', - 'duk_internal.h', - 'duk_jmpbuf.h', - 'duk_exception.h', - 'duk_js_arith.c', - 'duk_js_bytecode.h', - 'duk_js_call.c', - 'duk_js_compiler.c', - 'duk_js_compiler.h', - 'duk_js_executor.c', - 'duk_js.h', - 'duk_json.h', - 'duk_js_ops.c', - 'duk_js_var.c', - 'duk_lexer.c', - 'duk_lexer.h', - 'duk_numconv.c', - 'duk_numconv.h', - 'duk_refcount.h', - 'duk_regexp_compiler.c', - 'duk_regexp_executor.c', - 'duk_regexp.h', - 'duk_tval.c', - 'duk_tval.h', - 'duk_unicode.h', - 'duk_unicode_support.c', - 'duk_unicode_tables.c', - 'duk_util.h', - 'duk_util_bitdecoder.c', - 'duk_util_bitencoder.c', - 'duk_util_hashbytes.c', - 'duk_util_tinyrandom.c', - 'duk_util_bufwriter.c', - 'duk_util_double.c', - 'duk_util_cast.c', - 'duk_util_memory.c', - 'duk_util_memrw.c', - 'duk_util_misc.c', - 'duk_selftest.c', - 'duk_selftest.h', - 'duk_strings.h', - 'duk_replacements.c', - 'duk_replacements.h' - ], srcdir, os.path.join(tempdir, 'src')) - - # Build temp versions of LICENSE.txt and AUTHORS.rst for embedding into - # autogenerated C/H files. - - copy_and_cquote(license_file, os.path.join(tempdir, 'LICENSE.txt.tmp')) - copy_and_cquote(authors_file, os.path.join(tempdir, 'AUTHORS.rst.tmp')) - - # Scan used stridx, bidx, config options, etc. - - res = exec_get_stdout([ - sys.executable, - os.path.join(script_path, 'scan_used_stridx_bidx.py') - ] + glob.glob(os.path.join(srcdir, '*.c')) \ - + glob.glob(os.path.join(srcdir, '*.h')) \ - + glob.glob(os.path.join(srcdir, '*.h.in')) - ) - with open(os.path.join(tempdir, 'duk_used_stridx_bidx_defs.json.tmp'), 'wb') as f: - f.write(res) - - # Create a duk_config.h. - # XXX: might be easier to invoke genconfig directly, but there are a few - # options which currently conflict (output file, git commit info, etc). - def forward_genconfig_options(): - res = [] - res += [ '--metadata', os.path.abspath(opts.config_metadata) ] # rename option, --config-metadata => --metadata - if opts.platform is not None: - res += [ '--platform', opts.platform ] - if opts.compiler is not None: - res += [ '--compiler', opts.compiler ] - if opts.architecture is not None: - res += [ '--architecture', opts.architecture ] - if opts.c99_types_only: - res += [ '--c99-types-only' ] - if opts.dll: - res += [ '--dll' ] - if opts.support_feature_options: - res += [ '--support-feature-options' ] - if opts.emit_legacy_feature_check: - res += [ '--emit-legacy-feature-check' ] - if opts.emit_config_sanity_check: - res += [ '--emit-config-sanity-check' ] - if opts.omit_removed_config_options: - res += [ '--omit-removed-config-options' ] - if opts.omit_deprecated_config_options: - res += [ '--omit-deprecated-config-options' ] - if opts.omit_unused_config_options: - res += [ '--omit-unused-config-options' ] - if opts.add_active_defines_macro: - res += [ '--add-active-defines-macro' ] - if len(opts.force_options_yaml) > 0: - # Use temporary files so that large option sets don't create - # excessively large commands. - for idx,i in enumerate(opts.force_options_yaml): - tmpfn = os.path.join(tempdir, 'genconfig%d.yaml' % idx) - with open(tmpfn, 'wb') as f: - f.write(i) - with open(tmpfn, 'rb') as f: - logger.debug(f.read()) - res += [ '--option-file', tmpfn ] - for i in opts.fixup_header_lines: - res += [ '--fixup-line', i ] - if not opts.sanity_strict: - res += [ '--sanity-warning' ] - if opts.use_cpp_warning: - res += [ '--use-cpp-warning' ] - return res + nodejs_command = opts.nodejs_command + if nodejs_command is None: + raise Exception('failed to detect Node.js, override with --nodejs-command') + + duktool_path = None + for fn in [ + os.path.join(script_path, 'duktool.js'), + os.path.join(script_path, '..', 'src-tools', 'index.js'), + os.path.join(script_path, '..', 'src-tools', 'duktool.js') + ]: + if os.path.isfile(fn): + duktool_path = fn + break + if duktool_path is None: + raise Exception('could not find duktool.js or src-tools/index.js') cmd = [ - sys.executable, os.path.join(script_path, 'genconfig.py'), - '--output', os.path.join(tempdir, 'duk_config.h.tmp'), - '--output-active-options', os.path.join(tempdir, 'duk_config_active_options.json'), - '--git-commit', git_commit, '--git-describe', git_describe, '--git-branch', git_branch, - '--used-stridx-metadata', os.path.join(tempdir, 'duk_used_stridx_bidx_defs.json.tmp') + nodejs_command, + duktool_path, + 'configure' ] - cmd += forward_genconfig_options() - cmd += [ - 'duk-config-header' - ] + forward_loglevel - logger.debug(repr(cmd)) - exec_print_stdout(cmd) - - copy_file(os.path.join(tempdir, 'duk_config.h.tmp'), os.path.join(outdir, 'duk_config.h')) - - # Build duktape.h from parts, with some git-related replacements. - # The only difference between single and separate file duktape.h - # is the internal DUK_SINGLE_FILE define. - # - # Newline after 'i \': - # http://stackoverflow.com/questions/25631989/sed-insert-line-command-osx - copy_and_replace(os.path.join(srcdir, 'duktape.h.in'), os.path.join(tempdir, 'duktape.h'), { - '@DUK_SINGLE_FILE@': '#define DUK_SINGLE_FILE', - '@LICENSE_TXT@': read_file(os.path.join(tempdir, 'LICENSE.txt.tmp'), strip_last_nl=True), - '@AUTHORS_RST@': read_file(os.path.join(tempdir, 'AUTHORS.rst.tmp'), strip_last_nl=True), - '@DUK_VERSION_FORMATTED@': duk_version_formatted, - '@GIT_COMMIT@': git_commit, - '@GIT_COMMIT_CSTRING@': git_commit_cstring, - '@GIT_DESCRIBE@': git_describe, - '@GIT_DESCRIBE_CSTRING@': git_describe_cstring, - '@GIT_BRANCH@': git_branch, - '@GIT_BRANCH_CSTRING@': git_branch_cstring - }) - - if opts.separate_sources: - # keep the line so line numbers match between the two variant headers - copy_and_replace(os.path.join(tempdir, 'duktape.h'), os.path.join(outdir, 'duktape.h'), { - '#define DUK_SINGLE_FILE': '#undef DUK_SINGLE_FILE' - }) + if opts.output_directory is not None: + cmd += [ '--output-directory', opts.output_directory ] + if opts.source_directory is not None: + cmd += [ '--source-directory', opts.source_directory ] else: - copy_file(os.path.join(tempdir, 'duktape.h'), os.path.join(outdir, 'duktape.h')) - - # Autogenerated strings and built-in files - # - # There are currently no profile specific variants of strings/builtins, but - # this will probably change when functions are added/removed based on profile. - - cmd = [ - sys.executable, - os.path.join(script_path, 'genbuiltins.py'), - ] - cmd += [ - '--git-commit', git_commit, - '--git-branch', git_branch, - '--git-describe', git_describe, - '--duk-version', str(duk_version) - ] - cmd += [ - '--used-stridx-metadata', os.path.join(tempdir, 'duk_used_stridx_bidx_defs.json.tmp'), - '--strings-metadata', os.path.join(srcdir, 'strings.yaml'), - '--objects-metadata', os.path.join(srcdir, 'builtins.yaml'), - '--active-options', os.path.join(tempdir, 'duk_config_active_options.json'), - '--out-header', os.path.join(tempdir, 'src', 'duk_builtins.h'), - '--out-source', os.path.join(tempdir, 'src', 'duk_builtins.c'), - '--out-metadata-json', os.path.join(tempdir, 'genbuiltins_metadata.json') - ] - cmd.append('--ram-support') # enable by default - if opts.rom_support: - # ROM string/object support is not enabled by default because - # it increases the generated duktape.c considerably. - logger.debug('Enabling --rom-support for genbuiltins.py') - cmd.append('--rom-support') - if opts.rom_auto_lightfunc: - logger.debug('Enabling --rom-auto-lightfunc for genbuiltins.py') - cmd.append('--rom-auto-lightfunc') - for fn in opts.builtin_files: - logger.debug('Forwarding --builtin-file %s' % fn) - cmd.append('--builtin-file') - cmd.append(fn) - cmd += forward_loglevel - logger.debug(repr(cmd)) - exec_print_stdout(cmd) - - # Autogenerated Unicode files - # - # Note: not all of the generated headers are used. For instance, the - # match table for "WhiteSpace-Z" is not used, because a custom piece - # of code handles that particular match. - # - # UnicodeData.txt contains ranges expressed like this: - # - # 4E00;;Lo;0;L;;;;;N;;;;; - # 9FCB;;Lo;0;L;;;;;N;;;;; - # - # These are currently decoded into individual characters as a prestep. - # - # For IDPART: - # UnicodeCombiningMark -> categories Mn, Mc - # UnicodeDigit -> categories Nd - # UnicodeConnectorPunctuation -> categories Pc - - # Whitespace (unused now) - WHITESPACE_INCL='Zs' # USP = Any other Unicode space separator - WHITESPACE_EXCL='NONE' - - # Unicode letter (unused now) - LETTER_INCL='Lu,Ll,Lt,Lm,Lo' - LETTER_EXCL='NONE' - LETTER_NOA_INCL='Lu,Ll,Lt,Lm,Lo' - LETTER_NOA_EXCL='ASCII' - LETTER_NOABMP_INCL=LETTER_NOA_INCL - LETTER_NOABMP_EXCL='ASCII,NONBMP' - - # Identifier start - # E5 Section 7.6 - IDSTART_INCL='Lu,Ll,Lt,Lm,Lo,Nl,0024,005F' - IDSTART_EXCL='NONE' - IDSTART_NOA_INCL='Lu,Ll,Lt,Lm,Lo,Nl,0024,005F' - IDSTART_NOA_EXCL='ASCII' - IDSTART_NOABMP_INCL=IDSTART_NOA_INCL - IDSTART_NOABMP_EXCL='ASCII,NONBMP' - - # Identifier start - Letter: allows matching of (rarely needed) 'Letter' - # production space efficiently with the help of IdentifierStart. The - # 'Letter' production is only needed in case conversion of Greek final - # sigma. - IDSTART_MINUS_LETTER_INCL=IDSTART_NOA_INCL - IDSTART_MINUS_LETTER_EXCL='Lu,Ll,Lt,Lm,Lo' - IDSTART_MINUS_LETTER_NOA_INCL=IDSTART_NOA_INCL - IDSTART_MINUS_LETTER_NOA_EXCL='Lu,Ll,Lt,Lm,Lo,ASCII' - IDSTART_MINUS_LETTER_NOABMP_INCL=IDSTART_NOA_INCL - IDSTART_MINUS_LETTER_NOABMP_EXCL='Lu,Ll,Lt,Lm,Lo,ASCII,NONBMP' - - # Identifier start - Identifier part - # E5 Section 7.6: IdentifierPart, but remove IdentifierStart (already above) - IDPART_MINUS_IDSTART_INCL='Lu,Ll,Lt,Lm,Lo,Nl,0024,005F,Mn,Mc,Nd,Pc,200C,200D' - IDPART_MINUS_IDSTART_EXCL='Lu,Ll,Lt,Lm,Lo,Nl,0024,005F' - IDPART_MINUS_IDSTART_NOA_INCL='Lu,Ll,Lt,Lm,Lo,Nl,0024,005F,Mn,Mc,Nd,Pc,200C,200D' - IDPART_MINUS_IDSTART_NOA_EXCL='Lu,Ll,Lt,Lm,Lo,Nl,0024,005F,ASCII' - IDPART_MINUS_IDSTART_NOABMP_INCL=IDPART_MINUS_IDSTART_NOA_INCL - IDPART_MINUS_IDSTART_NOABMP_EXCL='Lu,Ll,Lt,Lm,Lo,Nl,0024,005F,ASCII,NONBMP' - - logger.debug('Expand UnicodeData.txt ranges') - - exec_print_stdout([ - sys.executable, - os.path.join(script_path, 'prepare_unicode_data.py'), - '--unicode-data', unicode_data, - '--output', os.path.join(tempdir, 'UnicodeData-expanded.tmp') - ] + forward_loglevel) - - def extract_chars(incl, excl, suffix): - logger.debug('- extract_chars: %s %s %s' % (incl, excl, suffix)) - res = exec_get_stdout([ - sys.executable, - os.path.join(script_path, 'extract_chars.py'), - '--unicode-data', os.path.join(tempdir, 'UnicodeData-expanded.tmp'), - '--include-categories', incl, - '--exclude-categories', excl, - '--out-source', os.path.join(tempdir, 'duk_unicode_%s.c.tmp' % suffix), - '--out-header', os.path.join(tempdir, 'duk_unicode_%s.h.tmp' % suffix), - '--table-name', 'duk_unicode_%s' % suffix - ]) - with open(os.path.join(tempdir, suffix + '.txt'), 'wb') as f: - f.write(res) - - def extract_caseconv(): - logger.debug('- extract_caseconv case conversion') - res = exec_get_stdout([ - sys.executable, - os.path.join(script_path, 'extract_caseconv.py'), - '--command=caseconv_bitpacked', - '--unicode-data', os.path.join(tempdir, 'UnicodeData-expanded.tmp'), - '--special-casing', special_casing, - '--out-source', os.path.join(tempdir, 'duk_unicode_caseconv.c.tmp'), - '--out-header', os.path.join(tempdir, 'duk_unicode_caseconv.h.tmp'), - '--table-name-lc', 'duk_unicode_caseconv_lc', - '--table-name-uc', 'duk_unicode_caseconv_uc' - ]) - with open(os.path.join(tempdir, 'caseconv.txt'), 'wb') as f: - f.write(res) - - logger.debug('- extract_caseconv canon lookup') - res = exec_get_stdout([ - sys.executable, - os.path.join(script_path, 'extract_caseconv.py'), - '--command=re_canon_lookup', - '--unicode-data', os.path.join(tempdir, 'UnicodeData-expanded.tmp'), - '--special-casing', special_casing, - '--out-source', os.path.join(tempdir, 'duk_unicode_re_canon_lookup.c.tmp'), - '--out-header', os.path.join(tempdir, 'duk_unicode_re_canon_lookup.h.tmp'), - '--table-name-re-canon-lookup', 'duk_unicode_re_canon_lookup' - ]) - with open(os.path.join(tempdir, 'caseconv_re_canon_lookup.txt'), 'wb') as f: - f.write(res) - - logger.debug('- extract_caseconv canon bitmap') - res = exec_get_stdout([ - sys.executable, - os.path.join(script_path, 'extract_caseconv.py'), - '--command=re_canon_bitmap', - '--unicode-data', os.path.join(tempdir, 'UnicodeData-expanded.tmp'), - '--special-casing', special_casing, - '--out-source', os.path.join(tempdir, 'duk_unicode_re_canon_bitmap.c.tmp'), - '--out-header', os.path.join(tempdir, 'duk_unicode_re_canon_bitmap.h.tmp'), - '--table-name-re-canon-bitmap', 'duk_unicode_re_canon_bitmap' - ]) - with open(os.path.join(tempdir, 'caseconv_re_canon_bitmap.txt'), 'wb') as f: - f.write(res) - - # XXX: Now with configure.py part of the distributable, could generate - # only those Unicode tables needed by desired configuration (e.g. BMP-only - # tables if BMP-only was enabled). - # XXX: Improve Unicode preparation performance; it consumes most of the - # source preparation time. - - logger.debug('Create Unicode tables for codepoint classes') - extract_chars(WHITESPACE_INCL, WHITESPACE_EXCL, 'ws') - extract_chars(LETTER_INCL, LETTER_EXCL, 'let') - extract_chars(LETTER_NOA_INCL, LETTER_NOA_EXCL, 'let_noa') - extract_chars(LETTER_NOABMP_INCL, LETTER_NOABMP_EXCL, 'let_noabmp') - extract_chars(IDSTART_INCL, IDSTART_EXCL, 'ids') - extract_chars(IDSTART_NOA_INCL, IDSTART_NOA_EXCL, 'ids_noa') - extract_chars(IDSTART_NOABMP_INCL, IDSTART_NOABMP_EXCL, 'ids_noabmp') - extract_chars(IDSTART_MINUS_LETTER_INCL, IDSTART_MINUS_LETTER_EXCL, 'ids_m_let') - extract_chars(IDSTART_MINUS_LETTER_NOA_INCL, IDSTART_MINUS_LETTER_NOA_EXCL, 'ids_m_let_noa') - extract_chars(IDSTART_MINUS_LETTER_NOABMP_INCL, IDSTART_MINUS_LETTER_NOABMP_EXCL, 'ids_m_let_noabmp') - extract_chars(IDPART_MINUS_IDSTART_INCL, IDPART_MINUS_IDSTART_EXCL, 'idp_m_ids') - extract_chars(IDPART_MINUS_IDSTART_NOA_INCL, IDPART_MINUS_IDSTART_NOA_EXCL, 'idp_m_ids_noa') - extract_chars(IDPART_MINUS_IDSTART_NOABMP_INCL, IDPART_MINUS_IDSTART_NOABMP_EXCL, 'idp_m_ids_noabmp') - - logger.debug('Create Unicode tables for case conversion') - extract_caseconv() - - logger.debug('Combine sources and clean up') - - # Inject autogenerated files into source and header files so that they are - # usable (for all profiles and define cases) directly. - # - # The injection points use a standard C preprocessor #include syntax - # (earlier these were actual includes). - - copy_and_replace(os.path.join(tempdir, 'src', 'duk_unicode.h'), os.path.join(tempdir, 'src', 'duk_unicode.h'), { - '#include "duk_unicode_ids_noa.h"': read_file(os.path.join(tempdir, 'duk_unicode_ids_noa.h.tmp'), strip_last_nl=True), - '#include "duk_unicode_ids_noabmp.h"': read_file(os.path.join(tempdir, 'duk_unicode_ids_noabmp.h.tmp'), strip_last_nl=True), - '#include "duk_unicode_ids_m_let_noa.h"': read_file(os.path.join(tempdir, 'duk_unicode_ids_m_let_noa.h.tmp'), strip_last_nl=True), - '#include "duk_unicode_ids_m_let_noabmp.h"': read_file(os.path.join(tempdir, 'duk_unicode_ids_m_let_noabmp.h.tmp'), strip_last_nl=True), - '#include "duk_unicode_idp_m_ids_noa.h"': read_file(os.path.join(tempdir, 'duk_unicode_idp_m_ids_noa.h.tmp'), strip_last_nl=True), - '#include "duk_unicode_idp_m_ids_noabmp.h"': read_file(os.path.join(tempdir, 'duk_unicode_idp_m_ids_noabmp.h.tmp'), strip_last_nl=True), - '#include "duk_unicode_caseconv.h"': read_file(os.path.join(tempdir, 'duk_unicode_caseconv.h.tmp'), strip_last_nl=True), - '#include "duk_unicode_re_canon_lookup.h"': read_file(os.path.join(tempdir, 'duk_unicode_re_canon_lookup.h.tmp'), strip_last_nl=True), - '#include "duk_unicode_re_canon_bitmap.h"': read_file(os.path.join(tempdir, 'duk_unicode_re_canon_bitmap.h.tmp'), strip_last_nl=True) - }) - - copy_and_replace(os.path.join(tempdir, 'src', 'duk_unicode_tables.c'), os.path.join(tempdir, 'src', 'duk_unicode_tables.c'), { - '#include "duk_unicode_ids_noa.c"': read_file(os.path.join(tempdir, 'duk_unicode_ids_noa.c.tmp'), strip_last_nl=True), - '#include "duk_unicode_ids_noabmp.c"': read_file(os.path.join(tempdir, 'duk_unicode_ids_noabmp.c.tmp'), strip_last_nl=True), - '#include "duk_unicode_ids_m_let_noa.c"': read_file(os.path.join(tempdir, 'duk_unicode_ids_m_let_noa.c.tmp'), strip_last_nl=True), - '#include "duk_unicode_ids_m_let_noabmp.c"': read_file(os.path.join(tempdir, 'duk_unicode_ids_m_let_noabmp.c.tmp'), strip_last_nl=True), - '#include "duk_unicode_idp_m_ids_noa.c"': read_file(os.path.join(tempdir, 'duk_unicode_idp_m_ids_noa.c.tmp'), strip_last_nl=True), - '#include "duk_unicode_idp_m_ids_noabmp.c"': read_file(os.path.join(tempdir, 'duk_unicode_idp_m_ids_noabmp.c.tmp'), strip_last_nl=True), - '#include "duk_unicode_caseconv.c"': read_file(os.path.join(tempdir, 'duk_unicode_caseconv.c.tmp'), strip_last_nl=True), - '#include "duk_unicode_re_canon_lookup.c"': read_file(os.path.join(tempdir, 'duk_unicode_re_canon_lookup.c.tmp'), strip_last_nl=True), - '#include "duk_unicode_re_canon_bitmap.c"': read_file(os.path.join(tempdir, 'duk_unicode_re_canon_bitmap.c.tmp'), strip_last_nl=True) - }) - - # Create a combined source file, duktape.c, into a separate combined source - # directory. This allows user to just include "duktape.c", "duktape.h", and - # "duk_config.h" into a project and maximizes inlining and size optimization - # opportunities even with older compilers. Because some projects include - # these files into their repository, the result should be deterministic and - # diffable. Also, it must retain __FILE__/__LINE__ behavior through - # preprocessor directives. Whitespace and comments can be stripped as long - # as the other requirements are met. For some users it's preferable *not* - # to use #line directives in the combined source, so a separate variant is - # created for that, see: https://github.com/svaarala/duktape/pull/363. - - def create_source_prologue(license_file, authors_file): - res = [] - - # Because duktape.c/duktape.h/duk_config.h are often distributed or - # included in project sources as is, add a license reminder and - # Duktape version information to the duktape.c header (duktape.h - # already contains them). - - duk_major = duk_version / 10000 - duk_minor = duk_version / 100 % 100 - duk_patch = duk_version % 100 - res.append('/*') - res.append(' * Single source autogenerated distributable for Duktape %d.%d.%d.' % (duk_major, duk_minor, duk_patch)) - res.append(' *') - res.append(' * Git commit %s (%s).' % (git_commit, git_describe)) - res.append(' * Git branch %s.' % git_branch) - res.append(' *') - res.append(' * See Duktape AUTHORS.rst and LICENSE.txt for copyright and') - res.append(' * licensing information.') - res.append(' */') - res.append('') - - # Add LICENSE.txt and AUTHORS.rst to combined source so that they're automatically - # included and are up-to-date. - - res.append('/* LICENSE.txt */') - with open(license_file, 'rb') as f: - for line in f: - res.append(line.strip()) - res.append('') - res.append('/* AUTHORS.rst */') - with open(authors_file, 'rb') as f: - for line in f: - res.append(line.strip()) - - return '\n'.join(res) + '\n' - - def select_combined_sources(): - # These files must appear before the alphabetically sorted - # ones so that static variables get defined before they're - # used. We can't forward declare them because that would - # cause C++ issues (see GH-63). When changing, verify by - # compiling with g++. - handpick = [ - 'duk_replacements.c', - 'duk_debug_macros.c', - 'duk_builtins.c', - 'duk_error_macros.c', - 'duk_unicode_support.c', - 'duk_util_memrw.c', - 'duk_util_misc.c', - 'duk_hobject_class.c' - ] - - files = [] - for fn in handpick: - files.append(fn) - - for fn in sorted(os.listdir(os.path.join(tempdir, 'src'))): - f_ext = os.path.splitext(fn)[1] - if f_ext not in [ '.c' ]: - continue - if fn in files: - continue - files.append(fn) - - res = map(lambda x: os.path.join(tempdir, 'src', x), files) - logger.debug(repr(files)) - logger.debug(repr(res)) - return res - - if opts.separate_sources: - for fn in os.listdir(os.path.join(tempdir, 'src')): - copy_file(os.path.join(tempdir, 'src', fn), os.path.join(outdir, fn)) - else: - with open(os.path.join(tempdir, 'prologue.tmp'), 'wb') as f: - f.write(create_source_prologue(os.path.join(tempdir, 'LICENSE.txt.tmp'), os.path.join(tempdir, 'AUTHORS.rst.tmp'))) - - cmd = [ - sys.executable, - os.path.join(script_path, 'combine_src.py'), - '--include-path', os.path.join(tempdir, 'src'), - '--include-exclude', 'duk_config.h', # don't inline - '--include-exclude', 'duktape.h', # don't inline - '--prologue', os.path.join(tempdir, 'prologue.tmp'), - '--output-source', os.path.join(outdir, 'duktape.c'), - '--output-metadata', os.path.join(tempdir, 'combine_src_metadata.json') - ] - if opts.line_directives: - cmd += [ '--line-directives' ] - cmd += select_combined_sources() - cmd += forward_loglevel - exec_print_stdout(cmd) - - # Merge metadata files. - - doc = { - 'type': 'duk_source_meta', - 'comment': 'Metadata for prepared Duktape sources and configuration', - 'git_commit': git_commit, - 'git_branch': git_branch, - 'git_describe': git_describe, - 'duk_version': duk_version, - 'duk_version_string': duk_version_formatted - } - with open(os.path.join(tempdir, 'genbuiltins_metadata.json'), 'rb') as f: - tmp = json.loads(f.read()) - for k in tmp.keys(): - doc[k] = tmp[k] - if opts.separate_sources: - pass - else: - with open(os.path.join(tempdir, 'combine_src_metadata.json'), 'rb') as f: - tmp = json.loads(f.read()) - for k in tmp.keys(): - doc[k] = tmp[k] - - with open(os.path.join(outdir, 'duk_source_meta.json'), 'wb') as f: - f.write(json.dumps(doc, indent=4)) - - logger.debug('Configure finished successfully') + src_dir = os.path.join(script_path, '..', 'src-input') + if os.path.isdir(src_dir) and os.path.isfile(os.path.join(src_dir, 'duktape.h.in')): + cmd += [ '--source-directory', src_dir ] + if opts.config_metadata is not None: + cmd += [ '--config-directory', opts.config_metadata ] + + forced = {} + for i in force_options_yaml: + doc = yaml.safe_load(i) + for k,v in doc.items(): + forced[k] = v + opts_fd, opts_fn = tempfile.mkstemp() + with os.fdopen(opts_fd, 'wb') as f: + f.write(yaml.safe_dump(forced).encode('utf-8')) + cmd += [ '--option-file', opts_fn ] + + fixup_fd, fixup_fn = tempfile.mkstemp() + with os.fdopen(fixup_fd, 'wb') as f: + f.write(('\n'.join(fixup_header_lines) + '\n').encode('utf-8')) + cmd += [ '--fixup-file', fixup_fn ] + + for i in opts.builtin_files: + cmd += [ '--builtin-file', i ] + + if opts.line_directives: + cmd += [ '--line-directives' ] + + if opts.platform is not None: + cmd += [ '--platform', opts.platform ] + if opts.compiler is not None: + cmd += [ '--compiler', opts.compiler ] + if opts.architecture is not None: + cmd += [ '--architecture', opts.architecture ] + + if opts.dll: + cmd += [ '--dll' ] + if opts.c99_types_only: + cmd += [ '--c99-types-only' ] + + sys.stderr.write('*** Executing JS-based tooling with command: ' + repr(cmd) + '\n\n') + subprocess.check_call(cmd) if __name__ == '__main__': main() diff --git a/util/dist.py b/util/dist.py index d68628ca..56835839 100644 --- a/util/dist.py +++ b/util/dist.py @@ -1,183 +1,38 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python # -# Create a distributable Duktape package into a dist directory. The contents -# of this directory can then be packaged into a source distributable. +# Compatibility stub which now executes JS-based tooling. # - -import logging -import sys -logging.basicConfig(level=logging.INFO, stream=sys.stdout, format='%(name)-21s %(levelname)-7s %(message)s') -logger = logging.getLogger('dist.py') -logger.setLevel(logging.INFO) +# Should be Python2 and Python3 compatible. import os -import re -import json -import shutil -import glob +import sys +import time import optparse import subprocess -import logging - -# Helpers. -def exec_get_stdout(cmd, input=None, default=None, print_stdout=False): +def detect_nodejs(): try: - proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - ret = proc.communicate(input=input) - if print_stdout: - sys.stdout.write(ret[0]) - sys.stdout.flush() - if proc.returncode != 0: - sys.stdout.write(ret[1]) # print stderr on error - sys.stdout.flush() - if default is not None: - logger.warning(' command %r failed, return default' % cmd) - return default - raise Exception('command failed, return code %d: %r' % (proc.returncode, cmd)) - return ret[0] + cmd = [ 'nodejs', '-e', 'console.log("test")' ] + res = subprocess.check_output(cmd) + if res[:4] == 'test'.encode('utf-8'): + return 'nodejs' except: - if default is not None: - logger.warning('command %r failed, return default' % cmd) - return default - raise - -def exec_print_stdout(cmd, input=None): - ret = exec_get_stdout(cmd, input=input, print_stdout=True) - -def mkdir(path): - os.mkdir(path) - -def copy_file(src, dst): - with open(src, 'rb') as f_in: - with open(dst, 'wb') as f_out: - f_out.write(f_in.read()) - -def copy_files(filelist, srcdir, dstdir): - for i in filelist: - copy_file(os.path.join(srcdir, i), os.path.join(dstdir, i)) - -def copy_and_replace(src, dst, rules): - # Read and write separately to allow in-place replacement - keys = sorted(rules.keys()) - res = [] - with open(src, 'rb') as f_in: - for line in f_in: - for k in keys: - line = line.replace(k, rules[k]) - res.append(line) - with open(dst, 'wb') as f_out: - f_out.write(''.join(res)) - -def copy_and_cquote(src, dst): - with open(src, 'rb') as f_in: - with open(dst, 'wb') as f_out: - f_out.write('/*\n') - for line in f_in: - line = line.decode('utf-8') - f_out.write(' * ') - for c in line: - if (ord(c) >= 0x20 and ord(c) <= 0x7e) or (c in '\x0a'): - f_out.write(c.encode('ascii')) - else: - f_out.write('\\u%04x' % ord(c)) - f_out.write(' */\n') - -def read_file(src, strip_last_nl=False): - with open(src, 'rb') as f: - data = f.read() - if len(data) > 0 and data[-1] == '\n': - data = data[:-1] - return data - -def delete_matching_files(dirpath, cb): - for fn in os.listdir(dirpath): - if os.path.isfile(os.path.join(dirpath, fn)) and cb(fn): - logger.debug('Deleting %r' % os.path.join(dirpath, fn)) - os.unlink(os.path.join(dirpath, fn)) - #print('Deleting matching file: %r' % fn) - -def glob_files(pattern): - return glob.glob(pattern) - -def cstring(x): - return '"' + x + '"' # good enough for now + pass -# Get Duktape version number as an integer. DUK_VERSION is grepped from -# duktape.h.in: it is needed for the public API and we want to avoid -# defining it in multiple places. -def get_duk_version(): - r = re.compile(r'^#define\s+DUK_VERSION\s+(.*?)L?\s*$') - with open(os.path.join('src-input', 'duktape.h.in'), 'rb') as f: - for line in f: - m = r.match(line) - if m is not None: - duk_version = int(m.group(1)) - duk_major = duk_version / 10000 - duk_minor = (duk_version % 10000) / 100 - duk_patch = duk_version % 100 - duk_version_formatted = '%d.%d.%d' % (duk_major, duk_minor, duk_patch) - return duk_version, duk_major, duk_minor, duk_patch, duk_version_formatted - - raise Exception('cannot figure out duktape version') - -def create_dist_directories(dist): - if os.path.exists(dist): - raise Exception('dist target directory %s already exists, please delete first' % repr(dist)) - mkdir(dist) - mkdir(os.path.join(dist, 'src-input')) - mkdir(os.path.join(dist, 'tools')) - mkdir(os.path.join(dist, 'config')) - mkdir(os.path.join(dist, 'extras')) - mkdir(os.path.join(dist, 'extras', 'duk-v1-compat')) - mkdir(os.path.join(dist, 'extras', 'print-alert')) - mkdir(os.path.join(dist, 'extras', 'console')) - mkdir(os.path.join(dist, 'extras', 'logging')) - mkdir(os.path.join(dist, 'extras', 'minimal-printf')) - mkdir(os.path.join(dist, 'extras', 'module-duktape')) - mkdir(os.path.join(dist, 'extras', 'module-node')) - mkdir(os.path.join(dist, 'extras', 'alloc-pool')) - mkdir(os.path.join(dist, 'extras', 'cbor')) - mkdir(os.path.join(dist, 'polyfills')) - #mkdir(os.path.join(dist, 'doc')) # Empty, so omit - mkdir(os.path.join(dist, 'licenses')) - mkdir(os.path.join(dist, 'debugger')) - mkdir(os.path.join(dist, 'debugger', 'static')) - mkdir(os.path.join(dist, 'examples')) - mkdir(os.path.join(dist, 'examples', 'hello')) - mkdir(os.path.join(dist, 'examples', 'eval')) - mkdir(os.path.join(dist, 'examples', 'cmdline')) - mkdir(os.path.join(dist, 'examples', 'eventloop')) - mkdir(os.path.join(dist, 'examples', 'guide')) - mkdir(os.path.join(dist, 'examples', 'coffee')) - mkdir(os.path.join(dist, 'examples', 'jxpretty')) - mkdir(os.path.join(dist, 'examples', 'sandbox')) - mkdir(os.path.join(dist, 'examples', 'alloc-logging')) - mkdir(os.path.join(dist, 'examples', 'alloc-torture')) - mkdir(os.path.join(dist, 'examples', 'alloc-hybrid')) - mkdir(os.path.join(dist, 'examples', 'debug-trans-socket')) - mkdir(os.path.join(dist, 'examples', 'debug-trans-dvalue')) - mkdir(os.path.join(dist, 'examples', 'codepage-conv')) - mkdir(os.path.join(dist, 'examples', 'dummy-date-provider')) - mkdir(os.path.join(dist, 'examples', 'cpp-exceptions')) - -# Spot check a few files to ensure we're in Duktape repo root, as dist only -# works from there. - -def check_cwd_duktape_repo_root(): - if not (os.path.isfile(os.path.join('src-input', 'duktape.h.in')) and \ - os.path.isfile(os.path.join('config', 'platforms.yaml'))): - sys.stderr.write('\n') - sys.stderr.write('*** Working directory must be Duktape repo checkout root!\n') - sys.stderr.write('\n') - raise Exception('Incorrect working directory') + try: + cmd = [ 'node', '-e', 'console.log("test")' ] + res = subprocess.check_output(cmd) + if res[:4] == 'test'.encode('utf-8'): + return 'node' + except: + pass -# Option parsing. + return None def parse_options(): parser = optparse.OptionParser() parser.add_option('--repo-directory', dest='repo_directory', default=None, help='Duktape repo directory (default is CWD)') - parser.add_option('--output-directory', dest='output_directory', default=None, help='Dist output directory (created automatically, must not exist; default is /dist)') + parser.add_option('--output-directory', dest='output_directory', default=None, help='Dist output directory (required)') parser.add_option('--git-commit', dest='git_commit', default=None, help='Force git commit hash') parser.add_option('--git-describe', dest='git_describe', default=None, help='Force git describe') parser.add_option('--git-branch', dest='git_branch', default=None, help='Force git branch name') @@ -187,672 +42,76 @@ def parse_options(): parser.add_option('--user-builtin-metadata', dest='user_builtin_metadata', action='append', default=[], help=optparse.SUPPRESS_HELP) parser.add_option('--quiet', dest='quiet', action='store_true', default=False, help='Suppress info messages (show warnings)') parser.add_option('--verbose', dest='verbose', action='store_true', default=False, help='Show verbose debug messages') + parser.add_option('--nodejs-command', dest='nodejs_command', default=None, help='Force Node.js command name') (opts, args) = parser.parse_args() return opts, args -# Python module check and friendly errors. - -def check_python_modules(opts): - # dist.py doesn't need yaml but other dist utils will; check for it and - # warn if it is missing. - failed = False - - def _warning(module, aptPackage, pipPackage): - sys.stderr.write('\n') - sys.stderr.write('*** NOTE: Could not "import %s" needed for dist. Install it using e.g.:\n' % module) - sys.stderr.write('\n') - sys.stderr.write(' # Linux\n') - sys.stderr.write(' $ sudo apt-get install %s\n' % aptPackage) - sys.stderr.write('\n') - sys.stderr.write(' # Windows\n') - sys.stderr.write(' > pip install %s\n' % pipPackage) - - try: - import yaml - except ImportError: - _warning('yaml', 'python-yaml', 'PyYAML') - failed = True - - try: - if opts.create_spdx: - import rdflib - except: - # Tolerate missing rdflib, just warn about it. - _warning('rdflib', 'python-rdflib', 'rdflib') - #failed = True - - if failed: - sys.stderr.write('\n') - raise Exception('Missing some required Python modules') - def main(): - # Basic option parsing, Python module check, CWD check. - - opts, args = parse_options() - - # Log level. - forward_loglevel = [] - if opts.quiet: - logger.setLevel(logging.WARNING) - forward_loglevel = [ '--quiet' ] - elif opts.verbose: - logger.setLevel(logging.DEBUG) - forward_loglevel = [ '--verbose' ] - - check_python_modules(opts) - - if opts.repo_directory is None: - opts.repo_directory = os.path.abspath('.') - logger.info('No --repo-directory option, defaulting to current directory %s' % opts.repo_directory) - check_cwd_duktape_repo_root() - opts.repo_directory = os.path.abspath(opts.repo_directory) - logger.debug('Using repo directory: %s' % opts.repo_directory) - - if opts.output_directory is None: - opts.output_directory = os.path.abspath(os.path.join(opts.repo_directory, 'dist', 'source')) - logger.info('No --output-directory option, defaulting to repo/dist directory %s' % opts.output_directory) - opts.output_directory = os.path.abspath(opts.output_directory) - logger.debug('Using output directory: %s' % opts.output_directory) - - # Obsolete options check. - - if opts.rom_support or opts.rom_auto_lightfunc: - raise Exception('obsolete ROM support argument(s), use tools/configure.py instead') - if len(opts.user_builtin_metadata) > 0: - raise Exception('obsolete --user-builtin-metadata argument, use tools/configure.py and --builtin-file instead') - - # Figure out directories, git info, Duktape version, etc. + sys.stderr.write('\n') + sys.stderr.write('****************************************************************************\n') + sys.stderr.write('*** Duktape python tooling is obsolete, migrate to JS-based tooling! ***\n') + sys.stderr.write('*** This tool now internally invokes the JS-based tooling. ***\n') + sys.stderr.write('*** Minimum Node.js version is 14.x. ***\n') + sys.stderr.write('****************************************************************************\n') + sys.stderr.write('\n') + time.sleep(2) entry_cwd = os.getcwd() - dist = opts.output_directory - os.chdir(opts.repo_directory) + script_path = sys.path[0] # http://stackoverflow.com/questions/4934806/how-can-i-find-scripts-directory-with-python - duk_version, duk_major, duk_minor, duk_patch, duk_version_formatted = get_duk_version() + opts, args = parse_options() - if opts.git_commit is not None: - git_commit = opts.git_commit + if opts.nodejs_command is None: + nodejs_command = detect_nodejs() else: - git_commit = exec_get_stdout([ 'git', 'rev-parse', 'HEAD' ], default='external').strip() - if opts.git_describe is not None: - git_describe = opts.git_describe - else: - git_describe = exec_get_stdout([ 'git', 'describe', '--always', '--dirty' ], default='external').strip() - if opts.git_branch is not None: - git_branch = opts.git_branch - else: - git_branch = exec_get_stdout([ 'git', 'rev-parse', '--abbrev-ref', 'HEAD' ], default='external').strip() - - git_commit_cstring = cstring(git_commit) - git_describe_cstring = cstring(git_describe) - git_branch_cstring = cstring(git_branch) - - logger.info('Dist for Duktape version %s, commit %s, describe %s, branch %s' % \ - (duk_version_formatted, git_commit, git_describe, git_branch)) - - # Create dist directory structure, copy files. - - logger.debug('Create dist directories and copy static files') - - os.chdir(opts.repo_directory) - create_dist_directories(dist) - - os.chdir(opts.repo_directory) - - copy_files([ - 'builtins.yaml', - 'duk_alloc_default.c', - 'duk_api_buffer.c', - 'duk_api_bytecode.c', - 'duk_api_call.c', - 'duk_api_codec.c', - 'duk_api_compile.c', - 'duk_api_debug.c', - 'duk_api_heap.c', - 'duk_api_internal.h', - 'duk_api_inspect.c', - 'duk_api_memory.c', - 'duk_api_object.c', - 'duk_api_random.c', - 'duk_api_stack.c', - 'duk_api_string.c', - 'duk_api_time.c', - 'duk_bi_array.c', - 'duk_bi_boolean.c', - 'duk_bi_buffer.c', - 'duk_bi_cbor.c', - 'duk_bi_date.c', - 'duk_bi_date_unix.c', - 'duk_bi_date_windows.c', - 'duk_bi_duktape.c', - 'duk_bi_encoding.c', - 'duk_bi_error.c', - 'duk_bi_function.c', - 'duk_bi_global.c', - 'duk_bi_json.c', - 'duk_bi_math.c', - 'duk_bi_number.c', - 'duk_bi_object.c', - 'duk_bi_performance.c', - 'duk_bi_pointer.c', - 'duk_bi_promise.c', - 'duk_bi_protos.h', - 'duk_bi_proxy.c', - 'duk_bi_reflect.c', - 'duk_bi_regexp.c', - 'duk_bi_string.c', - 'duk_bi_symbol.c', - 'duk_bi_thread.c', - 'duk_bi_thrower.c', - 'duk_dblunion.h', - 'duk_debug_fixedbuffer.c', - 'duk_debugger.c', - 'duk_debugger.h', - 'duk_debug.h', - 'duk_debug_macros.c', - 'duk_debug_vsnprintf.c', - 'duk_error_augment.c', - 'duk_error.h', - 'duk_error_longjmp.c', - 'duk_error_macros.c', - 'duk_error_misc.c', - 'duk_error_throw.c', - 'duk_exception.h', - 'duk_fltunion.h', - 'duk_forwdecl.h', - 'duk_harray.h', - 'duk_hboundfunc.h', - 'duk_hbuffer_alloc.c', - 'duk_hbuffer_assert.c', - 'duk_hbuffer.h', - 'duk_hbuffer_ops.c', - 'duk_hbufobj.h', - 'duk_hbufobj_misc.c', - 'duk_hcompfunc.h', - 'duk_heap_alloc.c', - 'duk_heap.h', - 'duk_heap_hashstring.c', - 'duk_heaphdr.h', - 'duk_heaphdr_assert.c', - 'duk_heap_finalize.c', - 'duk_heap_markandsweep.c', - 'duk_heap_memory.c', - 'duk_heap_misc.c', - 'duk_heap_refcount.c', - 'duk_heap_stringcache.c', - 'duk_heap_stringtable.c', - 'duk_henv.h', - 'duk_hnatfunc.h', - 'duk_hobject_alloc.c', - 'duk_hobject_assert.c', - 'duk_hobject_class.c', - 'duk_hobject_enum.c', - 'duk_hobject.h', - 'duk_hobject_misc.c', - 'duk_hobject_pc2line.c', - 'duk_hobject_props.c', - 'duk_hproxy.h', - 'duk_hstring.h', - 'duk_hstring_assert.c', - 'duk_hstring_misc.c', - 'duk_hthread_alloc.c', - 'duk_hthread_builtins.c', - 'duk_hthread.h', - 'duk_hthread_misc.c', - 'duk_hthread_stacks.c', - 'duk_internal.h', - 'duk_jmpbuf.h', - 'duk_js_arith.c', - 'duk_js_bytecode.h', - 'duk_js_call.c', - 'duk_js_compiler.c', - 'duk_js_compiler.h', - 'duk_js_executor.c', - 'duk_js.h', - 'duk_json.h', - 'duk_js_ops.c', - 'duk_js_var.c', - 'duk_lexer.c', - 'duk_lexer.h', - 'duk_numconv.c', - 'duk_numconv.h', - 'duk_refcount.h', - 'duk_regexp_compiler.c', - 'duk_regexp_executor.c', - 'duk_regexp.h', - 'duk_replacements.c', - 'duk_replacements.h', - 'duk_selftest.c', - 'duk_selftest.h', - 'duk_strings.h', - 'duktape.h.in', - 'duk_tval.c', - 'duk_tval.h', - 'duk_unicode.h', - 'duk_unicode_support.c', - 'duk_unicode_tables.c', - 'duk_util.h', - 'duk_util_bitdecoder.c', - 'duk_util_bitencoder.c', - 'duk_util_bufwriter.c', - 'duk_util_hashbytes.c', - 'duk_util_tinyrandom.c', - 'duk_util_double.c', - 'duk_util_cast.c', - 'duk_util_memory.c', - 'duk_util_memrw.c', - 'duk_util_misc.c', - 'strings.yaml', - 'SpecialCasing.txt', - 'SpecialCasing-8bit.txt', - 'UnicodeData.txt', - 'UnicodeData-8bit.txt', - ], 'src-input', os.path.join(dist, 'src-input')) + nodejs_command = opts.nodejs_command + if nodejs_command is None: + raise Exception('failed to detect Node.js, override with --nodejs-command') for fn in [ - 'tags.yaml', - 'platforms.yaml', - 'architectures.yaml', - 'compilers.yaml', - 'platforms', - 'architectures', - 'compilers', - 'feature-options', - 'config-options', - 'helper-snippets', - 'header-snippets', - 'examples' + os.path.join(script_path, 'duktool.js'), + os.path.join(script_path, '..', 'src-tools', 'index.js'), + os.path.join(script_path, '..', 'src-tools', 'duktool.js') ]: - # Copy directories in their entirety - if os.path.isfile(os.path.join('config', fn)): - shutil.copyfile(os.path.join('config', fn), os.path.join(dist, 'config', fn)) - else: - shutil.copytree(os.path.join('config', fn), os.path.join(dist, 'config', fn)) - - copy_files([ - 'configure.py', - 'combine_src.py', - 'create_spdx_license.py', - 'duk_meta_to_strarray.py', - 'dukutil.py', - 'dump_bytecode.py', - 'extract_caseconv.py', - 'extract_chars.py', - 'extract_unique_options.py', - 'genbuiltins.py', - 'genconfig.py', - 'json2yaml.py', - 'merge_debug_meta.py', - 'prepare_unicode_data.py', - 'resolve_combined_lineno.py', - 'scan_strings.py', - 'scan_used_stridx_bidx.py', - 'yaml2json.py', - ], 'tools', os.path.join(dist, 'tools')) - - copy_files([ - 'README.rst' - ], 'config', os.path.join(dist, 'config')) - - copy_files([ - 'README.rst', - 'Makefile', - 'package.json', - 'duk_debug.js', - 'duk_debug_proxy.js', - 'duk_classnames.yaml', - 'duk_debugcommands.yaml', - 'duk_debugerrors.yaml', - 'duk_opcodes.yaml' - ], 'debugger', os.path.join(dist, 'debugger')) - - copy_files([ - 'index.html', - 'style.css', - 'webui.js' - ], os.path.join('debugger', 'static'), os.path.join(dist, 'debugger', 'static')) - - copy_files([ - 'console-minimal.js', - 'global.js', - 'object-prototype-definegetter.js', - 'object-prototype-definesetter.js', - 'object-assign.js', - 'performance-now.js', - 'duktape-isfastint.js', - 'duktape-error-setter-writable.js', - 'duktape-error-setter-nonwritable.js', - 'duktape-buffer.js', - 'promise.js' - ], 'polyfills', os.path.join(dist, 'polyfills')) - - copy_files([ - 'README.rst' - ], 'examples', os.path.join(dist, 'examples')) - - copy_files([ - 'README.rst', - 'duk_cmdline.c', - 'duk_cmdline.h', - 'duk_cmdline_lowmem.c' - ], os.path.join('examples', 'cmdline'), os.path.join(dist, 'examples', 'cmdline')) - - copy_files([ - 'README.rst', - 'c_eventloop.c', - 'c_eventloop.h', - 'c_eventloop.js', - 'ecma_eventloop.js', - 'main.c', - 'poll.c', - 'socket.c', - 'fileio.c', - 'basic-test.js', - 'timer-test.js', - 'server-socket-test.js', - 'client-socket-test.js' - ], os.path.join('examples', 'eventloop'), os.path.join(dist, 'examples', 'eventloop')) - - copy_files([ - 'README.rst', - 'hello.c' - ], os.path.join('examples', 'hello'), os.path.join(dist, 'examples', 'hello')) - - copy_files([ - 'README.rst', - 'eval.c' - ], os.path.join('examples', 'eval'), os.path.join(dist, 'examples', 'eval')) - - copy_files([ - 'README.rst', - 'fib.js', - 'process.js', - 'processlines.c', - 'prime.js', - 'primecheck.c', - 'uppercase.c' - ], os.path.join('examples', 'guide'), os.path.join(dist, 'examples', 'guide')) - - copy_files([ - 'README.rst', - 'globals.coffee', - 'hello.coffee', - 'mandel.coffee' - ], os.path.join('examples', 'coffee'), os.path.join(dist, 'examples', 'coffee')) - - copy_files([ - 'README.rst', - 'jxpretty.c' - ], os.path.join('examples', 'jxpretty'), os.path.join(dist, 'examples', 'jxpretty')) - - copy_files([ - 'README.rst', - 'sandbox.c' - ], os.path.join('examples', 'sandbox'), os.path.join(dist, 'examples', 'sandbox')) - - copy_files([ - 'README.rst', - 'duk_alloc_logging.c', - 'duk_alloc_logging.h', - 'log2gnuplot.py' - ], os.path.join('examples', 'alloc-logging'), os.path.join(dist, 'examples', 'alloc-logging')) - - copy_files([ - 'README.rst', - 'duk_alloc_torture.c', - 'duk_alloc_torture.h' - ], os.path.join('examples', 'alloc-torture'), os.path.join(dist, 'examples', 'alloc-torture')) - - copy_files([ - 'README.rst', - 'duk_alloc_hybrid.c', - 'duk_alloc_hybrid.h' - ], os.path.join('examples', 'alloc-hybrid'), os.path.join(dist, 'examples', 'alloc-hybrid')) - - copy_files([ - 'README.rst', - 'duk_trans_socket_unix.c', - 'duk_trans_socket_windows.c', - 'duk_trans_socket.h' - ], os.path.join('examples', 'debug-trans-socket'), os.path.join(dist, 'examples', 'debug-trans-socket')) - - copy_files([ - 'README.rst', - 'duk_trans_dvalue.c', - 'duk_trans_dvalue.h', - 'test.c', - 'Makefile' - ], os.path.join('examples', 'debug-trans-dvalue'), os.path.join(dist, 'examples', 'debug-trans-dvalue')) - - copy_files([ - 'README.rst', - 'duk_codepage_conv.c', - 'duk_codepage_conv.h', - 'test.c' - ], os.path.join('examples', 'codepage-conv'), os.path.join(dist, 'examples', 'codepage-conv')) - - copy_files([ - 'README.rst', - 'dummy_date_provider.c' - ], os.path.join('examples', 'dummy-date-provider'), os.path.join(dist, 'examples', 'dummy-date-provider')) - - copy_files([ - 'README.rst', - 'cpp_exceptions.cpp' - ], os.path.join('examples', 'cpp-exceptions'), os.path.join(dist, 'examples', 'cpp-exceptions')) - - copy_files([ - 'README.rst' - ], 'extras', os.path.join(dist, 'extras')) - - copy_files([ - 'README.rst', - 'duk_logging.c', - 'duk_logging.h', - 'test.c', - 'Makefile' - ], os.path.join('extras', 'logging'), os.path.join(dist, 'extras', 'logging')) - - copy_files([ - 'README.rst', - 'duk_v1_compat.c', - 'duk_v1_compat.h', - 'test.c', - 'Makefile', - 'test_eval1.js', - 'test_eval2.js', - 'test_compile1.js', - 'test_compile2.js' - ], os.path.join('extras', 'duk-v1-compat'), os.path.join(dist, 'extras', 'duk-v1-compat')) - - copy_files([ - 'README.rst', - 'duk_print_alert.c', - 'duk_print_alert.h', - 'test.c', - 'Makefile' - ], os.path.join('extras', 'print-alert'), os.path.join(dist, 'extras', 'print-alert')) - - copy_files([ - 'README.rst', - 'duk_console.c', - 'duk_console.h', - 'test.c', - 'Makefile' - ], os.path.join('extras', 'console'), os.path.join(dist, 'extras', 'console')) - - copy_files([ - 'README.rst', - 'duk_minimal_printf.c', - 'duk_minimal_printf.h', - 'Makefile', - 'test.c' - ], os.path.join('extras', 'minimal-printf'), os.path.join(dist, 'extras', 'minimal-printf')) - - copy_files([ - 'README.rst', - 'duk_module_duktape.c', - 'duk_module_duktape.h', - 'Makefile', - 'test.c' - ], os.path.join('extras', 'module-duktape'), os.path.join(dist, 'extras', 'module-duktape')) - - copy_files([ - 'README.rst', - 'duk_module_node.c', - 'duk_module_node.h', - 'Makefile', - 'test.c' - ], os.path.join('extras', 'module-node'), os.path.join(dist, 'extras', 'module-node')) - - copy_files([ - 'README.rst', - 'duk_alloc_pool.c', - 'duk_alloc_pool.h', - 'ptrcomp.yaml', - 'ptrcomp_fixup.h', - 'Makefile', - 'test.c' - ], os.path.join('extras', 'alloc-pool'), os.path.join(dist, 'extras', 'alloc-pool')) - - copy_files([ - 'README.rst', - 'cbordecode.py', - 'duk_cbor.c', - 'duk_cbor.h', - 'jsoncbor.c', - 'run_testvectors.js', - 'Makefile' - ], os.path.join('extras', 'cbor'), os.path.join(dist, 'extras', 'cbor')) - - copy_files([ - 'Makefile.cmdline', - 'Makefile.dukdebug', - 'Makefile.eventloop', - 'Makefile.hello', - 'Makefile.eval', - 'Makefile.coffee', - 'Makefile.jxpretty', - 'Makefile.jsoncbor', - 'Makefile.sandbox', - 'Makefile.codepage', - 'mandel.js' - ], 'dist-files', dist) - - copy_and_replace(os.path.join('dist-files', 'Makefile.sharedlibrary'), os.path.join(dist, 'Makefile.sharedlibrary'), { - '@DUK_VERSION@': str(duk_version), - '@SONAME_VERSION@': str(int(duk_version / 100)) # 10500 -> 105 - }) - - copy_and_replace(os.path.join('dist-files', 'README.rst'), os.path.join(dist, 'README.rst'), { - '@DUK_VERSION_FORMATTED@': duk_version_formatted, - '@DUK_MAJOR@': str(duk_major), - '@DUK_MINOR@': str(duk_minor), - '@DUK_PATCH@': str(duk_patch), - '@GIT_COMMIT@': git_commit, - '@GIT_DESCRIBE@': git_describe, - '@GIT_BRANCH@': git_branch - }) - - copy_files([ - 'LICENSE.txt', # not strict RST so keep .txt suffix - 'AUTHORS.rst' - ], '.', os.path.join(dist)) - - # RELEASES.rst is only updated in master. It's not included in the dist to - # make maintenance fixes easier to make. - - copy_files([ - 'murmurhash2.txt', - 'lua.txt', - 'commonjs.txt', - 'xoroshiro128plus.txt', - 'splitmix64.txt' - ], 'licenses', os.path.join(dist, 'licenses')) - - # Merge debugger metadata. - - merged = exec_print_stdout([ - sys.executable, os.path.join('tools', 'merge_debug_meta.py'), - '--output', os.path.join(dist, 'debugger', 'duk_debug_meta.json'), - '--class-names', os.path.join('debugger', 'duk_classnames.yaml'), - '--debug-commands', os.path.join('debugger', 'duk_debugcommands.yaml'), - '--debug-errors', os.path.join('debugger', 'duk_debugerrors.yaml'), - '--opcodes', os.path.join('debugger', 'duk_opcodes.yaml') - ] + forward_loglevel) - - # Add a build metadata file. - - doc = { - 'type': 'duk_dist_meta', - 'comment': 'Metadata for Duktape distributable', - 'git_commit': git_commit, - 'git_branch': git_branch, - 'git_describe': git_describe, - 'duk_version': duk_version, - 'duk_version_string': duk_version_formatted - } - with open(os.path.join(dist, 'duk_dist_meta.json'), 'wb') as f: - f.write(json.dumps(doc, indent=4)) - - # Build prepared sources with default config. This is done using - # tools and metadata in the dist directory. - - logger.debug('Create prepared sources for default configuration') - - def prep_default_sources(dirname, extraopts): - cmd = [ - sys.executable, os.path.join(dist, 'tools', 'configure.py'), - '--source-directory', os.path.join(dist, 'src-input'), - '--output-directory', os.path.join(dist, dirname), - '--config-metadata', os.path.join(dist, 'config'), - '--git-commit', git_commit, '--git-describe', git_describe, '--git-branch', git_branch, - '--omit-removed-config-options', '--omit-unused-config-options', - '--emit-config-sanity-check', '--emit-legacy-feature-check' - ] - cmd += extraopts - if opts.rom_support: - cmd.append('--rom-support') - if opts.rom_auto_lightfunc: - cmd.append('--rom-auto-lightfunc') - for i in opts.user_builtin_metadata: - cmd.append('--user-builtin-metadata') - cmd.append(i) - cmd += forward_loglevel - exec_print_stdout(cmd) - - prep_default_sources('src', []) - - # Duktape 2.x: - #prep_default_sources('src', [ '--line-directives' ]) - #prep_default_sources('src-noline', []) - #prep_default_sources('src-separate', [ '--separate-sources' ]) - - # Clean up remaining temp files. - - delete_matching_files(dist, lambda x: x[-4:] == '.tmp') - delete_matching_files(os.path.join(dist, 'tools'), lambda x: x[-4:] == '.pyc') - - # Create SPDX license once all other files are in place (and cleaned). - + if os.path.isfile(fn): + duktool_path = fn + break + if duktool_path is None: + raise Exception('could not find duktool.js or src-tools/index.js') + + cmd = [ + nodejs_command, + duktool_path, + 'dist' + ] + if opts.output_directory is not None: + cmd += [ '--output-directory', opts.output_directory ] + if opts.repo_directory is not None: + cmd += [ '--repo-directory', opts.repo_directory ] + if opts.git_commit is not None: + cmd += [ '--git-commit', opts.git_commit ] + if opts.git_describe is not None: + cmd += [ '--git-describe', opts.git_describe ] + if opts.git_branch is not None: + cmd += [ '--git-branch', opts.git_branch ] if opts.create_spdx: - logger.debug('Create SPDX license') - try: - exec_get_stdout([ - sys.executable, - os.path.join('tools', 'create_spdx_license.py'), - os.path.join(dist, 'license.spdx') - ]) - except: - logger.warning('') - logger.warning('***') - logger.warning('*** WARNING: Failed to create SPDX license, this should not happen for an official release!') - logger.warning('***') - logger.warning('') - else: - logger.debug('Skip SPDX license creation') - - logger.info('Dist finished successfully') + cmd += [ '--create-spdx' ] + if opts.rom_support: + print('--rom-support ignored (now always enabled)') + if opts.rom_auto_lightfunc: + raise Exception('--rom-auto-lightfunc no longer supported for dist (use it with configure)') + if len(opts.user_builtin_metadata) > 0: + raise Exception('--user-builtin-metadata no longer supported for dist (use --builtin-file with configure') + if opts.quiet: + print('--quiet ignored') + if opts.verbose: + print('--verbose ignored') + if True: + cmd += [ '--validate-git' ] + + sys.stderr.write('*** Executing JS-based tooling with command: ' + repr(cmd) + '\n\n') + subprocess.check_call(cmd) if __name__ == '__main__': main() diff --git a/util/makeduk_base.yaml b/util/makeduk_base.yaml index 3a9e1369..6064c59b 100644 --- a/util/makeduk_base.yaml +++ b/util/makeduk_base.yaml @@ -2,7 +2,7 @@ # Some commented out options are kept so that it's easy to # tweak common development time options manually. -# If an unknown option is used, configure.py/genconfig.py will warn about it. +# If an unknown option is used, configure will warn about it. #DUK_USE_SOME_UNKNOWN_OPTION: true DUK_USE_TARGET_INFO: "\"duk command built from Duktape repo\""