1# 2# QuickJS Javascript Engine 3# 4# Copyright (c) 2017-2021 Fabrice Bellard 5# Copyright (c) 2017-2021 Charlie Gordon 6# 7# Permission is hereby granted, free of charge, to any person obtaining a copy 8# of this software and associated documentation files (the "Software"), to deal 9# in the Software without restriction, including without limitation the rights 10# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11# copies of the Software, and to permit persons to whom the Software is 12# furnished to do so, subject to the following conditions: 13# 14# The above copyright notice and this permission notice shall be included in 15# all copies or substantial portions of the Software. 16# 17# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23# THE SOFTWARE. 24 25ifeq ($(shell uname -s),Darwin) 26CONFIG_DARWIN=y 27endif 28ifeq ($(shell uname -s),DragonFly) 29CONFIG_DRAGONFLY=y 30endif 31ifeq ($(shell uname -s),FreeBSD) 32CONFIG_FREEBSD=y 33endif 34# Windows cross compilation from Linux 35#CONFIG_WIN32=y 36# use link time optimization (smaller and faster executables but slower build) 37CONFIG_LTO=y 38# consider warnings as errors (for development) 39#CONFIG_WERROR=y 40# force 32 bit build for some utilities 41#CONFIG_M32=y 42 43ifdef CONFIG_DARWIN 44# use clang instead of gcc 45CONFIG_CLANG=y 46CONFIG_DEFAULT_AR=y 47endif 48ifdef CONFIG_DRAGONFLY 49CONFIG_DEFAULT_AR=y 50CONFIG_LTO= 51endif 52ifdef CONFIG_FREEBSD 53# use clang instead of gcc 54CONFIG_CLANG= 55CONFIG_DEFAULT_AR=y 56CONFIG_LTO= 57endif 58 59# installation directory 60prefix=/usr/local 61 62# use the gprof profiler 63#CONFIG_PROFILE=y 64# use address sanitizer 65#CONFIG_ASAN=y 66# include the code for BigInt/BigFloat/BigDecimal and math mode 67CONFIG_BIGNUM=y 68 69OBJDIR=.obj 70 71ifdef CONFIG_WIN32 72 ifdef CONFIG_M32 73 CROSS_PREFIX=i686-w64-mingw32- 74 else 75 CROSS_PREFIX=x86_64-w64-mingw32- 76 endif 77 EXE=.exe 78else 79 CROSS_PREFIX= 80 EXE= 81endif 82ifdef CONFIG_CLANG 83 HOST_CC=gcc 84 CC=gcc 85 CFLAGS=-g -Wall -MMD -MF $(OBJDIR)/$(@F).d 86 CFLAGS += -Wextra 87 CFLAGS += -Wno-sign-compare 88 CFLAGS += -Wno-missing-field-initializers 89 CFLAGS += -Wundef -Wuninitialized 90 CFLAGS += -Wunused -Wno-unused-parameter 91 CFLAGS += -Wwrite-strings 92 CFLAGS += -Wchar-subscripts -funsigned-char 93 CFLAGS += -MMD -MF $(OBJDIR)/$(@F).d 94 ifdef CONFIG_DEFAULT_AR 95 AR=$(CROSS_PREFIX)ar 96 else 97 ifdef CONFIG_LTO 98 AR=$(CROSS_PREFIX)llvm-ar 99 else 100 AR=$(CROSS_PREFIX)ar 101 endif 102 endif 103else 104 HOST_CC=gcc 105 CC=gcc 106 CFLAGS=-g -Wall -MMD -MF $(OBJDIR)/$(@F).d 107 CFLAGS += -Wno-array-bounds -Wno-format-truncation 108 ifdef CONFIG_LTO 109 AR=$(CROSS_PREFIX)gcc-ar 110 else 111 AR=$(CROSS_PREFIX)ar 112 endif 113endif 114STRIP=$(CROSS_PREFIX)strip 115ifdef CONFIG_WERROR 116CFLAGS+=-Werror 117endif 118DEFINES:=-D_GNU_SOURCE -DCONFIG_VERSION=\"$(shell cat VERSION)\" 119ifdef CONFIG_BIGNUM 120DEFINES+=-DCONFIG_BIGNUM 121endif 122ifdef CONFIG_WIN32 123DEFINES+=-D__USE_MINGW_ANSI_STDIO # for standard snprintf behavior 124endif 125 126CFLAGS+=$(DEFINES) 127CFLAGS_DEBUG=$(CFLAGS) -O0 128CFLAGS_SMALL=$(CFLAGS) -Os 129CFLAGS_OPT=$(CFLAGS) -O2 130CFLAGS_NOLTO:=$(CFLAGS_OPT) 131LDFLAGS=-g 132ifdef CONFIG_LTO 133CFLAGS_SMALL+=-flto 134CFLAGS_OPT+=-flto 135LDFLAGS+=-flto 136endif 137ifdef CONFIG_PROFILE 138CFLAGS+=-p 139LDFLAGS+=-p 140endif 141ifdef CONFIG_ASAN 142CFLAGS+=-fsanitize=address -fno-omit-frame-pointer 143LDFLAGS+=-fsanitize=address -fno-omit-frame-pointer 144endif 145ifdef CONFIG_WIN32 146LDEXPORT= 147else 148LDEXPORT=-rdynamic 149endif 150 151PROGS=qjs$(EXE) qjsc$(EXE) run-test262 152ifneq ($(CROSS_PREFIX),) 153QJSC_CC=gcc 154QJSC=./host-qjsc 155PROGS+=$(QJSC) 156else 157QJSC_CC=$(CC) 158QJSC=./qjsc$(EXE) 159endif 160ifndef CONFIG_WIN32 161PROGS+=qjscalc 162endif 163ifdef CONFIG_M32 164PROGS+=qjs32 qjs32_s 165endif 166PROGS+=libquickjs.a 167ifdef CONFIG_LTO 168PROGS+=libquickjs.lto.a 169endif 170 171# examples 172ifeq ($(CROSS_PREFIX),) 173ifdef CONFIG_ASAN 174PROGS+= 175else 176PROGS+=examples/hello examples/hello_module examples/test_fib 177ifndef CONFIG_DARWIN 178PROGS+=examples/fib.so examples/point.so 179endif 180endif 181endif 182 183all: $(OBJDIR) $(OBJDIR)/quickjs.check.o $(OBJDIR)/qjs.check.o $(PROGS) 184 185QJS_LIB_OBJS=$(OBJDIR)/quickjs.o $(OBJDIR)/libregexp.o $(OBJDIR)/libunicode.o $(OBJDIR)/cutils.o $(OBJDIR)/quickjs-libc.o 186 187QJS_OBJS=$(OBJDIR)/qjs.o $(OBJDIR)/repl.o $(QJS_LIB_OBJS) 188ifdef CONFIG_BIGNUM 189QJS_LIB_OBJS+=$(OBJDIR)/libbf.o 190QJS_OBJS+=$(OBJDIR)/qjscalc.o 191endif 192 193HOST_LIBS=-lm -ldl -lpthread 194LIBS=-lm 195ifndef CONFIG_WIN32 196LIBS+=-ldl -lpthread 197endif 198LIBS+=$(EXTRA_LIBS) 199 200$(OBJDIR): 201 mkdir -p $(OBJDIR) $(OBJDIR)/examples $(OBJDIR)/tests 202 203qjs$(EXE): $(QJS_OBJS) 204 $(CC) $(LDFLAGS) $(LDEXPORT) -o $@ $^ $(LIBS) 205 206qjs-debug$(EXE): $(patsubst %.o, %.debug.o, $(QJS_OBJS)) 207 $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) 208 209qjsc$(EXE): $(OBJDIR)/qjsc.o $(QJS_LIB_OBJS) 210 $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) 211 212ifneq ($(CROSS_PREFIX),) 213 214$(QJSC): $(OBJDIR)/qjsc.host.o \ 215 $(patsubst %.o, %.host.o, $(QJS_LIB_OBJS)) 216 $(HOST_CC) $(LDFLAGS) -o $@ $^ $(HOST_LIBS) 217 218endif #CROSS_PREFIX 219 220QJSC_DEFINES:=-DCONFIG_CC=\"$(QJSC_CC)\" -DCONFIG_PREFIX=\"$(prefix)\" 221ifdef CONFIG_LTO 222QJSC_DEFINES+=-DCONFIG_LTO 223endif 224QJSC_HOST_DEFINES:=-DCONFIG_CC=\"$(HOST_CC)\" -DCONFIG_PREFIX=\"$(prefix)\" 225 226$(OBJDIR)/qjsc.o: CFLAGS+=$(QJSC_DEFINES) 227$(OBJDIR)/qjsc.host.o: CFLAGS+=$(QJSC_HOST_DEFINES) 228 229qjs32: $(patsubst %.o, %.m32.o, $(QJS_OBJS)) 230 $(CC) -m32 $(LDFLAGS) $(LDEXPORT) -o $@ $^ $(LIBS) 231 232qjs32_s: $(patsubst %.o, %.m32s.o, $(QJS_OBJS)) 233 $(CC) -m32 $(LDFLAGS) -o $@ $^ $(LIBS) 234 @size $@ 235 236qjscalc: qjs 237 ln -sf $< $@ 238 239ifdef CONFIG_LTO 240LTOEXT=.lto 241else 242LTOEXT= 243endif 244 245libquickjs$(LTOEXT).a: $(QJS_LIB_OBJS) 246 $(AR) rcs $@ $^ 247 248ifdef CONFIG_LTO 249libquickjs.a: $(patsubst %.o, %.nolto.o, $(QJS_LIB_OBJS)) 250 $(AR) rcs $@ $^ 251endif # CONFIG_LTO 252 253repl.c: $(QJSC) repl.js 254 $(QJSC) -c -o $@ -m repl.js 255 256qjscalc.c: $(QJSC) qjscalc.js 257 $(QJSC) -fbignum -c -o $@ qjscalc.js 258 259ifneq ($(wildcard unicode/UnicodeData.txt),) 260$(OBJDIR)/libunicode.o $(OBJDIR)/libunicode.m32.o $(OBJDIR)/libunicode.m32s.o \ 261 $(OBJDIR)/libunicode.nolto.o: libunicode-table.h 262 263libunicode-table.h: unicode_gen 264 ./unicode_gen unicode $@ 265endif 266 267run-test262: $(OBJDIR)/run-test262.o $(QJS_LIB_OBJS) 268 $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) 269 270run-test262-debug: $(patsubst %.o, %.debug.o, $(OBJDIR)/run-test262.o $(QJS_LIB_OBJS)) 271 $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) 272 273run-test262-32: $(patsubst %.o, %.m32.o, $(OBJDIR)/run-test262.o $(QJS_LIB_OBJS)) 274 $(CC) -m32 $(LDFLAGS) -o $@ $^ $(LIBS) 275 276# object suffix order: nolto, [m32|m32s] 277 278$(OBJDIR)/%.o: %.c | $(OBJDIR) 279 $(CC) $(CFLAGS_OPT) -c -o $@ $< 280 281$(OBJDIR)/%.host.o: %.c | $(OBJDIR) 282 $(HOST_CC) $(CFLAGS_OPT) -c -o $@ $< 283 284$(OBJDIR)/%.pic.o: %.c | $(OBJDIR) 285 $(CC) $(CFLAGS_OPT) -fPIC -DJS_SHARED_LIBRARY -c -o $@ $< 286 287$(OBJDIR)/%.nolto.o: %.c | $(OBJDIR) 288 $(CC) $(CFLAGS_NOLTO) -c -o $@ $< 289 290$(OBJDIR)/%.m32.o: %.c | $(OBJDIR) 291 $(CC) -m32 $(CFLAGS_OPT) -c -o $@ $< 292 293$(OBJDIR)/%.m32s.o: %.c | $(OBJDIR) 294 $(CC) -m32 $(CFLAGS_SMALL) -c -o $@ $< 295 296$(OBJDIR)/%.debug.o: %.c | $(OBJDIR) 297 $(CC) $(CFLAGS_DEBUG) -c -o $@ $< 298 299$(OBJDIR)/%.check.o: %.c | $(OBJDIR) 300 $(CC) $(CFLAGS) -DCONFIG_CHECK_JSVALUE -c -o $@ $< 301 302regexp_test: libregexp.c libunicode.c cutils.c 303 $(CC) $(LDFLAGS) $(CFLAGS) -DTEST -o $@ libregexp.c libunicode.c cutils.c $(LIBS) 304 305unicode_gen: $(OBJDIR)/unicode_gen.host.o $(OBJDIR)/cutils.host.o libunicode.c unicode_gen_def.h 306 $(HOST_CC) $(LDFLAGS) $(CFLAGS) -o $@ $(OBJDIR)/unicode_gen.host.o $(OBJDIR)/cutils.host.o 307 308clean: 309 rm -f repl.c qjscalc.c out.c 310 rm -f *.a *.o *.d *~ unicode_gen regexp_test $(PROGS) 311 rm -f hello.c test_fib.c 312 rm -f examples/*.so tests/*.so 313 rm -rf $(OBJDIR)/ *.dSYM/ qjs-debug 314 rm -rf run-test262-debug run-test262-32 315 316install: all 317 mkdir -p "$(DESTDIR)$(prefix)/bin" 318 $(STRIP) qjs qjsc 319 install -m755 qjs qjsc "$(DESTDIR)$(prefix)/bin" 320 ln -sf qjs "$(DESTDIR)$(prefix)/bin/qjscalc" 321 mkdir -p "$(DESTDIR)$(prefix)/lib/quickjs" 322 install -m644 libquickjs.a "$(DESTDIR)$(prefix)/lib/quickjs" 323ifdef CONFIG_LTO 324 install -m644 libquickjs.lto.a "$(DESTDIR)$(prefix)/lib/quickjs" 325endif 326 mkdir -p "$(DESTDIR)$(prefix)/include/quickjs" 327 install -m644 quickjs.h quickjs-libc.h "$(DESTDIR)$(prefix)/include/quickjs" 328 329############################################################################### 330# examples 331 332# example of static JS compilation 333HELLO_SRCS=examples/hello.js 334HELLO_OPTS=-fno-string-normalize -fno-map -fno-promise -fno-typedarray \ 335 -fno-typedarray -fno-regexp -fno-json -fno-eval -fno-proxy \ 336 -fno-date -fno-module-loader 337ifdef CONFIG_BIGNUM 338HELLO_OPTS+=-fno-bigint 339endif 340 341hello.c: $(QJSC) $(HELLO_SRCS) 342 $(QJSC) -e $(HELLO_OPTS) -o $@ $(HELLO_SRCS) 343 344ifdef CONFIG_M32 345examples/hello: $(OBJDIR)/hello.m32s.o $(patsubst %.o, %.m32s.o, $(QJS_LIB_OBJS)) 346 $(CC) -m32 $(LDFLAGS) -o $@ $^ $(LIBS) 347else 348examples/hello: $(OBJDIR)/hello.o $(QJS_LIB_OBJS) 349 $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) 350endif 351 352# example of static JS compilation with modules 353HELLO_MODULE_SRCS=examples/hello_module.js 354HELLO_MODULE_OPTS=-fno-string-normalize -fno-map -fno-promise -fno-typedarray \ 355 -fno-typedarray -fno-regexp -fno-json -fno-eval -fno-proxy \ 356 -fno-date -m 357examples/hello_module: $(QJSC) libquickjs$(LTOEXT).a $(HELLO_MODULE_SRCS) 358 $(QJSC) $(HELLO_MODULE_OPTS) -o $@ $(HELLO_MODULE_SRCS) 359 360# use of an external C module (static compilation) 361 362test_fib.c: $(QJSC) examples/test_fib.js 363 $(QJSC) -e -M examples/fib.so,fib -m -o $@ examples/test_fib.js 364 365examples/test_fib: $(OBJDIR)/test_fib.o $(OBJDIR)/examples/fib.o libquickjs$(LTOEXT).a 366 $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) 367 368examples/fib.so: $(OBJDIR)/examples/fib.pic.o 369 $(CC) $(LDFLAGS) -shared -o $@ $^ 370 371examples/point.so: $(OBJDIR)/examples/point.pic.o 372 $(CC) $(LDFLAGS) -shared -o $@ $^ 373 374############################################################################### 375# documentation 376 377DOCS=doc/quickjs.pdf doc/quickjs.html doc/jsbignum.pdf doc/jsbignum.html 378 379build_doc: $(DOCS) 380 381clean_doc: 382 rm -f $(DOCS) 383 384doc/%.pdf: doc/%.texi 385 texi2pdf --clean -o $@ -q $< 386 387doc/%.html.pre: doc/%.texi 388 makeinfo --html --no-headers --no-split --number-sections -o $@ $< 389 390doc/%.html: doc/%.html.pre 391 sed -e 's|</style>|</style>\n<meta name="viewport" content="width=device-width, initial-scale=1.0">|' < $< > $@ 392 393############################################################################### 394# tests 395 396ifndef CONFIG_DARWIN 397test: tests/bjson.so examples/point.so 398endif 399ifdef CONFIG_M32 400test: qjs32 401endif 402 403test: qjs 404 ./qjs tests/test_closure.js 405 ./qjs tests/test_language.js 406 ./qjs tests/test_builtin.js 407 ./qjs tests/test_loop.js 408 ./qjs tests/test_std.js 409 ./qjs tests/test_worker.js 410ifndef CONFIG_DARWIN 411ifdef CONFIG_BIGNUM 412 ./qjs --bignum tests/test_bjson.js 413else 414 ./qjs tests/test_bjson.js 415endif 416 ./qjs examples/test_point.js 417endif 418ifdef CONFIG_BIGNUM 419 ./qjs --bignum tests/test_op_overloading.js 420 ./qjs --bignum tests/test_bignum.js 421 ./qjs --qjscalc tests/test_qjscalc.js 422endif 423ifdef CONFIG_M32 424 ./qjs32 tests/test_closure.js 425 ./qjs32 tests/test_language.js 426 ./qjs32 tests/test_builtin.js 427 ./qjs32 tests/test_loop.js 428 ./qjs32 tests/test_std.js 429 ./qjs32 tests/test_worker.js 430ifdef CONFIG_BIGNUM 431 ./qjs32 --bignum tests/test_op_overloading.js 432 ./qjs32 --bignum tests/test_bignum.js 433 ./qjs32 --qjscalc tests/test_qjscalc.js 434endif 435endif 436 437stats: qjs qjs32 438 ./qjs -qd 439 ./qjs32 -qd 440 441microbench: qjs 442 ./qjs tests/microbench.js 443 444microbench-32: qjs32 445 ./qjs32 tests/microbench.js 446 447# ES5 tests (obsolete) 448test2o: run-test262 449 time ./run-test262 -m -c test262o.conf 450 451test2o-32: run-test262-32 452 time ./run-test262-32 -m -c test262o.conf 453 454test2o-update: run-test262 455 ./run-test262 -u -c test262o.conf 456 457# Test262 tests 458test2-default: run-test262 459 time ./run-test262 -m -c test262.conf 460 461test2: run-test262 462 time ./run-test262 -m -c test262.conf -a 463 464test2-32: run-test262-32 465 time ./run-test262-32 -m -c test262.conf -a 466 467test2-update: run-test262 468 ./run-test262 -u -c test262.conf -a 469 470test2-check: run-test262 471 time ./run-test262 -m -c test262.conf -E -a 472 473testall: all test microbench test2o test2 474 475testall-32: all test-32 microbench-32 test2o-32 test2-32 476 477testall-complete: testall testall-32 478 479bench-v8: qjs 480 make -C tests/bench-v8 481 ./qjs -d tests/bench-v8/combined.js 482 483tests/bjson.so: $(OBJDIR)/tests/bjson.pic.o 484 $(CC) $(LDFLAGS) -shared -o $@ $^ $(LIBS) 485 486-include $(wildcard $(OBJDIR)/*.d) 487