├── .dockerignore
├── .gitignore
├── CHANGELOG.md
├── README.md
├── builder
├── build_and_export_qjs.sh
├── custom
│ ├── README.md
│ ├── musl
│ │ ├── bin
│ │ │ └── musl-gcc
│ │ └── lib
│ │ │ └── musl-gcc.specs
│ └── qjs
│ │ ├── examples
│ │ └── ext-lib
│ │ │ ├── example1.js
│ │ │ ├── example2.js
│ │ │ ├── example3.js
│ │ │ └── example4.js
│ │ ├── files
│ │ ├── path.c
│ │ └── path.h
│ │ ├── patches
│ │ ├── 2020-09-06
│ │ │ ├── Makefile.patch
│ │ │ └── qjsc.patch
│ │ ├── 2020-11-08
│ │ │ ├── Makefile.patch
│ │ │ ├── qjs.patch
│ │ │ ├── qjsc.patch
│ │ │ └── quickjs-libc.patch
│ │ ├── 2021-03-27
│ │ │ ├── Makefile.patch
│ │ │ ├── qjs.patch
│ │ │ ├── qjsc.patch
│ │ │ └── quickjs-libc.patch
│ │ ├── 2023-12-09
│ │ │ ├── Makefile.patch
│ │ │ ├── qjs.patch
│ │ │ ├── qjsc.patch
│ │ │ └── quickjs-libc.patch
│ │ ├── 2024-01-13
│ │ │ ├── Makefile.patch
│ │ │ ├── qjs.patch
│ │ │ ├── qjsc.patch
│ │ │ └── quickjs-libc.patch
│ │ └── 2025-04-26
│ │ │ ├── Makefile.patch
│ │ │ ├── qjs.patch
│ │ │ ├── qjsc.patch
│ │ │ └── quickjs-libc.patch
│ │ ├── qjsc-x86_64
│ │ └── scripts
│ │ ├── examples
│ │ └── compile_examples.sh
│ │ ├── qjs.sh
│ │ └── qjsc.sh
├── env
│ ├── deps
│ └── qjs
└── scripts
│ ├── bootstrap-alpine.sh
│ ├── build_deps.sh
│ ├── build_qjs.sh
│ ├── checkout_qjs.sh
│ ├── export_qjs.sh
│ ├── fetch_deps.sh
│ └── prepare_qjs.sh
├── docker
├── Dockerfile
├── build_and_export_qjs.sh
└── scripts
│ └── build_docker_image.sh
├── flake.lock
└── flake.nix
/.dockerignore:
--------------------------------------------------------------------------------
1 | .git
2 | deps
3 | packages
4 | quickjs-repo
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | deps
2 | packages
3 | quickjs-repo
4 |
5 | .history
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | ## [2025-04-26_1]
4 |
5 | * chore: QuickJS release `2025-04-26`
6 |
7 | ## [2024-01-13_3]
8 |
9 | * refactor: refactor: use `type -p` instead of `which` in `qjsc.sh`
10 |
11 | ## [2024-01-13_2]
12 |
13 | * feat: improve `js_os_exec` performances by computing `fd_max` using `/proc`
14 |
15 | ## [2024-01-13_1]
16 |
17 | * chore: QuickJS release `2024-01-13`
18 |
19 | ## [2023-12-09_1]
20 |
21 | * chore: QuickJS release `2023-12-09`
22 |
23 | ## [2021-03-27_4]
24 |
25 | * feat: expose `mkdtemp` function to javascript
26 |
27 | ## [2021-03-27_3]
28 |
29 | * feat: expose `flock` function to javascript
30 | * feat: expose `mkstemp` function to javascript
31 | * fix: don't call [upx](https://upx.github.io/) if compilation failed
32 |
33 | ## [2021-03-27_2]
34 |
35 | * refactor: built [using](https://github.com/ctn-malone/musl-cross-maker/releases/tag/gcc-6.5.0_binutils-2.25.1_musl-1.2.2)
36 | * gcc : 6.5.0
37 | * binutils : 2.25.1
38 | * musl : 1.2.2
39 | * feat: QuickJS binaries are compressed using [upx](https://upx.github.io/) by default
40 | * feat: compiled files are compressed using [upx](https://upx.github.io/) by default (if possible)
41 | * feat: support for `QJS_LIB_DIR` environment variable
42 | * feat: expose `getpid` function to javascript
43 |
44 | ## [2021-03-27_1]
45 |
46 | * QuickJS release `2021-03-27`
47 |
48 | ## [2020-11-08_3]
49 |
50 | * Possibility to embed https://github.com/ctn-malone/qjs-ext-lib when building packages
51 |
52 | ## [2020-11-08_2]
53 |
54 | * Possibility to embed custom javascript modules when building packages
55 | * Fallback to the directory containing `qjs` & `qjsc` binaries when resolving imports
56 |
57 | ## [2020-11-08_1]
58 |
59 | * *QuickJS* release `2020-11-08`
60 |
61 | ## [2020-09-06_1]
62 |
63 | * *QuickJS* release `2020-09-06`
64 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Cross compile [QuickJS](https://bellard.org/quickjs/quickjs.html) interpreter & compiler statically. Resulting [QuickJS](https://github.com/ctn-malone/quickjs-cross-compiler) compiler also generates *static* binaries based on [musl libc](https://musl.libc.org/)
2 |
3 | Following target architectures are supported
4 |
5 | * x86_64
6 | * i686
7 | * armv7l
8 | * aarch64
9 |
10 | Cross compilation is performed using [musl.cc](https://github.com/ctn-malone/musl-cross-maker) static compilers (which means you should be able to generate a portable package of *QuickJS* from any recent *x86_64* Linux distribution with *gcc*)
11 |
12 | Final portable version should weight around 7MB (after decompression)
13 |
14 | Static compiler should work with any Linux distribution with *gcc* >= `4.3.2` and *binutils* >= `2.25`
15 |
16 | By default, packages will be exported to `packages` directory, at the root of the repository
17 |
18 | Don't forget to check the [qjs-ext-lib](https://github.com/ctn-malone/qjs-ext-lib) repo which provides some
19 | wrappers around common unix tools to do HTTP requests or execute external programs (and more) 😊
20 |
21 | **Table of content**
22 | - [Extra functions](#extra-functions)
23 | - [os.flock](#osflock)
24 | - [os.mkstemp](#osmkstemp)
25 | - [os.mkdtemp](#osmkdtemp)
26 | - [Other changes](#other-changes)
27 | - [Generate a portable package using *Docker*](#generate-a-portable-package-using-docker)
28 | - [Generate a portable package without using *Docker*](#generate-a-portable-package-without-using-docker)
29 | - [Using the portable compiler](#using-the-portable-compiler)
30 | - [Nix](#nix)
31 | - [Embed custom javascript modules](#embed-custom-javascript-modules)
32 | - [Embed QuickJS extension library](#embed-quickjs-extension-library)
33 | - [Limitations](#limitations)
34 |
35 | # Extra functions
36 |
37 | Some extra functions not part of [vanilla QuickJS](https://bellard.org/quickjs/quickjs.html) have been added
38 |
39 | ## os.flock
40 |
41 | `os.flock(fd, operation)`
42 |
43 | See https://linux.die.net/man/2/flock
44 |
45 | Example
46 |
47 | ```
48 | const fd = os.open('/tmp/lock', os.O_RDWR | os.O_CREAT, 0o644);
49 | // code will block until no other process is accessing the file
50 | os.flock(fd, os.LOCK_EX);
51 | ```
52 |
53 | ## os.mkstemp
54 |
55 | `os.mkstemp(template, outputObj)`
56 |
57 | See https://man7.org/linux/man-pages/man3/mkstemp.3.html
58 |
59 | Example
60 |
61 | ```
62 | const outputObj = {};
63 | // template MUST end with XXXXXX
64 | const fd = os.mkstemp('/tmp/randomXXXXXX', outputObj);
65 | std.puts(outputObj.filename)
66 | ```
67 |
68 | ## os.mkdtemp
69 |
70 | `os.mkdtemp(template, errObj)`
71 |
72 | See https://man7.org/linux/man-pages/man3/mkdtemp.3.html
73 |
74 | Example
75 |
76 | ```
77 | const errObj = {};
78 | // template MUST end with XXXXXX
79 | const dirname = os.mkdtemp('/tmp/randomXXXXXX', errObj);
80 | std.puts(dirname)
81 | ```
82 |
83 | # Other changes
84 |
85 | - improve `js_os_exec` performances by computing `fd_max` using `/proc`
86 |
87 | # Generate a portable package using *Docker*
88 |
89 | NB : This is the recommended way
90 |
91 | A portable package containing interpreter & compiler can be generated using `docker/build_and_export_qjs.sh` script
92 |
93 | ```
94 | ./docker/build_and_export_qjs.sh -h
95 | Build a static version of QuickJS (interpreter & compiler)
96 | Usage: ./docker/build_and_export_qjs.sh [-p|--packages-dir ] [-a|--arch ] [--(no-)ext-lib] [--ext-lib-version ] [-e|--extra-dir ] [--(no-)force-build-image] [-v|--(no-)verbose] [-u|--(no-)upx] [-h|--help] []
97 | : QuickJS version (ex: 2020-09-06) (default: '2025-04-26')
98 | -p, --packages-dir: directory where package will be exported (default: './packages')
99 | -a, --arch: target architecture. Can be one of: 'x86_64', 'i686', 'armv7l' and 'aarch64' (default: 'x86_64')
100 | --ext-lib, --no-ext-lib: add QuickJS extension library (off by default)
101 | --ext-lib-version: QuickJS extension library version (default: '0.14.2')
102 | -e, --extra-dir: extra directory to add into package (empty by default)
103 | --force-build-image, --no-force-build-image: force rebuilding docker image (off by default)
104 | -v, --verbose, --no-verbose: enable verbose mode (off by default)
105 | -u, --upx, --no-upx: compress binaries using upx (on by default)
106 | -h, --help: Prints help
107 | ```
108 |
109 | Examples
110 |
111 | ```
112 | ./docker/build_and_export_qjs.sh -v
113 | ```
114 |
115 | Above command will :
116 |
117 | * build a *Docker* image (only if it does not already exist) which will download and build necessary dependencies
118 | * run a temporary container and :
119 | * enable verbose mode inside the container
120 | * build *default* *QuickJS* version (`2025-04-26` as of 2025-04-26) for *default* architecture (`x86_64`)
121 | * export portable package to *default* location (`packages` directory at the root of the repository)
122 |
123 | ```
124 | for arch in x86_64 i686 armv7l aarch64 ; do ./docker/build_and_export_qjs.sh -va ${arch} ; done
125 | ```
126 |
127 | Same as previous command but will build packages for multiple target architectures
128 |
129 | # Generate a portable package without using *Docker*
130 |
131 | A portable package containing interpreter & compiler can be generated using `builder/build_and_export_qjs.sh` script
132 |
133 | ```
134 | ./builder/build_and_export_qjs.sh -h
135 | Build a static version of QuickJS (interpreter & compiler)
136 | Usage: ./builder/build_and_export_qjs.sh [-p|--packages-dir ] [--deps-dir ] [-a|--arch ] [--(no-)ext-lib] [--ext-lib-version ] [-e|--extra-dir ] [--(no-)force-fetch-deps] [--(no-)force-build-deps] [--(no-)force-checkout-qjs] [--(no-)force-build-qjs] [-v|--(no-)verbose] [-u|--(no-)upx] [-h|--help] []
137 | : QuickJS version (ex: 2020-09-06) (default: '2025-04-26')
138 | -p, --packages-dir: directory where package will be exported (default: './packages')
139 | --deps-dir: directory where dependencies should be stored/buil (default: './deps')
140 | -a, --arch: target architecture. Can be one of: 'x86_64', 'i686', 'armv7l' and 'aarch64' (default: 'x86_64')
141 | --ext-lib, --no-ext-lib: add QuickJS extension library (off by default)
142 | --ext-lib-version: QuickJS extension library version (default: '0.14.2')
143 | -e, --extra-dir: extra directory to add into package (empty by default)
144 | --force-fetch-deps, --no-force-fetch-deps: force re-fetching dependencies (off by default)
145 | --force-build-deps, --no-force-build-deps: force rebuild of dependencies (off by default)
146 | --force-checkout-qjs, --no-force-checkout-qjs: clone repository even if it exists (off by default)
147 | --force-build-qjs, --no-force-build-qjs: force rebuild of QuickJS (off by default)
148 | -v, --verbose, --no-verbose: enable verbose mode (off by default)
149 | -u, --upx, --no-upx: compress binaries using upx (on by default)
150 | -h, --help: Prints help
151 | ```
152 |
153 | Examples
154 |
155 | ```
156 | ./builder/build_and_export_qjs.sh
157 | ```
158 |
159 | Above command will :
160 |
161 | * download and build necessary dependencies under *default* location (`deps` directory at the root of the repository)
162 | * build *default* *QuickJS* version (`2025-04-26` as of 2024-01-14) for *default* architecture (`x86_64`)
163 | * export portable package to *default* location (`packages` directory at the root of the repository)
164 |
165 | ```
166 | ./builder/build_and_export_qjs.sh '2025-04-26' -a armv7l -p /usr/local/packages -d /usr/local/deps -v
167 | ```
168 |
169 | Above command will :
170 |
171 | * build *QuickJS* version `2025-04-26` for `armv7l` architecture
172 | * download and build necessary dependencies under `/usr/local/deps`
173 | * export portable package to `/usr/local/packages`
174 | * enable verbose mode
175 |
176 | # Using the portable compiler
177 |
178 | Assuming [package](https://github.com/ctn-malone/quickjs-cross-compiler/releases) was decompressed under `/usr/local/quickjs`, just run `/usr/local/quickjs/qjsc.sh` to compile a `.js` file
179 |
180 | Example `hello.js` file
181 |
182 | ```javascript
183 | import * as std from "std";
184 |
185 | let name = 'world';
186 | if (undefined !== scriptArgs[1]) {
187 | name = scriptArgs[1];
188 | }
189 | console.log(`Hello ${name} !`);
190 |
191 | while (true) {
192 | console.log(`Type 'exit' to exit script`);
193 | const str = std.in.getline();
194 | if ('exit' == str) {
195 | break;
196 | }
197 | }
198 | console.log(`Goodbye ${name}!`);
199 | ```
200 |
201 | File can be compiled using
202 |
203 | ```
204 | /usr/local/quickjs/qjsc.sh -o hello hello.js
205 | ```
206 |
207 | ```
208 | ls -l hello
209 | -rwxrwxr-x 1 user user 899160 oct. 19 15:32 hello
210 | ```
211 |
212 | ```
213 | file hello
214 | hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, stripped
215 | ```
216 |
217 | ```
218 | ldd hello
219 | not a dynamic executable
220 | ```
221 |
222 | NB : if [upx](https://upx.github.io/) exists, resulting binary will be automatically compressed (unless `QJS_UPX` environment variable is set to `0`)
223 |
224 | # Nix
225 |
226 | In order to get a shell with interpreter (`qjs.sh`) and compiler (`qjsc.sh`), run following command
227 |
228 | ```
229 | nix develop github:ctn-malone/quickjs-cross-compiler
230 | ```
231 |
232 | Following commands can also be used to run `qjs.sh` or `qjsc.sh` using `nix run`
233 |
234 | - run `qjs.sh`
235 |
236 | ```
237 | nix run github:ctn-malone/quickjs-cross-compiler
238 | ```
239 |
240 | - run `qjsc.sh`
241 |
242 | ```
243 | nix run github:ctn-malone/quickjs-cross-compiler#qjsc
244 | ```
245 |
246 | # Embed custom javascript modules
247 |
248 | Starting from release `2020-11-08_2`, any javascript file placed alongside `qjs` & `qjsc` binaries can be referenced relatively from your main script.
249 | This allows to bundle adhoc packages containing javascript modules (argument parsing, ...) which can be shared across various scripts
250 |
251 | Example
252 |
253 | For a package containing an `ext` directory alongside `qjs` & `qjsc` binaries, file `ext/myExt.js` can be imported from any script using `import * as myExt from 'ext/myExt.js';`
254 |
255 | ```
256 | .
257 | ├── [4.0K] examples
258 | ├── [4.0K] ext
259 | │ └── [ 335] myExt.js
260 | ├── [1.2M] libquickjs.a
261 | ├── [4.0K] musl-x86_64
262 | │ │ └...
263 | │ └── [4.0K] lib
264 | │ └...
265 | ├── [938K] qjs
266 | ├── [894K] qjsc
267 | ├── [ 364] qjsc.sh
268 | ├── [ 425] qjs.sh
269 | ├── [ 40K] quickjs.h
270 | └── [2.5K] quickjs-libc.h
271 | ```
272 |
273 | *ext/myExt.js*
274 | ```javascript
275 | const sayHello = (name) => {
276 | console.log(`Hello ${name}`);
277 | }
278 |
279 | const WEEKDAYS = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
280 | const sayWeekday = () => {
281 | const date = new Date();
282 | const wday = WEEKDAYS[date.getDay()];
283 | console.log(`Today is ${wday}`);
284 | }
285 |
286 | export default {
287 | sayHello:sayHello,
288 | sayWeekday:sayWeekday
289 | }
290 | export { sayHello, sayWeekday };
291 | ```
292 |
293 | *myScript.js*
294 | ```javascript
295 | import {sayHello, sayWeekday} from 'ext/myExt.js';
296 | sayHello('John Doe');
297 | sayWeekday();
298 | ```
299 |
300 | Both interpreter & compiler will first try to resolve import relatively to current directory and fallback to the directory containing `qjs` & `qjsc` binaries (or the directory defined using `QJS_LIB_DIR` environment variable)
301 |
302 | NB : fallback will only work when calling `qjs` & `qjsc` using their **absolute path** or through their corresponding **`sh` wrappers**
303 |
304 | Directories can be added to the package using argument `(--extra-dir, -e)` when calling `build_and_export_qjs.sh` script
305 |
306 | Examples
307 |
308 | ```
309 | ./builder/build_and_export_qjs.sh -e /tmp/ext1 -e /tmp/ext2
310 | ```
311 |
312 | Above command will copy `/tmp/ext1` & `/tmp/ext2` directories at the root of the package
313 |
314 | ```
315 | ./builder/build_and_export_qjs.sh -e /tmp/ext1:ext -e /tmp/ext2:ext
316 | ```
317 |
318 | Above command will copy **the content** of `/tmp/ext1` & `/tmp/ext2` directories into an `ext` subdirectory at the root of the package
319 |
320 | # Embed QuickJS extension library
321 |
322 | When using flag `--ext-lib`, [QuickJS extension library](https://github.com/ctn-malone/qjs-ext-lib) will be added to the package under `ext` directory
323 |
324 | This library contains a set of JS module to make creating static adhoc scripts easier
325 |
326 | # Limitations
327 |
328 | *QuickJS* is built without *LTO* support since `-flto` flag does not work when the host running `qjsc` is not using the same *gcc* bytecode version as the one used by the host where `qjsc` was compiled, resulting in a message such as below
329 |
330 | ```
331 | lto1: fatal error: bytecode stream in file ‘/usr/local/bin/quickjs/libquickjs.lto.a’ generated with LTO version 7.1 instead of the expected 6.0
332 | ```
333 |
--------------------------------------------------------------------------------
/builder/build_and_export_qjs.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ###
4 | #
5 | # Build a static version of QuickJS (interpreter & compiler)
6 | # Export a portable package which can be used to generate static binaries
7 | #
8 | ###
9 |
10 | script_dir="$(cd "$(dirname "$(readlink -f "$0")")" && pwd)" || { echo "Couldn't determine the script's running directory, which probably matters, bailing out" >&2; exit 2; }
11 | source "${script_dir}/env/qjs"
12 |
13 | # Created by argbash-init v2.10.0
14 | # ARG_OPTIONAL_SINGLE([packages-dir],[p],[directory where package will be exported],[$script_dir/../packages])
15 | # ARG_OPTIONAL_SINGLE([deps-dir],[],[directory where dependencies should be stored/buil],[$script_dir/../deps])
16 | # ARG_OPTIONAL_SINGLE([arch],[a],[target architecture],[x86_64])
17 | # ARG_OPTIONAL_BOOLEAN([ext-lib],[],[add QuickJS extension library],[off])
18 | # ARG_OPTIONAL_SINGLE([ext-lib-version],[],[QuickJS extension library version],[$default_qjs_ext_lib_version])
19 | # ARG_OPTIONAL_REPEATED([extra-dir],[e],[extra directory to add into package],[])
20 | # ARG_OPTIONAL_BOOLEAN([force-fetch-deps],[],[force re-fetching dependencies],[off])
21 | # ARG_OPTIONAL_BOOLEAN([force-build-deps],[],[force rebuild of dependencies],[off])
22 | # ARG_OPTIONAL_BOOLEAN([force-checkout-qjs],[],[clone repository even if it exists],[off])
23 | # ARG_OPTIONAL_BOOLEAN([force-build-qjs],[],[force rebuild of QuickJS],[off])
24 | # ARG_OPTIONAL_BOOLEAN([verbose],[v],[enable verbose mode],[off])
25 | # ARG_OPTIONAL_BOOLEAN([upx],[u],[compress binaries using upx],[on])
26 | # ARG_POSITIONAL_SINGLE([qjs-version],[QuickJS version (ex: 2020-09-06)],[$default_qjs_version])
27 | # ARG_TYPE_GROUP_SET([arch],[type string],[arch],[x86_64,i686,armv7l,aarch64])
28 | # ARG_HELP([Build a static version of QuickJS (interpreter & compiler)])
29 | # ARGBASH_GO()
30 | # needed because of Argbash --> m4_ignore([
31 | ### START OF CODE GENERATED BY Argbash v2.10.0 one line above ###
32 | # Argbash is a bash code generator used to get arguments parsing right.
33 | # Argbash is FREE SOFTWARE, see https://argbash.io for more info
34 |
35 |
36 | die()
37 | {
38 | local _ret="${2:-1}"
39 | test "${_PRINT_HELP:-no}" = yes && print_help >&2
40 | echo "$1" >&2
41 | exit "${_ret}"
42 | }
43 |
44 | # validators
45 |
46 | arch()
47 | {
48 | local _allowed=("x86_64" "i686" "armv7l" "aarch64") _seeking="$1"
49 | for element in "${_allowed[@]}"
50 | do
51 | test "$element" = "$_seeking" && echo "$element" && return 0
52 | done
53 | die "Value '$_seeking' (of argument '$2') doesn't match the list of allowed values: 'x86_64', 'i686', 'armv7l' and 'aarch64'" 4
54 | }
55 |
56 |
57 | begins_with_short_option()
58 | {
59 | local first_option all_short_options='paevuh'
60 | first_option="${1:0:1}"
61 | test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0
62 | }
63 |
64 | # THE DEFAULTS INITIALIZATION - POSITIONALS
65 | _positionals=()
66 | _arg_qjs_version="$default_qjs_version"
67 | # THE DEFAULTS INITIALIZATION - OPTIONALS
68 | _arg_packages_dir="$script_dir/../packages"
69 | _arg_deps_dir="$script_dir/../deps"
70 | _arg_arch="x86_64"
71 | _arg_ext_lib="off"
72 | _arg_ext_lib_version="$default_qjs_ext_lib_version"
73 | _arg_extra_dir=()
74 | _arg_force_fetch_deps="off"
75 | _arg_force_build_deps="off"
76 | _arg_force_checkout_qjs="off"
77 | _arg_force_build_qjs="off"
78 | _arg_verbose="off"
79 | _arg_upx="on"
80 |
81 |
82 | print_help()
83 | {
84 | printf '%s\n' "Build a static version of QuickJS (interpreter & compiler)"
85 | printf 'Usage: %s [-p|--packages-dir ] [--deps-dir ] [-a|--arch ] [--(no-)ext-lib] [--ext-lib-version ] [-e|--extra-dir ] [--(no-)force-fetch-deps] [--(no-)force-build-deps] [--(no-)force-checkout-qjs] [--(no-)force-build-qjs] [-v|--(no-)verbose] [-u|--(no-)upx] [-h|--help] []\n' "$0"
86 | printf '\t%s\n' ": QuickJS version (ex: 2020-09-06) (default: '$default_qjs_version')"
87 | printf '\t%s\n' "-p, --packages-dir: directory where package will be exported (default: '$script_dir/../packages')"
88 | printf '\t%s\n' "--deps-dir: directory where dependencies should be stored/buil (default: '$script_dir/../deps')"
89 | printf '\t%s\n' "-a, --arch: target architecture. Can be one of: 'x86_64', 'i686', 'armv7l' and 'aarch64' (default: 'x86_64')"
90 | printf '\t%s\n' "--ext-lib, --no-ext-lib: add QuickJS extension library (off by default)"
91 | printf '\t%s\n' "--ext-lib-version: QuickJS extension library version (default: '$default_qjs_ext_lib_version')"
92 | printf '\t%s\n' "-e, --extra-dir: extra directory to add into package (empty by default)"
93 | printf '\t%s\n' "--force-fetch-deps, --no-force-fetch-deps: force re-fetching dependencies (off by default)"
94 | printf '\t%s\n' "--force-build-deps, --no-force-build-deps: force rebuild of dependencies (off by default)"
95 | printf '\t%s\n' "--force-checkout-qjs, --no-force-checkout-qjs: clone repository even if it exists (off by default)"
96 | printf '\t%s\n' "--force-build-qjs, --no-force-build-qjs: force rebuild of QuickJS (off by default)"
97 | printf '\t%s\n' "-v, --verbose, --no-verbose: enable verbose mode (off by default)"
98 | printf '\t%s\n' "-u, --upx, --no-upx: compress binaries using upx (on by default)"
99 | printf '\t%s\n' "-h, --help: Prints help"
100 | }
101 |
102 |
103 | parse_commandline()
104 | {
105 | _positionals_count=0
106 | while test $# -gt 0
107 | do
108 | _key="$1"
109 | case "$_key" in
110 | -p|--packages-dir)
111 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
112 | _arg_packages_dir="$2"
113 | shift
114 | ;;
115 | --packages-dir=*)
116 | _arg_packages_dir="${_key##--packages-dir=}"
117 | ;;
118 | -p*)
119 | _arg_packages_dir="${_key##-p}"
120 | ;;
121 | --deps-dir)
122 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
123 | _arg_deps_dir="$2"
124 | shift
125 | ;;
126 | --deps-dir=*)
127 | _arg_deps_dir="${_key##--deps-dir=}"
128 | ;;
129 | -a|--arch)
130 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
131 | _arg_arch="$(arch "$2" "arch")" || exit 1
132 | shift
133 | ;;
134 | --arch=*)
135 | _arg_arch="$(arch "${_key##--arch=}" "arch")" || exit 1
136 | ;;
137 | -a*)
138 | _arg_arch="$(arch "${_key##-a}" "arch")" || exit 1
139 | ;;
140 | --no-ext-lib|--ext-lib)
141 | _arg_ext_lib="on"
142 | test "${1:0:5}" = "--no-" && _arg_ext_lib="off"
143 | ;;
144 | --ext-lib-version)
145 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
146 | _arg_ext_lib_version="$2"
147 | shift
148 | ;;
149 | --ext-lib-version=*)
150 | _arg_ext_lib_version="${_key##--ext-lib-version=}"
151 | ;;
152 | -e|--extra-dir)
153 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
154 | _arg_extra_dir+=("$2")
155 | shift
156 | ;;
157 | --extra-dir=*)
158 | _arg_extra_dir+=("${_key##--extra-dir=}")
159 | ;;
160 | -e*)
161 | _arg_extra_dir+=("${_key##-e}")
162 | ;;
163 | --no-force-fetch-deps|--force-fetch-deps)
164 | _arg_force_fetch_deps="on"
165 | test "${1:0:5}" = "--no-" && _arg_force_fetch_deps="off"
166 | ;;
167 | --no-force-build-deps|--force-build-deps)
168 | _arg_force_build_deps="on"
169 | test "${1:0:5}" = "--no-" && _arg_force_build_deps="off"
170 | ;;
171 | --no-force-checkout-qjs|--force-checkout-qjs)
172 | _arg_force_checkout_qjs="on"
173 | test "${1:0:5}" = "--no-" && _arg_force_checkout_qjs="off"
174 | ;;
175 | --no-force-build-qjs|--force-build-qjs)
176 | _arg_force_build_qjs="on"
177 | test "${1:0:5}" = "--no-" && _arg_force_build_qjs="off"
178 | ;;
179 | -v|--no-verbose|--verbose)
180 | _arg_verbose="on"
181 | test "${1:0:5}" = "--no-" && _arg_verbose="off"
182 | ;;
183 | -v*)
184 | _arg_verbose="on"
185 | _next="${_key##-v}"
186 | if test -n "$_next" -a "$_next" != "$_key"
187 | then
188 | { begins_with_short_option "$_next" && shift && set -- "-v" "-${_next}" "$@"; } || die "The short option '$_key' can't be decomposed to ${_key:0:2} and -${_key:2}, because ${_key:0:2} doesn't accept value and '-${_key:2:1}' doesn't correspond to a short option."
189 | fi
190 | ;;
191 | -u|--no-upx|--upx)
192 | _arg_upx="on"
193 | test "${1:0:5}" = "--no-" && _arg_upx="off"
194 | ;;
195 | -u*)
196 | _arg_upx="on"
197 | _next="${_key##-u}"
198 | if test -n "$_next" -a "$_next" != "$_key"
199 | then
200 | { begins_with_short_option "$_next" && shift && set -- "-u" "-${_next}" "$@"; } || die "The short option '$_key' can't be decomposed to ${_key:0:2} and -${_key:2}, because ${_key:0:2} doesn't accept value and '-${_key:2:1}' doesn't correspond to a short option."
201 | fi
202 | ;;
203 | -h|--help)
204 | print_help
205 | exit 0
206 | ;;
207 | -h*)
208 | print_help
209 | exit 0
210 | ;;
211 | *)
212 | _last_positional="$1"
213 | _positionals+=("$_last_positional")
214 | _positionals_count=$((_positionals_count + 1))
215 | ;;
216 | esac
217 | shift
218 | done
219 | }
220 |
221 |
222 | handle_passed_args_count()
223 | {
224 | test "${_positionals_count}" -le 1 || _PRINT_HELP=yes die "FATAL ERROR: There were spurious positional arguments --- we expect between 0 and 1, but got ${_positionals_count} (the last one was: '${_last_positional}')." 1
225 | }
226 |
227 |
228 | assign_positional_args()
229 | {
230 | local _positional_name _shift_for=$1
231 | _positional_names="_arg_qjs_version "
232 |
233 | shift "$_shift_for"
234 | for _positional_name in ${_positional_names}
235 | do
236 | test $# -gt 0 || break
237 | eval "$_positional_name=\${1}" || die "Error during argument parsing, possibly an Argbash bug." 1
238 | shift
239 | done
240 | }
241 |
242 | parse_commandline "$@"
243 | handle_passed_args_count
244 | assign_positional_args 1 "${_positionals[@]}"
245 |
246 | # OTHER STUFF GENERATED BY Argbash
247 | # Validation of values
248 |
249 |
250 | ### END OF CODE GENERATED BY Argbash (sortof) ### ])
251 | # [ <-- needed because of Argbash
252 |
253 |
254 | # vvv PLACE YOUR CODE HERE vvv
255 |
256 | source "${script_dir}/env/qjs"
257 |
258 | # ensure version exist
259 | qjs_commit="${qjs_commits[${_arg_qjs_version}]}"
260 | if [ -z ${qjs_commit} ]
261 | then
262 | _PRINT_HELP=yes die "QuickJS version '${_arg_qjs_version}' is not supported"
263 | fi
264 |
265 | _PRINT_HELP=no
266 |
267 | build_qjs()
268 | {
269 | _flag_verbose=""
270 | [ ${_arg_verbose} == "on" ] && _flag_verbose="-v"
271 | _flag_force_fetch_deps=""
272 | [ ${_arg_force_fetch_deps} == "on" ] && _flag_force_fetch_deps="-f"
273 | _flag_force_build_deps=""
274 | [ ${_arg_force_build_deps} == "on" ] && _flag_force_build_deps="-f"
275 | _flag_force_checkout_qjs=""
276 | [ ${_arg_force_checkout_qjs} == "on" ] && _flag_force_checkout_qjs="-f"
277 | _flag_force_build_qjs=""
278 | [ ${_arg_force_build_qjs} == "on" ] && _flag_force_build_qjs="-f"
279 |
280 | ${script_dir}/scripts/fetch_deps.sh ${_flag_verbose} -d ${_arg_deps_dir} -a ${_arg_arch} ${_flag_force_fetch_deps} || return 1
281 | ${script_dir}/scripts/build_deps.sh ${_flag_verbose} -d ${_arg_deps_dir} -a ${_arg_arch} ${_flag_force_build_deps} || return 1
282 | ${script_dir}/scripts/checkout_qjs.sh ${_arg_qjs_version} ${_flag_verbose} ${_flag_force_checkout_qjs} || return 1
283 | ${script_dir}/scripts/prepare_qjs.sh ${_arg_qjs_version} ${_flag_verbose} -d ${_arg_deps_dir} -a ${_arg_arch} || return 1
284 | ${script_dir}/scripts/build_qjs.sh ${_arg_qjs_version} ${_flag_verbose} -d ${_arg_deps_dir} -a ${_arg_arch} ${_flag_force_build_qjs} || return 1
285 |
286 | return 0
287 | }
288 |
289 | build_qjs || exit 1
290 | args_qjs_ext_lib=""
291 | if [ ${_arg_ext_lib} == "on" ]
292 | then
293 | args_qjs_ext_lib="--ext-lib --ext-lib-version ${_arg_ext_lib_version}"
294 | fi
295 | args_extra_dir=""
296 | for a in ${_arg_extra_dir[@]}
297 | do
298 | args_extra_dir="${args_extra_dir} -e ${a}"
299 | done
300 | _flag_disable_upx=""
301 | [ ${_arg_upx} == "off" ] && _flag_disable_upx="--no-upx"
302 |
303 | #echo "${script_dir}/scripts/export_qjs.sh ${_arg_qjs_version} ${_flag_verbose} -d ${_arg_deps_dir} -p ${_arg_packages_dir} -a ${_arg_arch} ${args_qjs_ext_lib} ${args_extra_dir} ${_flag_disable_upx}"
304 | ${script_dir}/scripts/export_qjs.sh ${_arg_qjs_version} ${_flag_verbose} -d ${_arg_deps_dir} -p ${_arg_packages_dir} -a ${_arg_arch} ${args_qjs_ext_lib} ${args_extra_dir} ${_flag_disable_upx} || exit 1
305 |
306 | echo "Successfully built & exported 'QuickJS' version '${_arg_qjs_version}' for '${_arg_arch}'"
307 |
308 | # ^^^ TERMINATE YOUR CODE BEFORE THE BOTTOM ARGBASH MARKER ^^^
309 |
310 | # ] <-- needed because of Argbash
311 |
--------------------------------------------------------------------------------
/builder/custom/README.md:
--------------------------------------------------------------------------------
1 | Cross compile [QuickJS](https://github.com/bellard/quickjs) interpreter & compiler statically. Resulting [QuickJS](https://github.com/bellard/quickjs) compiler also generates *static* binaries based on [musl libc](https://musl.libc.org/)
2 |
3 | Following target architectures are supported
4 |
5 | * x86_64
6 | * i686
7 | * armv7l
8 | * aarch64
9 |
10 | Cross compilation is performed using [musl.cc](https://musl.cc/) static compilers (which means you should be able to generate a portable package of *QuickJS* from any recent *x86_64* Linux distribution with *gcc*)
11 |
12 | Final portable version should weight around 7MB (after decompression)
13 |
14 | Static compiler should work with any Linux distribution with *gcc* >= `4.3.2`
15 |
16 | See https://github.com/ctn-malone/quickjs-cross-compiler for more informations
17 |
--------------------------------------------------------------------------------
/builder/custom/musl/bin/musl-gcc:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | ###
4 | #
5 | # Wrapper used to link to the musl library embedded in the portable package
6 | # Environment variable 'qjs_cc' will be used only when compiling QuickJS
7 | #
8 | ###
9 |
10 | script_dir="$( cd "$( dirname "${0}" )" >/dev/null && pwd )"
11 |
12 | # $1 version to check
13 | # $2 minimum version
14 | gte_version()
15 | {
16 | _major=$(echo $1 | cut -d'.' -f1)
17 | _major_minimum=$(echo $2 | cut -d'.' -f1)
18 | _minor=$(echo $1 | cut -s -d'.' -f2)
19 | [ -z ${_minor} ] && _minor=0
20 | _minor_minimum=$(echo $2 | cut -s -d'.' -f2)
21 | [ -z ${_minor_minimum} ] && _minor_minimum=0
22 | [ ${_major} -lt ${_major_minimum} ] && return 1
23 | [ ${_major} -gt ${_major_minimum} ] && return 0
24 | [ ${_minor} -lt ${_minor_minimum} ] && return 1
25 | return 0
26 | }
27 |
28 | musl_dir="${script_dir}/.."
29 | gcc_version=$(gcc -dumpversion)
30 | # extra gcc flags
31 | flags=""
32 |
33 | # only define new flags if ${qjs_cc} is not set (ie: if we're not building qjs)
34 | if [ -z ${qjs_cc} ]
35 | then
36 | # '-no-pie' flag is supported for gcc >= 6.1
37 | if gte_version ${gcc_version} "6.1"
38 | then
39 | flags="${flags} -no-pie"
40 | fi
41 | fi
42 |
43 | #echo "musl_dir=${musl_dir} exec \"${qjs_cc:-gcc}\" \"$@\" ${flags} -specs \"${musl_dir}/lib/musl-gcc.specs\""
44 | musl_dir=${musl_dir} exec "${qjs_cc:-gcc}" "$@" ${flags} -specs "${musl_dir}/lib/musl-gcc.specs"
45 |
--------------------------------------------------------------------------------
/builder/custom/musl/lib/musl-gcc.specs:
--------------------------------------------------------------------------------
1 | %rename cpp_options old_cpp_options
2 |
3 | *cpp_options:
4 | -nostdinc -isystem %:getenv(musl_dir /include) -isystem include%s %(old_cpp_options)
5 |
6 | *cc1:
7 | %(cc1_cpu) -nostdinc -isystem %:getenv(musl_dir /include) -isystem include%s
8 |
9 | *link_libgcc:
10 | -L %:getenv(musl_dir /lib) -L .%s
11 |
12 | *libgcc:
13 | libgcc.a%s %:if-exists(libgcc_eh.a%s)
14 |
15 | *startfile:
16 | %{!shared: %:getenv(musl_dir /lib/Scrt1.o)} %:getenv(musl_dir /lib/crti.o) crtbeginS.o%s
17 |
18 | *endfile:
19 | crtendS.o%s %:getenv(musl_dir /lib/crtn.o)
20 |
21 | *link:
22 | -dynamic-linker %:getenv(musl_dir /lib/ld-musl-x86_64.so.1) -nostdlib %{shared:-shared} %{static:-static} %{rdynamic:-export-dynamic}
23 |
24 | *esp_link:
25 |
26 |
27 | *esp_options:
28 |
29 |
30 | *esp_cpp_options:
31 |
32 |
33 | # comment to avoid gcc error "gcc: fatal error: specs file malformed after ..."
34 | # we need to have 2 lines after esp_cpp_options
35 |
--------------------------------------------------------------------------------
/builder/custom/qjs/examples/ext-lib/example1.js:
--------------------------------------------------------------------------------
1 | import { exec } from 'ext/process.js';
2 |
3 | /*
4 | Run 3 external commands in parallel
5 | */
6 |
7 | const main = async () => {
8 | const commands = [
9 | 'date',
10 | 'uptime',
11 | 'which sh'
12 | ];
13 | const promises = [];
14 | commands.forEach(c => promises.push(exec(c)));
15 | (await Promise.all(promises)).forEach((output, i) => {
16 | console.log(`${commands[i]} => ${output}`);
17 | });
18 | }
19 |
20 | main();
21 |
--------------------------------------------------------------------------------
/builder/custom/qjs/examples/ext-lib/example2.js:
--------------------------------------------------------------------------------
1 | import arg from 'ext/arg.js';
2 | import * as path from 'ext/path.js';
3 | import { exec } from 'ext/process.js';
4 |
5 | import * as std from 'std';
6 |
7 | /*
8 | Simple CLI example
9 | */
10 |
11 | const COMMANDS = ['date', 'uptime'];
12 |
13 | const getUsage = () => {
14 | const message = `
15 | Usage: ${path.getScriptName(true)} [-h|--help] [-c|--command] [-v|--verbose]
16 | -c --command: run command
17 | Should be one of [${COMMANDS.join(',')}]
18 | -v --verbose: enable verbose mode
19 | -h, --help: print help
20 | `.trim();
21 | return message;
22 | }
23 |
24 | const getHelp = () => {
25 | const message = `
26 | Run a command
27 | `.trim();
28 | return `${message}\n${getUsage()}`;
29 | }
30 |
31 | let args;
32 | try {
33 | args = arg({
34 | '--command': (v, n, p) => {
35 | const value = v.trim();
36 | if (!COMMANDS.includes(value)) {
37 | const err = new Error(`Invalid option value: ${n} (${v}) (should be one of [${COMMANDS.join(',')}])`);
38 | err.code = 'ARG_INVALID_OPTION';
39 | throw err;
40 | }
41 | return value;
42 | },
43 | '--help': Boolean,
44 | '--verbose':Boolean,
45 | // aliases
46 | '-c': '--command',
47 | '-v': '--verbose',
48 | '-h': '--help'
49 | });
50 | }
51 | catch (e) {
52 | switch (e.code) {
53 | case 'ARG_UNKNOWN_OPTION':
54 | case 'ARG_INVALID_OPTION':
55 | case 'ARG_MISSING_REQUIRED_SHORTARG':
56 | case 'ARG_MISSING_REQUIRED_LONGARG':
57 | std.err.printf(`${e.message.trim()}\n`);
58 | std.err.printf(`${getUsage()}\n`);
59 | std.exit(2);
60 | }
61 | throw e;
62 | }
63 | if (args['--help']) {
64 | std.err.printf(`${getHelp()}\n`);
65 | std.exit(2);
66 | }
67 |
68 | // ensure all required arguments were provided
69 | ['--command'].forEach((n) => {
70 | if (undefined === args[n]) {
71 | std.err.printf(`Option ${n} is required\n`);
72 | std.err.printf(`${getUsage()}\n`);
73 | std.exit(2);
74 | }
75 | });
76 |
77 | if (args['--verbose']) {
78 | console.log(`Will run command '${args['--command']}'`);
79 | }
80 | exec(args['--command']).then((output) => {
81 | console.log(output);
82 | });
83 |
--------------------------------------------------------------------------------
/builder/custom/qjs/examples/ext-lib/example3.js:
--------------------------------------------------------------------------------
1 | import { curlRequest } from 'ext/curl.js';
2 |
3 | /*
4 | Perform a POST request to https://jsonplaceholder.typicode.com/posts and print response payload
5 | */
6 |
7 | const main = async () => {
8 | const body = await curlRequest('https://jsonplaceholder.typicode.com/posts', {
9 | method:'post',
10 | json: {
11 | title: 'foo',
12 | body: 'bar',
13 | userId: 1
14 | }
15 | });
16 | console.log(JSON.stringify(body, null, 4));
17 | }
18 |
19 | main();
20 |
--------------------------------------------------------------------------------
/builder/custom/qjs/examples/ext-lib/example4.js:
--------------------------------------------------------------------------------
1 | import { sshExec } from 'ext/ssh.js';
2 | import * as std from 'std';
3 |
4 | /*
5 | Execute 'date' command over ssh on localhost
6 | */
7 |
8 | const main = async () => {
9 | try {
10 | const stdout = await sshExec('127.0.0.1', 'date');
11 | console.log(`Date: ${stdout}`);
12 | }
13 | catch (e) {
14 | if (undefined !== e.sshErrorReason) {
15 | console.log(`SSH failed (${e.sshErrorReason}) : ${e.sshError}`);
16 | }
17 | else {
18 | console.log(`SSH failed : ${e.message}`);
19 | }
20 | std.exit(1);
21 | }
22 | }
23 |
24 | main();
25 |
--------------------------------------------------------------------------------
/builder/custom/qjs/files/path.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #include "path.h"
5 |
6 | static char exe_dir[4096];
7 |
8 | /**
9 | * Build an absolute path by concatenating {dir} and a relative path
10 | *
11 | * @param {char*} buf buffer to update
12 | * @param {int} buf_size size of buffer
13 | * @param {char*} dir directory to concatenate
14 | * @param {char*} path path to concatenate
15 | */
16 | void get_path_with_dir(char *buf, int buf_size, char* dir, char* path)
17 | {
18 | // only use {dir} if it exists and path is relative
19 | if (NULL != dir && NULL != path && '/' != path[0]) {
20 | pstrcpy(buf, buf_size, dir);
21 | pstrcat(buf, buf_size, "/");
22 | }
23 | pstrcat(buf, buf_size, path);
24 | }
25 |
26 | /**
27 | * Update {exe_dir} variable based on executable name
28 | *
29 | * @param {char*} exe_name executable name
30 | */
31 | void set_exe_dir_from_exe_name(char* exe_name)
32 | {
33 | char *p;
34 | /* get the directory of the executable */
35 | pstrcpy(exe_dir, sizeof(exe_dir), exe_name);
36 | p = strrchr(exe_dir, '/');
37 | if (p) {
38 | *p = '\0';
39 | } else {
40 | pstrcpy(exe_dir, sizeof(exe_dir), ".");
41 | }
42 | }
43 |
44 | /**
45 | * Build an absolute path by concatenating {exe_dir} and a relative path
46 | *
47 | * @param {char*} buf buffer to update
48 | * @param {int} buf_size size of buffer
49 | * @param {char*} path path to concatenate
50 | */
51 | void get_path_with_exe_dir(char *buf, int buf_size, char* path)
52 | {
53 | get_path_with_dir(buf, buf_size, exe_dir, path);
54 | }
55 |
56 |
--------------------------------------------------------------------------------
/builder/custom/qjs/files/path.h:
--------------------------------------------------------------------------------
1 | #ifndef PATH_H
2 | #define PATH_H
3 |
4 | #include "cutils.h"
5 |
6 | void get_path_with_dir(char *buf, int buf_size, char* dir, char* path);
7 | void set_exe_dir_from_exe_name(char* exe_name);
8 | void get_path_with_exe_dir(char *buf, int buf_size, char* path);
9 |
10 | #endif /* PATH_H */
11 |
--------------------------------------------------------------------------------
/builder/custom/qjs/patches/2020-09-06/Makefile.patch:
--------------------------------------------------------------------------------
1 | diff --git a/Makefile b/Makefile
2 | index 94c8e31..faf35d4 100644
3 | --- a/Makefile
4 | +++ b/Makefile
5 | @@ -28,7 +28,8 @@ endif
6 | # Windows cross compilation from Linux
7 | #CONFIG_WIN32=y
8 | # use link time optimization (smaller and faster executables but slower build)
9 | -CONFIG_LTO=y
10 | +#-- disable LTO
11 | +#CONFIG_LTO=y
12 | # consider warnings as errors (for development)
13 | #CONFIG_WERROR=y
14 | # force 32 bit build for some utilities
15 | @@ -41,7 +42,9 @@ CONFIG_DEFAULT_AR=y
16 | endif
17 |
18 | # installation directory
19 | -prefix=/usr/local
20 | +#-- change prefix to /
21 | +#prefix=/usr/local
22 | +prefix=/
23 |
24 | # use the gprof profiler
25 | #CONFIG_PROFILE=y
26 | @@ -82,7 +85,9 @@ ifdef CONFIG_CLANG
27 | endif
28 | else
29 | HOST_CC=gcc
30 | - CC=$(CROSS_PREFIX)gcc
31 | + #-- use musl-gcc instead of gcc (symlink must exist)
32 | + #CC=$(CROSS_PREFIX)gcc
33 | + CC=$(CURDIR)/musl-$(musl_arch)/bin/musl-gcc
34 | CFLAGS=-g -Wall -MMD -MF $(OBJDIR)/$(@F).d
35 | CFLAGS += -Wno-array-bounds -Wno-format-truncation
36 | ifdef CONFIG_LTO
37 | @@ -96,6 +101,8 @@ ifdef CONFIG_WERROR
38 | CFLAGS+=-Werror
39 | endif
40 | DEFINES:=-D_GNU_SOURCE -DCONFIG_VERSION=\"$(shell cat VERSION)\"
41 | +#-- define target architecture
42 | +DEFINES+=-DMUSL_ARCH=\"$(musl_arch)\"
43 | ifdef CONFIG_BIGNUM
44 | DEFINES+=-DCONFIG_BIGNUM
45 | endif
46 | @@ -109,6 +116,10 @@ CFLAGS_SMALL=$(CFLAGS) -Os
47 | CFLAGS_OPT=$(CFLAGS) -O2
48 | CFLAGS_NOLTO:=$(CFLAGS_OPT)
49 | LDFLAGS=-g
50 | +#-- force static compilation
51 | +LDFLAGS+=-static
52 | +#-- disable PIE
53 | +CFLAGS+=-no-pie
54 | ifdef CONFIG_LTO
55 | CFLAGS_SMALL+=-flto
56 | CFLAGS_OPT+=-flto
57 | @@ -148,12 +159,17 @@ ifdef CONFIG_LTO
58 | PROGS+=libquickjs.lto.a
59 | endif
60 |
61 | +#--when architecture is not 'x86_64', we need to use the 'x86_64' version of the 'qjsc' binary to generate c files
62 | +QJSC_X86_64=$(qjsc_binary)
63 | +
64 | # examples
65 | ifeq ($(CROSS_PREFIX),)
66 | ifdef CONFIG_ASAN
67 | PROGS+=
68 | else
69 | -PROGS+=examples/hello examples/hello_module examples/test_fib
70 | +#-- disable 'hello_module' & 'test_fib' examples because of cross-compilation
71 | +#PROGS+=examples/hello examples/hello_module examples/test_fib
72 | +PROGS+=examples/hello
73 | ifndef CONFIG_DARWIN
74 | PROGS+=examples/fib.so examples/point.so
75 | endif
76 | @@ -176,6 +192,9 @@ ifndef CONFIG_WIN32
77 | LIBS+=-ldl -lpthread
78 | endif
79 |
80 | +#-- static linking to libatomic (necessary for armv7l)
81 | +LIBS+=-L $(CURDIR)/musl-$(musl_arch)/lib -latomic
82 | +
83 | $(OBJDIR):
84 | mkdir -p $(OBJDIR) $(OBJDIR)/examples $(OBJDIR)/tests
85 |
86 | @@ -230,10 +249,12 @@ libquickjs.a: $(patsubst %.o, %.nolto.o, $(QJS_LIB_OBJS))
87 | endif # CONFIG_LTO
88 |
89 | repl.c: $(QJSC) repl.js
90 | - $(QJSC) -c -o $@ -m repl.js
91 | + #-- will use the 'x86_64' version of 'qjsc' when architecture is not 'x86_64'
92 | + $(QJSC_X86_64) -c -o $@ -m repl.js
93 |
94 | qjscalc.c: $(QJSC) qjscalc.js
95 | - $(QJSC) -fbignum -c -o $@ qjscalc.js
96 | + #-- will use the 'x86_64' version of 'qjsc' when architecture is not 'x86_64'
97 | + $(QJSC_X86_64) -fbignum -c -o $@ qjscalc.js
98 |
99 | ifneq ($(wildcard unicode/UnicodeData.txt),)
100 | $(OBJDIR)/libunicode.o $(OBJDIR)/libunicode.m32.o $(OBJDIR)/libunicode.m32s.o \
101 | @@ -295,9 +316,12 @@ clean:
102 | rm -rf $(OBJDIR)/ *.dSYM/ qjs-debug
103 | rm -rf run-test262-debug run-test262-32
104 |
105 | -install: all
106 | +#-- only install
107 | +#install: all
108 | +install:
109 | mkdir -p "$(DESTDIR)$(prefix)/bin"
110 | - $(STRIP) qjs qjsc
111 | + #-- disable stripping (because of cross-compiling)
112 | + #$(STRIP) qjs qjsc
113 | install -m755 qjs qjsc "$(DESTDIR)$(prefix)/bin"
114 | ln -sf qjs "$(DESTDIR)$(prefix)/bin/qjscalc"
115 | mkdir -p "$(DESTDIR)$(prefix)/lib/quickjs"
116 | @@ -321,7 +345,8 @@ HELLO_OPTS+=-fno-bigint
117 | endif
118 |
119 | hello.c: $(QJSC) $(HELLO_SRCS)
120 | - $(QJSC) -e $(HELLO_OPTS) -o $@ $(HELLO_SRCS)
121 | + #-- will use the 'x86_64' version of 'qjsc' when architecture is not 'x86_64'
122 | + $(QJSC_X86_64) -e $(HELLO_OPTS) -o $@ $(HELLO_SRCS)
123 |
124 | ifdef CONFIG_M32
125 | examples/hello: $(OBJDIR)/hello.m32s.o $(patsubst %.o, %.m32s.o, $(QJS_LIB_OBJS))
126 |
--------------------------------------------------------------------------------
/builder/custom/qjs/patches/2020-09-06/qjsc.patch:
--------------------------------------------------------------------------------
1 | diff --git a/qjsc.c b/qjsc.c
2 | index f5bda57..7e1919d 100644
3 | --- a/qjsc.c
4 | +++ b/qjsc.c
5 | @@ -370,6 +370,13 @@
6 | printf("]\n"
7 | " disable selected language features (smaller code size)\n");
8 | }
9 | +#else
10 | + //-- define '-fbignum' if 'CONFIG_BIGNUM' is defined
11 | + #ifdef CONFIG_BIGNUM
12 | + {
13 | + printf("-fbignum enable bignum extensions\n");
14 | + }
15 | + #endif
16 | #endif
17 | exit(1);
18 | }
19 | @@ -401,6 +408,8 @@
20 | const char **arg, *bn_suffix, *lto_suffix;
21 | char libjsname[1024];
22 | char exe_dir[1024], inc_dir[1024], lib_dir[1024], buf[1024], *p;
23 | + //-- used to store relative path to musl-gcc
24 | + char musl_gcc[1024];
25 | int ret;
26 |
27 | /* get the directory of the executable */
28 | @@ -427,8 +436,15 @@
29 | bn_suffix = "";
30 |
31 | arg = argv;
32 | - *arg++ = CONFIG_CC;
33 | + //-- use included musl-gcc wrapper instead of default compiler
34 | + //*arg++ = CONFIG_CC;
35 | + snprintf(musl_gcc, sizeof(musl_gcc), "%s/musl-%s/bin/musl-gcc", exe_dir, MUSL_ARCH);
36 | + *arg++ = musl_gcc;
37 | *arg++ = "-O2";
38 | + //-- force static compilation
39 | + *arg++ = "-static";
40 | + //-- strip
41 | + *arg++ = "-s";
42 | #ifdef CONFIG_LTO
43 | if (use_lto) {
44 | *arg++ = "-flto";
45 | @@ -452,6 +468,8 @@
46 | *arg++ = "-lm";
47 | *arg++ = "-ldl";
48 | *arg++ = "-lpthread";
49 | + //-- link to libatomic (armv7l)
50 | + *arg++ = "-latomic";
51 | *arg = NULL;
52 |
53 | if (verbose) {
54 |
55 |
--------------------------------------------------------------------------------
/builder/custom/qjs/patches/2020-11-08/Makefile.patch:
--------------------------------------------------------------------------------
1 | diff --git a/Makefile b/Makefile
2 | index e6ae827..e36b8c4 100644
3 | --- a/Makefile
4 | +++ b/Makefile
5 | @@ -28,7 +28,8 @@ endif
6 | # Windows cross compilation from Linux
7 | #CONFIG_WIN32=y
8 | # use link time optimization (smaller and faster executables but slower build)
9 | -CONFIG_LTO=y
10 | +#-- disable LTO
11 | +#CONFIG_LTO=y
12 | # consider warnings as errors (for development)
13 | #CONFIG_WERROR=y
14 | # force 32 bit build for some utilities
15 | @@ -41,7 +42,9 @@ CONFIG_DEFAULT_AR=y
16 | endif
17 |
18 | # installation directory
19 | -prefix=/usr/local
20 | +#-- change prefix to /
21 | +#prefix=/usr/local
22 | +prefix=/
23 |
24 | # use the gprof profiler
25 | #CONFIG_PROFILE=y
26 | @@ -86,7 +89,9 @@ ifdef CONFIG_CLANG
27 | endif
28 | else
29 | HOST_CC=gcc
30 | - CC=$(CROSS_PREFIX)gcc
31 | + #-- use musl-gcc instead of gcc (symlink must exist)
32 | + #CC=$(CROSS_PREFIX)gcc
33 | + CC=$(CURDIR)/musl-$(musl_arch)/bin/musl-gcc
34 | CFLAGS=-g -Wall -MMD -MF $(OBJDIR)/$(@F).d
35 | CFLAGS += -Wno-array-bounds -Wno-format-truncation
36 | ifdef CONFIG_LTO
37 | @@ -100,6 +105,8 @@ ifdef CONFIG_WERROR
38 | CFLAGS+=-Werror
39 | endif
40 | DEFINES:=-D_GNU_SOURCE -DCONFIG_VERSION=\"$(shell cat VERSION)\"
41 | +#-- define target architecture
42 | +DEFINES+=-DMUSL_ARCH=\"$(musl_arch)\"
43 | ifdef CONFIG_BIGNUM
44 | DEFINES+=-DCONFIG_BIGNUM
45 | endif
46 | @@ -113,6 +120,10 @@ CFLAGS_SMALL=$(CFLAGS) -Os
47 | CFLAGS_OPT=$(CFLAGS) -O2
48 | CFLAGS_NOLTO:=$(CFLAGS_OPT)
49 | LDFLAGS=-g
50 | +#-- force static compilation
51 | +LDFLAGS+=-static
52 | +#-- disable PIE
53 | +CFLAGS+=-no-pie
54 | ifdef CONFIG_LTO
55 | CFLAGS_SMALL+=-flto
56 | CFLAGS_OPT+=-flto
57 | @@ -152,12 +163,17 @@ ifdef CONFIG_LTO
58 | PROGS+=libquickjs.lto.a
59 | endif
60 |
61 | +#--when architecture is not 'x86_64', we need to use the 'x86_64' version of the 'qjsc' binary to generate c files
62 | +QJSC_X86_64=$(qjsc_binary)
63 | +
64 | # examples
65 | ifeq ($(CROSS_PREFIX),)
66 | ifdef CONFIG_ASAN
67 | PROGS+=
68 | else
69 | -PROGS+=examples/hello examples/hello_module examples/test_fib
70 | +#-- disable 'hello_module' & 'test_fib' examples because of cross-compilation
71 | +#PROGS+=examples/hello examples/hello_module examples/test_fib
72 | +PROGS+=examples/hello
73 | ifndef CONFIG_DARWIN
74 | PROGS+=examples/fib.so examples/point.so
75 | endif
76 | @@ -166,7 +182,7 @@ endif
77 |
78 | all: $(OBJDIR) $(OBJDIR)/quickjs.check.o $(OBJDIR)/qjs.check.o $(PROGS)
79 |
80 | -QJS_LIB_OBJS=$(OBJDIR)/quickjs.o $(OBJDIR)/libregexp.o $(OBJDIR)/libunicode.o $(OBJDIR)/cutils.o $(OBJDIR)/quickjs-libc.o
81 | +QJS_LIB_OBJS=$(OBJDIR)/quickjs.o $(OBJDIR)/libregexp.o $(OBJDIR)/libunicode.o $(OBJDIR)/cutils.o $(OBJDIR)/quickjs-libc.o $(OBJDIR)/path.o
82 |
83 | QJS_OBJS=$(OBJDIR)/qjs.o $(OBJDIR)/repl.o $(QJS_LIB_OBJS)
84 | ifdef CONFIG_BIGNUM
85 | @@ -180,6 +196,9 @@ ifndef CONFIG_WIN32
86 | LIBS+=-ldl -lpthread
87 | endif
88 |
89 | +#-- static linking to libatomic (necessary for armv7l)
90 | +LIBS+=-L $(CURDIR)/musl-$(musl_arch)/lib -latomic
91 | +
92 | $(OBJDIR):
93 | mkdir -p $(OBJDIR) $(OBJDIR)/examples $(OBJDIR)/tests
94 |
95 | @@ -234,10 +253,12 @@ libquickjs.a: $(patsubst %.o, %.nolto.o, $(QJS_LIB_OBJS))
96 | endif # CONFIG_LTO
97 |
98 | repl.c: $(QJSC) repl.js
99 | - $(QJSC) -c -o $@ -m repl.js
100 | + #-- will use the 'x86_64' version of 'qjsc' when architecture is not 'x86_64'
101 | + $(QJSC_X86_64) -c -o $@ -m repl.js
102 |
103 | qjscalc.c: $(QJSC) qjscalc.js
104 | - $(QJSC) -fbignum -c -o $@ qjscalc.js
105 | + #-- will use the 'x86_64' version of 'qjsc' when architecture is not 'x86_64'
106 | + $(QJSC_X86_64) -fbignum -c -o $@ qjscalc.js
107 |
108 | ifneq ($(wildcard unicode/UnicodeData.txt),)
109 | $(OBJDIR)/libunicode.o $(OBJDIR)/libunicode.m32.o $(OBJDIR)/libunicode.m32s.o \
110 | @@ -296,9 +317,12 @@ clean:
111 | rm -rf $(OBJDIR)/ *.dSYM/ qjs-debug
112 | rm -rf run-test262-debug run-test262-32
113 |
114 | -install: all
115 | +#-- only install
116 | +#install: all
117 | +install:
118 | mkdir -p "$(DESTDIR)$(prefix)/bin"
119 | - $(STRIP) qjs qjsc
120 | + #-- disable stripping (because of cross-compiling)
121 | + #$(STRIP) qjs qjsc
122 | install -m755 qjs qjsc "$(DESTDIR)$(prefix)/bin"
123 | ln -sf qjs "$(DESTDIR)$(prefix)/bin/qjscalc"
124 | mkdir -p "$(DESTDIR)$(prefix)/lib/quickjs"
125 | @@ -322,7 +346,8 @@ HELLO_OPTS+=-fno-bigint
126 | endif
127 |
128 | hello.c: $(QJSC) $(HELLO_SRCS)
129 | - $(QJSC) -e $(HELLO_OPTS) -o $@ $(HELLO_SRCS)
130 | + #-- will use the 'x86_64' version of 'qjsc' when architecture is not 'x86_64'
131 | + $(QJSC_X86_64) -e $(HELLO_OPTS) -o $@ $(HELLO_SRCS)
132 |
133 | ifdef CONFIG_M32
134 | examples/hello: $(OBJDIR)/hello.m32s.o $(patsubst %.o, %.m32s.o, $(QJS_LIB_OBJS))
135 |
--------------------------------------------------------------------------------
/builder/custom/qjs/patches/2020-11-08/qjs.patch:
--------------------------------------------------------------------------------
1 | diff --git a/qjs.c b/qjs.c
2 | index 4dd11f8..ae19184 100644
3 | --- a/qjs.c
4 | +++ b/qjs.c
5 | @@ -41,6 +41,8 @@
6 | #include "cutils.h"
7 | #include "quickjs-libc.h"
8 |
9 | +#include "path.h"
10 | +
11 | extern const uint8_t qjsc_repl[];
12 | extern const uint32_t qjsc_repl_size;
13 | #ifdef CONFIG_BIGNUM
14 | @@ -331,7 +333,9 @@ int main(int argc, char **argv)
15 | load_jscalc = !strcmp(exename, "qjscalc");
16 | }
17 | #endif
18 | -
19 | +
20 | + set_exe_dir_from_exe_name(argv[0]);
21 | +
22 | /* cannot use getopt because we want to pass the command line to
23 | the script */
24 | optind = 1;
25 |
--------------------------------------------------------------------------------
/builder/custom/qjs/patches/2020-11-08/qjsc.patch:
--------------------------------------------------------------------------------
1 | diff --git a/qjsc.c b/qjsc.c
2 | index f5bda57..86db7fe 100644
3 | --- a/qjsc.c
4 | +++ b/qjsc.c
5 | @@ -1,6 +1,6 @@
6 | /*
7 | * QuickJS command line compiler
8 | - *
9 | + *
10 | * Copyright (c) 2018-2020 Fabrice Bellard
11 | *
12 | * Permission is hereby granted, free of charge, to any person obtaining a copy
13 | @@ -36,6 +36,8 @@
14 | #include "cutils.h"
15 | #include "quickjs-libc.h"
16 |
17 | +#include "path.h"
18 | +
19 | typedef struct {
20 | char *name;
21 | char *short_name;
22 | @@ -131,7 +133,7 @@ static void get_c_name(char *buf, size_t buf_size, const char *file)
23 | size_t len, i;
24 | int c;
25 | char *q;
26 | -
27 | +
28 | p = strrchr(file, '/');
29 | if (!p)
30 | p = file;
31 | @@ -189,8 +191,8 @@ static void output_object_code(JSContext *ctx,
32 | }
33 |
34 | namelist_add(&cname_list, c_name, NULL, load_only);
35 | -
36 | - fprintf(fo, "const uint32_t %s_size = %u;\n\n",
37 | +
38 | + fprintf(fo, "const uint32_t %s_size = %u;\n\n",
39 | c_name, (unsigned int)out_buf_len);
40 | fprintf(fo, "const uint8_t %s[%u] = {\n",
41 | c_name, (unsigned int)out_buf_len);
42 | @@ -253,14 +255,27 @@ JSModuleDef *jsc_module_loader(JSContext *ctx,
43 | uint8_t *buf;
44 | JSValue func_val;
45 | char cname[1024];
46 | -
47 | +
48 | buf = js_load_file(ctx, &buf_len, module_name);
49 | +/*
50 | if (!buf) {
51 | JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
52 | module_name);
53 | return NULL;
54 | }
55 | -
56 | +*/
57 | + if (!buf) {
58 | + // try with a path relative to qjsc exe
59 | + char path[4096];
60 | + get_path_with_exe_dir(path, sizeof(path), (char*)module_name);
61 | + buf = js_load_file(ctx, &buf_len, path);
62 | + if (!buf) {
63 | + JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
64 | + module_name);
65 | + return NULL;
66 | + }
67 | + }
68 | +
69 | /* compile the module */
70 | func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name,
71 | JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
72 | @@ -272,7 +287,7 @@ JSModuleDef *jsc_module_loader(JSContext *ctx,
73 | find_unique_cname(cname, sizeof(cname));
74 | }
75 | output_object_code(ctx, outfile, func_val, cname, TRUE);
76 | -
77 | +
78 | /* the module is already referenced, so we must free it */
79 | m = JS_VALUE_GET_PTR(func_val);
80 | JS_FreeValue(ctx, func_val);
81 | @@ -290,7 +305,7 @@ static void compile_file(JSContext *ctx, FILE *fo,
82 | int eval_flags;
83 | JSValue obj;
84 | size_t buf_len;
85 | -
86 | +
87 | buf = js_load_file(ctx, &buf_len, filename);
88 | if (!buf) {
89 | fprintf(stderr, "Could not load '%s'\n", filename);
90 | @@ -370,6 +385,13 @@ void help(void)
91 | printf("]\n"
92 | " disable selected language features (smaller code size)\n");
93 | }
94 | +#else
95 | + //-- define '-fbignum' if 'CONFIG_BIGNUM' is defined
96 | + #ifdef CONFIG_BIGNUM
97 | + {
98 | + printf("-fbignum enable bignum extensions\n");
99 | + }
100 | + #endif
101 | #endif
102 | exit(1);
103 | }
104 | @@ -384,7 +406,7 @@ int exec_cmd(char **argv)
105 | if (pid == 0) {
106 | execvp(argv[0], argv);
107 | exit(1);
108 | - }
109 | + }
110 |
111 | for(;;) {
112 | ret = waitpid(pid, &status, 0);
113 | @@ -401,8 +423,10 @@ static int output_executable(const char *out_filename, const char *cfilename,
114 | const char **arg, *bn_suffix, *lto_suffix;
115 | char libjsname[1024];
116 | char exe_dir[1024], inc_dir[1024], lib_dir[1024], buf[1024], *p;
117 | + //-- used to store relative path to musl-gcc
118 | + char musl_gcc[4096];
119 | int ret;
120 | -
121 | +
122 | /* get the directory of the executable */
123 | pstrcpy(exe_dir, sizeof(exe_dir), exename);
124 | p = strrchr(exe_dir, '/');
125 | @@ -422,13 +446,20 @@ static int output_executable(const char *out_filename, const char *cfilename,
126 | snprintf(inc_dir, sizeof(inc_dir), "%s/include/quickjs", CONFIG_PREFIX);
127 | snprintf(lib_dir, sizeof(lib_dir), "%s/lib/quickjs", CONFIG_PREFIX);
128 | }
129 | -
130 | +
131 | lto_suffix = "";
132 | bn_suffix = "";
133 | -
134 | +
135 | arg = argv;
136 | - *arg++ = CONFIG_CC;
137 | + //-- use included musl-gcc wrapper instead of default compiler
138 | + //*arg++ = CONFIG_CC;
139 | + snprintf(musl_gcc, sizeof(musl_gcc), "%s/musl-%s/bin/musl-gcc", exe_dir, MUSL_ARCH);
140 | + *arg++ = musl_gcc;
141 | *arg++ = "-O2";
142 | + //-- force static compilation
143 | + *arg++ = "-static";
144 | + //-- strip
145 | + *arg++ = "-s";
146 | #ifdef CONFIG_LTO
147 | if (use_lto) {
148 | *arg++ = "-flto";
149 | @@ -452,14 +483,16 @@ static int output_executable(const char *out_filename, const char *cfilename,
150 | *arg++ = "-lm";
151 | *arg++ = "-ldl";
152 | *arg++ = "-lpthread";
153 | + //-- link to libatomic (armv7l)
154 | + *arg++ = "-latomic";
155 | *arg = NULL;
156 | -
157 | +
158 | if (verbose) {
159 | for(arg = argv; *arg != NULL; arg++)
160 | printf("%s ", *arg);
161 | printf("\n");
162 | }
163 | -
164 | +
165 | ret = exec_cmd((char **)argv);
166 | unlink(cfilename);
167 | return ret;
168 | @@ -497,7 +530,7 @@ int main(int argc, char **argv)
169 | BOOL bignum_ext = FALSE;
170 | #endif
171 | namelist_t dynamic_module_list;
172 | -
173 | +
174 | out_filename = NULL;
175 | output_type = OUTPUT_EXECUTABLE;
176 | cname = NULL;
177 | @@ -508,11 +541,13 @@ int main(int argc, char **argv)
178 | use_lto = FALSE;
179 | stack_size = 0;
180 | memset(&dynamic_module_list, 0, sizeof(dynamic_module_list));
181 | -
182 | +
183 | /* add system modules */
184 | namelist_add(&cmodule_list, "std", "std", 0);
185 | namelist_add(&cmodule_list, "os", "os", 0);
186 |
187 | + set_exe_dir_from_exe_name(argv[0]);
188 | +
189 | for(;;) {
190 | c = getopt(argc, argv, "ho:cN:f:mxevM:p:S:D:");
191 | if (c == -1)
192 | @@ -621,14 +656,14 @@ int main(int argc, char **argv)
193 | } else {
194 | pstrcpy(cfilename, sizeof(cfilename), out_filename);
195 | }
196 | -
197 | +
198 | fo = fopen(cfilename, "w");
199 | if (!fo) {
200 | perror(cfilename);
201 | exit(1);
202 | }
203 | outfile = fo;
204 | -
205 | +
206 | rt = JS_NewRuntime();
207 | ctx = JS_NewContext(rt);
208 | #ifdef CONFIG_BIGNUM
209 | @@ -639,14 +674,14 @@ int main(int argc, char **argv)
210 | JS_EnableBignumExt(ctx, TRUE);
211 | }
212 | #endif
213 | -
214 | +
215 | /* loader for ES6 modules */
216 | JS_SetModuleLoaderFunc(rt, NULL, jsc_module_loader, NULL);
217 |
218 | fprintf(fo, "/* File generated automatically by the QuickJS compiler. */\n"
219 | "\n"
220 | );
221 | -
222 | +
223 | if (output_type != OUTPUT_C) {
224 | fprintf(fo, "#include \"quickjs-libc.h\"\n"
225 | "\n"
226 | @@ -670,7 +705,7 @@ int main(int argc, char **argv)
227 | exit(1);
228 | }
229 | }
230 | -
231 | +
232 | if (output_type != OUTPUT_C) {
233 | fprintf(fo,
234 | "static JSContext *JS_NewCustomContext(JSRuntime *rt)\n"
235 | @@ -701,7 +736,7 @@ int main(int argc, char **argv)
236 | for(i = 0; i < init_module_list.count; i++) {
237 | namelist_entry_t *e = &init_module_list.array[i];
238 | /* initialize the static C modules */
239 | -
240 | +
241 | fprintf(fo,
242 | " {\n"
243 | " extern JSModuleDef *js_init_module_%s(JSContext *ctx, const char *name);\n"
244 | @@ -719,19 +754,19 @@ int main(int argc, char **argv)
245 | fprintf(fo,
246 | " return ctx;\n"
247 | "}\n\n");
248 | -
249 | +
250 | fputs(main_c_template1, fo);
251 |
252 | if (stack_size != 0) {
253 | fprintf(fo, " JS_SetMaxStackSize(rt, %u);\n",
254 | (unsigned int)stack_size);
255 | }
256 | -
257 | +
258 | /* add the module loader if necessary */
259 | if (feature_bitmap & (1 << FE_MODULE_LOADER)) {
260 | fprintf(fo, " JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);\n");
261 | }
262 | -
263 | +
264 | fprintf(fo,
265 | " ctx = JS_NewCustomContext(rt);\n"
266 | " js_std_add_helpers(ctx, argc, argv);\n");
267 | @@ -745,7 +780,7 @@ int main(int argc, char **argv)
268 | }
269 | fputs(main_c_template2, fo);
270 | }
271 | -
272 | +
273 | JS_FreeContext(ctx);
274 | JS_FreeRuntime(rt);
275 |
276 |
--------------------------------------------------------------------------------
/builder/custom/qjs/patches/2020-11-08/quickjs-libc.patch:
--------------------------------------------------------------------------------
1 | diff --git a/quickjs-libc.c b/quickjs-libc.c
2 | index e8b81e9..946790e 100644
3 | --- a/quickjs-libc.c
4 | +++ b/quickjs-libc.c
5 | @@ -71,6 +71,8 @@ typedef sig_t sighandler_t;
6 | #include "list.h"
7 | #include "quickjs-libc.h"
8 |
9 | +#include "path.h"
10 | +
11 | /* TODO:
12 | - add socket calls
13 | */
14 | @@ -577,11 +579,24 @@ JSModuleDef *js_module_loader(JSContext *ctx,
15 | JSValue func_val;
16 |
17 | buf = js_load_file(ctx, &buf_len, module_name);
18 | +/*
19 | if (!buf) {
20 | JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
21 | module_name);
22 | return NULL;
23 | }
24 | +*/
25 | + if (!buf) {
26 | + // try with a path relative to exe
27 | + char path[4096];
28 | + get_path_with_exe_dir(path, sizeof(path), (char*)module_name);
29 | + buf = js_load_file(ctx, &buf_len, path);
30 | + if (!buf) {
31 | + JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
32 | + module_name);
33 | + return NULL;
34 | + }
35 | + }
36 |
37 | /* compile the module */
38 | func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name,
39 |
--------------------------------------------------------------------------------
/builder/custom/qjs/patches/2021-03-27/Makefile.patch:
--------------------------------------------------------------------------------
1 | diff --git a/Makefile b/Makefile
2 | index 49b1f6f..9dc1097 100644
3 | --- a/Makefile
4 | +++ b/Makefile
5 | @@ -28,7 +28,8 @@ endif
6 | # Windows cross compilation from Linux
7 | #CONFIG_WIN32=y
8 | # use link time optimization (smaller and faster executables but slower build)
9 | -CONFIG_LTO=y
10 | +#-- disable LTO
11 | +#CONFIG_LTO=y
12 | # consider warnings as errors (for development)
13 | #CONFIG_WERROR=y
14 | # force 32 bit build for some utilities
15 | @@ -41,7 +42,9 @@ CONFIG_DEFAULT_AR=y
16 | endif
17 |
18 | # installation directory
19 | -prefix=/usr/local
20 | +#-- change prefix to /
21 | +#prefix=/usr/local
22 | +prefix=/
23 |
24 | # use the gprof profiler
25 | #CONFIG_PROFILE=y
26 | @@ -86,7 +89,9 @@ ifdef CONFIG_CLANG
27 | endif
28 | else
29 | HOST_CC=gcc
30 | - CC=$(CROSS_PREFIX)gcc
31 | + #-- use musl-gcc instead of gcc (symlink must exist)
32 | + #CC=$(CROSS_PREFIX)gcc
33 | + CC=$(CURDIR)/musl-$(musl_arch)/bin/musl-gcc
34 | CFLAGS=-g -Wall -MMD -MF $(OBJDIR)/$(@F).d
35 | CFLAGS += -Wno-array-bounds -Wno-format-truncation
36 | ifdef CONFIG_LTO
37 | @@ -100,6 +105,8 @@ ifdef CONFIG_WERROR
38 | CFLAGS+=-Werror
39 | endif
40 | DEFINES:=-D_GNU_SOURCE -DCONFIG_VERSION=\"$(shell cat VERSION)\"
41 | +#-- define target architecture
42 | +DEFINES+=-DMUSL_ARCH=\"$(musl_arch)\"
43 | ifdef CONFIG_BIGNUM
44 | DEFINES+=-DCONFIG_BIGNUM
45 | endif
46 | @@ -113,6 +120,10 @@ CFLAGS_SMALL=$(CFLAGS) -Os
47 | CFLAGS_OPT=$(CFLAGS) -O2
48 | CFLAGS_NOLTO:=$(CFLAGS_OPT)
49 | LDFLAGS=-g
50 | +#-- force static compilation
51 | +LDFLAGS+=-static
52 | +#-- disable PIE
53 | +CFLAGS+=-no-pie
54 | ifdef CONFIG_LTO
55 | CFLAGS_SMALL+=-flto
56 | CFLAGS_OPT+=-flto
57 | @@ -152,12 +163,17 @@ ifdef CONFIG_LTO
58 | PROGS+=libquickjs.lto.a
59 | endif
60 |
61 | +#--when architecture is not 'x86_64', we need to use the 'x86_64' version of the 'qjsc' binary to generate c files
62 | +QJSC_X86_64=$(qjsc_binary)
63 | +
64 | # examples
65 | ifeq ($(CROSS_PREFIX),)
66 | ifdef CONFIG_ASAN
67 | PROGS+=
68 | else
69 | -PROGS+=examples/hello examples/hello_module examples/test_fib
70 | +#-- disable 'hello_module' & 'test_fib' examples because of cross-compilation
71 | +#PROGS+=examples/hello examples/hello_module examples/test_fib
72 | +PROGS+=examples/hello
73 | ifndef CONFIG_DARWIN
74 | PROGS+=examples/fib.so examples/point.so
75 | endif
76 | @@ -166,7 +182,7 @@ endif
77 |
78 | all: $(OBJDIR) $(OBJDIR)/quickjs.check.o $(OBJDIR)/qjs.check.o $(PROGS)
79 |
80 | -QJS_LIB_OBJS=$(OBJDIR)/quickjs.o $(OBJDIR)/libregexp.o $(OBJDIR)/libunicode.o $(OBJDIR)/cutils.o $(OBJDIR)/quickjs-libc.o
81 | +QJS_LIB_OBJS=$(OBJDIR)/quickjs.o $(OBJDIR)/libregexp.o $(OBJDIR)/libunicode.o $(OBJDIR)/cutils.o $(OBJDIR)/quickjs-libc.o $(OBJDIR)/path.o
82 |
83 | QJS_OBJS=$(OBJDIR)/qjs.o $(OBJDIR)/repl.o $(QJS_LIB_OBJS)
84 | ifdef CONFIG_BIGNUM
85 | @@ -181,6 +197,9 @@ LIBS+=-ldl -lpthread
86 | endif
87 | LIBS+=$(EXTRA_LIBS)
88 |
89 | +#-- static linking to libatomic (necessary for armv7l)
90 | +LIBS+=-L $(CURDIR)/musl-$(musl_arch)/lib -latomic
91 | +
92 | $(OBJDIR):
93 | mkdir -p $(OBJDIR) $(OBJDIR)/examples $(OBJDIR)/tests
94 |
95 | @@ -235,10 +254,12 @@ libquickjs.a: $(patsubst %.o, %.nolto.o, $(QJS_LIB_OBJS))
96 | endif # CONFIG_LTO
97 |
98 | repl.c: $(QJSC) repl.js
99 | - $(QJSC) -c -o $@ -m repl.js
100 | + #-- will use the 'x86_64' version of 'qjsc' when architecture is not 'x86_64'
101 | + $(QJSC_X86_64) -c -o $@ -m repl.js
102 |
103 | qjscalc.c: $(QJSC) qjscalc.js
104 | - $(QJSC) -fbignum -c -o $@ qjscalc.js
105 | + #-- will use the 'x86_64' version of 'qjsc' when architecture is not 'x86_64'
106 | + $(QJSC_X86_64) -fbignum -c -o $@ qjscalc.js
107 |
108 | ifneq ($(wildcard unicode/UnicodeData.txt),)
109 | $(OBJDIR)/libunicode.o $(OBJDIR)/libunicode.m32.o $(OBJDIR)/libunicode.m32s.o \
110 | @@ -297,9 +318,12 @@ clean:
111 | rm -rf $(OBJDIR)/ *.dSYM/ qjs-debug
112 | rm -rf run-test262-debug run-test262-32
113 |
114 | -install: all
115 | +#-- only install
116 | +#install: all
117 | +install:
118 | mkdir -p "$(DESTDIR)$(prefix)/bin"
119 | - $(STRIP) qjs qjsc
120 | + #-- disable stripping (because of cross-compiling)
121 | + #$(STRIP) qjs qjsc
122 | install -m755 qjs qjsc "$(DESTDIR)$(prefix)/bin"
123 | ln -sf qjs "$(DESTDIR)$(prefix)/bin/qjscalc"
124 | mkdir -p "$(DESTDIR)$(prefix)/lib/quickjs"
125 | @@ -323,7 +347,8 @@ HELLO_OPTS+=-fno-bigint
126 | endif
127 |
128 | hello.c: $(QJSC) $(HELLO_SRCS)
129 | - $(QJSC) -e $(HELLO_OPTS) -o $@ $(HELLO_SRCS)
130 | + #-- will use the 'x86_64' version of 'qjsc' when architecture is not 'x86_64'
131 | + $(QJSC_X86_64) -e $(HELLO_OPTS) -o $@ $(HELLO_SRCS)
132 |
133 | ifdef CONFIG_M32
134 | examples/hello: $(OBJDIR)/hello.m32s.o $(patsubst %.o, %.m32s.o, $(QJS_LIB_OBJS))
135 |
--------------------------------------------------------------------------------
/builder/custom/qjs/patches/2021-03-27/qjs.patch:
--------------------------------------------------------------------------------
1 | diff --git a/qjs.c b/qjs.c
2 | index d56b843..d6b32b6 100644
3 | --- a/qjs.c
4 | +++ b/qjs.c
5 | @@ -41,6 +41,8 @@
6 | #include "cutils.h"
7 | #include "quickjs-libc.h"
8 |
9 | +#include "path.h"
10 | +
11 | extern const uint8_t qjsc_repl[];
12 | extern const uint32_t qjsc_repl_size;
13 | #ifdef CONFIG_BIGNUM
14 | @@ -337,7 +339,9 @@ int main(int argc, char **argv)
15 | load_jscalc = !strcmp(exename, "qjscalc");
16 | }
17 | #endif
18 | -
19 | +
20 | + set_exe_dir_from_exe_name(argv[0]);
21 | +
22 | /* cannot use getopt because we want to pass the command line to
23 | the script */
24 | optind = 1;
25 |
--------------------------------------------------------------------------------
/builder/custom/qjs/patches/2021-03-27/qjsc.patch:
--------------------------------------------------------------------------------
1 | diff --git a/qjsc.c b/qjsc.c
2 | index b9f1e4c..1150c1e 100644
3 | --- a/qjsc.c
4 | +++ b/qjsc.c
5 | @@ -36,6 +36,8 @@
6 | #include "cutils.h"
7 | #include "quickjs-libc.h"
8 |
9 | +#include "path.h"
10 | +
11 | typedef struct {
12 | char *name;
13 | char *short_name;
14 | @@ -255,12 +257,31 @@ JSModuleDef *jsc_module_loader(JSContext *ctx,
15 | char cname[1024];
16 |
17 | buf = js_load_file(ctx, &buf_len, module_name);
18 | +/*
19 | if (!buf) {
20 | JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
21 | module_name);
22 | return NULL;
23 | }
24 | -
25 | +*/
26 | + if (!buf) {
27 | + char path[4096];
28 | + // check if a custom lib dir has been defined
29 | + char* lib_dir = getenv("QJS_LIB_DIR");
30 | + if (NULL == lib_dir) {
31 | + get_path_with_exe_dir(path, sizeof(path), (char*)module_name);
32 | + }
33 | + else {
34 | + get_path_with_dir(path, sizeof(path), lib_dir, (char*)module_name);
35 | + }
36 | + buf = js_load_file(ctx, &buf_len, path);
37 | + if (!buf) {
38 | + JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
39 | + module_name);
40 | + return NULL;
41 | + }
42 | + }
43 | +
44 | /* compile the module */
45 | func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name,
46 | JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
47 | @@ -370,6 +391,13 @@ void help(void)
48 | printf("]\n"
49 | " disable selected language features (smaller code size)\n");
50 | }
51 | +#else
52 | + //-- define '-fbignum' if 'CONFIG_BIGNUM' is defined
53 | + #ifdef CONFIG_BIGNUM
54 | + {
55 | + printf("-fbignum enable bignum extensions\n");
56 | + }
57 | + #endif
58 | #endif
59 | exit(1);
60 | }
61 | @@ -401,6 +429,8 @@ static int output_executable(const char *out_filename, const char *cfilename,
62 | const char **arg, *bn_suffix, *lto_suffix;
63 | char libjsname[1024];
64 | char exe_dir[1024], inc_dir[1024], lib_dir[1024], buf[1024], *p;
65 | + //-- used to store relative path to musl-gcc
66 | + char musl_gcc[4096];
67 | int ret;
68 |
69 | /* get the directory of the executable */
70 | @@ -427,8 +457,15 @@ static int output_executable(const char *out_filename, const char *cfilename,
71 | bn_suffix = "";
72 |
73 | arg = argv;
74 | - *arg++ = CONFIG_CC;
75 | + //-- use included musl-gcc wrapper instead of default compiler
76 | + //*arg++ = CONFIG_CC;
77 | + snprintf(musl_gcc, sizeof(musl_gcc), "%s/musl-%s/bin/musl-gcc", exe_dir, MUSL_ARCH);
78 | + *arg++ = musl_gcc;
79 | *arg++ = "-O2";
80 | + //-- force static compilation
81 | + *arg++ = "-static";
82 | + //-- strip
83 | + *arg++ = "-s";
84 | #ifdef CONFIG_LTO
85 | if (use_lto) {
86 | *arg++ = "-flto";
87 | @@ -452,6 +489,8 @@ static int output_executable(const char *out_filename, const char *cfilename,
88 | *arg++ = "-lm";
89 | *arg++ = "-ldl";
90 | *arg++ = "-lpthread";
91 | + //-- link to libatomic (armv7l)
92 | + *arg++ = "-latomic";
93 | *arg = NULL;
94 |
95 | if (verbose) {
96 | @@ -462,6 +501,24 @@ static int output_executable(const char *out_filename, const char *cfilename,
97 |
98 | ret = exec_cmd((char **)argv);
99 | unlink(cfilename);
100 | +
101 | + //-- compress executable using upx
102 | + if (0 == ret) {
103 | + p = getenv("QJS_UPX");
104 | + if (NULL != p && 0 == strcmp(p, "1")) {
105 | + arg = argv;
106 | + *arg++ = "upx";
107 | + *arg++ = out_filename;
108 | + *arg = NULL;
109 | + if (verbose) {
110 | + for(arg = argv; *arg != NULL; arg++)
111 | + printf("%s ", *arg);
112 | + printf("\n");
113 | + }
114 | + exec_cmd((char **)argv);
115 | + }
116 | + }
117 | +
118 | return ret;
119 | }
120 | #else
121 | @@ -513,6 +570,8 @@ int main(int argc, char **argv)
122 | namelist_add(&cmodule_list, "std", "std", 0);
123 | namelist_add(&cmodule_list, "os", "os", 0);
124 |
125 | + set_exe_dir_from_exe_name(argv[0]);
126 | +
127 | for(;;) {
128 | c = getopt(argc, argv, "ho:cN:f:mxevM:p:S:D:");
129 | if (c == -1)
130 |
--------------------------------------------------------------------------------
/builder/custom/qjs/patches/2021-03-27/quickjs-libc.patch:
--------------------------------------------------------------------------------
1 | diff --git a/quickjs-libc.c b/quickjs-libc.c
2 | index e180dd0..3fcfa79 100644
3 | --- a/quickjs-libc.c
4 | +++ b/quickjs-libc.c
5 | @@ -71,6 +71,13 @@ typedef sig_t sighandler_t;
6 | #include "list.h"
7 | #include "quickjs-libc.h"
8 |
9 | +#include "path.h"
10 | +
11 | +#if !defined(_WIN32) && !defined(__APPLE__)
12 | +// flock
13 | +#include
14 | +#endif /* !_WIN32 && !_APPLE_
15 | +
16 | /* TODO:
17 | - add socket calls
18 | */
19 | @@ -577,11 +584,30 @@ JSModuleDef *js_module_loader(JSContext *ctx,
20 | JSValue func_val;
21 |
22 | buf = js_load_file(ctx, &buf_len, module_name);
23 | +/*
24 | if (!buf) {
25 | JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
26 | module_name);
27 | return NULL;
28 | }
29 | +*/
30 | + if (!buf) {
31 | + char path[4096];
32 | + // check if a custom lib dir has been defined
33 | + char* lib_dir = getenv("QJS_LIB_DIR");
34 | + if (NULL == lib_dir) {
35 | + get_path_with_exe_dir(path, sizeof(path), (char*)module_name);
36 | + }
37 | + else {
38 | + get_path_with_dir(path, sizeof(path), lib_dir, (char*)module_name);
39 | + }
40 | + buf = js_load_file(ctx, &buf_len, path);
41 | + if (!buf) {
42 | + JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
43 | + module_name);
44 | + return NULL;
45 | + }
46 | + }
47 |
48 | /* compile the module */
49 | func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name,
50 | @@ -1477,6 +1503,13 @@ static const JSCFunctionListEntry js_std_error_props[] = {
51 | DEF(EPERM),
52 | DEF(EPIPE),
53 | DEF(EBADF),
54 | +#if !defined(_WIN32) && !defined(_APPLE_)
55 | + // flock
56 | + DEF(EINTR),
57 | + DEF(ENOLCK),
58 | + DEF(EWOULDBLOCK)
59 | +#endif /* !_WIN32 && !_APPLE_ */
60 | +
61 | #undef DEF
62 | };
63 |
64 | @@ -3030,6 +3063,13 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val,
65 | goto done;
66 | }
67 |
68 | +/* getpid() -> pid */
69 | +static JSValue js_os_getpid(JSContext *ctx, JSValueConst this_val,
70 | + int argc, JSValueConst *argv)
71 | +{
72 | + return JS_NewInt32(ctx, getpid());
73 | +}
74 | +
75 | /* waitpid(pid, block) -> [pid, status] */
76 | static JSValue js_os_waitpid(JSContext *ctx, JSValueConst this_val,
77 | int argc, JSValueConst *argv)
78 | @@ -3118,6 +3158,73 @@ static JSValue js_os_dup2(JSContext *ctx, JSValueConst this_val,
79 | return JS_NewInt32(ctx, ret);
80 | }
81 |
82 | +#if !defined(_APPLE_)
83 | +
84 | +/* flock(fd, operation) */
85 | +static JSValue js_os_flock(JSContext *ctx, JSValueConst this_val,
86 | + int argc, JSValueConst *argv)
87 | +{
88 | + int fd, operation, ret;
89 | + if (JS_ToInt32(ctx, &fd, argv[0]))
90 | + return JS_EXCEPTION;
91 | + if (JS_ToInt32(ctx, &operation, argv[1]))
92 | + return JS_EXCEPTION;
93 | + ret = js_get_errno(flock(fd, operation));
94 | + return JS_NewInt32(ctx, ret);
95 | +}
96 | +
97 | +/* mkstemp(template, outputObj) */
98 | +static JSValue js_os_mkstemp(JSContext *ctx, JSValueConst this_val,
99 | + int argc, JSValueConst *argv)
100 | +{
101 | + char buffer[PATH_MAX];
102 | + const char *template;
103 | + int ret;
104 | +
105 | + template = JS_ToCString(ctx, argv[0]);
106 | + if (!template)
107 | + return JS_EXCEPTION;
108 | + strncpy(buffer, template, sizeof(buffer));
109 | + JS_FreeCString(ctx, template);
110 | + ret = js_get_errno(mkstemp(buffer));
111 | + // check if we can pass the final filename back
112 | + if (argc >= 2 && ret > 0) {
113 | + if (!JS_IsUndefined(argv[1])) {
114 | + JS_SetPropertyStr(ctx, argv[1], "filename", JS_NewString(ctx, buffer));
115 | + }
116 | + }
117 | + return JS_NewInt32(ctx, ret);
118 | +}
119 | +
120 | +/* mkdtemp(template, errorObj) */
121 | +static JSValue js_os_mkdtemp(JSContext *ctx, JSValueConst this_val,
122 | + int argc, JSValueConst *argv)
123 | +{
124 | + char buffer[PATH_MAX];
125 | + const char *template;
126 | + const char *ptr;
127 | + int err = 0;
128 | +
129 | + template = JS_ToCString(ctx, argv[0]);
130 | + if (!template)
131 | + return JS_EXCEPTION;
132 | + strncpy(buffer, template, sizeof(buffer));
133 | + JS_FreeCString(ctx, template);
134 | + ptr = mkdtemp(buffer);
135 | + if (NULL == ptr) {
136 | + err = errno;
137 | + }
138 | + if (argc >= 2) {
139 | + js_set_error_object(ctx, argv[1], err);
140 | + }
141 | + if (NULL == ptr) {
142 | + return JS_NULL;
143 | + }
144 | + return JS_NewString(ctx, ptr);
145 | +}
146 | +
147 | +#endif /* !_APPLE_ */
148 | +
149 | #endif /* !_WIN32 */
150 |
151 | #ifdef USE_WORKER
152 | @@ -3650,6 +3757,7 @@ static const JSCFunctionListEntry js_os_funcs[] = {
153 | JS_CFUNC_DEF("symlink", 2, js_os_symlink ),
154 | JS_CFUNC_DEF("readlink", 1, js_os_readlink ),
155 | JS_CFUNC_DEF("exec", 1, js_os_exec ),
156 | + JS_CFUNC_DEF("getpid", 0, js_os_getpid ),
157 | JS_CFUNC_DEF("waitpid", 2, js_os_waitpid ),
158 | OS_FLAG(WNOHANG),
159 | JS_CFUNC_DEF("pipe", 0, js_os_pipe ),
160 | @@ -3657,6 +3765,16 @@ static const JSCFunctionListEntry js_os_funcs[] = {
161 | JS_CFUNC_DEF("dup", 1, js_os_dup ),
162 | JS_CFUNC_DEF("dup2", 2, js_os_dup2 ),
163 | #endif
164 | +#if !defined(_WIN32) && !defined(_APPLE_)
165 | + // flock
166 | + JS_CFUNC_DEF("flock", 2, js_os_flock ),
167 | + OS_FLAG(LOCK_EX),
168 | + OS_FLAG(LOCK_NB),
169 | + // mkstemp
170 | + JS_CFUNC_DEF("mkstemp", 1, js_os_mkstemp ),
171 | + // mkdtemp
172 | + JS_CFUNC_DEF("mkdtemp", 1, js_os_mkdtemp ),
173 | +#endif
174 | };
175 |
176 | static int js_os_init(JSContext *ctx, JSModuleDef *m)
177 |
--------------------------------------------------------------------------------
/builder/custom/qjs/patches/2023-12-09/Makefile.patch:
--------------------------------------------------------------------------------
1 | diff --git a/Makefile b/Makefile
2 | index 39bd3ad..3975a93 100644
3 | --- a/Makefile
4 | +++ b/Makefile
5 | @@ -28,7 +28,8 @@ endif
6 | # Windows cross compilation from Linux
7 | #CONFIG_WIN32=y
8 | # use link time optimization (smaller and faster executables but slower build)
9 | -CONFIG_LTO=y
10 | +#-- disable LTO
11 | +#CONFIG_LTO=y
12 | # consider warnings as errors (for development)
13 | #CONFIG_WERROR=y
14 | # force 32 bit build for some utilities
15 | @@ -41,7 +42,9 @@ CONFIG_DEFAULT_AR=y
16 | endif
17 |
18 | # installation directory
19 | -prefix=/usr/local
20 | +#-- change prefix to /
21 | +#prefix=/usr/local
22 | +prefix=/
23 |
24 | # use the gprof profiler
25 | #CONFIG_PROFILE=y
26 | @@ -86,7 +89,9 @@ ifdef CONFIG_CLANG
27 | endif
28 | else
29 | HOST_CC=gcc
30 | - CC=$(CROSS_PREFIX)gcc
31 | + #-- use musl-gcc instead of gcc (symlink must exist)
32 | + #CC=$(CROSS_PREFIX)gcc
33 | + CC=$(CURDIR)/musl-$(musl_arch)/bin/musl-gcc
34 | CFLAGS=-g -Wall -MMD -MF $(OBJDIR)/$(@F).d
35 | CFLAGS += -Wno-array-bounds -Wno-format-truncation
36 | ifdef CONFIG_LTO
37 | @@ -100,6 +105,8 @@ ifdef CONFIG_WERROR
38 | CFLAGS+=-Werror
39 | endif
40 | DEFINES:=-D_GNU_SOURCE -DCONFIG_VERSION=\"$(shell cat VERSION)\"
41 | +#-- define target architecture
42 | +DEFINES+=-DMUSL_ARCH=\"$(musl_arch)\"
43 | ifdef CONFIG_BIGNUM
44 | DEFINES+=-DCONFIG_BIGNUM
45 | endif
46 | @@ -113,6 +120,10 @@ CFLAGS_SMALL=$(CFLAGS) -Os
47 | CFLAGS_OPT=$(CFLAGS) -O2
48 | CFLAGS_NOLTO:=$(CFLAGS_OPT)
49 | LDFLAGS=-g
50 | +#-- force static compilation
51 | +LDFLAGS+=-static
52 | +#-- disable PIE
53 | +CFLAGS+=-no-pie
54 | ifdef CONFIG_LTO
55 | CFLAGS_SMALL+=-flto
56 | CFLAGS_OPT+=-flto
57 | @@ -152,12 +163,17 @@ ifdef CONFIG_LTO
58 | PROGS+=libquickjs.lto.a
59 | endif
60 |
61 | +#--when architecture is not 'x86_64', we need to use the 'x86_64' version of the 'qjsc' binary to generate c files
62 | +QJSC_X86_64=$(qjsc_binary)
63 | +
64 | # examples
65 | ifeq ($(CROSS_PREFIX),)
66 | ifdef CONFIG_ASAN
67 | PROGS+=
68 | else
69 | -PROGS+=examples/hello examples/hello_module examples/test_fib
70 | +#-- disable 'hello_module' & 'test_fib' examples because of cross-compilation
71 | +#PROGS+=examples/hello examples/hello_module examples/test_fib
72 | +PROGS+=examples/hello
73 | ifndef CONFIG_DARWIN
74 | PROGS+=examples/fib.so examples/point.so
75 | endif
76 | @@ -166,7 +182,7 @@ endif
77 |
78 | all: $(OBJDIR) $(OBJDIR)/quickjs.check.o $(OBJDIR)/qjs.check.o $(PROGS)
79 |
80 | -QJS_LIB_OBJS=$(OBJDIR)/quickjs.o $(OBJDIR)/libregexp.o $(OBJDIR)/libunicode.o $(OBJDIR)/cutils.o $(OBJDIR)/quickjs-libc.o $(OBJDIR)/libbf.o
81 | +QJS_LIB_OBJS=$(OBJDIR)/quickjs.o $(OBJDIR)/libregexp.o $(OBJDIR)/libunicode.o $(OBJDIR)/cutils.o $(OBJDIR)/quickjs-libc.o $(OBJDIR)/libbf.o $(OBJDIR)/path.o
82 |
83 | QJS_OBJS=$(OBJDIR)/qjs.o $(OBJDIR)/repl.o $(QJS_LIB_OBJS)
84 | ifdef CONFIG_BIGNUM
85 | @@ -180,6 +196,9 @@ LIBS+=-ldl -lpthread
86 | endif
87 | LIBS+=$(EXTRA_LIBS)
88 |
89 | +#-- static linking to libatomic (necessary for armv7l)
90 | +LIBS+=-L $(CURDIR)/musl-$(musl_arch)/lib -latomic
91 | +
92 | $(OBJDIR):
93 | mkdir -p $(OBJDIR) $(OBJDIR)/examples $(OBJDIR)/tests
94 |
95 | @@ -234,10 +253,12 @@ libquickjs.a: $(patsubst %.o, %.nolto.o, $(QJS_LIB_OBJS))
96 | endif # CONFIG_LTO
97 |
98 | repl.c: $(QJSC) repl.js
99 | - $(QJSC) -c -o $@ -m repl.js
100 | + #-- will use the 'x86_64' version of 'qjsc' when architecture is not 'x86_64'
101 | + $(QJSC_X86_64) -c -o $@ -m repl.js
102 |
103 | qjscalc.c: $(QJSC) qjscalc.js
104 | - $(QJSC) -fbignum -c -o $@ qjscalc.js
105 | + #-- will use the 'x86_64' version of 'qjsc' when architecture is not 'x86_64'
106 | + $(QJSC_X86_64) -fbignum -c -o $@ qjscalc.js
107 |
108 | ifneq ($(wildcard unicode/UnicodeData.txt),)
109 | $(OBJDIR)/libunicode.o $(OBJDIR)/libunicode.m32.o $(OBJDIR)/libunicode.m32s.o \
110 | @@ -296,9 +317,12 @@ clean:
111 | rm -rf $(OBJDIR)/ *.dSYM/ qjs-debug
112 | rm -rf run-test262-debug run-test262-32
113 |
114 | -install: all
115 | +#-- only install
116 | +#install: all
117 | +install:
118 | mkdir -p "$(DESTDIR)$(prefix)/bin"
119 | - $(STRIP) qjs qjsc
120 | + #-- disable stripping (because of cross-compiling)
121 | + #$(STRIP) qjs qjsc
122 | install -m755 qjs qjsc "$(DESTDIR)$(prefix)/bin"
123 | ln -sf qjs "$(DESTDIR)$(prefix)/bin/qjscalc"
124 | mkdir -p "$(DESTDIR)$(prefix)/lib/quickjs"
125 | @@ -319,7 +343,8 @@ HELLO_OPTS=-fno-string-normalize -fno-map -fno-promise -fno-typedarray \
126 | -fno-date -fno-module-loader -fno-bigint
127 |
128 | hello.c: $(QJSC) $(HELLO_SRCS)
129 | - $(QJSC) -e $(HELLO_OPTS) -o $@ $(HELLO_SRCS)
130 | + #-- will use the 'x86_64' version of 'qjsc' when architecture is not 'x86_64'
131 | + $(QJSC_X86_64) -e $(HELLO_OPTS) -o $@ $(HELLO_SRCS)
132 |
133 | ifdef CONFIG_M32
134 | examples/hello: $(OBJDIR)/hello.m32s.o $(patsubst %.o, %.m32s.o, $(QJS_LIB_OBJS))
135 |
--------------------------------------------------------------------------------
/builder/custom/qjs/patches/2023-12-09/qjs.patch:
--------------------------------------------------------------------------------
1 | diff --git a/qjs.c b/qjs.c
2 | index c2d63e9..8084d8f 100644
3 | --- a/qjs.c
4 | +++ b/qjs.c
5 | @@ -41,6 +41,8 @@
6 | #include "cutils.h"
7 | #include "quickjs-libc.h"
8 |
9 | +#include "path.h"
10 | +
11 | extern const uint8_t qjsc_repl[];
12 | extern const uint32_t qjsc_repl_size;
13 | #ifdef CONFIG_BIGNUM
14 | @@ -337,7 +339,9 @@ int main(int argc, char **argv)
15 | load_jscalc = !strcmp(exename, "qjscalc");
16 | }
17 | #endif
18 | -
19 | +
20 | + set_exe_dir_from_exe_name(argv[0]);
21 | +
22 | /* cannot use getopt because we want to pass the command line to
23 | the script */
24 | optind = 1;
25 |
--------------------------------------------------------------------------------
/builder/custom/qjs/patches/2023-12-09/qjsc.patch:
--------------------------------------------------------------------------------
1 | diff --git a/qjsc.c b/qjsc.c
2 | index d317826..26261b9 100644
3 | --- a/qjsc.c
4 | +++ b/qjsc.c
5 | @@ -36,6 +36,8 @@
6 | #include "cutils.h"
7 | #include "quickjs-libc.h"
8 |
9 | +#include "path.h"
10 | +
11 | typedef struct {
12 | char *name;
13 | char *short_name;
14 | @@ -253,12 +255,31 @@ JSModuleDef *jsc_module_loader(JSContext *ctx,
15 | char cname[1024];
16 |
17 | buf = js_load_file(ctx, &buf_len, module_name);
18 | +/*
19 | if (!buf) {
20 | JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
21 | module_name);
22 | return NULL;
23 | }
24 | -
25 | +*/
26 | + if (!buf) {
27 | + char path[4096];
28 | + // check if a custom lib dir has been defined
29 | + char* lib_dir = getenv("QJS_LIB_DIR");
30 | + if (NULL == lib_dir) {
31 | + get_path_with_exe_dir(path, sizeof(path), (char*)module_name);
32 | + }
33 | + else {
34 | + get_path_with_dir(path, sizeof(path), lib_dir, (char*)module_name);
35 | + }
36 | + buf = js_load_file(ctx, &buf_len, path);
37 | + if (!buf) {
38 | + JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
39 | + module_name);
40 | + return NULL;
41 | + }
42 | + }
43 | +
44 | /* compile the module */
45 | func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name,
46 | JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
47 | @@ -368,6 +389,13 @@ void help(void)
48 | printf("]\n"
49 | " disable selected language features (smaller code size)\n");
50 | }
51 | +#else
52 | + //-- define '-fbignum' if 'CONFIG_BIGNUM' is defined
53 | + #ifdef CONFIG_BIGNUM
54 | + {
55 | + printf("-fbignum enable bignum extensions\n");
56 | + }
57 | + #endif
58 | #endif
59 | exit(1);
60 | }
61 | @@ -399,6 +427,8 @@ static int output_executable(const char *out_filename, const char *cfilename,
62 | const char **arg, *bn_suffix, *lto_suffix;
63 | char libjsname[1024];
64 | char exe_dir[1024], inc_dir[1024], lib_dir[1024], buf[1024], *p;
65 | + //-- used to store relative path to musl-gcc
66 | + char musl_gcc[4096];
67 | int ret;
68 |
69 | /* get the directory of the executable */
70 | @@ -425,8 +455,15 @@ static int output_executable(const char *out_filename, const char *cfilename,
71 | bn_suffix = "";
72 |
73 | arg = argv;
74 | - *arg++ = CONFIG_CC;
75 | + //-- use included musl-gcc wrapper instead of default compiler
76 | + //*arg++ = CONFIG_CC;
77 | + snprintf(musl_gcc, sizeof(musl_gcc), "%s/musl-%s/bin/musl-gcc", exe_dir, MUSL_ARCH);
78 | + *arg++ = musl_gcc;
79 | *arg++ = "-O2";
80 | + //-- force static compilation
81 | + *arg++ = "-static";
82 | + //-- strip
83 | + *arg++ = "-s";
84 | #ifdef CONFIG_LTO
85 | if (use_lto) {
86 | *arg++ = "-flto";
87 | @@ -450,6 +487,8 @@ static int output_executable(const char *out_filename, const char *cfilename,
88 | *arg++ = "-lm";
89 | *arg++ = "-ldl";
90 | *arg++ = "-lpthread";
91 | + //-- link to libatomic (armv7l)
92 | + *arg++ = "-latomic";
93 | *arg = NULL;
94 |
95 | if (verbose) {
96 | @@ -460,6 +499,24 @@ static int output_executable(const char *out_filename, const char *cfilename,
97 |
98 | ret = exec_cmd((char **)argv);
99 | unlink(cfilename);
100 | +
101 | + //-- compress executable using upx
102 | + if (0 == ret) {
103 | + p = getenv("QJS_UPX");
104 | + if (NULL != p && 0 == strcmp(p, "1")) {
105 | + arg = argv;
106 | + *arg++ = "upx";
107 | + *arg++ = out_filename;
108 | + *arg = NULL;
109 | + if (verbose) {
110 | + for(arg = argv; *arg != NULL; arg++)
111 | + printf("%s ", *arg);
112 | + printf("\n");
113 | + }
114 | + exec_cmd((char **)argv);
115 | + }
116 | + }
117 | +
118 | return ret;
119 | }
120 | #else
121 | @@ -511,6 +568,8 @@ int main(int argc, char **argv)
122 | namelist_add(&cmodule_list, "std", "std", 0);
123 | namelist_add(&cmodule_list, "os", "os", 0);
124 |
125 | + set_exe_dir_from_exe_name(argv[0]);
126 | +
127 | for(;;) {
128 | c = getopt(argc, argv, "ho:cN:f:mxevM:p:S:D:");
129 | if (c == -1)
130 |
--------------------------------------------------------------------------------
/builder/custom/qjs/patches/2023-12-09/quickjs-libc.patch:
--------------------------------------------------------------------------------
1 | diff --git a/quickjs-libc.c b/quickjs-libc.c
2 | index e180dd0..3fcfa79 100644
3 | --- a/quickjs-libc.c
4 | +++ b/quickjs-libc.c
5 | @@ -71,6 +71,13 @@ typedef sig_t sighandler_t;
6 | #include "list.h"
7 | #include "quickjs-libc.h"
8 |
9 | +#include "path.h"
10 | +
11 | +#if !defined(_WIN32) && !defined(__APPLE__)
12 | +// flock
13 | +#include
14 | +#endif /* !_WIN32 && !_APPLE_
15 | +
16 | /* TODO:
17 | - add socket calls
18 | */
19 | @@ -577,11 +584,30 @@ JSModuleDef *js_module_loader(JSContext *ctx,
20 | JSValue func_val;
21 |
22 | buf = js_load_file(ctx, &buf_len, module_name);
23 | +/*
24 | if (!buf) {
25 | JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
26 | module_name);
27 | return NULL;
28 | }
29 | +*/
30 | + if (!buf) {
31 | + char path[4096];
32 | + // check if a custom lib dir has been defined
33 | + char* lib_dir = getenv("QJS_LIB_DIR");
34 | + if (NULL == lib_dir) {
35 | + get_path_with_exe_dir(path, sizeof(path), (char*)module_name);
36 | + }
37 | + else {
38 | + get_path_with_dir(path, sizeof(path), lib_dir, (char*)module_name);
39 | + }
40 | + buf = js_load_file(ctx, &buf_len, path);
41 | + if (!buf) {
42 | + JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
43 | + module_name);
44 | + return NULL;
45 | + }
46 | + }
47 |
48 | /* compile the module */
49 | func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name,
50 | @@ -1477,6 +1503,13 @@ static const JSCFunctionListEntry js_std_error_props[] = {
51 | DEF(EPERM),
52 | DEF(EPIPE),
53 | DEF(EBADF),
54 | +#if !defined(_WIN32) && !defined(_APPLE_)
55 | + // flock
56 | + DEF(EINTR),
57 | + DEF(ENOLCK),
58 | + DEF(EWOULDBLOCK)
59 | +#endif /* !_WIN32 && !_APPLE_ */
60 | +
61 | #undef DEF
62 | };
63 |
64 | @@ -3030,6 +3063,13 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val,
65 | goto done;
66 | }
67 |
68 | +/* getpid() -> pid */
69 | +static JSValue js_os_getpid(JSContext *ctx, JSValueConst this_val,
70 | + int argc, JSValueConst *argv)
71 | +{
72 | + return JS_NewInt32(ctx, getpid());
73 | +}
74 | +
75 | /* waitpid(pid, block) -> [pid, status] */
76 | static JSValue js_os_waitpid(JSContext *ctx, JSValueConst this_val,
77 | int argc, JSValueConst *argv)
78 | @@ -3118,6 +3158,73 @@ static JSValue js_os_dup2(JSContext *ctx, JSValueConst this_val,
79 | return JS_NewInt32(ctx, ret);
80 | }
81 |
82 | +#if !defined(_APPLE_)
83 | +
84 | +/* flock(fd, operation) */
85 | +static JSValue js_os_flock(JSContext *ctx, JSValueConst this_val,
86 | + int argc, JSValueConst *argv)
87 | +{
88 | + int fd, operation, ret;
89 | + if (JS_ToInt32(ctx, &fd, argv[0]))
90 | + return JS_EXCEPTION;
91 | + if (JS_ToInt32(ctx, &operation, argv[1]))
92 | + return JS_EXCEPTION;
93 | + ret = js_get_errno(flock(fd, operation));
94 | + return JS_NewInt32(ctx, ret);
95 | +}
96 | +
97 | +/* mkstemp(template, outputObj) */
98 | +static JSValue js_os_mkstemp(JSContext *ctx, JSValueConst this_val,
99 | + int argc, JSValueConst *argv)
100 | +{
101 | + char buffer[PATH_MAX];
102 | + const char *template;
103 | + int ret;
104 | +
105 | + template = JS_ToCString(ctx, argv[0]);
106 | + if (!template)
107 | + return JS_EXCEPTION;
108 | + strncpy(buffer, template, sizeof(buffer));
109 | + JS_FreeCString(ctx, template);
110 | + ret = js_get_errno(mkstemp(buffer));
111 | + // check if we can pass the final filename back
112 | + if (argc >= 2 && ret > 0) {
113 | + if (!JS_IsUndefined(argv[1])) {
114 | + JS_SetPropertyStr(ctx, argv[1], "filename", JS_NewString(ctx, buffer));
115 | + }
116 | + }
117 | + return JS_NewInt32(ctx, ret);
118 | +}
119 | +
120 | +/* mkdtemp(template, errorObj) */
121 | +static JSValue js_os_mkdtemp(JSContext *ctx, JSValueConst this_val,
122 | + int argc, JSValueConst *argv)
123 | +{
124 | + char buffer[PATH_MAX];
125 | + const char *template;
126 | + const char *ptr;
127 | + int err = 0;
128 | +
129 | + template = JS_ToCString(ctx, argv[0]);
130 | + if (!template)
131 | + return JS_EXCEPTION;
132 | + strncpy(buffer, template, sizeof(buffer));
133 | + JS_FreeCString(ctx, template);
134 | + ptr = mkdtemp(buffer);
135 | + if (NULL == ptr) {
136 | + err = errno;
137 | + }
138 | + if (argc >= 2) {
139 | + js_set_error_object(ctx, argv[1], err);
140 | + }
141 | + if (NULL == ptr) {
142 | + return JS_NULL;
143 | + }
144 | + return JS_NewString(ctx, ptr);
145 | +}
146 | +
147 | +#endif /* !_APPLE_ */
148 | +
149 | #endif /* !_WIN32 */
150 |
151 | #ifdef USE_WORKER
152 | @@ -3650,6 +3757,7 @@ static const JSCFunctionListEntry js_os_funcs[] = {
153 | JS_CFUNC_DEF("symlink", 2, js_os_symlink ),
154 | JS_CFUNC_DEF("readlink", 1, js_os_readlink ),
155 | JS_CFUNC_DEF("exec", 1, js_os_exec ),
156 | + JS_CFUNC_DEF("getpid", 0, js_os_getpid ),
157 | JS_CFUNC_DEF("waitpid", 2, js_os_waitpid ),
158 | OS_FLAG(WNOHANG),
159 | JS_CFUNC_DEF("pipe", 0, js_os_pipe ),
160 | @@ -3657,6 +3765,16 @@ static const JSCFunctionListEntry js_os_funcs[] = {
161 | JS_CFUNC_DEF("dup", 1, js_os_dup ),
162 | JS_CFUNC_DEF("dup2", 2, js_os_dup2 ),
163 | #endif
164 | +#if !defined(_WIN32) && !defined(_APPLE_)
165 | + // flock
166 | + JS_CFUNC_DEF("flock", 2, js_os_flock ),
167 | + OS_FLAG(LOCK_EX),
168 | + OS_FLAG(LOCK_NB),
169 | + // mkstemp
170 | + JS_CFUNC_DEF("mkstemp", 1, js_os_mkstemp ),
171 | + // mkdtemp
172 | + JS_CFUNC_DEF("mkdtemp", 1, js_os_mkdtemp ),
173 | +#endif
174 | };
175 |
176 | static int js_os_init(JSContext *ctx, JSModuleDef *m)
177 |
--------------------------------------------------------------------------------
/builder/custom/qjs/patches/2024-01-13/Makefile.patch:
--------------------------------------------------------------------------------
1 | diff --git a/Makefile b/Makefile
2 | index 57cdd7e..d037ebf 100644
3 | --- a/Makefile
4 | +++ b/Makefile
5 | @@ -28,7 +28,8 @@ endif
6 | # Windows cross compilation from Linux
7 | #CONFIG_WIN32=y
8 | # use link time optimization (smaller and faster executables but slower build)
9 | -CONFIG_LTO=y
10 | +#-- disable LTO
11 | +#CONFIG_LTO=y
12 | # consider warnings as errors (for development)
13 | #CONFIG_WERROR=y
14 | # force 32 bit build for some utilities
15 | @@ -37,7 +38,10 @@ CONFIG_LTO=y
16 | #CONFIG_COSMO=y
17 |
18 | # installation directory
19 | -PREFIX?=/usr/local
20 | +#PREFIX?=/usr/local
21 | +#-- change prefix to /
22 | +PREFIX?=/
23 | +
24 |
25 | # use the gprof profiler
26 | #CONFIG_PROFILE=y
27 | @@ -97,7 +101,9 @@ else ifdef CONFIG_COSMO
28 | AR=cosmoar
29 | else
30 | HOST_CC=gcc
31 | - CC=$(CROSS_PREFIX)gcc
32 | + #-- use musl-gcc instead of gcc (symlink must exist)
33 | + #CC=$(CROSS_PREFIX)gcc
34 | + CC=$(CURDIR)/musl-$(musl_arch)/bin/musl-gcc
35 | CFLAGS+=-g -Wall -MMD -MF $(OBJDIR)/$(@F).d
36 | CFLAGS += -Wno-array-bounds -Wno-format-truncation
37 | ifdef CONFIG_LTO
38 | @@ -112,6 +118,8 @@ ifdef CONFIG_WERROR
39 | CFLAGS+=-Werror
40 | endif
41 | DEFINES:=-D_GNU_SOURCE -DCONFIG_VERSION=\"$(shell cat VERSION)\"
42 | +#-- define target architecture
43 | +DEFINES+=-DMUSL_ARCH=\"$(musl_arch)\"
44 | ifdef CONFIG_BIGNUM
45 | DEFINES+=-DCONFIG_BIGNUM
46 | endif
47 | @@ -128,6 +136,10 @@ ifdef CONFIG_COSMO
48 | LDFLAGS+=-s # better to strip by default
49 | else
50 | LDFLAGS+=-g
51 | +#-- force static compilation
52 | +LDFLAGS+=-static
53 | +#-- disable PIE
54 | +CFLAGS+=-no-pie
55 | endif
56 | ifdef CONFIG_LTO
57 | CFLAGS_SMALL+=-flto
58 | @@ -174,20 +186,25 @@ ifdef CONFIG_LTO
59 | PROGS+=libquickjs.lto.a
60 | endif
61 |
62 | +#--when architecture is not 'x86_64', we need to use the 'x86_64' version of the 'qjsc' binary to generate c files
63 | +QJSC_X86_64=$(qjsc_binary)
64 | +
65 | # examples
66 | ifeq ($(CROSS_PREFIX),)
67 | PROGS+=examples/hello
68 | ifndef CONFIG_ASAN
69 | -PROGS+=examples/hello_module
70 | +#-- disable because of cross-compilation
71 | +#PROGS+=examples/hello_module
72 | endif
73 | ifdef CONFIG_SHARED_LIBS
74 | -PROGS+=examples/test_fib examples/fib.so examples/point.so
75 | +#-- disable because of cross-compilation
76 | +#PROGS+=examples/test_fib examples/fib.so examples/point.so
77 | endif
78 | endif
79 |
80 | all: $(OBJDIR) $(OBJDIR)/quickjs.check.o $(OBJDIR)/qjs.check.o $(PROGS)
81 |
82 | -QJS_LIB_OBJS=$(OBJDIR)/quickjs.o $(OBJDIR)/libregexp.o $(OBJDIR)/libunicode.o $(OBJDIR)/cutils.o $(OBJDIR)/quickjs-libc.o $(OBJDIR)/libbf.o
83 | +QJS_LIB_OBJS=$(OBJDIR)/quickjs.o $(OBJDIR)/libregexp.o $(OBJDIR)/libunicode.o $(OBJDIR)/cutils.o $(OBJDIR)/quickjs-libc.o $(OBJDIR)/libbf.o $(OBJDIR)/path.o
84 |
85 | QJS_OBJS=$(OBJDIR)/qjs.o $(OBJDIR)/repl.o $(QJS_LIB_OBJS)
86 | ifdef CONFIG_BIGNUM
87 | @@ -201,6 +218,9 @@ LIBS+=-ldl -lpthread
88 | endif
89 | LIBS+=$(EXTRA_LIBS)
90 |
91 | +#-- static linking to libatomic (necessary for armv7l)
92 | +LIBS+=-L $(CURDIR)/musl-$(musl_arch)/lib -latomic
93 | +
94 | $(OBJDIR):
95 | mkdir -p $(OBJDIR) $(OBJDIR)/examples $(OBJDIR)/tests
96 |
97 | @@ -255,10 +275,12 @@ libquickjs.a: $(patsubst %.o, %.nolto.o, $(QJS_LIB_OBJS))
98 | endif # CONFIG_LTO
99 |
100 | repl.c: $(QJSC) repl.js
101 | - $(QJSC) -c -o $@ -m repl.js
102 | + #-- will use the 'x86_64' version of 'qjsc' when architecture is not 'x86_64'
103 | + $(QJSC_X86_64) -c -o $@ -m repl.js
104 |
105 | qjscalc.c: $(QJSC) qjscalc.js
106 | - $(QJSC) -fbignum -c -o $@ qjscalc.js
107 | + #-- will use the 'x86_64' version of 'qjsc' when architecture is not 'x86_64'
108 | + $(QJSC_X86_64) -fbignum -c -o $@ qjscalc.js
109 |
110 | ifneq ($(wildcard unicode/UnicodeData.txt),)
111 | $(OBJDIR)/libunicode.o $(OBJDIR)/libunicode.m32.o $(OBJDIR)/libunicode.m32s.o \
112 | @@ -317,9 +339,12 @@ clean:
113 | rm -rf $(OBJDIR)/ *.dSYM/ qjs-debug
114 | rm -rf run-test262-debug run-test262-32
115 |
116 | -install: all
117 | +#-- only install
118 | +#install: all
119 | +install:
120 | mkdir -p "$(DESTDIR)$(PREFIX)/bin"
121 | - $(STRIP) qjs qjsc
122 | + #-- disable stripping (because of cross-compiling)
123 | + #$(STRIP) qjs qjsc
124 | install -m755 qjs qjsc "$(DESTDIR)$(PREFIX)/bin"
125 | ln -sf qjs "$(DESTDIR)$(PREFIX)/bin/qjscalc"
126 | mkdir -p "$(DESTDIR)$(PREFIX)/lib/quickjs"
127 | @@ -340,7 +365,8 @@ HELLO_OPTS=-fno-string-normalize -fno-map -fno-promise -fno-typedarray \
128 | -fno-date -fno-module-loader -fno-bigint
129 |
130 | hello.c: $(QJSC) $(HELLO_SRCS)
131 | - $(QJSC) -e $(HELLO_OPTS) -o $@ $(HELLO_SRCS)
132 | + #-- will use the 'x86_64' version of 'qjsc' when architecture is not 'x86_64'
133 | + $(QJSC_X86_64) -e $(HELLO_OPTS) -o $@ $(HELLO_SRCS)
134 |
135 | ifdef CONFIG_M32
136 | examples/hello: $(OBJDIR)/hello.m32s.o $(patsubst %.o, %.m32s.o, $(QJS_LIB_OBJS))
137 |
--------------------------------------------------------------------------------
/builder/custom/qjs/patches/2024-01-13/qjs.patch:
--------------------------------------------------------------------------------
1 | diff --git a/qjs.c b/qjs.c
2 | index 77b5cfb..ad684e9 100644
3 | --- a/qjs.c
4 | +++ b/qjs.c
5 | @@ -41,6 +41,8 @@
6 | #include "cutils.h"
7 | #include "quickjs-libc.h"
8 |
9 | +#include "path.h"
10 | +
11 | extern const uint8_t qjsc_repl[];
12 | extern const uint32_t qjsc_repl_size;
13 | #ifdef CONFIG_BIGNUM
14 | @@ -326,7 +328,9 @@ int main(int argc, char **argv)
15 | load_jscalc = !strcmp(exename, "qjscalc");
16 | }
17 | #endif
18 | -
19 | +
20 | + set_exe_dir_from_exe_name(argv[0]);
21 | +
22 | /* cannot use getopt because we want to pass the command line to
23 | the script */
24 | optind = 1;
25 |
--------------------------------------------------------------------------------
/builder/custom/qjs/patches/2024-01-13/qjsc.patch:
--------------------------------------------------------------------------------
1 | diff --git a/qjsc.c b/qjsc.c
2 | index f8e60b3..0505445 100644
3 | --- a/qjsc.c
4 | +++ b/qjsc.c
5 | @@ -36,6 +36,8 @@
6 | #include "cutils.h"
7 | #include "quickjs-libc.h"
8 |
9 | +#include "path.h"
10 | +
11 | typedef struct {
12 | char *name;
13 | char *short_name;
14 | @@ -253,12 +255,31 @@ JSModuleDef *jsc_module_loader(JSContext *ctx,
15 | char cname[1024];
16 |
17 | buf = js_load_file(ctx, &buf_len, module_name);
18 | +/*
19 | if (!buf) {
20 | JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
21 | module_name);
22 | return NULL;
23 | }
24 | -
25 | +*/
26 | + if (!buf) {
27 | + char path[4096];
28 | + // check if a custom lib dir has been defined
29 | + char* lib_dir = getenv("QJS_LIB_DIR");
30 | + if (NULL == lib_dir) {
31 | + get_path_with_exe_dir(path, sizeof(path), (char*)module_name);
32 | + }
33 | + else {
34 | + get_path_with_dir(path, sizeof(path), lib_dir, (char*)module_name);
35 | + }
36 | + buf = js_load_file(ctx, &buf_len, path);
37 | + if (!buf) {
38 | + JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
39 | + module_name);
40 | + return NULL;
41 | + }
42 | + }
43 | +
44 | /* compile the module */
45 | func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name,
46 | JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
47 | @@ -369,6 +390,13 @@ void help(void)
48 | printf("]\n"
49 | " disable selected language features (smaller code size)\n");
50 | }
51 | +#else
52 | + //-- define '-fbignum' if 'CONFIG_BIGNUM' is defined
53 | + #ifdef CONFIG_BIGNUM
54 | + {
55 | + printf("-fbignum enable bignum extensions\n");
56 | + }
57 | + #endif
58 | #endif
59 | exit(1);
60 | }
61 | @@ -400,6 +428,8 @@ static int output_executable(const char *out_filename, const char *cfilename,
62 | const char **arg, *bn_suffix, *lto_suffix;
63 | char libjsname[1024];
64 | char exe_dir[1024], inc_dir[1024], lib_dir[1024], buf[1024], *p;
65 | + //-- used to store relative path to musl-gcc
66 | + char musl_gcc[4096];
67 | int ret;
68 |
69 | /* get the directory of the executable */
70 | @@ -426,8 +456,15 @@ static int output_executable(const char *out_filename, const char *cfilename,
71 | bn_suffix = "";
72 |
73 | arg = argv;
74 | - *arg++ = CONFIG_CC;
75 | + //-- use included musl-gcc wrapper instead of default compiler
76 | + //*arg++ = CONFIG_CC;
77 | + snprintf(musl_gcc, sizeof(musl_gcc), "%s/musl-%s/bin/musl-gcc", exe_dir, MUSL_ARCH);
78 | + *arg++ = musl_gcc;
79 | *arg++ = "-O2";
80 | + //-- force static compilation
81 | + *arg++ = "-static";
82 | + //-- strip
83 | + *arg++ = "-s";
84 | #ifdef CONFIG_LTO
85 | if (use_lto) {
86 | *arg++ = "-flto";
87 | @@ -451,6 +488,8 @@ static int output_executable(const char *out_filename, const char *cfilename,
88 | *arg++ = "-lm";
89 | *arg++ = "-ldl";
90 | *arg++ = "-lpthread";
91 | + //-- link to libatomic (armv7l)
92 | + *arg++ = "-latomic";
93 | *arg = NULL;
94 |
95 | if (verbose) {
96 | @@ -461,6 +500,24 @@ static int output_executable(const char *out_filename, const char *cfilename,
97 |
98 | ret = exec_cmd((char **)argv);
99 | unlink(cfilename);
100 | +
101 | + //-- compress executable using upx
102 | + if (0 == ret) {
103 | + p = getenv("QJS_UPX");
104 | + if (NULL != p && 0 == strcmp(p, "1")) {
105 | + arg = argv;
106 | + *arg++ = "upx";
107 | + *arg++ = out_filename;
108 | + *arg = NULL;
109 | + if (verbose) {
110 | + for(arg = argv; *arg != NULL; arg++)
111 | + printf("%s ", *arg);
112 | + printf("\n");
113 | + }
114 | + exec_cmd((char **)argv);
115 | + }
116 | + }
117 | +
118 | return ret;
119 | }
120 | #else
121 | @@ -512,6 +569,8 @@ int main(int argc, char **argv)
122 | namelist_add(&cmodule_list, "std", "std", 0);
123 | namelist_add(&cmodule_list, "os", "os", 0);
124 |
125 | + set_exe_dir_from_exe_name(argv[0]);
126 | +
127 | for(;;) {
128 | c = getopt(argc, argv, "ho:cN:f:mxevM:p:S:D:");
129 | if (c == -1)
130 |
--------------------------------------------------------------------------------
/builder/custom/qjs/patches/2024-01-13/quickjs-libc.patch:
--------------------------------------------------------------------------------
1 | diff --git a/quickjs-libc.c b/quickjs-libc.c
2 | index d4f4d67..26d7f7f 100644
3 | --- a/quickjs-libc.c
4 | +++ b/quickjs-libc.c
5 | @@ -71,6 +71,13 @@ typedef sig_t sighandler_t;
6 | #include "list.h"
7 | #include "quickjs-libc.h"
8 |
9 | +#include "path.h"
10 | +
11 | +#if !defined(_WIN32) && !defined(__APPLE__)
12 | +// flock
13 | +#include
14 | +#endif /* !_WIN32 && !_APPLE_
15 | +
16 | /* TODO:
17 | - add socket calls
18 | */
19 | @@ -577,11 +584,30 @@ JSModuleDef *js_module_loader(JSContext *ctx,
20 | JSValue func_val;
21 |
22 | buf = js_load_file(ctx, &buf_len, module_name);
23 | +/*
24 | if (!buf) {
25 | JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
26 | module_name);
27 | return NULL;
28 | }
29 | +*/
30 | + if (!buf) {
31 | + char path[4096];
32 | + // check if a custom lib dir has been defined
33 | + char* lib_dir = getenv("QJS_LIB_DIR");
34 | + if (NULL == lib_dir) {
35 | + get_path_with_exe_dir(path, sizeof(path), (char*)module_name);
36 | + }
37 | + else {
38 | + get_path_with_dir(path, sizeof(path), lib_dir, (char*)module_name);
39 | + }
40 | + buf = js_load_file(ctx, &buf_len, path);
41 | + if (!buf) {
42 | + JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
43 | + module_name);
44 | + return NULL;
45 | + }
46 | + }
47 |
48 | /* compile the module */
49 | func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name,
50 | @@ -1483,6 +1509,13 @@ static const JSCFunctionListEntry js_std_error_props[] = {
51 | DEF(EPERM),
52 | DEF(EPIPE),
53 | DEF(EBADF),
54 | +#if !defined(_WIN32) && !defined(_APPLE_)
55 | + // flock
56 | + DEF(EINTR),
57 | + DEF(ENOLCK),
58 | + DEF(EWOULDBLOCK)
59 | +#endif /* !_WIN32 && !_APPLE_ */
60 | +
61 | #undef DEF
62 | };
63 |
64 | @@ -3026,6 +3059,36 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val,
65 | }
66 | }
67 |
68 | +#if defined(__linux__)
69 | + int pid = getpid();
70 | + int max_fd = 0;
71 | + char path[32];
72 | + struct stat statbuf;
73 | + sprintf(path, "/proc/%d/fd", pid);
74 | + if (stat(path, &statbuf) == 0) {
75 | + if (S_ISDIR(statbuf.st_mode)) {
76 | + DIR *dir = opendir(path);
77 | + if (dir) {
78 | + struct dirent *subdir;
79 | + int fd;
80 | + for(;;) {
81 | + subdir = readdir(dir);
82 | + if (!subdir) {
83 | + break;
84 | + }
85 | + fd = atoi(subdir->d_name);
86 | + if (fd > max_fd) {
87 | + max_fd = fd;
88 | + }
89 | + }
90 | + if (max_fd > 0) {
91 | + fd_max = max_fd;
92 | + }
93 | + closedir(dir);
94 | + }
95 | + }
96 | + }
97 | +#endif
98 | for(i = 3; i < fd_max; i++)
99 | close(i);
100 | if (cwd) {
101 | @@ -3183,6 +3246,73 @@ static JSValue js_os_dup2(JSContext *ctx, JSValueConst this_val,
102 | return JS_NewInt32(ctx, ret);
103 | }
104 |
105 | +#if !defined(_APPLE_)
106 | +
107 | +/* flock(fd, operation) */
108 | +static JSValue js_os_flock(JSContext *ctx, JSValueConst this_val,
109 | + int argc, JSValueConst *argv)
110 | +{
111 | + int fd, operation, ret;
112 | + if (JS_ToInt32(ctx, &fd, argv[0]))
113 | + return JS_EXCEPTION;
114 | + if (JS_ToInt32(ctx, &operation, argv[1]))
115 | + return JS_EXCEPTION;
116 | + ret = js_get_errno(flock(fd, operation));
117 | + return JS_NewInt32(ctx, ret);
118 | +}
119 | +
120 | +/* mkstemp(template, outputObj) */
121 | +static JSValue js_os_mkstemp(JSContext *ctx, JSValueConst this_val,
122 | + int argc, JSValueConst *argv)
123 | +{
124 | + char buffer[PATH_MAX];
125 | + const char *template;
126 | + int ret;
127 | +
128 | + template = JS_ToCString(ctx, argv[0]);
129 | + if (!template)
130 | + return JS_EXCEPTION;
131 | + strncpy(buffer, template, sizeof(buffer));
132 | + JS_FreeCString(ctx, template);
133 | + ret = js_get_errno(mkstemp(buffer));
134 | + // check if we can pass the final filename back
135 | + if (argc >= 2 && ret > 0) {
136 | + if (!JS_IsUndefined(argv[1])) {
137 | + JS_SetPropertyStr(ctx, argv[1], "filename", JS_NewString(ctx, buffer));
138 | + }
139 | + }
140 | + return JS_NewInt32(ctx, ret);
141 | +}
142 | +
143 | +/* mkdtemp(template, errorObj) */
144 | +static JSValue js_os_mkdtemp(JSContext *ctx, JSValueConst this_val,
145 | + int argc, JSValueConst *argv)
146 | +{
147 | + char buffer[PATH_MAX];
148 | + const char *template;
149 | + const char *ptr;
150 | + int err = 0;
151 | +
152 | + template = JS_ToCString(ctx, argv[0]);
153 | + if (!template)
154 | + return JS_EXCEPTION;
155 | + strncpy(buffer, template, sizeof(buffer));
156 | + JS_FreeCString(ctx, template);
157 | + ptr = mkdtemp(buffer);
158 | + if (NULL == ptr) {
159 | + err = errno;
160 | + }
161 | + if (argc >= 2) {
162 | + js_set_error_object(ctx, argv[1], err);
163 | + }
164 | + if (NULL == ptr) {
165 | + return JS_NULL;
166 | + }
167 | + return JS_NewString(ctx, ptr);
168 | +}
169 | +
170 | +#endif /* !_APPLE_ */
171 | +
172 | #endif /* !_WIN32 */
173 |
174 | #ifdef USE_WORKER
175 | @@ -3729,6 +3859,16 @@ static const JSCFunctionListEntry js_os_funcs[] = {
176 | JS_CFUNC_DEF("dup", 1, js_os_dup ),
177 | JS_CFUNC_DEF("dup2", 2, js_os_dup2 ),
178 | #endif
179 | +#if !defined(_WIN32) && !defined(_APPLE_)
180 | + // flock
181 | + JS_CFUNC_DEF("flock", 2, js_os_flock ),
182 | + OS_FLAG(LOCK_EX),
183 | + OS_FLAG(LOCK_NB),
184 | + // mkstemp
185 | + JS_CFUNC_DEF("mkstemp", 1, js_os_mkstemp ),
186 | + // mkdtemp
187 | + JS_CFUNC_DEF("mkdtemp", 1, js_os_mkdtemp ),
188 | +#endif
189 | };
190 |
191 | static int js_os_init(JSContext *ctx, JSModuleDef *m)
192 |
--------------------------------------------------------------------------------
/builder/custom/qjs/patches/2025-04-26/Makefile.patch:
--------------------------------------------------------------------------------
1 | diff --git a/Makefile b/Makefile
2 | index 3b1c745..ad50e54 100644
3 | --- a/Makefile
4 | +++ b/Makefile
5 | @@ -43,7 +43,9 @@ endif
6 | #CONFIG_COSMO=y
7 |
8 | # installation directory
9 | -PREFIX?=/usr/local
10 | +#PREFIX?=/usr/local
11 | +#-- change prefix to /
12 | +PREFIX?=/
13 |
14 | # use the gprof profiler
15 | #CONFIG_PROFILE=y
16 | @@ -126,7 +128,9 @@ else ifdef CONFIG_COSMO
17 | AR=cosmoar
18 | else
19 | HOST_CC=gcc
20 | - CC=$(CROSS_PREFIX)gcc
21 | + #-- use musl-gcc instead of gcc (symlink must exist)
22 | + #CC=$(CROSS_PREFIX)gcc
23 | + CC=$(CURDIR)/musl-$(musl_arch)/bin/musl-gcc
24 | CFLAGS+=-g -Wall -MMD -MF $(OBJDIR)/$(@F).d
25 | CFLAGS += -Wno-array-bounds -Wno-format-truncation -Wno-infinite-recursion
26 | ifdef CONFIG_LTO
27 | @@ -148,6 +152,8 @@ ifdef CONFIG_WERROR
28 | CFLAGS+=-Werror
29 | endif
30 | DEFINES:=-D_GNU_SOURCE -DCONFIG_VERSION=\"$(shell cat VERSION)\"
31 | +#-- define target architecture
32 | +DEFINES+=-DMUSL_ARCH=\"$(musl_arch)\"
33 | ifdef CONFIG_WIN32
34 | DEFINES+=-D__USE_MINGW_ANSI_STDIO # for standard snprintf behavior
35 | endif
36 | @@ -166,6 +172,10 @@ ifdef CONFIG_COSMO
37 | LDFLAGS+=-s # better to strip by default
38 | else
39 | LDFLAGS+=-g
40 | +#-- force static compilation
41 | +LDFLAGS+=-static
42 | +#-- disable PIE
43 | +CFLAGS+=-no-pie
44 | endif
45 | ifdef CONFIG_LTO
46 | CFLAGS_SMALL+=-flto
47 | @@ -217,6 +227,9 @@ ifdef CONFIG_LTO
48 | PROGS+=libquickjs.lto.a
49 | endif
50 |
51 | +#--when architecture is not 'x86_64', we need to use the 'x86_64' version of the 'qjsc' binary to generate c files
52 | +QJSC_X86_64=$(qjsc_binary)
53 | +
54 | # examples
55 | ifeq ($(CROSS_PREFIX),)
56 | ifndef CONFIG_ASAN
57 | @@ -226,11 +239,13 @@ PROGS+=examples/hello examples/test_fib
58 | # no -m32 option in qjsc
59 | ifndef CONFIG_M32
60 | ifndef CONFIG_WIN32
61 | -PROGS+=examples/hello_module
62 | +#-- disable because of cross-compilation
63 | +#PROGS+=examples/hello_module
64 | endif
65 | endif
66 | ifdef CONFIG_SHARED_LIBS
67 | -PROGS+=examples/fib.so examples/point.so
68 | +#-- disable because of cross-compilation
69 | +#PROGS+=examples/fib.so examples/point.so
70 | endif
71 | endif
72 | endif
73 | @@ -239,7 +254,7 @@ endif
74 |
75 | all: $(OBJDIR) $(OBJDIR)/quickjs.check.o $(OBJDIR)/qjs.check.o $(PROGS)
76 |
77 | -QJS_LIB_OBJS=$(OBJDIR)/quickjs.o $(OBJDIR)/dtoa.o $(OBJDIR)/libregexp.o $(OBJDIR)/libunicode.o $(OBJDIR)/cutils.o $(OBJDIR)/quickjs-libc.o
78 | +QJS_LIB_OBJS=$(OBJDIR)/quickjs.o $(OBJDIR)/dtoa.o $(OBJDIR)/libregexp.o $(OBJDIR)/libunicode.o $(OBJDIR)/cutils.o $(OBJDIR)/quickjs-libc.o $(OBJDIR)/path.o
79 |
80 | QJS_OBJS=$(OBJDIR)/qjs.o $(OBJDIR)/repl.o $(QJS_LIB_OBJS)
81 |
82 | @@ -250,6 +265,9 @@ LIBS+=-ldl
83 | endif
84 | LIBS+=$(EXTRA_LIBS)
85 |
86 | +#-- static linking to libatomic (necessary for armv7l)
87 | +LIBS+=-L $(CURDIR)/musl-$(musl_arch)/lib -latomic
88 | +
89 | $(OBJDIR):
90 | mkdir -p $(OBJDIR) $(OBJDIR)/examples $(OBJDIR)/tests
91 |
92 | @@ -308,7 +326,8 @@ libquickjs.fuzz.a: $(patsubst %.o, %.fuzz.o, $(QJS_LIB_OBJS))
93 | $(AR) rcs $@ $^
94 |
95 | repl.c: $(QJSC) repl.js
96 | - $(QJSC) -s -c -o $@ -m repl.js
97 | + #-- we use the 'x86_64' version of 'qjsc' when architecture is not 'x86_64'
98 | + $(QJSC_X86_64) -s -c -o $@ -m repl.js
99 |
100 | ifneq ($(wildcard unicode/UnicodeData.txt),)
101 | $(OBJDIR)/libunicode.o $(OBJDIR)/libunicode.nolto.o: libunicode-table.h
102 | @@ -364,9 +383,12 @@ clean:
103 | rm -rf run-test262-debug$(EXE)
104 | rm -f run_octane run_sunspider_like
105 |
106 | -install: all
107 | +#-- only install
108 | +#install: all
109 | +install:
110 | mkdir -p "$(DESTDIR)$(PREFIX)/bin"
111 | - $(STRIP) qjs$(EXE) qjsc$(EXE)
112 | + #-- disable stripping (because of cross-compiling)
113 | + #$(STRIP) qjs$(EXE) qjsc$(EXE)
114 | install -m755 qjs$(EXE) qjsc$(EXE) "$(DESTDIR)$(PREFIX)/bin"
115 | mkdir -p "$(DESTDIR)$(PREFIX)/lib/quickjs"
116 | install -m644 libquickjs.a "$(DESTDIR)$(PREFIX)/lib/quickjs"
117 | @@ -386,7 +408,8 @@ HELLO_OPTS=-fno-string-normalize -fno-map -fno-promise -fno-typedarray \
118 | -fno-date -fno-module-loader
119 |
120 | hello.c: $(QJSC) $(HELLO_SRCS)
121 | - $(QJSC) -e $(HELLO_OPTS) -o $@ $(HELLO_SRCS)
122 | + #-- we use the 'x86_64' version of 'qjsc' when architecture is not 'x86_64'
123 | + $(QJSC_X86_64) -e $(HELLO_OPTS) -o $@ $(HELLO_SRCS)
124 |
125 | examples/hello: $(OBJDIR)/hello.o $(QJS_LIB_OBJS)
126 | $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
127 |
--------------------------------------------------------------------------------
/builder/custom/qjs/patches/2025-04-26/qjs.patch:
--------------------------------------------------------------------------------
1 | diff --git a/qjs.c b/qjs.c
2 | index 2eaa9ee..f16e2d6 100644
3 | --- a/qjs.c
4 | +++ b/qjs.c
5 | @@ -43,6 +43,8 @@
6 | #include "cutils.h"
7 | #include "quickjs-libc.h"
8 |
9 | +#include "path.h"
10 | +
11 | extern const uint8_t qjsc_repl[];
12 | extern const uint32_t qjsc_repl_size;
13 |
14 | @@ -327,6 +329,8 @@ int main(int argc, char **argv)
15 | int strip_flags = 0;
16 | size_t stack_size = 0;
17 |
18 | + set_exe_dir_from_exe_name(argv[0]);
19 | +
20 | /* cannot use getopt because we want to pass the command line to
21 | the script */
22 | optind = 1;
23 |
--------------------------------------------------------------------------------
/builder/custom/qjs/patches/2025-04-26/qjsc.patch:
--------------------------------------------------------------------------------
1 | diff --git a/qjsc.c b/qjsc.c
2 | index f9e1928..e94d00e 100644
3 | --- a/qjsc.c
4 | +++ b/qjsc.c
5 | @@ -36,6 +36,8 @@
6 | #include "cutils.h"
7 | #include "quickjs-libc.h"
8 |
9 | +#include "path.h"
10 | +
11 | typedef struct {
12 | char *name;
13 | char *short_name;
14 | @@ -253,11 +255,30 @@ JSModuleDef *jsc_module_loader(JSContext *ctx,
15 | char cname[1024];
16 |
17 | buf = js_load_file(ctx, &buf_len, module_name);
18 | +/*
19 | if (!buf) {
20 | JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
21 | module_name);
22 | return NULL;
23 | }
24 | +*/
25 | + if (!buf) {
26 | + char path[4096];
27 | + // check if a custom lib dir has been defined
28 | + char* lib_dir = getenv("QJS_LIB_DIR");
29 | + if (NULL == lib_dir) {
30 | + get_path_with_exe_dir(path, sizeof(path), (char*)module_name);
31 | + }
32 | + else {
33 | + get_path_with_dir(path, sizeof(path), lib_dir, (char*)module_name);
34 | + }
35 | + buf = js_load_file(ctx, &buf_len, path);
36 | + if (!buf) {
37 | + JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
38 | + module_name);
39 | + return NULL;
40 | + }
41 | + }
42 |
43 | /* compile the module */
44 | func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name,
45 | @@ -401,6 +422,8 @@ static int output_executable(const char *out_filename, const char *cfilename,
46 | const char **arg, *bn_suffix, *lto_suffix;
47 | char libjsname[1024];
48 | char exe_dir[1024], inc_dir[1024], lib_dir[1024], buf[1024], *p;
49 | + //-- used to store relative path to musl-gcc
50 | + char musl_gcc[4096];
51 | int ret;
52 |
53 | /* get the directory of the executable */
54 | @@ -427,8 +450,15 @@ static int output_executable(const char *out_filename, const char *cfilename,
55 | bn_suffix = "";
56 |
57 | arg = argv;
58 | - *arg++ = CONFIG_CC;
59 | + //-- use included musl-gcc wrapper instead of default compiler
60 | + //*arg++ = CONFIG_CC;
61 | + snprintf(musl_gcc, sizeof(musl_gcc), "%s/musl-%s/bin/musl-gcc", exe_dir, MUSL_ARCH);
62 | + *arg++ = musl_gcc;
63 | *arg++ = "-O2";
64 | + //-- force static compilation
65 | + *arg++ = "-static";
66 | + //-- strip
67 | + *arg++ = "-s";
68 | #ifdef CONFIG_LTO
69 | if (use_lto) {
70 | *arg++ = "-flto";
71 | @@ -452,6 +482,8 @@ static int output_executable(const char *out_filename, const char *cfilename,
72 | *arg++ = "-lm";
73 | *arg++ = "-ldl";
74 | *arg++ = "-lpthread";
75 | + //-- link to libatomic (armv7l)
76 | + *arg++ = "-latomic";
77 | *arg = NULL;
78 |
79 | if (verbose) {
80 | @@ -462,6 +494,22 @@ static int output_executable(const char *out_filename, const char *cfilename,
81 |
82 | ret = exec_cmd((char **)argv);
83 | unlink(cfilename);
84 | + //-- compress executable using upx
85 | + if (0 == ret) {
86 | + p = getenv("QJS_UPX");
87 | + if (NULL != p && 0 == strcmp(p, "1")) {
88 | + arg = argv;
89 | + *arg++ = "upx";
90 | + *arg++ = out_filename;
91 | + *arg = NULL;
92 | + if (verbose) {
93 | + for(arg = argv; *arg != NULL; arg++)
94 | + printf("%s ", *arg);
95 | + printf("\n");
96 | + }
97 | + exec_cmd((char **)argv);
98 | + }
99 | + }
100 | return ret;
101 | }
102 | #else
103 | @@ -551,6 +599,8 @@ int main(int argc, char **argv)
104 | namelist_add(&cmodule_list, "std", "std", 0);
105 | namelist_add(&cmodule_list, "os", "os", 0);
106 |
107 | + set_exe_dir_from_exe_name(argv[0]);
108 | +
109 | optind = 1;
110 | while (optind < argc && *argv[optind] == '-') {
111 | char *arg = argv[optind] + 1;
112 |
--------------------------------------------------------------------------------
/builder/custom/qjs/patches/2025-04-26/quickjs-libc.patch:
--------------------------------------------------------------------------------
1 | diff --git a/quickjs-libc.c b/quickjs-libc.c
2 | index 0788d8c..27919c3 100644
3 | --- a/quickjs-libc.c
4 | +++ b/quickjs-libc.c
5 | @@ -76,10 +76,17 @@ typedef sig_t sighandler_t;
6 | #include "list.h"
7 | #include "quickjs-libc.h"
8 |
9 | +#include "path.h"
10 | +
11 | #if !defined(PATH_MAX)
12 | #define PATH_MAX 4096
13 | #endif
14 |
15 | +#if !defined(_WIN32) && !defined(__APPLE__)
16 | +// flock
17 | +#include
18 | +#endif /* !_WIN32 && !_APPLE_
19 | +
20 | /* TODO:
21 | - add socket calls
22 | */
23 | @@ -596,11 +603,30 @@ JSModuleDef *js_module_loader(JSContext *ctx,
24 | JSValue func_val;
25 |
26 | buf = js_load_file(ctx, &buf_len, module_name);
27 | +/*
28 | if (!buf) {
29 | JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
30 | module_name);
31 | return NULL;
32 | }
33 | +*/
34 | + if (!buf) {
35 | + char path[4096];
36 | + // check if a custom lib dir has been defined
37 | + char* lib_dir = getenv("QJS_LIB_DIR");
38 | + if (NULL == lib_dir) {
39 | + get_path_with_exe_dir(path, sizeof(path), (char*)module_name);
40 | + }
41 | + else {
42 | + get_path_with_dir(path, sizeof(path), lib_dir, (char*)module_name);
43 | + }
44 | + buf = js_load_file(ctx, &buf_len, path);
45 | + if (!buf) {
46 | + JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
47 | + module_name);
48 | + return NULL;
49 | + }
50 | + }
51 |
52 | /* compile the module */
53 | func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name,
54 | @@ -1511,6 +1537,12 @@ static const JSCFunctionListEntry js_std_error_props[] = {
55 | DEF(EPERM),
56 | DEF(EPIPE),
57 | DEF(EBADF),
58 | +#if !defined(_WIN32) && !defined(_APPLE_)
59 | + // flock
60 | + DEF(EINTR),
61 | + DEF(ENOLCK),
62 | + DEF(EWOULDBLOCK)
63 | +#endif /* !_WIN32 && !_APPLE_ */
64 | #undef DEF
65 | };
66 |
67 | @@ -3112,6 +3144,7 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val,
68 | }
69 | if (pid == 0) {
70 | /* child */
71 | + int fd_max = sysconf(_SC_OPEN_MAX);
72 |
73 | /* remap the stdin/stdout/stderr handles if necessary */
74 | for(i = 0; i < 3; i++) {
75 | @@ -3120,28 +3153,39 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val,
76 | _exit(127);
77 | }
78 | }
79 | -#if defined(HAVE_CLOSEFROM)
80 | - /* closefrom() is available on many recent unix systems:
81 | - Linux with glibc 2.34+, Solaris 9+, FreeBSD 7.3+,
82 | - NetBSD 3.0+, OpenBSD 3.5+.
83 | - Linux with the musl libc and macOS don't have it.
84 | - */
85 | -
86 | - closefrom(3);
87 | -#else
88 | - {
89 | - /* Close the file handles manually, limit to 1024 to avoid
90 | - costly loop on linux Alpine where sysconf(_SC_OPEN_MAX)
91 | - returns a huge value 1048576.
92 | - Patch inspired by nicolas-duteil-nova. See also:
93 | - https://stackoverflow.com/questions/73229353/
94 | - https://stackoverflow.com/questions/899038/#918469
95 | - */
96 | - int fd_max = min_int(sysconf(_SC_OPEN_MAX), 1024);
97 | - for(i = 3; i < fd_max; i++)
98 | - close(i);
99 | +
100 | +#if defined(__linux__)
101 | + int pid = getpid();
102 | + int max_fd = 0;
103 | + char path[32];
104 | + struct stat statbuf;
105 | + sprintf(path, "/proc/%d/fd", pid);
106 | + if (stat(path, &statbuf) == 0) {
107 | + if (S_ISDIR(statbuf.st_mode)) {
108 | + DIR *dir = opendir(path);
109 | + if (dir) {
110 | + struct dirent *subdir;
111 | + int fd;
112 | + for(;;) {
113 | + subdir = readdir(dir);
114 | + if (!subdir) {
115 | + break;
116 | + }
117 | + fd = atoi(subdir->d_name);
118 | + if (fd > max_fd) {
119 | + max_fd = fd;
120 | + }
121 | + }
122 | + if (max_fd > 0) {
123 | + fd_max = max_fd;
124 | + }
125 | + closedir(dir);
126 | + }
127 | + }
128 | }
129 | #endif
130 | + for(i = 3; i < fd_max; i++)
131 | + close(i);
132 | if (cwd) {
133 | if (chdir(cwd) < 0)
134 | _exit(127);
135 | @@ -3296,6 +3340,72 @@ static JSValue js_os_dup2(JSContext *ctx, JSValueConst this_val,
136 | ret = js_get_errno(dup2(fd, fd2));
137 | return JS_NewInt32(ctx, ret);
138 | }
139 | +#if !defined(_APPLE_)
140 | +
141 | +/* flock(fd, operation) */
142 | +static JSValue js_os_flock(JSContext *ctx, JSValueConst this_val,
143 | + int argc, JSValueConst *argv)
144 | +{
145 | + int fd, operation, ret;
146 | + if (JS_ToInt32(ctx, &fd, argv[0]))
147 | + return JS_EXCEPTION;
148 | + if (JS_ToInt32(ctx, &operation, argv[1]))
149 | + return JS_EXCEPTION;
150 | + ret = js_get_errno(flock(fd, operation));
151 | + return JS_NewInt32(ctx, ret);
152 | +}
153 | +
154 | +/* mkstemp(template, outputObj) */
155 | +static JSValue js_os_mkstemp(JSContext *ctx, JSValueConst this_val,
156 | + int argc, JSValueConst *argv)
157 | +{
158 | + char buffer[PATH_MAX];
159 | + const char *template;
160 | + int ret;
161 | +
162 | + template = JS_ToCString(ctx, argv[0]);
163 | + if (!template)
164 | + return JS_EXCEPTION;
165 | + strncpy(buffer, template, sizeof(buffer));
166 | + JS_FreeCString(ctx, template);
167 | + ret = js_get_errno(mkstemp(buffer));
168 | + // check if we can pass the final filename back
169 | + if (argc >= 2 && ret > 0) {
170 | + if (!JS_IsUndefined(argv[1])) {
171 | + JS_SetPropertyStr(ctx, argv[1], "filename", JS_NewString(ctx, buffer));
172 | + }
173 | + }
174 | + return JS_NewInt32(ctx, ret);
175 | +}
176 | +
177 | +/* mkdtemp(template, errorObj) */
178 | +static JSValue js_os_mkdtemp(JSContext *ctx, JSValueConst this_val,
179 | + int argc, JSValueConst *argv)
180 | +{
181 | + char buffer[PATH_MAX];
182 | + const char *template;
183 | + const char *ptr;
184 | + int err = 0;
185 | +
186 | + template = JS_ToCString(ctx, argv[0]);
187 | + if (!template)
188 | + return JS_EXCEPTION;
189 | + strncpy(buffer, template, sizeof(buffer));
190 | + JS_FreeCString(ctx, template);
191 | + ptr = mkdtemp(buffer);
192 | + if (NULL == ptr) {
193 | + err = errno;
194 | + }
195 | + if (argc >= 2) {
196 | + js_set_error_object(ctx, argv[1], err);
197 | + }
198 | + if (NULL == ptr) {
199 | + return JS_NULL;
200 | + }
201 | + return JS_NewString(ctx, ptr);
202 | +}
203 | +
204 | +#endif /* !_APPLE_ */
205 |
206 | #endif /* !_WIN32 */
207 |
208 | @@ -3834,6 +3944,16 @@ static const JSCFunctionListEntry js_os_funcs[] = {
209 | JS_CFUNC_DEF("dup", 1, js_os_dup ),
210 | JS_CFUNC_DEF("dup2", 2, js_os_dup2 ),
211 | #endif
212 | +#if !defined(_WIN32) && !defined(_APPLE_)
213 | + // flock
214 | + JS_CFUNC_DEF("flock", 2, js_os_flock ),
215 | + OS_FLAG(LOCK_EX),
216 | + OS_FLAG(LOCK_NB),
217 | + // mkstemp
218 | + JS_CFUNC_DEF("mkstemp", 1, js_os_mkstemp ),
219 | + // mkdtemp
220 | + JS_CFUNC_DEF("mkdtemp", 1, js_os_mkdtemp ),
221 | +#endif
222 | };
223 |
224 | static int js_os_init(JSContext *ctx, JSModuleDef *m)
225 |
--------------------------------------------------------------------------------
/builder/custom/qjs/qjsc-x86_64:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ctn-malone/quickjs-cross-compiler/36bc7985737c6b3e9e4701e2d369dfa17ed96c0b/builder/custom/qjs/qjsc-x86_64
--------------------------------------------------------------------------------
/builder/custom/qjs/scripts/examples/compile_examples.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | ###
4 | #
5 | # Compile all .js sources in this directory
6 | #
7 | ###
8 |
9 | script_dir="$(cd "$(dirname "$(readlink -f "$0")")" && pwd)"
10 | # compile binaries
11 | for js_file in $(ls ${script_dir}/*.js)
12 | do
13 | echo "Compiling '${js_file}'..."
14 | filename="$(basename ${js_file} .js)"
15 | binary_file="${script_dir}/${filename}"
16 | ${script_dir}/../qjsc.sh -o ${binary_file} ${js_file} || exit 1
17 | done
18 | # compile binaries for ext-lib
19 | if [ -d ${script_dir}/ext-lib ]
20 | then
21 | for js_file in $(ls ${script_dir}/ext-lib/*.js)
22 | do
23 | echo "Compiling '${js_file}'..."
24 | filename="$(basename ${js_file} .js)"
25 | binary_file="${script_dir}/ext-lib/${filename}"
26 | ${script_dir}/../qjsc.sh -o ${binary_file} ${js_file} || exit 1
27 | done
28 | fi
29 |
--------------------------------------------------------------------------------
/builder/custom/qjs/scripts/qjs.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | ###
4 | #
5 | # This script should be use if you want to symlink 'qjs' binary
6 | # When using a direct symlink, import of js files located in the
7 | # directory containing 'qjs' binary will fail since 'qjs' binary
8 | # won't be able to find includes & libraries
9 | #
10 | # Using an intermediate shell script ensure symlink is correctly
11 | # resolved
12 | #
13 | ###
14 |
15 | # ensure we're returning exit code from child process
16 | trap ignore 2
17 |
18 | ignore() {
19 | :
20 | }
21 |
22 | script_dir="$(cd "$(dirname "$(readlink -f "$0")")" && pwd)"
23 | ${script_dir}/qjs "$@"
24 |
--------------------------------------------------------------------------------
/builder/custom/qjs/scripts/qjsc.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | ###
4 | #
5 | # This script should be use if you want to symlink 'qjsc' binary
6 | # When using a direct symlink, compilation will fail since 'qjsc'
7 | # won't be able to find includes & libraries
8 | #
9 | # Using an intermediate shell script ensure symlink is correctly
10 | # resolved
11 | #
12 | ###
13 |
14 | # if variable is not defined yet, check if upx is available
15 | if [ -z ${QJS_UPX} ]
16 | then
17 | upx=$(command -v upx)
18 | if ! [ -z ${upx} ]
19 | then
20 | QJS_UPX=1
21 | fi
22 | fi
23 | script_dir="$(cd "$(dirname "$(readlink -f "$0")")" && pwd)"
24 | QJS_UPX=${QJS_UPX} ${script_dir}/qjsc "$@"
25 |
--------------------------------------------------------------------------------
/builder/env/deps:
--------------------------------------------------------------------------------
1 | # musl library
2 | declare -A cfg_musl_lib=(
3 | ["archive_url"]="https://musl.libc.org/releases/musl-1.2.2.tar.gz"
4 | ["archive_dir"]="musl-1.2.2"
5 | ["archive_dir_symlink"]="musl"
6 | )
7 |
8 | # musl.cc cross-compiler for x86_64 target
9 | declare -A cfg_musl_cc_x86_64=(
10 | #["archive_url"]="https://more.musl.cc/10.2.1/x86_64-linux-musl/x86_64-linux-musl-cross.tgz"
11 | ["archive_url"]="https://github.com/ctn-malone/musl-cross-maker/releases/download/gcc-6.5.0_binutils-2.25.1_musl-1.2.2/x86_64-linux-musl-cross.tgz"
12 | ["archive_dir"]="x86_64-linux-musl-cross"
13 | ["archive_dir_symlink"]="musl_cc-x86_64"
14 | )
15 |
16 | # musl.cc cross-compiler for i686 target
17 | declare -A cfg_musl_cc_i686=(
18 | #["archive_url"]="https://more.musl.cc/10.2.1/x86_64-linux-musl/i686-linux-musl-cross.tgz"
19 | ["archive_url"]="https://github.com/ctn-malone/musl-cross-maker/releases/download/gcc-6.5.0_binutils-2.25.1_musl-1.2.2/i686-linux-musl-cross.tgz"
20 | ["archive_dir"]="i686-linux-musl-cross"
21 | ["archive_dir_symlink"]="musl_cc-i686"
22 | )
23 |
24 | # musl.cc cross-compiler for armv7l target
25 | declare -A cfg_musl_cc_armv7l=(
26 | #["archive_url"]="https://more.musl.cc/10.2.1/x86_64-linux-musl/armv7l-linux-musleabihf-cross.tgz"
27 | ["archive_url"]="https://github.com/ctn-malone/musl-cross-maker/releases/download/gcc-6.5.0_binutils-2.25.1_musl-1.2.2/armv7l-linux-musleabihf-cross.tgz"
28 | ["archive_dir"]="armv7l-linux-musleabihf-cross"
29 | ["archive_dir_symlink"]="musl_cc-armv7l"
30 | )
31 |
32 | # musl.cc cross-compiler for aarch64 target
33 | declare -A cfg_musl_cc_aarch64=(
34 | #["archive_url"]="https://more.musl.cc/10.2.1/x86_64-linux-musl/aarch64-linux-musl-cross.tgz"
35 | ["archive_url"]="https://github.com/ctn-malone/musl-cross-maker/releases/download/gcc-6.5.0_binutils-2.25.1_musl-1.2.2/aarch64-linux-musl-cross.tgz"
36 | ["archive_dir"]="aarch64-linux-musl-cross"
37 | ["archive_dir_symlink"]="musl_cc-aarch64"
38 | )
39 |
--------------------------------------------------------------------------------
/builder/env/qjs:
--------------------------------------------------------------------------------
1 | # QuickJS repository to clone
2 | qjs_repository="https://github.com/bellard/quickjs.git"
3 |
4 | default_qjs_version="2025-04-26"
5 |
6 | # mapping qjs version => commit id
7 | declare -A qjs_commits=(
8 | ["2020-09-06"]="7c312df422572cf867f29a1d80693e8a77f7fb2a"
9 | ["2020-11-08"]="204682fb87ab9312f0cf81f959ecd181180457bc"
10 | ["2021-03-27"]="b5e62895c619d4ffc75c9d822c8d85f1ece77e5b"
11 | ["2023-12-09"]="daa35bc1e5d43192098af9b51caeb4f18f73f9f9"
12 | ["2024-01-13"]="3f81070e573e3592728dbbbd04c84c498b20d6dc"
13 | ["2025-04-26"]="19abf1888db5884a5758036ff6e7fa2b340acedc"
14 | )
15 |
16 | # mapping qjs version => package name
17 | declare -A qjs_packages=(
18 | ["2020-09-06"]="2020-09-06"
19 | ["2020-11-08"]="2020-11-08_3"
20 | ["2021-03-27"]="2021-03-27_4"
21 | ["2023-12-09"]="2023-12-09_1"
22 | ["2024-01-13"]="2024-01-13_3"
23 | ["2025-04-26"]="2025-04-26_1"
24 | )
25 |
26 | # default tag for https://github.com/ctn-malone/qjs-ext-lib
27 | qjs_ext_lib_repository="https://github.com/ctn-malone/qjs-ext-lib"
28 | default_qjs_ext_lib_version="0.14.2"
29 |
--------------------------------------------------------------------------------
/builder/scripts/bootstrap-alpine.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | ###
4 | #
5 | # Used to install necessary Alpine packages (only needed when building under Alpine)
6 | #
7 | ###
8 |
9 | apk add build-base xz bash git curl upx
10 |
--------------------------------------------------------------------------------
/builder/scripts/build_deps.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ###
4 | #
5 | # Build dependencies
6 | # - compile musl lib for a specific architecture
7 | # - strip static libraries
8 | # - copy some static libraries from the musl-cc tree
9 | # - copy musl-gcc wrapper & specs
10 | #
11 | ###
12 |
13 | script_dir="$(cd "$(dirname "$(readlink -f "$0")")" && pwd)" || { echo "Couldn't determine the script's running directory, which probably matters, bailing out" >&2; exit 2; }
14 | source "${script_dir}/../env/qjs"
15 |
16 | # Created by argbash-init v2.10.0
17 | # ARG_OPTIONAL_SINGLE([deps-dir],[d],[directory containing dependencies],[$script_dir/../../deps])
18 | # ARG_OPTIONAL_SINGLE([arch],[a],[target architecture],[x86_64])
19 | # ARG_OPTIONAL_BOOLEAN([force],[f],[force rebuild],[off])
20 | # ARG_OPTIONAL_BOOLEAN([verbose],[v],[enable verbose mode],[off])
21 | # ARG_TYPE_GROUP_SET([arch],[type string],[arch],[x86_64,i686,armv7l,aarch64])
22 | # ARG_HELP([Build dependencies needed to build a static version of QuickJS])
23 | # ARGBASH_GO()
24 | # needed because of Argbash --> m4_ignore([
25 | ### START OF CODE GENERATED BY Argbash v2.10.0 one line above ###
26 | # Argbash is a bash code generator used to get arguments parsing right.
27 | # Argbash is FREE SOFTWARE, see https://argbash.io for more info
28 |
29 |
30 | die()
31 | {
32 | local _ret="${2:-1}"
33 | test "${_PRINT_HELP:-no}" = yes && print_help >&2
34 | echo "$1" >&2
35 | exit "${_ret}"
36 | }
37 |
38 | # validators
39 |
40 | arch()
41 | {
42 | local _allowed=("x86_64" "i686" "armv7l" "aarch64") _seeking="$1"
43 | for element in "${_allowed[@]}"
44 | do
45 | test "$element" = "$_seeking" && echo "$element" && return 0
46 | done
47 | die "Value '$_seeking' (of argument '$2') doesn't match the list of allowed values: 'x86_64', 'i686', 'armv7l' and 'aarch64'" 4
48 | }
49 |
50 |
51 | begins_with_short_option()
52 | {
53 | local first_option all_short_options='dafvh'
54 | first_option="${1:0:1}"
55 | test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0
56 | }
57 |
58 | # THE DEFAULTS INITIALIZATION - OPTIONALS
59 | _arg_deps_dir="$script_dir/../../deps"
60 | _arg_arch="x86_64"
61 | _arg_force="off"
62 | _arg_verbose="off"
63 |
64 |
65 | print_help()
66 | {
67 | printf '%s\n' "Build dependencies needed to build a static version of QuickJS"
68 | printf 'Usage: %s [-d|--deps-dir ] [-a|--arch ] [-f|--(no-)force] [-v|--(no-)verbose] [-h|--help]\n' "$0"
69 | printf '\t%s\n' "-d, --deps-dir: directory containing dependencies (default: '$script_dir/../../deps')"
70 | printf '\t%s\n' "-a, --arch: target architecture. Can be one of: 'x86_64', 'i686', 'armv7l' and 'aarch64' (default: 'x86_64')"
71 | printf '\t%s\n' "-f, --force, --no-force: force rebuild (off by default)"
72 | printf '\t%s\n' "-v, --verbose, --no-verbose: enable verbose mode (off by default)"
73 | printf '\t%s\n' "-h, --help: Prints help"
74 | }
75 |
76 |
77 | parse_commandline()
78 | {
79 | while test $# -gt 0
80 | do
81 | _key="$1"
82 | case "$_key" in
83 | -d|--deps-dir)
84 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
85 | _arg_deps_dir="$2"
86 | shift
87 | ;;
88 | --deps-dir=*)
89 | _arg_deps_dir="${_key##--deps-dir=}"
90 | ;;
91 | -d*)
92 | _arg_deps_dir="${_key##-d}"
93 | ;;
94 | -a|--arch)
95 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
96 | _arg_arch="$(arch "$2" "arch")" || exit 1
97 | shift
98 | ;;
99 | --arch=*)
100 | _arg_arch="$(arch "${_key##--arch=}" "arch")" || exit 1
101 | ;;
102 | -a*)
103 | _arg_arch="$(arch "${_key##-a}" "arch")" || exit 1
104 | ;;
105 | -f|--no-force|--force)
106 | _arg_force="on"
107 | test "${1:0:5}" = "--no-" && _arg_force="off"
108 | ;;
109 | -f*)
110 | _arg_force="on"
111 | _next="${_key##-f}"
112 | if test -n "$_next" -a "$_next" != "$_key"
113 | then
114 | { begins_with_short_option "$_next" && shift && set -- "-f" "-${_next}" "$@"; } || die "The short option '$_key' can't be decomposed to ${_key:0:2} and -${_key:2}, because ${_key:0:2} doesn't accept value and '-${_key:2:1}' doesn't correspond to a short option."
115 | fi
116 | ;;
117 | -v|--no-verbose|--verbose)
118 | _arg_verbose="on"
119 | test "${1:0:5}" = "--no-" && _arg_verbose="off"
120 | ;;
121 | -v*)
122 | _arg_verbose="on"
123 | _next="${_key##-v}"
124 | if test -n "$_next" -a "$_next" != "$_key"
125 | then
126 | { begins_with_short_option "$_next" && shift && set -- "-v" "-${_next}" "$@"; } || die "The short option '$_key' can't be decomposed to ${_key:0:2} and -${_key:2}, because ${_key:0:2} doesn't accept value and '-${_key:2:1}' doesn't correspond to a short option."
127 | fi
128 | ;;
129 | -h|--help)
130 | print_help
131 | exit 0
132 | ;;
133 | -h*)
134 | print_help
135 | exit 0
136 | ;;
137 | *)
138 | _PRINT_HELP=yes die "FATAL ERROR: Got an unexpected argument '$1'" 1
139 | ;;
140 | esac
141 | shift
142 | done
143 | }
144 |
145 | parse_commandline "$@"
146 |
147 | # OTHER STUFF GENERATED BY Argbash
148 | # Validation of values
149 |
150 |
151 | ### END OF CODE GENERATED BY Argbash (sortof) ### ])
152 | # [ <-- needed because of Argbash
153 |
154 |
155 | # vvv PLACE YOUR CODE HERE vvv
156 |
157 | source "${script_dir}/../env/deps"
158 |
159 | # build 'musl lib'
160 | build_musl_lib()
161 | {
162 | [ ${_arg_verbose} == "on" ] && echo "Building 'musl lib' for '${_arg_arch}'..."
163 |
164 | declare -n _cfg="cfg_musl_lib"
165 |
166 | # directory containing 'musl' sources
167 | _archive_dir="${deps_dir}/${_cfg["archive_dir_symlink"]}"
168 | # directory where built library will be installed
169 | _build_dir="${_archive_dir}/BUILD-${_arg_arch}"
170 | # used to keep track of whether or not library was built
171 | _built_marker="${_archive_dir}/.built-${_arg_arch}"
172 | # compiler binary
173 | _cc="${deps_dir}/musl_cc-${_arg_arch}/cc"
174 | # library which will be copied from 'musl_cc' directory (required for 'armv7l' compilation)
175 | _libatomic="${deps_dir}/musl_cc-${_arg_arch}/libatomic.a"
176 | # library which will be copied from 'musl_cc' directory (to avoid linking error 'cannot find -lssp_nonshared' on alpine)
177 | _libssp_nonshared="${deps_dir}/musl_cc-${_arg_arch}/libssp_nonshared.a"
178 | # use 'strip' binary from cross compiler
179 | _strip="${deps_dir}/musl_cc-${_arg_arch}/strip"
180 | # directory containing custom files which will be copied after build
181 | _custom_dir="${custom_dir}/musl"
182 |
183 | # ensure all dependencies exist
184 | if ! [ -d ${_archive_dir} ] || ! [ -f ${_cc} ]
185 | then
186 | echo "Missing dependencies. Run 'fetch_deps.sh' script first" 1>&2
187 | return 1
188 | fi
189 |
190 | # already built
191 | if [ -f ${_built_marker} ] && [ ${_arg_force} == "off" ]
192 | then
193 | [ ${_arg_verbose} == "on" ] && echo "No need to build 'musl lib' for '${_arg_arch}'"
194 | else
195 | # build
196 | (rm -f ${_built_marker} && \
197 | rm -fr ${_build_dir} && \
198 | cd ${_archive_dir} && \
199 | make clean && \
200 | CC=${_cc} LDFLAGS=-s ./configure --disable-shared \
201 | --prefix=/ \
202 | --syslibdir=/lib \
203 | --exec-prefix=/ \
204 | --enable-wrapper=no && \
205 | DESTDIR=${_build_dir} make install) || return 1
206 | [ ${_arg_verbose} == "on" ] && echo "Successfully built 'musl lib' for '${_arg_arch}'"
207 | fi
208 |
209 | # copy script & specs
210 | cp -R ${_custom_dir}/* ${_build_dir} || return 1
211 |
212 | # copy 'libatomic' from musl-cc
213 | cp -L ${_libatomic} ${_build_dir}/lib || return 1
214 |
215 | # copy 'libssp_nonshared' from musl-cc
216 | cp -L ${_libssp_nonshared} ${_build_dir}/lib || return 1
217 |
218 | # strip all static libraries
219 | for _file in $(find "${_build_dir}/" -type f -name '*.a')
220 | do
221 | ${_strip} -d ${_file} || return 1
222 | done
223 |
224 | # create build marker
225 | touch ${_built_marker} || return 1
226 |
227 | return 0
228 | }
229 |
230 | # build all dependencies
231 | build_deps()
232 | {
233 | [ ${_arg_verbose} == "on" ] && echo "Building dependencies for '${_arg_arch}'..."
234 |
235 | build_musl_lib || return 1
236 |
237 | [ ${_arg_verbose} == "on" ] && echo "Dependencies for '${_arg_arch}' successfully built"
238 |
239 | return 0
240 | }
241 |
242 | _PRINT_HELP=no
243 | deps_dir=${_arg_deps_dir}
244 | custom_dir="${script_dir}/../custom"
245 |
246 | build_deps || die "Could not build dependencies for '${_arg_arch}'"
247 |
248 | # ^^^ TERMINATE YOUR CODE BEFORE THE BOTTOM ARGBASH MARKER ^^^
249 |
250 | # ] <-- needed because of Argbash
251 |
--------------------------------------------------------------------------------
/builder/scripts/build_qjs.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ###
4 | #
5 | # Compile QuickJS
6 | # - compile interpreter & compiler statically
7 | #
8 | ###
9 |
10 | script_dir="$(cd "$(dirname "$(readlink -f "$0")")" && pwd)" || { echo "Couldn't determine the script's running directory, which probably matters, bailing out" >&2; exit 2; }
11 | source "${script_dir}/../env/qjs"
12 |
13 | # Created by argbash-init v2.10.0
14 | # ARG_OPTIONAL_SINGLE([deps-dir],[d],[directory containing dependencies],[$script_dir/../../deps])
15 | # ARG_OPTIONAL_SINGLE([arch],[a],[target architecture],[x86_64])
16 | # ARG_OPTIONAL_BOOLEAN([force],[f],[force rebuild],[off])
17 | # ARG_OPTIONAL_BOOLEAN([verbose],[v],[enable verbose mode],[off])
18 | # ARG_POSITIONAL_SINGLE([qjs-version],[QuickJS version (ex: 2020-09-06)],[$default_qjs_version])
19 | # ARG_TYPE_GROUP_SET([arch],[type string],[arch],[x86_64,i686,armv7l,aarch64])
20 | # ARG_HELP([Build a static version of QuickJS (interpreter & compiler)])
21 | # ARGBASH_GO()
22 | # needed because of Argbash --> m4_ignore([
23 | ### START OF CODE GENERATED BY Argbash v2.10.0 one line above ###
24 | # Argbash is a bash code generator used to get arguments parsing right.
25 | # Argbash is FREE SOFTWARE, see https://argbash.io for more info
26 |
27 |
28 | die()
29 | {
30 | local _ret="${2:-1}"
31 | test "${_PRINT_HELP:-no}" = yes && print_help >&2
32 | echo "$1" >&2
33 | exit "${_ret}"
34 | }
35 |
36 | # validators
37 |
38 | arch()
39 | {
40 | local _allowed=("x86_64" "i686" "armv7l" "aarch64") _seeking="$1"
41 | for element in "${_allowed[@]}"
42 | do
43 | test "$element" = "$_seeking" && echo "$element" && return 0
44 | done
45 | die "Value '$_seeking' (of argument '$2') doesn't match the list of allowed values: 'x86_64', 'i686', 'armv7l' and 'aarch64'" 4
46 | }
47 |
48 |
49 | begins_with_short_option()
50 | {
51 | local first_option all_short_options='dafvh'
52 | first_option="${1:0:1}"
53 | test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0
54 | }
55 |
56 | # THE DEFAULTS INITIALIZATION - POSITIONALS
57 | _positionals=()
58 | _arg_qjs_version="$default_qjs_version"
59 | # THE DEFAULTS INITIALIZATION - OPTIONALS
60 | _arg_deps_dir="$script_dir/../../deps"
61 | _arg_arch="x86_64"
62 | _arg_force="off"
63 | _arg_verbose="off"
64 |
65 |
66 | print_help()
67 | {
68 | printf '%s\n' "Build a static version of QuickJS (interpreter & compiler)"
69 | printf 'Usage: %s [-d|--deps-dir ] [-a|--arch ] [-f|--(no-)force] [-v|--(no-)verbose] [-h|--help] []\n' "$0"
70 | printf '\t%s\n' ": QuickJS version (ex: 2020-09-06) (default: '$default_qjs_version')"
71 | printf '\t%s\n' "-d, --deps-dir: directory containing dependencies (default: '$script_dir/../../deps')"
72 | printf '\t%s\n' "-a, --arch: target architecture. Can be one of: 'x86_64', 'i686', 'armv7l' and 'aarch64' (default: 'x86_64')"
73 | printf '\t%s\n' "-f, --force, --no-force: force rebuild (off by default)"
74 | printf '\t%s\n' "-v, --verbose, --no-verbose: enable verbose mode (off by default)"
75 | printf '\t%s\n' "-h, --help: Prints help"
76 | }
77 |
78 |
79 | parse_commandline()
80 | {
81 | _positionals_count=0
82 | while test $# -gt 0
83 | do
84 | _key="$1"
85 | case "$_key" in
86 | -d|--deps-dir)
87 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
88 | _arg_deps_dir="$2"
89 | shift
90 | ;;
91 | --deps-dir=*)
92 | _arg_deps_dir="${_key##--deps-dir=}"
93 | ;;
94 | -d*)
95 | _arg_deps_dir="${_key##-d}"
96 | ;;
97 | -a|--arch)
98 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
99 | _arg_arch="$(arch "$2" "arch")" || exit 1
100 | shift
101 | ;;
102 | --arch=*)
103 | _arg_arch="$(arch "${_key##--arch=}" "arch")" || exit 1
104 | ;;
105 | -a*)
106 | _arg_arch="$(arch "${_key##-a}" "arch")" || exit 1
107 | ;;
108 | -f|--no-force|--force)
109 | _arg_force="on"
110 | test "${1:0:5}" = "--no-" && _arg_force="off"
111 | ;;
112 | -f*)
113 | _arg_force="on"
114 | _next="${_key##-f}"
115 | if test -n "$_next" -a "$_next" != "$_key"
116 | then
117 | { begins_with_short_option "$_next" && shift && set -- "-f" "-${_next}" "$@"; } || die "The short option '$_key' can't be decomposed to ${_key:0:2} and -${_key:2}, because ${_key:0:2} doesn't accept value and '-${_key:2:1}' doesn't correspond to a short option."
118 | fi
119 | ;;
120 | -v|--no-verbose|--verbose)
121 | _arg_verbose="on"
122 | test "${1:0:5}" = "--no-" && _arg_verbose="off"
123 | ;;
124 | -v*)
125 | _arg_verbose="on"
126 | _next="${_key##-v}"
127 | if test -n "$_next" -a "$_next" != "$_key"
128 | then
129 | { begins_with_short_option "$_next" && shift && set -- "-v" "-${_next}" "$@"; } || die "The short option '$_key' can't be decomposed to ${_key:0:2} and -${_key:2}, because ${_key:0:2} doesn't accept value and '-${_key:2:1}' doesn't correspond to a short option."
130 | fi
131 | ;;
132 | -h|--help)
133 | print_help
134 | exit 0
135 | ;;
136 | -h*)
137 | print_help
138 | exit 0
139 | ;;
140 | *)
141 | _last_positional="$1"
142 | _positionals+=("$_last_positional")
143 | _positionals_count=$((_positionals_count + 1))
144 | ;;
145 | esac
146 | shift
147 | done
148 | }
149 |
150 |
151 | handle_passed_args_count()
152 | {
153 | test "${_positionals_count}" -le 1 || _PRINT_HELP=yes die "FATAL ERROR: There were spurious positional arguments --- we expect between 0 and 1, but got ${_positionals_count} (the last one was: '${_last_positional}')." 1
154 | }
155 |
156 |
157 | assign_positional_args()
158 | {
159 | local _positional_name _shift_for=$1
160 | _positional_names="_arg_qjs_version "
161 |
162 | shift "$_shift_for"
163 | for _positional_name in ${_positional_names}
164 | do
165 | test $# -gt 0 || break
166 | eval "$_positional_name=\${1}" || die "Error during argument parsing, possibly an Argbash bug." 1
167 | shift
168 | done
169 | }
170 |
171 | parse_commandline "$@"
172 | handle_passed_args_count
173 | assign_positional_args 1 "${_positionals[@]}"
174 |
175 | # OTHER STUFF GENERATED BY Argbash
176 | # Validation of values
177 |
178 |
179 | ### END OF CODE GENERATED BY Argbash (sortof) ### ])
180 | # [ <-- needed because of Argbash
181 |
182 |
183 | # vvv PLACE YOUR CODE HERE vvv
184 |
185 | source "${script_dir}/../env/qjs"
186 |
187 | # ensure version exist
188 | qjs_commit="${qjs_commits[${_arg_qjs_version}]}"
189 | if [ -z ${qjs_commit} ]
190 | then
191 | _PRINT_HELP=yes die "QuickJS version '${_arg_qjs_version}' is not supported"
192 | fi
193 |
194 | # build QuickJS
195 | build_qjs()
196 | {
197 | [ ${_arg_verbose} == "on" ] && echo "Building 'QuickJS' version '${_arg_qjs_version}'..."
198 |
199 | # compiler binary
200 | _cc="${deps_dir}/musl_cc-${_arg_arch}/cc"
201 |
202 | # ensure cross compiler exists
203 | if ! [ -f ${_cc} ]
204 | then
205 | echo "Missing dependencies. Run 'fetch_deps.sh' script first" 1>&2
206 | return 1
207 | fi
208 |
209 | # ensure repository exists
210 | if ! [ -d ${repo_dir} ]
211 | then
212 | echo "Local repository does not exist. Run 'checkout_qjs.sh' script first" 1>&2
213 | return 1
214 | fi
215 |
216 | # If target architecture is not 'x86_64', ensure 'qjsc-x86_64' exists
217 | # since we will need its 'qjsc' binary to generate c files
218 | # It is supposed to be copied by 'checkout_qjs' script
219 | _qjsc_binary="${repo_dir}/qjsc"
220 | if [ ${_arg_arch} != "x86_64" ]
221 | then
222 | _qjsc_binary="${repo_dir}/qjsc-x86_64"
223 | if ! [ -f ${_qjsc_binary} ]
224 | then
225 | echo "File '${_qjsc_binary}' does not exist. Run 'prepare_qjs.sh' script first" 1>&2
226 | return 1
227 | fi
228 | fi
229 |
230 | # ensure expected commit is checked out
231 | cd ${repo_dir} && \
232 | current_commit="$(git rev-parse HEAD)"
233 | if [ ${current_commit} != ${qjs_commit} ]
234 | then
235 | echo "Current commit (${current_commit}) does not match expected one (${qjs_commit}). Run 'checkout_qjs.sh' script first" 1>&2
236 | return 1
237 | fi
238 |
239 | # directory where QuickJS will be installed after being built
240 | _build_dir="${repo_dir}/BUILD-${_arg_qjs_version}-${_arg_arch}"
241 | # used to keep track of whether or not repo was patched
242 | _patched_marker="${repo_dir}/.patched-${_arg_qjs_version}"
243 | # used to keep track of whether or not QuickJS was already built
244 | _built_marker="${repo_dir}/.built-${_arg_qjs_version}-${_arg_arch}"
245 | # symlink in the repository, referencing the directory containing 'musl' build
246 | _musl_dir_symlink="${repo_dir}/musl-${_arg_arch}"
247 |
248 | # ensure patches were applied
249 | if ! [ -f ${_patched_marker} ]
250 | then
251 | echo "Local repository not patched. Run 'prepare_qjs.sh' script first" 1>&2
252 | return 1
253 | fi
254 |
255 | # ensure link to 'musl lib' exists
256 | if ! [ -d ${_musl_dir_symlink} ]
257 | then
258 | echo "'musl lib' symlink not found. Run 'prepare_qjs.sh' script first" 1>&2
259 | return 1
260 | fi
261 |
262 | # QuickJS was already built
263 | if [ -f ${_built_marker} ] && [ ${_arg_force} == "off" ]
264 | then
265 | [ ${_arg_verbose} == "on" ] && echo "No need to build 'QuickJS' version '${_arg_qjs_version}' for '${_arg_arch}'"
266 | else
267 | # build
268 | [ ${_arg_verbose} == "on" ] && echo "qjs_cc=${_cc} musl_arch=${_arg_arch} qjsc_binary=${_qjsc_binary} make"
269 | (rm -f ${_built_marker} && \
270 | rm -f ${_commit_marker} && \
271 | rm -fr ${_build_dir} && \
272 | cd ${repo_dir} && \
273 | make clean && \
274 | qjs_cc=${_cc} musl_arch=${_arg_arch} qjsc_binary=${_qjsc_binary} make && \
275 | DESTDIR=${_build_dir} make install) || return 1
276 | [ ${_arg_verbose} == "on" ] && echo "'QuickJS' version '${_arg_qjs_version}' successfully built for '${_arg_arch}'"
277 | fi
278 |
279 | # create build marker
280 | echo ${qjs_commit} >${_built_marker} || return 1
281 |
282 | return 0
283 | }
284 |
285 | _PRINT_HELP=no
286 | deps_dir=${_arg_deps_dir}
287 | repo_dir="${script_dir}/../../quickjs-repo"
288 |
289 | build_qjs || die "Could not build 'QuickJS' version '${_arg_qjs_version}' for '${_arg_arch}'"
290 |
291 | # ^^^ TERMINATE YOUR CODE BEFORE THE BOTTOM ARGBASH MARKER ^^^
292 |
293 | # ] <-- needed because of Argbash
294 |
--------------------------------------------------------------------------------
/builder/scripts/checkout_qjs.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ###
4 | #
5 | # Checkout a specific version of QuickJS from github
6 | #
7 | ###
8 |
9 | script_dir="$(cd "$(dirname "$(readlink -f "$0")")" && pwd)" || { echo "Couldn't determine the script's running directory, which probably matters, bailing out" >&2; exit 2; }
10 | source "${script_dir}/../env/qjs"
11 |
12 | # Created by argbash-init v2.10.0
13 | # ARG_OPTIONAL_BOOLEAN([force],[f],[clone repository even if it exists],[off])
14 | # ARG_OPTIONAL_BOOLEAN([verbose],[v],[enable verbose mode],[off])
15 | # ARG_POSITIONAL_SINGLE([qjs-version],[QuickJS version (ex: 2020-09-06)],[$default_qjs_version])
16 | # ARG_HELP([Clone QuickJS repository & checkout a specific commit])
17 | # ARGBASH_GO()
18 | # needed because of Argbash --> m4_ignore([
19 | ### START OF CODE GENERATED BY Argbash v2.10.0 one line above ###
20 | # Argbash is a bash code generator used to get arguments parsing right.
21 | # Argbash is FREE SOFTWARE, see https://argbash.io for more info
22 |
23 |
24 | die()
25 | {
26 | local _ret="${2:-1}"
27 | test "${_PRINT_HELP:-no}" = yes && print_help >&2
28 | echo "$1" >&2
29 | exit "${_ret}"
30 | }
31 |
32 |
33 | begins_with_short_option()
34 | {
35 | local first_option all_short_options='fvh'
36 | first_option="${1:0:1}"
37 | test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0
38 | }
39 |
40 | # THE DEFAULTS INITIALIZATION - POSITIONALS
41 | _positionals=()
42 | _arg_qjs_version="$default_qjs_version"
43 | # THE DEFAULTS INITIALIZATION - OPTIONALS
44 | _arg_force="off"
45 | _arg_verbose="off"
46 |
47 |
48 | print_help()
49 | {
50 | printf '%s\n' "Clone QuickJS repository & checkout a specific commit"
51 | printf 'Usage: %s [-f|--(no-)force] [-v|--(no-)verbose] [-h|--help] []\n' "$0"
52 | printf '\t%s\n' ": QuickJS version (ex: 2020-09-06) (default: '$default_qjs_version')"
53 | printf '\t%s\n' "-f, --force, --no-force: clone repository even if it exists (off by default)"
54 | printf '\t%s\n' "-v, --verbose, --no-verbose: enable verbose mode (off by default)"
55 | printf '\t%s\n' "-h, --help: Prints help"
56 | }
57 |
58 |
59 | parse_commandline()
60 | {
61 | _positionals_count=0
62 | while test $# -gt 0
63 | do
64 | _key="$1"
65 | case "$_key" in
66 | -f|--no-force|--force)
67 | _arg_force="on"
68 | test "${1:0:5}" = "--no-" && _arg_force="off"
69 | ;;
70 | -f*)
71 | _arg_force="on"
72 | _next="${_key##-f}"
73 | if test -n "$_next" -a "$_next" != "$_key"
74 | then
75 | { begins_with_short_option "$_next" && shift && set -- "-f" "-${_next}" "$@"; } || die "The short option '$_key' can't be decomposed to ${_key:0:2} and -${_key:2}, because ${_key:0:2} doesn't accept value and '-${_key:2:1}' doesn't correspond to a short option."
76 | fi
77 | ;;
78 | -v|--no-verbose|--verbose)
79 | _arg_verbose="on"
80 | test "${1:0:5}" = "--no-" && _arg_verbose="off"
81 | ;;
82 | -v*)
83 | _arg_verbose="on"
84 | _next="${_key##-v}"
85 | if test -n "$_next" -a "$_next" != "$_key"
86 | then
87 | { begins_with_short_option "$_next" && shift && set -- "-v" "-${_next}" "$@"; } || die "The short option '$_key' can't be decomposed to ${_key:0:2} and -${_key:2}, because ${_key:0:2} doesn't accept value and '-${_key:2:1}' doesn't correspond to a short option."
88 | fi
89 | ;;
90 | -h|--help)
91 | print_help
92 | exit 0
93 | ;;
94 | -h*)
95 | print_help
96 | exit 0
97 | ;;
98 | *)
99 | _last_positional="$1"
100 | _positionals+=("$_last_positional")
101 | _positionals_count=$((_positionals_count + 1))
102 | ;;
103 | esac
104 | shift
105 | done
106 | }
107 |
108 |
109 | handle_passed_args_count()
110 | {
111 | test "${_positionals_count}" -le 1 || _PRINT_HELP=yes die "FATAL ERROR: There were spurious positional arguments --- we expect between 0 and 1, but got ${_positionals_count} (the last one was: '${_last_positional}')." 1
112 | }
113 |
114 |
115 | assign_positional_args()
116 | {
117 | local _positional_name _shift_for=$1
118 | _positional_names="_arg_qjs_version "
119 |
120 | shift "$_shift_for"
121 | for _positional_name in ${_positional_names}
122 | do
123 | test $# -gt 0 || break
124 | eval "$_positional_name=\${1}" || die "Error during argument parsing, possibly an Argbash bug." 1
125 | shift
126 | done
127 | }
128 |
129 | parse_commandline "$@"
130 | handle_passed_args_count
131 | assign_positional_args 1 "${_positionals[@]}"
132 |
133 | # OTHER STUFF GENERATED BY Argbash
134 |
135 | ### END OF CODE GENERATED BY Argbash (sortof) ### ])
136 | # [ <-- needed because of Argbash
137 |
138 |
139 | # vvv PLACE YOUR CODE HERE vvv
140 |
141 | # ensure version exist
142 | qjs_commit="${qjs_commits[${_arg_qjs_version}]}"
143 | if [ -z ${qjs_commit} ]
144 | then
145 | _PRINT_HELP=yes die "QuickJS version '${_arg_qjs_version}' is not supported"
146 | fi
147 |
148 | # clone QuickJS repo
149 | clone_repo()
150 | {
151 | [ ${_arg_verbose} == "on" ] && echo "Cloning 'QuickJS' repository '${qjs_repository}'..."
152 |
153 | # no need to clone repository
154 | if [ -d ${repo_dir} ] && [ ${_arg_force} == "off" ]
155 | then
156 | [ ${_arg_verbose} == "on" ] && echo "No need to clone 'QuickJS' repository '${qjs_repository}'"
157 | else
158 | (rm -fr ${repo_dir} && \
159 | cd ${script_dir}/.. &&
160 | git clone ${qjs_repository} ${repo_dir}) || return 1
161 | [ ${_arg_verbose} == "on" ] && echo "Successfully cloned 'QuickJS' repository '$qjs_repository'"
162 | fi
163 |
164 | return 0
165 | }
166 |
167 | # Checkout a specific commit corresponding to the requested version
168 | checkout_commit()
169 | {
170 | [ ${_arg_verbose} == "on" ] && echo "Checking out 'QuickJS' commit '${qjs_commits[${_arg_qjs_version}]}'..."
171 |
172 | (cd ${repo_dir} &&
173 | git checkout ${qjs_commits[${_arg_qjs_version}]}) || return 1
174 |
175 | [ ${_arg_verbose} == "on" ] && echo "Successfully checked out 'QuickJS' commit '${qjs_commits[${_arg_qjs_version}]}'"
176 |
177 | return 0
178 | }
179 |
180 | _PRINT_HELP=no
181 | src_dir="${script_dir}/../src"
182 | repo_dir="${script_dir}/../../quickjs-repo"
183 |
184 | clone_repo || die "Could not clone repository"
185 | checkout_commit || die "Could not checkout commit"
186 |
187 | # ^^^ TERMINATE YOUR CODE BEFORE THE BOTTOM ARGBASH MARKER ^^^
188 |
189 | # ] <-- needed because of Argbash
190 |
--------------------------------------------------------------------------------
/builder/scripts/export_qjs.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ###
4 | #
5 | # Export a portable package which can be used to generate static binaries
6 | # - strip binaries & static libraries
7 | # - compress binaries using upx
8 | # - add extra directories (optional)
9 | # - generate an archive compressed with xz
10 | #
11 | ###
12 |
13 | script_dir="$(cd "$(dirname "$(readlink -f "$0")")" && pwd)" || { echo "Couldn't determine the script's running directory, which probably matters, bailing out" >&2; exit 2; }
14 | source "${script_dir}/../env/qjs"
15 |
16 | # Created by argbash-init v2.10.0
17 | # ARG_OPTIONAL_SINGLE([deps-dir],[d],[directory containing dependencies],[$script_dir/../../deps])
18 | # ARG_OPTIONAL_SINGLE([packages-dir],[p],[directory where package will be exported],[$script_dir/../../packages])
19 | # ARG_OPTIONAL_BOOLEAN([verbose],[v],[enable verbose mode],[off])
20 | # ARG_OPTIONAL_BOOLEAN([upx],[u],[compress binaries using upx],[on])
21 | # ARG_OPTIONAL_SINGLE([arch],[a],[target architecture],[x86_64])
22 | # ARG_OPTIONAL_BOOLEAN([ext-lib],[],[add QuickJS extension library],[off])
23 | # ARG_OPTIONAL_SINGLE([ext-lib-version],[],[QuickJS extension library version],[$default_qjs_ext_lib_version])
24 | # ARG_OPTIONAL_REPEATED([extra-dir],[e],[extra directory to add into package],[])
25 | # ARG_POSITIONAL_SINGLE([qjs-version],[QuickJS version (ex: 2020-09-06)],[$default_qjs_version])
26 | # ARG_TYPE_GROUP_SET([arch],[type string],[arch],[x86_64,i686,armv7l,aarch64])
27 | # ARG_HELP([Export a tarball containing a static version of QuickJS and a static version of musl library])
28 | # ARGBASH_GO()
29 | # needed because of Argbash --> m4_ignore([
30 | ### START OF CODE GENERATED BY Argbash v2.10.0 one line above ###
31 | # Argbash is a bash code generator used to get arguments parsing right.
32 | # Argbash is FREE SOFTWARE, see https://argbash.io for more info
33 |
34 |
35 | die()
36 | {
37 | local _ret="${2:-1}"
38 | test "${_PRINT_HELP:-no}" = yes && print_help >&2
39 | echo "$1" >&2
40 | exit "${_ret}"
41 | }
42 |
43 | # validators
44 |
45 | arch()
46 | {
47 | local _allowed=("x86_64" "i686" "armv7l" "aarch64") _seeking="$1"
48 | for element in "${_allowed[@]}"
49 | do
50 | test "$element" = "$_seeking" && echo "$element" && return 0
51 | done
52 | die "Value '$_seeking' (of argument '$2') doesn't match the list of allowed values: 'x86_64', 'i686', 'armv7l' and 'aarch64'" 4
53 | }
54 |
55 |
56 | begins_with_short_option()
57 | {
58 | local first_option all_short_options='dpvuaeh'
59 | first_option="${1:0:1}"
60 | test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0
61 | }
62 |
63 | # THE DEFAULTS INITIALIZATION - POSITIONALS
64 | _positionals=()
65 | _arg_qjs_version="$default_qjs_version"
66 | # THE DEFAULTS INITIALIZATION - OPTIONALS
67 | _arg_deps_dir="$script_dir/../../deps"
68 | _arg_packages_dir="$script_dir/../../packages"
69 | _arg_verbose="off"
70 | _arg_upx="on"
71 | _arg_arch="x86_64"
72 | _arg_ext_lib="off"
73 | _arg_ext_lib_version="$default_qjs_ext_lib_version"
74 | _arg_extra_dir=()
75 |
76 |
77 | print_help()
78 | {
79 | printf '%s\n' "Export a tarball containing a static version of QuickJS and a static version of musl library"
80 | printf 'Usage: %s [-d|--deps-dir ] [-p|--packages-dir ] [-v|--(no-)verbose] [-u|--(no-)upx] [-a|--arch ] [--(no-)ext-lib] [--ext-lib-version ] [-e|--extra-dir ] [-h|--help] []\n' "$0"
81 | printf '\t%s\n' ": QuickJS version (ex: 2020-09-06) (default: '$default_qjs_version')"
82 | printf '\t%s\n' "-d, --deps-dir: directory containing dependencies (default: '$script_dir/../../deps')"
83 | printf '\t%s\n' "-p, --packages-dir: directory where package will be exported (default: '$script_dir/../../packages')"
84 | printf '\t%s\n' "-v, --verbose, --no-verbose: enable verbose mode (off by default)"
85 | printf '\t%s\n' "-u, --upx, --no-upx: compress binaries using upx (on by default)"
86 | printf '\t%s\n' "-a, --arch: target architecture. Can be one of: 'x86_64', 'i686', 'armv7l' and 'aarch64' (default: 'x86_64')"
87 | printf '\t%s\n' "--ext-lib, --no-ext-lib: add QuickJS extension library (off by default)"
88 | printf '\t%s\n' "--ext-lib-version: QuickJS extension library version (default: '$default_qjs_ext_lib_version')"
89 | printf '\t%s\n' "-e, --extra-dir: extra directory to add into package (empty by default)"
90 | printf '\t%s\n' "-h, --help: Prints help"
91 | }
92 |
93 |
94 | parse_commandline()
95 | {
96 | _positionals_count=0
97 | while test $# -gt 0
98 | do
99 | _key="$1"
100 | case "$_key" in
101 | -d|--deps-dir)
102 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
103 | _arg_deps_dir="$2"
104 | shift
105 | ;;
106 | --deps-dir=*)
107 | _arg_deps_dir="${_key##--deps-dir=}"
108 | ;;
109 | -d*)
110 | _arg_deps_dir="${_key##-d}"
111 | ;;
112 | -p|--packages-dir)
113 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
114 | _arg_packages_dir="$2"
115 | shift
116 | ;;
117 | --packages-dir=*)
118 | _arg_packages_dir="${_key##--packages-dir=}"
119 | ;;
120 | -p*)
121 | _arg_packages_dir="${_key##-p}"
122 | ;;
123 | -v|--no-verbose|--verbose)
124 | _arg_verbose="on"
125 | test "${1:0:5}" = "--no-" && _arg_verbose="off"
126 | ;;
127 | -v*)
128 | _arg_verbose="on"
129 | _next="${_key##-v}"
130 | if test -n "$_next" -a "$_next" != "$_key"
131 | then
132 | { begins_with_short_option "$_next" && shift && set -- "-v" "-${_next}" "$@"; } || die "The short option '$_key' can't be decomposed to ${_key:0:2} and -${_key:2}, because ${_key:0:2} doesn't accept value and '-${_key:2:1}' doesn't correspond to a short option."
133 | fi
134 | ;;
135 | -u|--no-upx|--upx)
136 | _arg_upx="on"
137 | test "${1:0:5}" = "--no-" && _arg_upx="off"
138 | ;;
139 | -u*)
140 | _arg_upx="on"
141 | _next="${_key##-u}"
142 | if test -n "$_next" -a "$_next" != "$_key"
143 | then
144 | { begins_with_short_option "$_next" && shift && set -- "-u" "-${_next}" "$@"; } || die "The short option '$_key' can't be decomposed to ${_key:0:2} and -${_key:2}, because ${_key:0:2} doesn't accept value and '-${_key:2:1}' doesn't correspond to a short option."
145 | fi
146 | ;;
147 | -a|--arch)
148 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
149 | _arg_arch="$(arch "$2" "arch")" || exit 1
150 | shift
151 | ;;
152 | --arch=*)
153 | _arg_arch="$(arch "${_key##--arch=}" "arch")" || exit 1
154 | ;;
155 | -a*)
156 | _arg_arch="$(arch "${_key##-a}" "arch")" || exit 1
157 | ;;
158 | --no-ext-lib|--ext-lib)
159 | _arg_ext_lib="on"
160 | test "${1:0:5}" = "--no-" && _arg_ext_lib="off"
161 | ;;
162 | --ext-lib-version)
163 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
164 | _arg_ext_lib_version="$2"
165 | shift
166 | ;;
167 | --ext-lib-version=*)
168 | _arg_ext_lib_version="${_key##--ext-lib-version=}"
169 | ;;
170 | -e|--extra-dir)
171 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
172 | _arg_extra_dir+=("$2")
173 | shift
174 | ;;
175 | --extra-dir=*)
176 | _arg_extra_dir+=("${_key##--extra-dir=}")
177 | ;;
178 | -e*)
179 | _arg_extra_dir+=("${_key##-e}")
180 | ;;
181 | -h|--help)
182 | print_help
183 | exit 0
184 | ;;
185 | -h*)
186 | print_help
187 | exit 0
188 | ;;
189 | *)
190 | _last_positional="$1"
191 | _positionals+=("$_last_positional")
192 | _positionals_count=$((_positionals_count + 1))
193 | ;;
194 | esac
195 | shift
196 | done
197 | }
198 |
199 |
200 | handle_passed_args_count()
201 | {
202 | test "${_positionals_count}" -le 1 || _PRINT_HELP=yes die "FATAL ERROR: There were spurious positional arguments --- we expect between 0 and 1, but got ${_positionals_count} (the last one was: '${_last_positional}')." 1
203 | }
204 |
205 |
206 | assign_positional_args()
207 | {
208 | local _positional_name _shift_for=$1
209 | _positional_names="_arg_qjs_version "
210 |
211 | shift "$_shift_for"
212 | for _positional_name in ${_positional_names}
213 | do
214 | test $# -gt 0 || break
215 | eval "$_positional_name=\${1}" || die "Error during argument parsing, possibly an Argbash bug." 1
216 | shift
217 | done
218 | }
219 |
220 | parse_commandline "$@"
221 | handle_passed_args_count
222 | assign_positional_args 1 "${_positionals[@]}"
223 |
224 | # OTHER STUFF GENERATED BY Argbash
225 | # Validation of values
226 |
227 |
228 | ### END OF CODE GENERATED BY Argbash (sortof) ### ])
229 | # [ <-- needed because of Argbash
230 |
231 |
232 | # vvv PLACE YOUR CODE HERE vvv
233 |
234 | # ensure version exists
235 | qjs_commit="${qjs_commits[${_arg_qjs_version}]}"
236 | if [ -z ${qjs_commit} ]
237 | then
238 | _PRINT_HELP=yes die "QuickJS version '${_arg_qjs_version}' is not supported (commit unknown)"
239 | fi
240 |
241 | # ensure package name exists
242 | qjs_package="${qjs_packages[${_arg_qjs_version}]}"
243 | if [ -z ${qjs_package} ]
244 | then
245 | _PRINT_HELP=yes die "QuickJS version '${_arg_qjs_version}' is not supported (package unknown)"
246 | fi
247 |
248 | package_type=core
249 | if ! [ -z ${_arg_extra_dir} ] || [ ${_arg_ext_lib} == "on" ]
250 | then
251 | # we have been given directories to add to package
252 | package_type=ext
253 | fi
254 |
255 | # export QuickJS
256 | export_qjs()
257 | {
258 | [ ${_arg_verbose} == "on" ] && echo "Exporting 'QuickJS' version '${_arg_qjs_version}' (${package_type}) for '${_arg_arch}'..."
259 |
260 | if ! [ -d ${repo_dir} ]
261 | then
262 | echo "Local repository does not exist. Run 'checkout_qjs.sh' script first" 1>&2
263 | return 1
264 | fi
265 |
266 | # directory where QuickJS was installed afte being built
267 | _build_dir="${repo_dir}/BUILD-${_arg_qjs_version}-${_arg_arch}"
268 | # used to keep track of whether or not QuickJS was already built
269 | _built_marker="${repo_dir}/.built-${_arg_qjs_version}-${_arg_arch}"
270 |
271 | # ensure version was built
272 | if ! [ -f ${_built_marker} ]
273 | then
274 | echo "QuickJS version '${_arg_qjs_version}' was not built. Run 'build_qjs.sh' script first" 1>&2
275 | return 1
276 | fi
277 |
278 | # ensure version was built with expected commit
279 | _build_commit=$(head -1 ${_built_marker})
280 | if [ ${_build_commit} != ${qjs_commit} ]
281 | then
282 | echo "QuickJS version '${_arg_qjs_version}' was built using commit (${_build_commit}) instead of expected one (${qjs_commit}). Run 'checkout_qjs.sh' script first" 1>&2
283 | return 1
284 | fi
285 |
286 | # name of the package which will be exported
287 | _package_name="quickjs.${package_type}.${qjs_package}.${_arg_arch}"
288 | # add qjs ext lib to the name if it has been added
289 | if [ ${_arg_ext_lib} == "on" ]
290 | then
291 | _package_name="quickjs.${package_type}.${qjs_package}.ext-lib-${_arg_ext_lib_version}.${_arg_arch}"
292 | fi
293 | # directory where package will be exported
294 | _package_dir="${packages_dir}/${_package_name}"
295 | # name of the exported tarball
296 | _package_tarball_filename="${_package_name}.tar.xz"
297 | # location of the final tarball
298 | _package_tarball="${packages_dir}/${_package_tarball_filename}"
299 | # symlink in the repository, referencing the directory containing 'musl' build
300 | _musl_dir_symlink="${repo_dir}/musl-${_arg_arch}"
301 | # list of files which need to be copied from the directory where QuickJS was installed
302 | _qjs_export_list="bin/qjs bin/qjsc lib/quickjs/libquickjs.a include/quickjs/quickjs-libc.h include/quickjs/quickjs.h"
303 | # list of QuickJS files which need to be stripped
304 | _qjs_strip_list="qjs qjsc libquickjs.a"
305 | # list of QuickJS files which need to be compressed using upx
306 | _qjs_upx_list="qjs qjsc"
307 | # list of qjs examples/tests files to copy
308 | _qjs_examples="examples/fib_module.js examples/hello.js examples/hello_module.js examples/pi_bigdecimal.js examples/pi_bigfloat.js examples/pi_bigint.js tests/microbench.js"
309 | # use 'strip' binary from cross compiler
310 | _strip="${deps_dir}/musl_cc-${_arg_arch}/strip"
311 |
312 | # create package directory
313 | (rm -fr ${_package_dir} && \
314 | mkdir -p ${_package_dir}) || return 1
315 |
316 | # copy QuickJS files
317 | for _e in ${_qjs_export_list}
318 | do
319 | _file="${_build_dir}/${_e}"
320 | cp ${_file} ${_package_dir} || return 1
321 | done
322 |
323 | # strip QuickJS binaries & lib
324 | for _e in ${_qjs_strip_list}
325 | do
326 | _file="${_package_dir}/${_e}"
327 | if [ "$(basename ${_e} .a)" != "$(basename ${_e})" ]
328 | then
329 | # this is a static library
330 | ${_strip} -d ${_file} || return 1
331 | else
332 | # this is a binary
333 | ${_strip} ${_file} || return 1
334 | fi
335 | done
336 |
337 | if [ ${_arg_upx} == "on" ]
338 | then
339 | _upx_binary=$(which upx)
340 | if [ -z ${_upx_binary} ]
341 | then
342 | if [ ${_arg_verbose} == "on" ]
343 | then
344 | echo "Skipping 'QuickJS' binaries compression since 'upx' is not installed"
345 | fi
346 | else
347 | [ ${_arg_verbose} == "on" ] && echo "Compressing 'QuickJS' binaries..."
348 | for _e in ${_qjs_upx_list}
349 | do
350 | _file="${_package_dir}/${_e}"
351 | ${_upx_binary} ${_file}
352 | _result=$?
353 | if [ ${_result} -ne 0 ]
354 | then
355 | # don't do anything if binary is already compressed
356 | if [ ${_result} -ne 2 ]
357 | then
358 | echo "Could not compress 'QuickJS' binary '${_e}'" 1>&2
359 | return 1
360 | fi
361 | fi
362 | done
363 | fi
364 | fi
365 |
366 | # copy musl directory
367 | cp -RL ${_musl_dir_symlink} ${_package_dir} || return 1
368 |
369 | # copy examples & tests
370 | mkdir -p ${_package_dir}/examples || return 1
371 | for _filename in ${_qjs_examples}
372 | do
373 | _file="${repo_dir}/${_filename}"
374 | ! [ -f ${_file} ] && continue
375 | cp ${_file} ${_package_dir}/examples || return 1
376 | done
377 |
378 | # copy ext lib
379 | if [ ${_arg_ext_lib} == "on" ]
380 | then
381 | _ext_lib_tmp_dir=${_package_dir}/.ext_lib
382 | rm -fr ${_ext_lib_tmp_dir} && \
383 | git clone ${qjs_ext_lib_repository} ${_ext_lib_tmp_dir}
384 | if [ $? -ne 0 ]
385 | then
386 | echo "Could not retrieve QuickJS extension library '${_arg_ext_lib_version}'" 1>&2
387 | return 1
388 | fi
389 | if [ ${_arg_ext_lib_version} != "master" ]
390 | then
391 | cd ${_ext_lib_tmp_dir} && git checkout tags/${_arg_ext_lib_version}
392 | if [ $? -ne 0 ]
393 | then
394 | echo "Could not retrieve QuickJS extension library '${_arg_ext_lib_version}'" 1>&2
395 | return 1
396 | fi
397 | fi
398 | # copy src files
399 | mkdir -p ${_package_dir}/ext && \
400 | cp -R ${_ext_lib_tmp_dir}/src/* ${_package_dir}/ext && \
401 | rm -fr ${_ext_lib_tmp_dir}
402 | fi
403 |
404 | # copy extra directories
405 | for _dir in ${_arg_extra_dir[@]}
406 | do
407 | # it might have been passed using format src:dest
408 | _src=$(echo ${_dir} | cut -d ':' -f1)
409 | _dest=$(echo ${_dir} | cut -d ':' -f2)
410 | # no destination was given
411 | if [ -z ${_dest} ] || [ ${_src} == ${_dest} ]
412 | then
413 | # copy directory
414 | cp -R ${_src} ${_package_dir} || return 1
415 | else
416 | _dirname=$(basename ${_dest})
417 | # copy directory content
418 | mkdir -p ${_package_dir}/${_dirname} || return 1
419 | cp -R ${_src}/* ${_package_dir}/${_dirname} || return 1
420 | fi
421 | done
422 |
423 | # copy all scripts from 'custom' directory
424 | cp -R ${custom_dir}/qjs/scripts/* ${_package_dir} || return 1
425 |
426 | # copy ext lib examples
427 | if [ ${_arg_ext_lib} == "on" ]
428 | then
429 | cp -R ${custom_dir}/qjs/examples/ext-lib ${_package_dir}/examples || return 1
430 | fi
431 |
432 | # copy README
433 | cp -R ${custom_dir}/README.md ${_package_dir} || return 1
434 |
435 | # compress directory
436 | (cd ${packages_dir} &&
437 | tar -C ${packages_dir} -cJf ${_package_tarball_filename} ${_package_name} && \
438 | chmod 666 ${_package_tarball_filename} && \
439 | rm -fr ${_package_dir}) || return 1
440 |
441 | [ ${_arg_verbose} == "on" ] && echo "'QuickJS' version '${_arg_qjs_version}' (${package_type}) successfully exported for '${_arg_arch}' to '${_package_tarball}'"
442 |
443 | return 0
444 | }
445 |
446 | # ensure all extra directories which should be copied exist
447 | for _dir in ${_arg_extra_dir[@]}
448 | do
449 | # it might have been passed using format src:dest
450 | _src=$(echo ${_dir} | cut -d ':' -f 1)
451 | ([ -z ${_src} ] || ! [ -d ${_src} ]) && die "Extra directory '${_src}' does not exist"
452 | done
453 |
454 | _PRINT_HELP=no
455 | repo_dir="${script_dir}/../../quickjs-repo"
456 | deps_dir=${_arg_deps_dir}
457 | packages_dir=${_arg_packages_dir}
458 | custom_dir="${script_dir}/../custom"
459 |
460 | mkdir -p ${packages_dir}
461 |
462 | export_qjs || die "Could not export 'QuickJS' version '${_arg_qjs_version}' for '${_arg_arch}'"
463 |
464 | # ^^^ TERMINATE YOUR CODE BEFORE THE BOTTOM ARGBASH MARKER ^^^
465 |
466 | # ] <-- needed because of Argbash
467 |
--------------------------------------------------------------------------------
/builder/scripts/fetch_deps.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ###
4 | #
5 | # Fetch dependencies
6 | # - download musl sources
7 | # - download musl-based cross compiler (see https://github.com/ctn-malone/musl-cross-maker)
8 | # - create symlinks under the root directory ofr musl-cc compiler to maje compilation process easier
9 | #
10 | ###
11 |
12 | script_dir="$(cd "$(dirname "$(readlink -f "$0")")" && pwd)" || { echo "Couldn't determine the script's running directory, which probably matters, bailing out" >&2; exit 2; }
13 |
14 | # Created by argbash-init v2.10.0
15 | # ARG_OPTIONAL_SINGLE([deps-dir],[d],[directory where dependencies should be stored/built],[$script_dir/../../deps])
16 | # ARG_OPTIONAL_SINGLE([arch],[a],[target architecture],[x86_64])
17 | # ARG_OPTIONAL_BOOLEAN([force],[f],[force re-fetching dependencies],[off])
18 | # ARG_OPTIONAL_BOOLEAN([verbose],[v],[enable verbose mode],[off])
19 | # ARG_TYPE_GROUP_SET([arch],[type string],[arch],[x86_64,i686,armv7l,aarch64])
20 | # ARG_HELP([Fetch dependencies needed to build a static version of QuickJS])
21 | # ARGBASH_GO()
22 | # needed because of Argbash --> m4_ignore([
23 | ### START OF CODE GENERATED BY Argbash v2.10.0 one line above ###
24 | # Argbash is a bash code generator used to get arguments parsing right.
25 | # Argbash is FREE SOFTWARE, see https://argbash.io for more info
26 |
27 |
28 | die()
29 | {
30 | local _ret="${2:-1}"
31 | test "${_PRINT_HELP:-no}" = yes && print_help >&2
32 | echo "$1" >&2
33 | exit "${_ret}"
34 | }
35 |
36 | # validators
37 |
38 | arch()
39 | {
40 | local _allowed=("x86_64" "i686" "armv7l" "aarch64") _seeking="$1"
41 | for element in "${_allowed[@]}"
42 | do
43 | test "$element" = "$_seeking" && echo "$element" && return 0
44 | done
45 | die "Value '$_seeking' (of argument '$2') doesn't match the list of allowed values: 'x86_64', 'i686', 'armv7l' and 'aarch64'" 4
46 | }
47 |
48 |
49 | begins_with_short_option()
50 | {
51 | local first_option all_short_options='dafvh'
52 | first_option="${1:0:1}"
53 | test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0
54 | }
55 |
56 | # THE DEFAULTS INITIALIZATION - OPTIONALS
57 | _arg_deps_dir="$script_dir/../../deps"
58 | _arg_arch="x86_64"
59 | _arg_force="off"
60 | _arg_verbose="off"
61 |
62 |
63 | print_help()
64 | {
65 | printf '%s\n' "Fetch dependencies needed to build a static version of QuickJS"
66 | printf 'Usage: %s [-d|--deps-dir ] [-a|--arch ] [-f|--(no-)force] [-v|--(no-)verbose] [-h|--help]\n' "$0"
67 | printf '\t%s\n' "-d, --deps-dir: directory where dependencies should be stored/built (default: '$script_dir/../../deps')"
68 | printf '\t%s\n' "-a, --arch: target architecture. Can be one of: 'x86_64', 'i686', 'armv7l' and 'aarch64' (default: 'x86_64')"
69 | printf '\t%s\n' "-f, --force, --no-force: force re-fetching dependencies (off by default)"
70 | printf '\t%s\n' "-v, --verbose, --no-verbose: enable verbose mode (off by default)"
71 | printf '\t%s\n' "-h, --help: Prints help"
72 | }
73 |
74 |
75 | parse_commandline()
76 | {
77 | while test $# -gt 0
78 | do
79 | _key="$1"
80 | case "$_key" in
81 | -d|--deps-dir)
82 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
83 | _arg_deps_dir="$2"
84 | shift
85 | ;;
86 | --deps-dir=*)
87 | _arg_deps_dir="${_key##--deps-dir=}"
88 | ;;
89 | -d*)
90 | _arg_deps_dir="${_key##-d}"
91 | ;;
92 | -a|--arch)
93 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
94 | _arg_arch="$(arch "$2" "arch")" || exit 1
95 | shift
96 | ;;
97 | --arch=*)
98 | _arg_arch="$(arch "${_key##--arch=}" "arch")" || exit 1
99 | ;;
100 | -a*)
101 | _arg_arch="$(arch "${_key##-a}" "arch")" || exit 1
102 | ;;
103 | -f|--no-force|--force)
104 | _arg_force="on"
105 | test "${1:0:5}" = "--no-" && _arg_force="off"
106 | ;;
107 | -f*)
108 | _arg_force="on"
109 | _next="${_key##-f}"
110 | if test -n "$_next" -a "$_next" != "$_key"
111 | then
112 | { begins_with_short_option "$_next" && shift && set -- "-f" "-${_next}" "$@"; } || die "The short option '$_key' can't be decomposed to ${_key:0:2} and -${_key:2}, because ${_key:0:2} doesn't accept value and '-${_key:2:1}' doesn't correspond to a short option."
113 | fi
114 | ;;
115 | -v|--no-verbose|--verbose)
116 | _arg_verbose="on"
117 | test "${1:0:5}" = "--no-" && _arg_verbose="off"
118 | ;;
119 | -v*)
120 | _arg_verbose="on"
121 | _next="${_key##-v}"
122 | if test -n "$_next" -a "$_next" != "$_key"
123 | then
124 | { begins_with_short_option "$_next" && shift && set -- "-v" "-${_next}" "$@"; } || die "The short option '$_key' can't be decomposed to ${_key:0:2} and -${_key:2}, because ${_key:0:2} doesn't accept value and '-${_key:2:1}' doesn't correspond to a short option."
125 | fi
126 | ;;
127 | -h|--help)
128 | print_help
129 | exit 0
130 | ;;
131 | -h*)
132 | print_help
133 | exit 0
134 | ;;
135 | *)
136 | _PRINT_HELP=yes die "FATAL ERROR: Got an unexpected argument '$1'" 1
137 | ;;
138 | esac
139 | shift
140 | done
141 | }
142 |
143 | parse_commandline "$@"
144 |
145 | # OTHER STUFF GENERATED BY Argbash
146 | # Validation of values
147 |
148 |
149 | ### END OF CODE GENERATED BY Argbash (sortof) ### ])
150 | # [ <-- needed because of Argbash
151 |
152 |
153 | # vvv PLACE YOUR CODE HERE vvv
154 | source "${script_dir}/../env/deps"
155 |
156 | # Fetch 'musl-cc' tarball, decompress & create symlink under ${deps_dir}
157 | fetch_musl_cc()
158 | {
159 | [ ${_arg_verbose} == "on" ] && echo "Downloading 'musl-cc' for '${_arg_arch}'..."
160 |
161 | case ${_arg_arch} in
162 | x86_64)
163 | declare -n _cfg="cfg_musl_cc_x86_64"
164 | ;;
165 | i686)
166 | declare -n _cfg="cfg_musl_cc_i686"
167 | ;;
168 | armv7l)
169 | declare -n _cfg="cfg_musl_cc_armv7l"
170 | ;;
171 | aarch64)
172 | declare -n _cfg="cfg_musl_cc_aarch64"
173 | ;;
174 | esac
175 |
176 | # directory which will contain 'musl-cc' files after decompression
177 | _archive_dir="${archives_dir}/${_cfg["archive_dir"]}"
178 | # location of the archive file after download
179 | _archive=${archives_dir}/$(basename "${_cfg["archive_url"]}")
180 | # symlink under 'deps' directory, referencing the directory containing 'musl-cc' files
181 | _archive_dir_symlink=${deps_dir}/${_cfg["archive_dir_symlink"]}
182 | # compiler's target (ex: x86_64-linux-musl)
183 | _machine=$(echo "${_cfg["archive_dir"]}" | sed 's/-cross.*//')
184 | # symlinks created at the root of the directory containing 'musl_cc' files
185 | _cc_symlink=${_archive_dir}/cc
186 | _strip_symlink=${_archive_dir}/strip
187 | _libatomic_symlink=${_archive_dir}/libatomic.a
188 | _libssp_nonshared_symlink=${_archive_dir}/libssp_nonshared.a
189 |
190 | # dependency already fetched & decompressed
191 | if [ -d ${_archive_dir} ] && [ ${_arg_force} == "off" ]
192 | then
193 | [ ${_arg_verbose} == "on" ] && echo "No need to download 'musl-cc' for '${_arg_arch}'"
194 | else
195 | # fetch tarball & decompress
196 | (rm -fr ${_archive_dir} && \
197 | wget -O ${_archive} ${_cfg["archive_url"]} && \
198 | tar -C ${archives_dir} -xzf ${_archive}) || return 1
199 | [ ${_arg_verbose} == "on" ] && echo "Successfully downloaded 'musl-cc' for '${_arg_arch}'"
200 | fi
201 |
202 | # create symlink to archive directory
203 | (rm -f ${_archive_dir_symlink} &&
204 | ln -s "$(basename ${archives_dir})/${_cfg["archive_dir"]}" ${_archive_dir_symlink}) || return 1
205 |
206 | # create symlink to 'cc' binary
207 | (rm -f ${_cc_symlink} &&
208 | ln -s "bin/${_machine}-cc" ${_cc_symlink}) || return 1
209 |
210 | # create symlink to 'strip' binary
211 | (rm -f ${_strip_symlink} &&
212 | ln -s "bin/${_machine}-strip" ${_strip_symlink}) || return 1
213 |
214 | # create symlink to 'libatomic' static library
215 | (rm -f ${_libatomic_symlink} &&
216 | ln -s "${_machine}/lib/libatomic.a" ${_libatomic_symlink}) || return 1
217 |
218 | # create symlink to 'libssp_nonshared' static library
219 | (rm -f ${_libssp_nonshared_symlink} &&
220 | ln -s "${_machine}/lib/libssp_nonshared.a" ${_libssp_nonshared_symlink}) || return 1
221 |
222 | return 0
223 | }
224 |
225 | # Fetch 'musl lib' tarball, decompress & create symlink under ${deps_dir}
226 | fetch_musl_lib()
227 | {
228 | [ ${_arg_verbose} == "on" ] && echo "Downloading 'musl lib'..."
229 |
230 | declare -n _cfg="cfg_musl_lib"
231 |
232 | # directory which will contain 'musl' sources after decompression
233 | _archive_dir="${archives_dir}/${_cfg["archive_dir"]}"
234 | # location of the archive file after download
235 | _archive=${archives_dir}/$(basename "${_cfg["archive_url"]}")
236 | # symlink under 'deps' directory, referencing the directory containing 'musl-cc' sources
237 | _archive_dir_symlink=${deps_dir}/${_cfg["archive_dir_symlink"]}
238 |
239 | # dependency already fetched & decompressed
240 | if [ -d ${_archive_dir} ] && [ ${_arg_force} == "off" ]
241 | then
242 | [ ${_arg_verbose} == "on" ] && echo "No need to download 'musl lib'"
243 | else
244 | # fetch tarball & decompress
245 | (rm -fr ${_archive_dir} && \
246 | wget -O ${_archive} ${_cfg["archive_url"]} && \
247 | tar -C ${archives_dir} -xzf ${_archive}) || return 1
248 | [ ${_arg_verbose} == "on" ] && echo "Successfully downloaded 'musl lib'"
249 | fi
250 |
251 | # create symlink to archive directory
252 | (rm -f ${_archive_dir_symlink} &&
253 | ln -s "$(basename ${archives_dir})/${_cfg["archive_dir"]}" ${_archive_dir_symlink}) || return 1
254 |
255 | return 0
256 | }
257 |
258 | # fetch all dependencies
259 | fetch_deps()
260 | {
261 | [ ${_arg_verbose} == "on" ] && echo "Fetching dependencies for '${_arg_arch}'..."
262 |
263 | fetch_musl_lib || return 1
264 | fetch_musl_cc || return 1
265 |
266 | [ ${_arg_verbose} == "on" ] && echo "Dependencies for '${_arg_arch}' successfully fetched"
267 |
268 | return 0
269 | }
270 |
271 | _PRINT_HELP=no
272 | deps_dir=${_arg_deps_dir}
273 | # directory where archives will be downloaded
274 | archives_dir=${deps_dir}/archives
275 |
276 | mkdir -p ${archives_dir}
277 |
278 | fetch_deps || die "Could not fetch dependencies"
279 |
280 | # ^^^ TERMINATE YOUR CODE BEFORE THE BOTTOM ARGBASH MARKER ^^^
281 |
282 | # ] <-- needed because of Argbash
283 |
--------------------------------------------------------------------------------
/builder/scripts/prepare_qjs.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ###
4 | #
5 | # Prepare QuickJS repository
6 | # - apply some patches (Makefile, qjsc.c ...)
7 | # - create a symlink to the directory containing the musl lib build
8 | # - copy the qjsc_x86_64 binary which will be needed to generate .c file during cross-compilation
9 | #
10 | ###
11 |
12 | script_dir="$(cd "$(dirname "$(readlink -f "$0")")" && pwd)" || { echo "Couldn't determine the script's running directory, which probably matters, bailing out" >&2; exit 2; }
13 | source "${script_dir}/../env/qjs"
14 |
15 | # Created by argbash-init v2.10.0
16 | # ARG_OPTIONAL_SINGLE([deps-dir],[d],[directory containing dependencies],[$script_dir/../../deps])
17 | # ARG_OPTIONAL_SINGLE([arch],[a],[target architecture],[x86_64])
18 | # ARG_OPTIONAL_BOOLEAN([verbose],[v],[enable verbose mode],[off])
19 | # ARG_POSITIONAL_SINGLE([qjs-version],[QuickJS version (ex: 2020-09-06)],[$default_qjs_version])
20 | # ARG_TYPE_GROUP_SET([arch],[type string],[arch],[x86_64,i686,armv7l,aarch64])
21 | # ARG_HELP([Patch QuickJS sources & create symlink to static musl lib])
22 | # ARGBASH_GO()
23 | # needed because of Argbash --> m4_ignore([
24 | ### START OF CODE GENERATED BY Argbash v2.10.0 one line above ###
25 | # Argbash is a bash code generator used to get arguments parsing right.
26 | # Argbash is FREE SOFTWARE, see https://argbash.io for more info
27 |
28 |
29 | die()
30 | {
31 | local _ret="${2:-1}"
32 | test "${_PRINT_HELP:-no}" = yes && print_help >&2
33 | echo "$1" >&2
34 | exit "${_ret}"
35 | }
36 |
37 | # validators
38 |
39 | arch()
40 | {
41 | local _allowed=("x86_64" "i686" "armv7l" "aarch64") _seeking="$1"
42 | for element in "${_allowed[@]}"
43 | do
44 | test "$element" = "$_seeking" && echo "$element" && return 0
45 | done
46 | die "Value '$_seeking' (of argument '$2') doesn't match the list of allowed values: 'x86_64', 'i686', 'armv7l' and 'aarch64'" 4
47 | }
48 |
49 |
50 | begins_with_short_option()
51 | {
52 | local first_option all_short_options='davh'
53 | first_option="${1:0:1}"
54 | test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0
55 | }
56 |
57 | # THE DEFAULTS INITIALIZATION - POSITIONALS
58 | _positionals=()
59 | _arg_qjs_version="$default_qjs_version"
60 | # THE DEFAULTS INITIALIZATION - OPTIONALS
61 | _arg_deps_dir="$script_dir/../../deps"
62 | _arg_arch="x86_64"
63 | _arg_verbose="off"
64 |
65 |
66 | print_help()
67 | {
68 | printf '%s\n' "Patch QuickJS sources & create symlink to static musl lib"
69 | printf 'Usage: %s [-d|--deps-dir ] [-a|--arch ] [-v|--(no-)verbose] [-h|--help] []\n' "$0"
70 | printf '\t%s\n' ": QuickJS version (ex: 2020-09-06) (default: '$default_qjs_version')"
71 | printf '\t%s\n' "-d, --deps-dir: directory containing dependencies (default: '$script_dir/../../deps')"
72 | printf '\t%s\n' "-a, --arch: target architecture. Can be one of: 'x86_64', 'i686', 'armv7l' and 'aarch64' (default: 'x86_64')"
73 | printf '\t%s\n' "-v, --verbose, --no-verbose: enable verbose mode (off by default)"
74 | printf '\t%s\n' "-h, --help: Prints help"
75 | }
76 |
77 |
78 | parse_commandline()
79 | {
80 | _positionals_count=0
81 | while test $# -gt 0
82 | do
83 | _key="$1"
84 | case "$_key" in
85 | -d|--deps-dir)
86 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
87 | _arg_deps_dir="$2"
88 | shift
89 | ;;
90 | --deps-dir=*)
91 | _arg_deps_dir="${_key##--deps-dir=}"
92 | ;;
93 | -d*)
94 | _arg_deps_dir="${_key##-d}"
95 | ;;
96 | -a|--arch)
97 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
98 | _arg_arch="$(arch "$2" "arch")" || exit 1
99 | shift
100 | ;;
101 | --arch=*)
102 | _arg_arch="$(arch "${_key##--arch=}" "arch")" || exit 1
103 | ;;
104 | -a*)
105 | _arg_arch="$(arch "${_key##-a}" "arch")" || exit 1
106 | ;;
107 | -v|--no-verbose|--verbose)
108 | _arg_verbose="on"
109 | test "${1:0:5}" = "--no-" && _arg_verbose="off"
110 | ;;
111 | -v*)
112 | _arg_verbose="on"
113 | _next="${_key##-v}"
114 | if test -n "$_next" -a "$_next" != "$_key"
115 | then
116 | { begins_with_short_option "$_next" && shift && set -- "-v" "-${_next}" "$@"; } || die "The short option '$_key' can't be decomposed to ${_key:0:2} and -${_key:2}, because ${_key:0:2} doesn't accept value and '-${_key:2:1}' doesn't correspond to a short option."
117 | fi
118 | ;;
119 | -h|--help)
120 | print_help
121 | exit 0
122 | ;;
123 | -h*)
124 | print_help
125 | exit 0
126 | ;;
127 | *)
128 | _last_positional="$1"
129 | _positionals+=("$_last_positional")
130 | _positionals_count=$((_positionals_count + 1))
131 | ;;
132 | esac
133 | shift
134 | done
135 | }
136 |
137 |
138 | handle_passed_args_count()
139 | {
140 | test "${_positionals_count}" -le 1 || _PRINT_HELP=yes die "FATAL ERROR: There were spurious positional arguments --- we expect between 0 and 1, but got ${_positionals_count} (the last one was: '${_last_positional}')." 1
141 | }
142 |
143 |
144 | assign_positional_args()
145 | {
146 | local _positional_name _shift_for=$1
147 | _positional_names="_arg_qjs_version "
148 |
149 | shift "$_shift_for"
150 | for _positional_name in ${_positional_names}
151 | do
152 | test $# -gt 0 || break
153 | eval "$_positional_name=\${1}" || die "Error during argument parsing, possibly an Argbash bug." 1
154 | shift
155 | done
156 | }
157 |
158 | parse_commandline "$@"
159 | handle_passed_args_count
160 | assign_positional_args 1 "${_positionals[@]}"
161 |
162 | # OTHER STUFF GENERATED BY Argbash
163 | # Validation of values
164 |
165 |
166 | ### END OF CODE GENERATED BY Argbash (sortof) ### ])
167 | # [ <-- needed because of Argbash
168 |
169 |
170 | # vvv PLACE YOUR CODE HERE vvv
171 |
172 | # ensure version exist
173 | qjs_commit="${qjs_commits[${_arg_qjs_version}]}"
174 | if [ -z ${qjs_commit} ]
175 | then
176 | _PRINT_HELP=yes die "QuickJS version '${_arg_qjs_version}' is not supported"
177 | fi
178 |
179 | # patch QuickJS source files
180 | patch_qjs()
181 | {
182 | [ ${_arg_verbose} == "on" ] && echo "Patching 'QuickJS' sources..."
183 |
184 | # ensure repository exists
185 | if ! [ -d ${repo_dir} ]
186 | then
187 | echo "Local repository does not exist. Run 'checkout_qjs.sh' script first" 1>&2
188 | return 1
189 | fi
190 |
191 | # ensure expected commit is checked out
192 | cd ${repo_dir} && \
193 | current_commit="$(git rev-parse HEAD)"
194 | if [ ${current_commit} != ${qjs_commit} ]
195 | then
196 | echo "Current commit (${current_commit}) does not match expected one (${qjs_commit}). Run 'checkout_qjs.sh' script first" 1>&2
197 | return 1
198 | fi
199 |
200 | # change VERSION file
201 | qjs_package="${qjs_packages[${_arg_qjs_version}]}"
202 | if [ -z ${qjs_package} ]
203 | then
204 | _PRINT_HELP=yes die "QuickJS version '${_arg_qjs_version}' is not supported (package unknown)"
205 | fi
206 | echo "${qjs_package}\ \(https://github.com/ctn-malone/quickjs-cross-compiler\)" >${repo_dir}/VERSION
207 |
208 | _patch_dir="${custom_dir}/qjs/patches/${_arg_qjs_version}"
209 | _need_patch=0
210 | # used to keep track of whether or not repo was patched
211 | _patched_marker="${repo_dir}/.patched-${_arg_qjs_version}"
212 |
213 | # patches have already been applied
214 | if ! [ -f ${_patched_marker} ]
215 | then
216 | cd ${repo_dir}
217 |
218 | for file in $(ls $_patch_dir/*.patch)
219 | do
220 | # check if patch has already been applied
221 | patch -Rp1 -s -f --dry-run <$file >/dev/null 2>&1
222 | if [ $? -ne 0 ]
223 | then
224 | _need_patch=1
225 | patch -Np1 <$file || return 1
226 | fi
227 | done
228 | # create marker
229 | touch ${_patched_marker}
230 | fi
231 |
232 | if [ ${_need_patch} -eq 0 ]
233 | then
234 | [ ${_arg_verbose} == "on" ] && echo "'QuickJS' sources already patched"
235 | else
236 | [ ${_arg_verbose} == "on" ] && echo "Successfully patched 'QuickJS' sources"
237 | fi
238 |
239 | return 0
240 | }
241 |
242 | # create symlink to static musl lib
243 | create_musl_symlink()
244 | {
245 | [ ${_arg_verbose} == "on" ] && echo "Creating symlink to 'musl lib' for '${_arg_arch}'..."
246 |
247 | # used to keep track of whether or not musl lib was built
248 | _musl_built_marker="${deps_dir}/musl/.built-${_arg_arch}"
249 | # directory where musl was build
250 | _musl_dir="${deps_dir}/musl/BUILD-${_arg_arch}"
251 | # symlink in the repository, referencing the directory containing 'musl' build
252 | _musl_dir_symlink="${repo_dir}/musl-${_arg_arch}"
253 |
254 | # ensure musl was built
255 | if ! [ -f ${_musl_built_marker} ]
256 | then
257 | echo "'musl lib' was not built for '${_arg_arch}'. Run 'build_deps.sh' script first" 1>&2
258 | return 1
259 | fi
260 |
261 | (rm -f ${_musl_dir_symlink} && \
262 | ln -s ${_musl_dir} ${_musl_dir_symlink}) || return 1
263 |
264 | [ ${_arg_verbose} == "on" ] && echo "Successfully created symlink to 'musl lib' for '${_arg_arch}'"
265 |
266 | return 0
267 | }
268 |
269 | _PRINT_HELP=no
270 | deps_dir=${_arg_deps_dir}
271 | repo_dir="${script_dir}/../../quickjs-repo"
272 | # directory containing custom files such as patches to apply
273 | custom_dir="${script_dir}/../custom"
274 |
275 | patch_qjs || die "Could not patch 'QuickJS'"
276 | # 'x86_64' version of the binary is needed to generate c files when doing cross-compilation
277 | cp ${custom_dir}/qjs/qjsc-x86_64 ${repo_dir} || die "Could not copy 'qjsc-x86_64' to repository"
278 | # copy extra source files
279 | cp -R ${custom_dir}/qjs/files/* ${repo_dir} || die "Could not copy extra source files to repository"
280 | create_musl_symlink || die "Could not create symlink to 'musl lib'"
281 |
282 | # ^^^ TERMINATE YOUR CODE BEFORE THE BOTTOM ARGBASH MARKER ^^^
283 |
284 | # ] <-- needed because of Argbash
285 |
--------------------------------------------------------------------------------
/docker/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM alpine:3.12.0
2 | ARG arch=x86_64
3 | WORKDIR /usr/local/src/quickjs-cross-compiler/builder
4 | COPY builder /tmp/builder
5 | RUN /tmp/builder/scripts/bootstrap-alpine.sh && \
6 | /tmp/builder/scripts/fetch_deps.sh -va $arch -d /usr/local/src/quickjs-cross-compiler/deps && \
7 | /tmp/builder/scripts/build_deps.sh -va $arch -d /usr/local/src/quickjs-cross-compiler/deps
8 |
--------------------------------------------------------------------------------
/docker/build_and_export_qjs.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ###
4 | #
5 | # Build a static version of QuickJS (interpreter & compiler)
6 | # Export a portable package which can be used to generate static binaries
7 | #
8 | ###
9 |
10 | script_dir="$(cd "$(dirname "$(readlink -f "$0")")" && pwd)" || { echo "Couldn't determine the script's running directory, which probably matters, bailing out" >&2; exit 2; }
11 | source "${script_dir}/../builder/env/qjs"
12 |
13 | # Created by argbash-init v2.10.0
14 | # ARG_OPTIONAL_SINGLE([packages-dir],[p],[directory where package will be exported],[$script_dir/../packages])
15 | # ARG_OPTIONAL_SINGLE([arch],[a],[target architecture],[x86_64])
16 | # ARG_OPTIONAL_BOOLEAN([ext-lib],[],[add QuickJS extension library],[off])
17 | # ARG_OPTIONAL_SINGLE([ext-lib-version],[],[QuickJS extension library version],[$default_qjs_ext_lib_version])
18 | # ARG_OPTIONAL_REPEATED([extra-dir],[e],[extra directory to add into package],[])
19 | # ARG_OPTIONAL_BOOLEAN([force-build-image],[],[force rebuilding docker image],[off])
20 | # ARG_OPTIONAL_BOOLEAN([verbose],[v],[enable verbose mode],[off])
21 | # ARG_OPTIONAL_BOOLEAN([upx],[u],[compress binaries using upx],[on])
22 | # ARG_POSITIONAL_SINGLE([qjs-version],[QuickJS version (ex: 2020-09-06)],[$default_qjs_version])
23 | # ARG_TYPE_GROUP_SET([arch],[type string],[arch],[x86_64,i686,armv7l,aarch64])
24 | # ARG_HELP([Build a static version of QuickJS (interpreter & compiler)])
25 | # ARGBASH_GO()
26 | # needed because of Argbash --> m4_ignore([
27 | ### START OF CODE GENERATED BY Argbash v2.10.0 one line above ###
28 | # Argbash is a bash code generator used to get arguments parsing right.
29 | # Argbash is FREE SOFTWARE, see https://argbash.io for more info
30 |
31 |
32 | die()
33 | {
34 | local _ret="${2:-1}"
35 | test "${_PRINT_HELP:-no}" = yes && print_help >&2
36 | echo "$1" >&2
37 | exit "${_ret}"
38 | }
39 |
40 | # validators
41 |
42 | arch()
43 | {
44 | local _allowed=("x86_64" "i686" "armv7l" "aarch64") _seeking="$1"
45 | for element in "${_allowed[@]}"
46 | do
47 | test "$element" = "$_seeking" && echo "$element" && return 0
48 | done
49 | die "Value '$_seeking' (of argument '$2') doesn't match the list of allowed values: 'x86_64', 'i686', 'armv7l' and 'aarch64'" 4
50 | }
51 |
52 |
53 | begins_with_short_option()
54 | {
55 | local first_option all_short_options='paevuh'
56 | first_option="${1:0:1}"
57 | test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0
58 | }
59 |
60 | # THE DEFAULTS INITIALIZATION - POSITIONALS
61 | _positionals=()
62 | _arg_qjs_version="$default_qjs_version"
63 | # THE DEFAULTS INITIALIZATION - OPTIONALS
64 | _arg_packages_dir="$script_dir/../packages"
65 | _arg_arch="x86_64"
66 | _arg_ext_lib="off"
67 | _arg_ext_lib_version="$default_qjs_ext_lib_version"
68 | _arg_extra_dir=()
69 | _arg_force_build_image="off"
70 | _arg_verbose="off"
71 | _arg_upx="on"
72 |
73 |
74 | print_help()
75 | {
76 | printf '%s\n' "Build a static version of QuickJS (interpreter & compiler)"
77 | printf 'Usage: %s [-p|--packages-dir ] [-a|--arch ] [--(no-)ext-lib] [--ext-lib-version ] [-e|--extra-dir ] [--(no-)force-build-image] [-v|--(no-)verbose] [-u|--(no-)upx] [-h|--help] []\n' "$0"
78 | printf '\t%s\n' ": QuickJS version (ex: 2020-09-06) (default: '$default_qjs_version')"
79 | printf '\t%s\n' "-p, --packages-dir: directory where package will be exported (default: '$script_dir/../packages')"
80 | printf '\t%s\n' "-a, --arch: target architecture. Can be one of: 'x86_64', 'i686', 'armv7l' and 'aarch64' (default: 'x86_64')"
81 | printf '\t%s\n' "--ext-lib, --no-ext-lib: add QuickJS extension library (off by default)"
82 | printf '\t%s\n' "--ext-lib-version: QuickJS extension library version (default: '$default_qjs_ext_lib_version')"
83 | printf '\t%s\n' "-e, --extra-dir: extra directory to add into package (empty by default)"
84 | printf '\t%s\n' "--force-build-image, --no-force-build-image: force rebuilding docker image (off by default)"
85 | printf '\t%s\n' "-v, --verbose, --no-verbose: enable verbose mode (off by default)"
86 | printf '\t%s\n' "-u, --upx, --no-upx: compress binaries using upx (on by default)"
87 | printf '\t%s\n' "-h, --help: Prints help"
88 | }
89 |
90 |
91 | parse_commandline()
92 | {
93 | _positionals_count=0
94 | while test $# -gt 0
95 | do
96 | _key="$1"
97 | case "$_key" in
98 | -p|--packages-dir)
99 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
100 | _arg_packages_dir="$2"
101 | shift
102 | ;;
103 | --packages-dir=*)
104 | _arg_packages_dir="${_key##--packages-dir=}"
105 | ;;
106 | -p*)
107 | _arg_packages_dir="${_key##-p}"
108 | ;;
109 | -a|--arch)
110 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
111 | _arg_arch="$(arch "$2" "arch")" || exit 1
112 | shift
113 | ;;
114 | --arch=*)
115 | _arg_arch="$(arch "${_key##--arch=}" "arch")" || exit 1
116 | ;;
117 | -a*)
118 | _arg_arch="$(arch "${_key##-a}" "arch")" || exit 1
119 | ;;
120 | --no-ext-lib|--ext-lib)
121 | _arg_ext_lib="on"
122 | test "${1:0:5}" = "--no-" && _arg_ext_lib="off"
123 | ;;
124 | --ext-lib-version)
125 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
126 | _arg_ext_lib_version="$2"
127 | shift
128 | ;;
129 | --ext-lib-version=*)
130 | _arg_ext_lib_version="${_key##--ext-lib-version=}"
131 | ;;
132 | -e|--extra-dir)
133 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
134 | _arg_extra_dir+=("$2")
135 | shift
136 | ;;
137 | --extra-dir=*)
138 | _arg_extra_dir+=("${_key##--extra-dir=}")
139 | ;;
140 | -e*)
141 | _arg_extra_dir+=("${_key##-e}")
142 | ;;
143 | --no-force-build-image|--force-build-image)
144 | _arg_force_build_image="on"
145 | test "${1:0:5}" = "--no-" && _arg_force_build_image="off"
146 | ;;
147 | -v|--no-verbose|--verbose)
148 | _arg_verbose="on"
149 | test "${1:0:5}" = "--no-" && _arg_verbose="off"
150 | ;;
151 | -v*)
152 | _arg_verbose="on"
153 | _next="${_key##-v}"
154 | if test -n "$_next" -a "$_next" != "$_key"
155 | then
156 | { begins_with_short_option "$_next" && shift && set -- "-v" "-${_next}" "$@"; } || die "The short option '$_key' can't be decomposed to ${_key:0:2} and -${_key:2}, because ${_key:0:2} doesn't accept value and '-${_key:2:1}' doesn't correspond to a short option."
157 | fi
158 | ;;
159 | -u|--no-upx|--upx)
160 | _arg_upx="on"
161 | test "${1:0:5}" = "--no-" && _arg_upx="off"
162 | ;;
163 | -u*)
164 | _arg_upx="on"
165 | _next="${_key##-u}"
166 | if test -n "$_next" -a "$_next" != "$_key"
167 | then
168 | { begins_with_short_option "$_next" && shift && set -- "-u" "-${_next}" "$@"; } || die "The short option '$_key' can't be decomposed to ${_key:0:2} and -${_key:2}, because ${_key:0:2} doesn't accept value and '-${_key:2:1}' doesn't correspond to a short option."
169 | fi
170 | ;;
171 | -h|--help)
172 | print_help
173 | exit 0
174 | ;;
175 | -h*)
176 | print_help
177 | exit 0
178 | ;;
179 | *)
180 | _last_positional="$1"
181 | _positionals+=("$_last_positional")
182 | _positionals_count=$((_positionals_count + 1))
183 | ;;
184 | esac
185 | shift
186 | done
187 | }
188 |
189 |
190 | handle_passed_args_count()
191 | {
192 | test "${_positionals_count}" -le 1 || _PRINT_HELP=yes die "FATAL ERROR: There were spurious positional arguments --- we expect between 0 and 1, but got ${_positionals_count} (the last one was: '${_last_positional}')." 1
193 | }
194 |
195 |
196 | assign_positional_args()
197 | {
198 | local _positional_name _shift_for=$1
199 | _positional_names="_arg_qjs_version "
200 |
201 | shift "$_shift_for"
202 | for _positional_name in ${_positional_names}
203 | do
204 | test $# -gt 0 || break
205 | eval "$_positional_name=\${1}" || die "Error during argument parsing, possibly an Argbash bug." 1
206 | shift
207 | done
208 | }
209 |
210 | parse_commandline "$@"
211 | handle_passed_args_count
212 | assign_positional_args 1 "${_positionals[@]}"
213 |
214 | # OTHER STUFF GENERATED BY Argbash
215 | # Validation of values
216 |
217 |
218 | ### END OF CODE GENERATED BY Argbash (sortof) ### ])
219 | # [ <-- needed because of Argbash
220 |
221 |
222 | # vvv PLACE YOUR CODE HERE vvv
223 |
224 | # ensure version exist
225 | qjs_commit="${qjs_commits[${_arg_qjs_version}]}"
226 | if [ -z ${qjs_commit} ]
227 | then
228 | _PRINT_HELP=yes die "QuickJS version '${_arg_qjs_version}' is not supported"
229 | fi
230 |
231 | _PRINT_HELP=no
232 |
233 | build_docker_image()
234 | {
235 | _flag_verbose=""
236 | [ ${_arg_verbose} == "on" ] && _flag_verbose="-v"
237 | _flag_force_build_image=""
238 | [ ${_arg_force_build_image} == "on" ] && _flag_force_build_image="-f"
239 |
240 | ${script_dir}/scripts/build_docker_image.sh ${_flag_verbose} -a ${_arg_arch} ${_flag_force_build_image} || return 1
241 |
242 | return 0
243 | }
244 |
245 | build_and_export_package()
246 | {
247 | _image_name="quickjs-cross-compiler:${_arg_arch}"
248 |
249 | _flag_verbose=""
250 | [ ${_arg_verbose} == "on" ] && _flag_verbose="-v"
251 | args_qjs_ext_lib=""
252 | if [ ${_arg_ext_lib} == "on" ]
253 | then
254 | args_qjs_ext_lib="--ext-lib --ext-lib-version ${_arg_ext_lib_version}"
255 | fi
256 | args_extra_dir=""
257 | for a in ${_arg_extra_dir[@]}
258 | do
259 | args_extra_dir="${args_extra_dir} -e ${a}"
260 | done
261 | _flag_disable_upx=""
262 | [ ${_arg_upx} == "off" ] && _flag_disable_upx="--no-upx"
263 |
264 | _docker_cmd="./build_and_export_qjs.sh ${_flag_verbose} -a ${_arg_arch} ${args_qjs_ext_lib} ${args_extra_dir} ${_flag_disable_upx}"
265 |
266 | (mkdir -p ${_arg_packages_dir} && \
267 | docker run --rm \
268 | --mount type=bind,source="${script_dir}/../builder",target="/usr/local/src/quickjs-cross-compiler/builder" \
269 | --mount type=bind,source="${_arg_packages_dir}",target="/usr/local/src/quickjs-cross-compiler/packages" \
270 | ${_image_name} ${_docker_cmd}) || return 1
271 | return 0
272 | }
273 |
274 | build_docker_image || exit 1
275 | build_and_export_package || exit 1
276 |
277 | # ^^^ TERMINATE YOUR CODE BEFORE THE BOTTOM ARGBASH MARKER ^^^
278 |
279 | # ] <-- needed because of Argbash
280 |
--------------------------------------------------------------------------------
/docker/scripts/build_docker_image.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ###
4 | #
5 | # Build a docker image which can be used to cross-compile QuickJS
6 | # Image will contain :
7 | # - musl.cc cross-compiler
8 | # - a built version of musl lib
9 | #
10 | ###
11 |
12 | script_dir="$(cd "$(dirname "$(readlink -f "$0")")" && pwd)" || { echo "Couldn't determine the script's running directory, which probably matters, bailing out" >&2; exit 2; }
13 |
14 | # Created by argbash-init v2.10.0
15 | # ARG_OPTIONAL_SINGLE([arch],[a],[target architecture],[x86_64])
16 | # ARG_OPTIONAL_BOOLEAN([force],[f],[rebuild image even if it exists],[off])
17 | # ARG_OPTIONAL_BOOLEAN([verbose],[v],[enable verbose mode],[off])
18 | # ARG_TYPE_GROUP_SET([arch],[type string],[arch],[x86_64,i686,armv7l,aarch64])
19 | # ARG_HELP([Build a Docker image which can be used to cross-compile QuickJS])
20 | # ARGBASH_GO()
21 | # needed because of Argbash --> m4_ignore([
22 | ### START OF CODE GENERATED BY Argbash v2.10.0 one line above ###
23 | # Argbash is a bash code generator used to get arguments parsing right.
24 | # Argbash is FREE SOFTWARE, see https://argbash.io for more info
25 |
26 |
27 | die()
28 | {
29 | local _ret="${2:-1}"
30 | test "${_PRINT_HELP:-no}" = yes && print_help >&2
31 | echo "$1" >&2
32 | exit "${_ret}"
33 | }
34 |
35 | # validators
36 |
37 | arch()
38 | {
39 | local _allowed=("x86_64" "i686" "armv7l" "aarch64") _seeking="$1"
40 | for element in "${_allowed[@]}"
41 | do
42 | test "$element" = "$_seeking" && echo "$element" && return 0
43 | done
44 | die "Value '$_seeking' (of argument '$2') doesn't match the list of allowed values: 'x86_64', 'i686', 'armv7l' and 'aarch64'" 4
45 | }
46 |
47 |
48 | begins_with_short_option()
49 | {
50 | local first_option all_short_options='afvh'
51 | first_option="${1:0:1}"
52 | test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0
53 | }
54 |
55 | # THE DEFAULTS INITIALIZATION - OPTIONALS
56 | _arg_arch="x86_64"
57 | _arg_force="off"
58 | _arg_verbose="off"
59 |
60 |
61 | print_help()
62 | {
63 | printf '%s\n' "Build a Docker image which can be used to cross-compile QuickJS"
64 | printf 'Usage: %s [-a|--arch ] [-f|--(no-)force] [-v|--(no-)verbose] [-h|--help]\n' "$0"
65 | printf '\t%s\n' "-a, --arch: target architecture. Can be one of: 'x86_64', 'i686', 'armv7l' and 'aarch64' (default: 'x86_64')"
66 | printf '\t%s\n' "-f, --force, --no-force: rebuild image even if it exists (off by default)"
67 | printf '\t%s\n' "-v, --verbose, --no-verbose: enable verbose mode (off by default)"
68 | printf '\t%s\n' "-h, --help: Prints help"
69 | }
70 |
71 |
72 | parse_commandline()
73 | {
74 | while test $# -gt 0
75 | do
76 | _key="$1"
77 | case "$_key" in
78 | -a|--arch)
79 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
80 | _arg_arch="$(arch "$2" "arch")" || exit 1
81 | shift
82 | ;;
83 | --arch=*)
84 | _arg_arch="$(arch "${_key##--arch=}" "arch")" || exit 1
85 | ;;
86 | -a*)
87 | _arg_arch="$(arch "${_key##-a}" "arch")" || exit 1
88 | ;;
89 | -f|--no-force|--force)
90 | _arg_force="on"
91 | test "${1:0:5}" = "--no-" && _arg_force="off"
92 | ;;
93 | -f*)
94 | _arg_force="on"
95 | _next="${_key##-f}"
96 | if test -n "$_next" -a "$_next" != "$_key"
97 | then
98 | { begins_with_short_option "$_next" && shift && set -- "-f" "-${_next}" "$@"; } || die "The short option '$_key' can't be decomposed to ${_key:0:2} and -${_key:2}, because ${_key:0:2} doesn't accept value and '-${_key:2:1}' doesn't correspond to a short option."
99 | fi
100 | ;;
101 | -v|--no-verbose|--verbose)
102 | _arg_verbose="on"
103 | test "${1:0:5}" = "--no-" && _arg_verbose="off"
104 | ;;
105 | -v*)
106 | _arg_verbose="on"
107 | _next="${_key##-v}"
108 | if test -n "$_next" -a "$_next" != "$_key"
109 | then
110 | { begins_with_short_option "$_next" && shift && set -- "-v" "-${_next}" "$@"; } || die "The short option '$_key' can't be decomposed to ${_key:0:2} and -${_key:2}, because ${_key:0:2} doesn't accept value and '-${_key:2:1}' doesn't correspond to a short option."
111 | fi
112 | ;;
113 | -h|--help)
114 | print_help
115 | exit 0
116 | ;;
117 | -h*)
118 | print_help
119 | exit 0
120 | ;;
121 | *)
122 | _PRINT_HELP=yes die "FATAL ERROR: Got an unexpected argument '$1'" 1
123 | ;;
124 | esac
125 | shift
126 | done
127 | }
128 |
129 | parse_commandline "$@"
130 |
131 | # OTHER STUFF GENERATED BY Argbash
132 | # Validation of values
133 |
134 |
135 | ### END OF CODE GENERATED BY Argbash (sortof) ### ])
136 | # [ <-- needed because of Argbash
137 |
138 |
139 | # vvv PLACE YOUR CODE HERE vvv
140 |
141 | # Build docker image
142 | build_image()
143 | {
144 | # check if image exist
145 | _image_name="quickjs-cross-compiler:${_arg_arch}"
146 | _image=$(docker images --format "{{.ID}}" --filter=reference="${_image_name}" | head -1)
147 |
148 | [ ${_arg_verbose} == "on" ] && echo "Building docker image for '${_arg_arch}'..."
149 |
150 | # no need to build image
151 | if ! [ -z ${_image} ] && [ ${_arg_force} == "off" ]
152 | then
153 | [ ${_arg_verbose} == "on" ] && echo "No need to build docker image for '${_arg_arch}'..."
154 | else
155 | docker build --build-arg arch=${_arg_arch} --no-cache --force-rm=true --rm=true -f ${script_dir}/../Dockerfile -t ${_image_name} ${script_dir}/../.. || return 1
156 | [ ${_arg_verbose} == "on" ] && echo "Successfully built docker image for '${_arg_arch}'"
157 | fi
158 |
159 | return 0
160 | }
161 |
162 | _PRINT_HELP=no
163 |
164 | build_image || die "Could not build docker image for '${_arg_arch}'"
165 |
166 | # ^^^ TERMINATE YOUR CODE BEFORE THE BOTTOM ARGBASH MARKER ^^^
167 |
168 | # ] <-- needed because of Argbash
169 |
--------------------------------------------------------------------------------
/flake.lock:
--------------------------------------------------------------------------------
1 | {
2 | "nodes": {
3 | "flake-utils": {
4 | "inputs": {
5 | "systems": "systems"
6 | },
7 | "locked": {
8 | "lastModified": 1710146030,
9 | "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
10 | "owner": "numtide",
11 | "repo": "flake-utils",
12 | "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
13 | "type": "github"
14 | },
15 | "original": {
16 | "owner": "numtide",
17 | "repo": "flake-utils",
18 | "type": "github"
19 | }
20 | },
21 | "nixpkgs": {
22 | "locked": {
23 | "lastModified": 1724479785,
24 | "narHash": "sha256-pP3Azj5d6M5nmG68Fu4JqZmdGt4S4vqI5f8te+E/FTw=",
25 | "owner": "nixos",
26 | "repo": "nixpkgs",
27 | "rev": "d0e1602ddde669d5beb01aec49d71a51937ed7be",
28 | "type": "github"
29 | },
30 | "original": {
31 | "owner": "nixos",
32 | "ref": "nixos-unstable",
33 | "repo": "nixpkgs",
34 | "type": "github"
35 | }
36 | },
37 | "root": {
38 | "inputs": {
39 | "flake-utils": "flake-utils",
40 | "nixpkgs": "nixpkgs"
41 | }
42 | },
43 | "systems": {
44 | "locked": {
45 | "lastModified": 1681028828,
46 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
47 | "owner": "nix-systems",
48 | "repo": "default",
49 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
50 | "type": "github"
51 | },
52 | "original": {
53 | "owner": "nix-systems",
54 | "repo": "default",
55 | "type": "github"
56 | }
57 | }
58 | },
59 | "root": "root",
60 | "version": 7
61 | }
62 |
--------------------------------------------------------------------------------
/flake.nix:
--------------------------------------------------------------------------------
1 | {
2 | description = "QuickJS Static Compiler";
3 |
4 | inputs = {
5 | nixpkgs = {
6 | url = "github:nixos/nixpkgs/nixos-unstable";
7 | };
8 |
9 | flake-utils.url = "github:numtide/flake-utils";
10 | };
11 |
12 | outputs = { self, nixpkgs, flake-utils }:
13 | flake-utils.lib.eachSystem [ "x86_64-linux" "armv7l-linux" "aarch64-linux" ] (system:
14 | let
15 | pkgs = import nixpkgs {
16 | inherit system;
17 | };
18 |
19 | highlight = text: "\\x1b[1;38;5;212m${text}\\x1b[0m";
20 |
21 | qjs_version = "2025-04-26_1";
22 | arch =
23 | if system == "x86_64-linux" then "x86_64"
24 | else if system == "armv7l-linux" then "armv7l"
25 | else if system == "aarch64-linux" then "aarch64"
26 | else "unknown-arch";
27 | sha256 =
28 | if system == "x86_64-linux" then "sha256:12i025crfdggf2h2sr5lkfriwxdy98309b50mvkzfqk4f23kww70"
29 | else if system == "armv7l-linux" then "sha256:0imv0f9arajjxj5hapd09sn43mf79lswpgpdcqfaajnhcha4m592"
30 | else if system == "aarch64-linux" then "sha256:06y42w0ak9brapvwszm74qrgs5yhlkbcs44kj4anwnx9mmgdv3an"
31 | else "sha256:0000000000000000000000000000000000000000000000000000";
32 |
33 | quickjsStatic = pkgs.stdenv.mkDerivation {
34 | name = "quickjs-static";
35 |
36 | src = builtins.fetchTarball {
37 | url = "https://github.com/ctn-malone/quickjs-cross-compiler/releases/download/v${qjs_version}/quickjs.core.${qjs_version}.${arch}.tar.xz";
38 | sha256 = sha256;
39 | };
40 |
41 | configurePhase = false;
42 | buildPhase = false;
43 |
44 | installPhase = ''
45 | mkdir -p $out/bin
46 | cp -R $src/* $out/bin
47 | '';
48 | };
49 |
50 | in
51 | {
52 |
53 | packages.quickjs-static = quickjsStatic;
54 |
55 | defaultPackage = self.packages.${system}.quickjs-static;
56 |
57 | apps = {
58 | # interpreter
59 | default = {
60 | type = "app";
61 | program = "${quickjsStatic}/bin/qjs.sh";
62 | };
63 |
64 | qjs = self.apps.${system}.default;
65 |
66 | # compiler
67 | qjsc = {
68 | type = "app";
69 | program = "${quickjsStatic}/bin/qjsc.sh";
70 | };
71 | };
72 |
73 | devShell = pkgs.mkShell {
74 | name = "quickjs-static";
75 |
76 | buildInputs = [
77 | pkgs.upx
78 | quickjsStatic
79 | ];
80 |
81 | shellHook = ''
82 | echo -e "To compile a JS file, use ${highlight "qjsc.sh -o "}" 1>&2
83 | echo -e "To run a JS file, use ${highlight "qjs.sh "}" 1>&2
84 | '';
85 | };
86 | }
87 | );
88 | }
89 |
--------------------------------------------------------------------------------