xbintsc 0.5.23 → 0.5.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +11 -2
- package/README.md +47 -16
- package/README.zh-CN.md +21 -2
- package/dist/scripts/support-matrix.d.ts +18 -0
- package/dist/scripts/support-matrix.js +141 -0
- package/dist/scripts/support-matrix.js.map +1 -0
- package/dist/src/ast/common.d.ts +2 -2
- package/dist/src/ast/declarations.d.ts +7 -1
- package/dist/src/ast/expressions.d.ts +5 -0
- package/dist/src/ast/kinds.d.ts +2 -0
- package/dist/src/ast/kinds.js +2 -0
- package/dist/src/ast/kinds.js.map +1 -1
- package/dist/src/binder/binder.d.ts +2 -1
- package/dist/src/binder/binder.js +2 -0
- package/dist/src/binder/binder.js.map +1 -1
- package/dist/src/binder/declarations.d.ts +9 -0
- package/dist/src/binder/declarations.js +64 -0
- package/dist/src/binder/declarations.js.map +1 -1
- package/dist/src/binder/references.js +99 -4
- package/dist/src/binder/references.js.map +1 -1
- package/dist/src/binder/types.d.ts +32 -0
- package/dist/src/binder/types.js.map +1 -1
- package/dist/src/canonical.d.ts +29 -0
- package/dist/src/canonical.js +35 -0
- package/dist/src/canonical.js.map +1 -0
- package/dist/src/checker/assignability.d.ts +13 -0
- package/dist/src/checker/assignability.js +146 -0
- package/dist/src/checker/assignability.js.map +1 -0
- package/dist/src/checker/calls.d.ts +13 -0
- package/dist/src/checker/calls.js +127 -0
- package/dist/src/checker/calls.js.map +1 -0
- package/dist/src/checker/checker.d.ts +26 -0
- package/dist/src/checker/checker.js +31 -0
- package/dist/src/checker/checker.js.map +1 -0
- package/dist/src/checker/declarations.d.ts +9 -0
- package/dist/src/checker/declarations.js +15 -0
- package/dist/src/checker/declarations.js.map +1 -0
- package/dist/src/checker/flow.d.ts +21 -0
- package/dist/src/checker/flow.js +241 -0
- package/dist/src/checker/flow.js.map +1 -0
- package/dist/src/checker/globals.d.ts +9 -0
- package/dist/src/checker/globals.js +29 -0
- package/dist/src/checker/globals.js.map +1 -0
- package/dist/src/checker/source.d.ts +38 -0
- package/dist/src/checker/source.js +48 -0
- package/dist/src/checker/source.js.map +1 -0
- package/dist/src/checker/type-infer.d.ts +18 -0
- package/dist/src/checker/type-infer.js +173 -0
- package/dist/src/checker/type-infer.js.map +1 -0
- package/dist/src/checker/type-model.d.ts +73 -0
- package/dist/src/checker/type-model.js +151 -0
- package/dist/src/checker/type-model.js.map +1 -0
- package/dist/src/checker/type-system.d.ts +58 -0
- package/dist/src/checker/type-system.js +569 -0
- package/dist/src/checker/type-system.js.map +1 -0
- package/dist/src/checker/typecheck-types.d.ts +22 -0
- package/dist/src/checker/typecheck-types.js +109 -0
- package/dist/src/checker/typecheck-types.js.map +1 -0
- package/dist/src/checker/typecheck.d.ts +62 -0
- package/dist/src/checker/typecheck.js +574 -0
- package/dist/src/checker/typecheck.js.map +1 -0
- package/dist/src/checker/undefined.d.ts +14 -0
- package/dist/src/checker/undefined.js +32 -0
- package/dist/src/checker/undefined.js.map +1 -0
- package/dist/src/checker/walk.d.ts +10 -0
- package/dist/src/checker/walk.js +15 -0
- package/dist/src/checker/walk.js.map +1 -0
- package/dist/src/cli/help.d.ts +7 -0
- package/dist/src/cli/help.js +64 -0
- package/dist/src/cli/help.js.map +1 -0
- package/dist/src/cli/hints.js +2 -1
- package/dist/src/cli/hints.js.map +1 -1
- package/dist/src/cli/main.js +12 -48
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/codegen/generator/calls/access.js +8 -8
- package/dist/src/codegen/generator/calls/access.js.map +1 -1
- package/dist/src/codegen/generator/calls/invocation.js +9 -4
- package/dist/src/codegen/generator/calls/invocation.js.map +1 -1
- package/dist/src/codegen/generator/calls/super.d.ts +9 -1
- package/dist/src/codegen/generator/calls/super.js +56 -5
- package/dist/src/codegen/generator/calls/super.js.map +1 -1
- package/dist/src/codegen/generator/context.d.ts +13 -2
- package/dist/src/codegen/generator/context.js +25 -19
- package/dist/src/codegen/generator/context.js.map +1 -1
- package/dist/src/codegen/generator/debug.js +2 -1
- package/dist/src/codegen/generator/debug.js.map +1 -1
- package/dist/src/codegen/generator/expressions/primary.d.ts +4 -1
- package/dist/src/codegen/generator/expressions/primary.js +68 -8
- package/dist/src/codegen/generator/expressions/primary.js.map +1 -1
- package/dist/src/codegen/generator/generator.js +11 -1
- package/dist/src/codegen/generator/generator.js.map +1 -1
- package/dist/src/codegen/generator/module.d.ts +3 -0
- package/dist/src/codegen/generator/module.js +116 -26
- package/dist/src/codegen/generator/module.js.map +1 -1
- package/dist/src/codegen/generator/state.d.ts +11 -1
- package/dist/src/codegen/generator/state.js.map +1 -1
- package/dist/src/codegen/generator/statements/variables.js +26 -7
- package/dist/src/codegen/generator/statements/variables.js.map +1 -1
- package/dist/src/codegen/generator/tables.d.ts +2 -0
- package/dist/src/codegen/generator/tables.js +4 -0
- package/dist/src/codegen/generator/tables.js.map +1 -1
- package/dist/src/driver/build-key.d.ts +2 -0
- package/dist/src/driver/build-key.js +1 -0
- package/dist/src/driver/build-key.js.map +1 -1
- package/dist/src/driver/bundler/graph.js +5 -1
- package/dist/src/driver/bundler/graph.js.map +1 -1
- package/dist/src/driver/bundler/merge.js +16 -1
- package/dist/src/driver/bundler/merge.js.map +1 -1
- package/dist/src/driver/bundler/types.d.ts +12 -0
- package/dist/src/driver/compiler.d.ts +1 -1
- package/dist/src/driver/compiler.js +3 -0
- package/dist/src/driver/compiler.js.map +1 -1
- package/dist/src/driver/fingerprint.js +2 -1
- package/dist/src/driver/fingerprint.js.map +1 -1
- package/dist/src/driver/frontend.d.ts +8 -6
- package/dist/src/driver/frontend.js +4 -0
- package/dist/src/driver/frontend.js.map +1 -1
- package/dist/src/driver/options.d.ts +6 -0
- package/dist/src/driver/version.d.ts +1 -1
- package/dist/src/driver/version.js +1 -1
- package/dist/src/extensions/gui/css.d.ts +26 -0
- package/dist/src/extensions/gui/css.js +100 -0
- package/dist/src/extensions/gui/css.js.map +1 -0
- package/dist/src/extensions/gui/html.js +28 -7
- package/dist/src/extensions/gui/html.js.map +1 -1
- package/dist/src/extensions/gui/index.js +79 -2
- package/dist/src/extensions/gui/index.js.map +1 -1
- package/dist/src/extensions/gui/three.d.ts +16 -0
- package/dist/src/extensions/gui/three.js +22 -0
- package/dist/src/extensions/gui/three.js.map +1 -0
- package/dist/src/extensions/media/index.d.ts +6 -5
- package/dist/src/extensions/media/index.js +12 -14
- package/dist/src/extensions/media/index.js.map +1 -1
- package/dist/src/extensions/registry.d.ts +38 -0
- package/dist/src/extensions/registry.js +10 -0
- package/dist/src/extensions/registry.js.map +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/parser/declarations/classes.js +7 -0
- package/dist/src/parser/declarations/classes.js.map +1 -1
- package/dist/src/parser/expressions.js +14 -1
- package/dist/src/parser/expressions.js.map +1 -1
- package/dist/src/parser/literals.js +6 -2
- package/dist/src/parser/literals.js.map +1 -1
- package/dist/tests/binder/binder.test.js +29 -0
- package/dist/tests/binder/binder.test.js.map +1 -1
- package/dist/tests/canonical.test.d.ts +1 -0
- package/dist/tests/canonical.test.js +19 -0
- package/dist/tests/canonical.test.js.map +1 -0
- package/dist/tests/checker/checker.test.d.ts +1 -0
- package/dist/tests/checker/checker.test.js +245 -0
- package/dist/tests/checker/checker.test.js.map +1 -0
- package/dist/tests/cli/check.test.js +20 -0
- package/dist/tests/cli/check.test.js.map +1 -1
- package/dist/tests/conformance/matrix.test.d.ts +6 -0
- package/dist/tests/conformance/matrix.test.js +23 -0
- package/dist/tests/conformance/matrix.test.js.map +1 -0
- package/dist/tests/conformance/test262/manifest.d.ts +115 -0
- package/dist/tests/conformance/test262/manifest.js +257 -0
- package/dist/tests/conformance/test262/manifest.js.map +1 -0
- package/dist/tests/conformance/test262.test.d.ts +11 -0
- package/dist/tests/conformance/test262.test.js +74 -0
- package/dist/tests/conformance/test262.test.js.map +1 -0
- package/dist/tests/docs/structure.test.js +9 -11
- package/dist/tests/docs/structure.test.js.map +1 -1
- package/dist/tests/e2e/child-process.test.js +3 -2
- package/dist/tests/e2e/child-process.test.js.map +1 -1
- package/dist/tests/e2e/compile-builtins.test.js +45 -0
- package/dist/tests/e2e/compile-builtins.test.js.map +1 -1
- package/dist/tests/e2e/compile-objects-classes.test.js +77 -0
- package/dist/tests/e2e/compile-objects-classes.test.js.map +1 -1
- package/dist/tests/e2e/differential-syntax.test.d.ts +5 -0
- package/dist/tests/e2e/differential-syntax.test.js +95 -0
- package/dist/tests/e2e/differential-syntax.test.js.map +1 -0
- package/dist/tests/e2e/differential-values.test.js +15 -0
- package/dist/tests/e2e/differential-values.test.js.map +1 -1
- package/dist/tests/e2e/gui-browser.test.d.ts +13 -0
- package/dist/tests/e2e/gui-browser.test.js +163 -0
- package/dist/tests/e2e/gui-browser.test.js.map +1 -0
- package/dist/tests/e2e/gui-effects.test.d.ts +6 -0
- package/dist/tests/e2e/gui-effects.test.js +262 -0
- package/dist/tests/e2e/gui-effects.test.js.map +1 -0
- package/dist/tests/e2e/gui-example-browser.test.js +2 -2
- package/dist/tests/e2e/gui-example-browser.test.js.map +1 -1
- package/dist/tests/e2e/gui-example-canvas.test.js +5 -4
- package/dist/tests/e2e/gui-example-canvas.test.js.map +1 -1
- package/dist/tests/e2e/gui-example-svg.test.js +4 -3
- package/dist/tests/e2e/gui-example-svg.test.js.map +1 -1
- package/dist/tests/e2e/gui-example-webgl.test.d.ts +10 -0
- package/dist/tests/e2e/gui-example-webgl.test.js +75 -0
- package/dist/tests/e2e/gui-example-webgl.test.js.map +1 -0
- package/dist/tests/e2e/gui-example-webgl2.test.d.ts +8 -0
- package/dist/tests/e2e/gui-example-webgl2.test.js +72 -0
- package/dist/tests/e2e/gui-example-webgl2.test.js.map +1 -0
- package/dist/tests/e2e/gui-example.test.js +4 -3
- package/dist/tests/e2e/gui-example.test.js.map +1 -1
- package/dist/tests/e2e/gui-helpers.js +4 -3
- package/dist/tests/e2e/gui-helpers.js.map +1 -1
- package/dist/tests/e2e/gui-layout.test.js +48 -0
- package/dist/tests/e2e/gui-layout.test.js.map +1 -1
- package/dist/tests/e2e/gui-media.test.js +10 -8
- package/dist/tests/e2e/gui-media.test.js.map +1 -1
- package/dist/tests/e2e/gui-webgl.test.d.ts +11 -0
- package/dist/tests/e2e/gui-webgl.test.js +179 -0
- package/dist/tests/e2e/gui-webgl.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2.test.d.ts +10 -0
- package/dist/tests/e2e/gui-webgl2.test.js +238 -0
- package/dist/tests/e2e/gui-webgl2.test.js.map +1 -0
- package/dist/tests/e2e/harness.d.ts +9 -0
- package/dist/tests/e2e/harness.js +14 -2
- package/dist/tests/e2e/harness.js.map +1 -1
- package/dist/tests/e2e/native-extensions.test.js +2 -1
- package/dist/tests/e2e/native-extensions.test.js.map +1 -1
- package/dist/tests/e2e/property-descriptors.test.js +20 -0
- package/dist/tests/e2e/property-descriptors.test.js.map +1 -1
- package/dist/tests/e2e/unicode-output.test.js +5 -3
- package/dist/tests/e2e/unicode-output.test.js.map +1 -1
- package/dist/tests/e2e/weak-collections.test.js +16 -2
- package/dist/tests/e2e/weak-collections.test.js.map +1 -1
- package/dist/tests/extensions/gui.test.js +41 -0
- package/dist/tests/extensions/gui.test.js.map +1 -1
- package/dist/tests/extensions/media.test.js +7 -3
- package/dist/tests/extensions/media.test.js.map +1 -1
- package/dist/tests/helpers.d.ts +1 -0
- package/dist/tests/helpers.js +1 -0
- package/dist/tests/helpers.js.map +1 -1
- package/dist/tests/parser/declarations.test.js +20 -0
- package/dist/tests/parser/declarations.test.js.map +1 -1
- package/dist/tests/parser/expressions.test.js +36 -0
- package/dist/tests/parser/expressions.test.js.map +1 -1
- package/dist/tests/platform.d.ts +32 -0
- package/dist/tests/platform.js +40 -0
- package/dist/tests/platform.js.map +1 -0
- package/dist/tests/platform.test.d.ts +12 -0
- package/dist/tests/platform.test.js +51 -0
- package/dist/tests/platform.test.js.map +1 -0
- package/dist/tests/version.test.js +4 -4
- package/dist/tests/version.test.js.map +1 -1
- package/doc/ai/README.md +10 -4
- package/doc/ai/build-recipe.md +1 -0
- package/doc/ai/cli.md +17 -5
- package/doc/ai/contributing.md +59 -2
- package/doc/ai/extensions.md +38 -7
- package/doc/ai/language-support.md +25 -16
- package/doc/ai/troubleshooting.md +12 -8
- package/doc/ai/zh-CN/README.md +9 -4
- package/doc/ai/zh-CN/build-recipe.md +1 -0
- package/doc/ai/zh-CN/cli.md +13 -3
- package/doc/ai/zh-CN/contributing.md +49 -3
- package/doc/ai/zh-CN/extensions.md +33 -6
- package/doc/ai/zh-CN/language-support.md +23 -14
- package/doc/ai/zh-CN/troubleshooting.md +10 -6
- package/doc/gui/api.md +47 -1
- package/doc/gui/build.md +72 -16
- package/doc/gui/canvas.md +11 -3
- package/doc/gui/dom.md +33 -18
- package/doc/gui/known-issues.md +58 -15
- package/doc/gui/layout.md +18 -0
- package/doc/gui/media.md +17 -13
- package/doc/gui/rendering.md +50 -3
- package/doc/gui/runtime.md +18 -0
- package/doc/gui/webgl.md +256 -0
- package/doc/gui-scripts.md +7 -0
- package/doc/gui.md +108 -17
- package/doc/implemented/binder.md +2 -0
- package/doc/implemented/checker.md +117 -0
- package/doc/implemented/cli.md +13 -1
- package/doc/implemented/codegen.md +3 -2
- package/doc/implemented/driver.md +2 -2
- package/doc/implemented/operators.md +2 -1
- package/doc/implemented/parser.md +3 -2
- package/doc/implemented/pipeline.md +8 -1
- package/doc/implemented/stdlib.md +2 -1
- package/doc/implemented/tests.md +3 -1
- package/doc/implemented.md +2 -0
- package/doc/npm-package.md +419 -0
- package/doc/requirements.md +22 -10
- package/doc/support-matrix.md +83 -0
- package/doc/unimplemented/classes.md +3 -0
- package/doc/unimplemented/deviations.md +3 -2
- package/doc/unimplemented/toolchain.md +1 -1
- package/doc/unimplemented/types.md +24 -8
- package/doc/unimplemented.md +1 -1
- package/doc/zh-CN/gui/api.md +43 -1
- package/doc/zh-CN/gui/build.md +64 -15
- package/doc/zh-CN/gui/canvas.md +9 -2
- package/doc/zh-CN/gui/dom.md +20 -7
- package/doc/zh-CN/gui/known-issues.md +46 -13
- package/doc/zh-CN/gui/layout.md +14 -0
- package/doc/zh-CN/gui/media.md +15 -11
- package/doc/zh-CN/gui/rendering.md +41 -4
- package/doc/zh-CN/gui/runtime.md +16 -0
- package/doc/zh-CN/gui/webgl.md +115 -0
- package/doc/zh-CN/gui-scripts.md +5 -0
- package/doc/zh-CN/gui.md +89 -14
- package/doc/zh-CN/implemented/binder.md +2 -0
- package/doc/zh-CN/implemented/checker.md +99 -0
- package/doc/zh-CN/implemented/cli.md +12 -1
- package/doc/zh-CN/implemented/codegen.md +3 -2
- package/doc/zh-CN/implemented/driver.md +2 -2
- package/doc/zh-CN/implemented/operators.md +1 -1
- package/doc/zh-CN/implemented/parser.md +3 -2
- package/doc/zh-CN/implemented/pipeline.md +3 -1
- package/doc/zh-CN/implemented/stdlib.md +2 -1
- package/doc/zh-CN/implemented/tests.md +3 -1
- package/doc/zh-CN/implemented.md +2 -0
- package/doc/zh-CN/npm-package.md +394 -0
- package/doc/zh-CN/post/announce.md +47 -47
- package/doc/zh-CN/requirements.md +16 -7
- package/doc/zh-CN/support-matrix.md +82 -0
- package/doc/zh-CN/unimplemented/classes.md +3 -0
- package/doc/zh-CN/unimplemented/deviations.md +3 -2
- package/doc/zh-CN/unimplemented/toolchain.md +1 -1
- package/doc/zh-CN/unimplemented/types.md +16 -6
- package/doc/zh-CN/unimplemented.md +1 -1
- package/llms.txt +6 -1
- package/package.json +2 -1
- package/runtime/ext_gui/audio.cpp +316 -0
- package/runtime/ext_gui/browser.cpp +573 -0
- package/runtime/ext_gui/browser_escape.cpp +85 -0
- package/runtime/ext_gui/browser_loop.cpp +83 -0
- package/runtime/ext_gui/canvas.cpp +12 -21
- package/runtime/ext_gui/canvas_internal.h +10 -0
- package/runtime/ext_gui/canvas_raster.cpp +79 -1
- package/runtime/ext_gui/clip_values.cpp +246 -0
- package/runtime/ext_gui/css.cpp +94 -0
- package/runtime/ext_gui/css.h +22 -1
- package/runtime/ext_gui/css_match.cpp +3 -0
- package/runtime/ext_gui/css_selector.cpp +9 -0
- package/runtime/ext_gui/css_sheet.cpp +89 -45
- package/runtime/ext_gui/document.cpp +4 -1
- package/runtime/ext_gui/document.h +2 -0
- package/runtime/ext_gui/dom.h +16 -0
- package/runtime/ext_gui/dom_api.cpp +37 -0
- package/runtime/ext_gui/dom_api_canvas.cpp +17 -80
- package/runtime/ext_gui/dom_api_canvas_extra.cpp +130 -1
- package/runtime/ext_gui/dom_api_canvas_pending.cpp +41 -0
- package/runtime/ext_gui/dom_api_document.cpp +96 -5
- package/runtime/ext_gui/dom_api_events.cpp +20 -0
- package/runtime/ext_gui/dom_api_internal.h +278 -0
- package/runtime/ext_gui/dom_api_proto.cpp +6 -0
- package/runtime/ext_gui/dom_api_webgl.cpp +376 -0
- package/runtime/ext_gui/dom_api_webgl2.cpp +434 -0
- package/runtime/ext_gui/dom_api_webgl2_draw.cpp +269 -0
- package/runtime/ext_gui/dom_api_webgl_buffer.cpp +212 -0
- package/runtime/ext_gui/dom_api_webgl_rt.h +30 -0
- package/runtime/ext_gui/dom_api_webgl_shader.cpp +443 -0
- package/runtime/ext_gui/dom_api_webgl_state.cpp +444 -0
- package/runtime/ext_gui/dom_api_webgl_texture.cpp +445 -0
- package/runtime/ext_gui/effect_values.cpp +312 -0
- package/runtime/ext_gui/gradient_values.cpp +476 -0
- package/runtime/ext_gui/grid_values.cpp +230 -0
- package/runtime/ext_gui/gui.cpp +90 -23
- package/runtime/ext_gui/gui_canvas.cpp +50 -2
- package/runtime/ext_gui/gui_engine.h +71 -0
- package/runtime/ext_gui/gui_events.cpp +4 -1
- package/runtime/ext_gui/gui_media.cpp +1 -1
- package/runtime/ext_gui/gui_webgl.cpp +83 -0
- package/runtime/ext_gui/layout.cpp +21 -0
- package/runtime/ext_gui/layout_flow.cpp +81 -4
- package/runtime/ext_gui/layout_flow_internal.h +31 -0
- package/runtime/ext_gui/layout_grid.cpp +374 -0
- package/runtime/ext_gui/media.h +1 -1
- package/runtime/ext_gui/media_api.h +2 -2
- package/runtime/ext_gui/media_query.cpp +211 -0
- package/runtime/ext_gui/paint.cpp +111 -77
- package/runtime/ext_gui/paint.h +33 -3
- package/runtime/ext_gui/paint_background.cpp +229 -0
- package/runtime/ext_gui/paint_clip.cpp +268 -0
- package/runtime/ext_gui/paint_effects.cpp +324 -0
- package/runtime/ext_gui/paint_internal.h +85 -0
- package/runtime/ext_gui/renderer.cpp +8 -31
- package/runtime/ext_gui/renderer_clip.cpp +196 -0
- package/runtime/ext_gui/renderer_image.cpp +13 -8
- package/runtime/ext_gui/renderer_internal.h +15 -8
- package/runtime/ext_gui/renderer_text.cpp +6 -31
- package/runtime/ext_gui/style.cpp +343 -20
- package/runtime/ext_gui/style.h +144 -3
- package/runtime/ext_gui/style_print.cpp +134 -1
- package/runtime/ext_gui/style_values.cpp +152 -126
- package/runtime/ext_gui/style_values_internal.h +35 -0
- package/runtime/ext_gui/webgl.h +466 -0
- package/runtime/ext_gui/webgl2_constants.h +274 -0
- package/runtime/ext_gui/webgl_buffer.cpp +565 -0
- package/runtime/ext_gui/webgl_constants.h +317 -0
- package/runtime/ext_gui/webgl_context.cpp +466 -0
- package/runtime/ext_gui/webgl_draw.cpp +495 -0
- package/runtime/ext_gui/webgl_glsl.h +125 -0
- package/runtime/ext_gui/webgl_glsl_compile.cpp +431 -0
- package/runtime/ext_gui/webgl_glsl_rewrite.cpp +349 -0
- package/runtime/ext_gui/webgl_glsl_scan.cpp +581 -0
- package/runtime/ext_gui/webgl_msl.cpp +62 -0
- package/runtime/ext_gui/webgl_msl.h +33 -0
- package/runtime/ext_gui/webgl_pipeline.cpp +274 -0
- package/runtime/ext_gui/webgl_program_internal.h +18 -0
- package/runtime/ext_gui/webgl_shader.cpp +582 -0
- package/runtime/ext_gui/webgl_texture.cpp +293 -0
- package/runtime/ext_gui/webgl_uniform.cpp +167 -0
- package/runtime/ext_gui/webgl_webgl2.cpp +224 -0
- package/runtime/ext_gui/window.cpp +9 -0
- package/runtime/ext_media/media.cpp +1 -1
- package/runtime/ext_media/media_bridge.c +9 -3
- package/runtime/ext_node/path/path.c +7 -7
- package/runtime/ext_node/url/url.c +4 -2
- package/runtime/rt.h +15 -0
- package/runtime/rt_internal.h +1 -0
- package/runtime/xt_constructors.c +2 -1
- package/runtime/xt_containers/access.inc +8 -0
- package/runtime/xt_containers/objects.inc +22 -2
- package/runtime/xt_io/exception.inc +4 -2
- package/runtime/xt_regex/api.inc +2 -0
- package/runtime/xt_regex/matcher.inc +16 -3
- package/runtime/xt_regex/parser.inc +8 -2
- package/runtime/xt_regex/types.inc +3 -0
- package/runtime/xt_stdlib/math.inc +62 -0
- package/runtime/xt_stdlib2/date.inc +7 -1
- package/runtime/xt_stdlib2/objects.inc +14 -0
- package/runtime/xt_stdlib2/regexp-match.inc +60 -21
- package/runtime/xt_stdlib2/regexp.inc +1 -0
- package/runtime/xt_typed_array.c +1 -1
- package/scripts/build-gui.ts +90 -3
- package/scripts/build-media.ts +323 -58
- package/scripts/setup-vs-toolchain.ps1 +152 -0
- package/scripts/support-matrix.ts +167 -0
- package/src/ast/common.ts +2 -0
- package/src/ast/declarations.ts +12 -1
- package/src/ast/expressions.ts +6 -0
- package/src/ast/kinds.ts +2 -0
- package/src/binder/binder.ts +3 -0
- package/src/binder/declarations.ts +70 -0
- package/src/binder/references.ts +97 -4
- package/src/binder/types.ts +30 -0
- package/src/canonical.ts +37 -0
- package/src/checker/assignability.ts +134 -0
- package/src/checker/calls.ts +135 -0
- package/src/checker/checker.ts +47 -0
- package/src/checker/declarations.ts +26 -0
- package/src/checker/flow.ts +236 -0
- package/src/checker/globals.ts +40 -0
- package/src/checker/source.ts +53 -0
- package/src/checker/type-infer.ts +185 -0
- package/src/checker/type-model.ts +212 -0
- package/src/checker/type-system.ts +578 -0
- package/src/checker/typecheck-types.ts +112 -0
- package/src/checker/typecheck.ts +586 -0
- package/src/checker/undefined.ts +43 -0
- package/src/checker/walk.ts +16 -0
- package/src/cli/help.ts +65 -0
- package/src/cli/hints.ts +2 -1
- package/src/cli/main.ts +12 -49
- package/src/codegen/generator/calls/access.ts +8 -8
- package/src/codegen/generator/calls/invocation.ts +8 -5
- package/src/codegen/generator/calls/super.ts +67 -5
- package/src/codegen/generator/context.ts +31 -19
- package/src/codegen/generator/debug.ts +2 -1
- package/src/codegen/generator/expressions/primary.ts +84 -13
- package/src/codegen/generator/generator.ts +11 -1
- package/src/codegen/generator/module.ts +115 -24
- package/src/codegen/generator/state.ts +11 -1
- package/src/codegen/generator/statements/variables.ts +26 -6
- package/src/codegen/generator/tables.ts +5 -0
- package/src/driver/build-key.ts +3 -0
- package/src/driver/bundler/graph.ts +6 -2
- package/src/driver/bundler/merge.ts +14 -1
- package/src/driver/bundler/types.ts +13 -0
- package/src/driver/compiler.ts +4 -1
- package/src/driver/fingerprint.ts +2 -1
- package/src/driver/frontend.ts +13 -2
- package/src/driver/options.ts +6 -0
- package/src/driver/version.ts +1 -1
- package/src/extensions/gui/css.ts +113 -0
- package/src/extensions/gui/html.ts +31 -11
- package/src/extensions/gui/index.ts +81 -2
- package/src/extensions/gui/three.ts +25 -0
- package/src/extensions/media/index.ts +13 -16
- package/src/extensions/registry.ts +48 -0
- package/src/index.ts +1 -0
- package/src/parser/declarations/classes.ts +7 -0
- package/src/parser/expressions.ts +13 -1
- package/src/parser/literals.ts +6 -2
package/scripts/build-gui.ts
CHANGED
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
* 1. fetch the pinned SDL3 source into `vendor/SDL` (gitignored),
|
|
14
14
|
* 2. build `libSDL3.a` with CMake,
|
|
15
15
|
* 2b. fetch + build static FreeType and HarfBuzz for text,
|
|
16
|
+
* 2c. fetch + build static glslang (GLSL ES -> SPIR-V) and SPIRV-Cross
|
|
17
|
+
* (SPIR-V -> Metal Shading Language),
|
|
16
18
|
* 3. compile the engine translation units,
|
|
17
19
|
* 4. merge everything into `gui.a` (libtool on macOS, `ar -M` elsewhere;
|
|
18
20
|
* `gui.lib` on Windows, built from MSVC-compatible COFF objects).
|
|
@@ -28,6 +30,7 @@
|
|
|
28
30
|
* SDL3_TAG SDL3 git tag to check out (default: release-3.2.10)
|
|
29
31
|
* FREETYPE_VERSION FreeType version (default: 2.13.3)
|
|
30
32
|
* HARFBUZZ_VERSION HarfBuzz version (default: 10.1.0)
|
|
33
|
+
* SPIRV_CROSS_VERSION SPIRV-Cross tag (default: vulkan-sdk-1.4.313.0)
|
|
31
34
|
*
|
|
32
35
|
* The C/C++ compiler is the same clang the driver resolves (see
|
|
33
36
|
* `src/driver/toolchain-provider.ts`), so the archive always matches the ABI of
|
|
@@ -63,6 +66,17 @@ const freetypeSrc = join(vendorDir, "freetype");
|
|
|
63
66
|
const freetypeBuild = join(vendorDir, "freetype-build");
|
|
64
67
|
const harfbuzzSrc = join(vendorDir, "harfbuzz");
|
|
65
68
|
const harfbuzzBuild = join(vendorDir, "harfbuzz-build");
|
|
69
|
+
/* glslang translates the GLSL ES that WebGL programs supply at run time; it is
|
|
70
|
+
* built statically and merged into the archive, so a compiled binary needs no
|
|
71
|
+
* Vulkan SDK. The SPIR-V headers are its only external dependency. */
|
|
72
|
+
const glslangSrc = join(vendorDir, "glslang");
|
|
73
|
+
const glslangBuild = join(vendorDir, "glslang-build");
|
|
74
|
+
const spirvHeadersSrc = join(glslangSrc, "External", "spirv-headers");
|
|
75
|
+
/* SPIRV-Cross turns the same SPIR-V into the Metal Shading Language that
|
|
76
|
+
* SDL_GPU's Metal backend consumes at run time (macOS). It needs no external
|
|
77
|
+
* headers: its own parser reads the module that glslang produced. */
|
|
78
|
+
const spirvCrossSrc = join(vendorDir, "spirv-cross");
|
|
79
|
+
const spirvCrossBuild = join(vendorDir, "spirv-cross-build");
|
|
66
80
|
const objDir = join(root, "build", "gui-obj");
|
|
67
81
|
const outDir = join(runtimeDir, "lib", platformSlug());
|
|
68
82
|
|
|
@@ -108,8 +122,14 @@ function cmakeToolchainArgs(): string[] {
|
|
|
108
122
|
const SDL_TAG = process.env.SDL3_TAG || "release-3.2.10";
|
|
109
123
|
const FREETYPE_VERSION = process.env.FREETYPE_VERSION || "2.13.3";
|
|
110
124
|
const HARFBUZZ_VERSION = process.env.HARFBUZZ_VERSION || "10.1.0";
|
|
125
|
+
const GLSLANG_VERSION = process.env.GLSLANG_VERSION || "16.6.0";
|
|
126
|
+
const SPIRV_HEADERS_VERSION = process.env.SPIRV_HEADERS_VERSION || "vulkan-sdk-1.4.363.0";
|
|
127
|
+
const SPIRV_CROSS_VERSION = process.env.SPIRV_CROSS_VERSION || "vulkan-sdk-1.4.313.0";
|
|
111
128
|
const FREETYPE_URL = `https://download.savannah.gnu.org/releases/freetype/freetype-${FREETYPE_VERSION}.tar.xz`;
|
|
112
129
|
const HARFBUZZ_URL = `https://github.com/harfbuzz/harfbuzz/releases/download/${HARFBUZZ_VERSION}/harfbuzz-${HARFBUZZ_VERSION}.tar.xz`;
|
|
130
|
+
const GLSLANG_URL = `https://codeload.github.com/KhronosGroup/glslang/tar.gz/refs/tags/${GLSLANG_VERSION}`;
|
|
131
|
+
const SPIRV_HEADERS_URL = `https://codeload.github.com/KhronosGroup/SPIRV-Headers/tar.gz/refs/tags/${SPIRV_HEADERS_VERSION}`;
|
|
132
|
+
const SPIRV_CROSS_URL = `https://codeload.github.com/KhronosGroup/SPIRV-Cross/tar.gz/refs/tags/${SPIRV_CROSS_VERSION}`;
|
|
113
133
|
|
|
114
134
|
function fail(message: string): never {
|
|
115
135
|
console.error(`xbintsc: ${message}`);
|
|
@@ -326,6 +346,17 @@ function freetypeArchive(): string | undefined {
|
|
|
326
346
|
function harfbuzzArchive(): string | undefined {
|
|
327
347
|
return builtLibrary(harfbuzzBuild, ["libharfbuzz.a", "harfbuzz.lib"], /^harfbuzz[-\d.]*\.lib$/);
|
|
328
348
|
}
|
|
349
|
+
function glslangArchive(): string | undefined {
|
|
350
|
+
return builtLibrary(join(glslangBuild, "glslang"), ["libglslang.a", "glslang.lib"]);
|
|
351
|
+
}
|
|
352
|
+
function glslangLimitsArchive(): string | undefined {
|
|
353
|
+
return builtLibrary(join(glslangBuild, "glslang"),
|
|
354
|
+
["libglslang-default-resource-limits.a", "glslang-default-resource-limits.lib"]);
|
|
355
|
+
}
|
|
356
|
+
/* SPIRV-Cross's MSL target pulls in its GLSL base class and the core module. */
|
|
357
|
+
function spirvCrossArchive(name: string): string | undefined {
|
|
358
|
+
return builtLibrary(spirvCrossBuild, [`lib${name}.a`, `${name}.lib`]);
|
|
359
|
+
}
|
|
329
360
|
|
|
330
361
|
/* -- 1. SDL3 source ------------------------------------------------------- */
|
|
331
362
|
|
|
@@ -434,6 +465,50 @@ if (!existsSync(harfbuzzArchive() ?? "")) {
|
|
|
434
465
|
console.log(`xbintsc: reusing existing ${harfbuzzArchive()}`);
|
|
435
466
|
}
|
|
436
467
|
|
|
468
|
+
/* -- 2c. glslang (WebGL GLSL ES -> SPIR-V) -------------------------------- */
|
|
469
|
+
|
|
470
|
+
ensureTarballSource("glslang", GLSLANG_URL, `glslang-${GLSLANG_VERSION}`);
|
|
471
|
+
ensureTarballSource(join("glslang", "External", "spirv-headers"), SPIRV_HEADERS_URL,
|
|
472
|
+
`SPIRV-Headers-${SPIRV_HEADERS_VERSION}`);
|
|
473
|
+
|
|
474
|
+
if (!existsSync(glslangArchive() ?? "")) {
|
|
475
|
+
const cmake = configureCmake("glslang", glslangSrc, glslangBuild, [
|
|
476
|
+
"-DCMAKE_BUILD_TYPE=Release",
|
|
477
|
+
"-DBUILD_SHARED_LIBS=OFF",
|
|
478
|
+
"-DENABLE_OPT=OFF",
|
|
479
|
+
"-DENABLE_HLSL=OFF",
|
|
480
|
+
"-DENABLE_GLSLANG_BINARIES=OFF",
|
|
481
|
+
"-DGLSLANG_TESTS=OFF",
|
|
482
|
+
]);
|
|
483
|
+
console.log("xbintsc: building static glslang");
|
|
484
|
+
run(cmake, ["--build", glslangBuild, "--config", "Release", "--parallel"]);
|
|
485
|
+
} else {
|
|
486
|
+
console.log(`xbintsc: reusing existing ${glslangArchive()}`);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/* -- 2d. SPIRV-Cross (SPIR-V -> Metal Shading Language) ------------------- */
|
|
490
|
+
|
|
491
|
+
ensureTarballSource("spirv-cross", SPIRV_CROSS_URL, `SPIRV-Cross-${SPIRV_CROSS_VERSION}`);
|
|
492
|
+
|
|
493
|
+
if (!existsSync(spirvCrossArchive("spirv-cross-msl") ?? "")) {
|
|
494
|
+
const cmake = configureCmake("SPIRV-Cross", spirvCrossSrc, spirvCrossBuild, [
|
|
495
|
+
"-DCMAKE_BUILD_TYPE=Release",
|
|
496
|
+
"-DSPIRV_CROSS_CLI=OFF",
|
|
497
|
+
"-DSPIRV_CROSS_ENABLE_TESTS=OFF",
|
|
498
|
+
/* Only the MSL target is used; skip the C++, HLSL, reflection and C APIs
|
|
499
|
+
* so the archive stays small. MSL links against the GLSL base class. */
|
|
500
|
+
"-DSPIRV_CROSS_ENABLE_HLSL=OFF",
|
|
501
|
+
"-DSPIRV_CROSS_ENABLE_CPP=OFF",
|
|
502
|
+
"-DSPIRV_CROSS_ENABLE_REFLECT=OFF",
|
|
503
|
+
"-DSPIRV_CROSS_ENABLE_UTIL=OFF",
|
|
504
|
+
"-DSPIRV_CROSS_ENABLE_C_API=OFF",
|
|
505
|
+
]);
|
|
506
|
+
console.log("xbintsc: building static SPIRV-Cross");
|
|
507
|
+
run(cmake, ["--build", spirvCrossBuild, "--config", "Release", "--parallel"]);
|
|
508
|
+
} else {
|
|
509
|
+
console.log(`xbintsc: reusing existing ${spirvCrossArchive("spirv-cross-msl")}`);
|
|
510
|
+
}
|
|
511
|
+
|
|
437
512
|
/* -- 3. engine objects ---------------------------------------------------- */
|
|
438
513
|
|
|
439
514
|
mkdirSync(objDir, { recursive: true });
|
|
@@ -443,6 +518,9 @@ const includeFlags = [
|
|
|
443
518
|
"-I", join(freetypeSrc, "include"),
|
|
444
519
|
"-I", join(freetypeBuild, "include"),
|
|
445
520
|
"-I", join(harfbuzzSrc, "src"),
|
|
521
|
+
"-I", glslangSrc,
|
|
522
|
+
"-I", join(spirvHeadersSrc, "include"),
|
|
523
|
+
"-I", spirvCrossSrc,
|
|
446
524
|
];
|
|
447
525
|
const sources = readdirSync(engineDir)
|
|
448
526
|
.filter((entry) => entry.endsWith(".cpp"))
|
|
@@ -470,10 +548,19 @@ for (const source of sources) {
|
|
|
470
548
|
const sdl = sdlArchive();
|
|
471
549
|
const freetype = freetypeArchive();
|
|
472
550
|
const harfbuzz = harfbuzzArchive();
|
|
473
|
-
|
|
474
|
-
|
|
551
|
+
const glslang = glslangArchive();
|
|
552
|
+
const glslangLimits = glslangLimitsArchive();
|
|
553
|
+
const spirvCrossCore = spirvCrossArchive("spirv-cross-core");
|
|
554
|
+
const spirvCrossGlsl = spirvCrossArchive("spirv-cross-glsl");
|
|
555
|
+
const spirvCrossMsl = spirvCrossArchive("spirv-cross-msl");
|
|
556
|
+
if (!sdl || !freetype || !harfbuzz || !glslang || !glslangLimits ||
|
|
557
|
+
!spirvCrossCore || !spirvCrossGlsl || !spirvCrossMsl) {
|
|
558
|
+
fail("one of the SDL3/FreeType/HarfBuzz/glslang/SPIRV-Cross archives was not found after building");
|
|
475
559
|
}
|
|
476
|
-
const libraries = [
|
|
560
|
+
const libraries = [
|
|
561
|
+
sdl, freetype, harfbuzz, glslang, glslangLimits,
|
|
562
|
+
spirvCrossCore, spirvCrossGlsl, spirvCrossMsl,
|
|
563
|
+
];
|
|
477
564
|
|
|
478
565
|
mkdirSync(outDir, { recursive: true });
|
|
479
566
|
rmSync(output, { force: true });
|
package/scripts/build-media.ts
CHANGED
|
@@ -2,38 +2,53 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Build the media extension archive:
|
|
4
4
|
*
|
|
5
|
-
* runtime/lib/<os>-<arch>/media.a
|
|
5
|
+
* runtime/lib/<os>-<arch>/media.a (POSIX: ELF/Mach-O objects)
|
|
6
|
+
* runtime/lib/<os>-<arch>/media.lib (Windows: MSVC/COFF objects)
|
|
6
7
|
*
|
|
7
|
-
* The GUI engine (`gui.a`) deliberately contains no decoder. This
|
|
8
|
-
* `<video>`/`<audio>` support: it bundles the FFmpeg-backed player
|
|
9
|
-
* `runtime/ext_media/media.cpp` together with a minimal static FFmpeg, and
|
|
10
|
-
* `media` extension links it only when the program asks for it. A program
|
|
11
|
-
* with `--ext gui` alone therefore stays FFmpeg-free.
|
|
8
|
+
* The GUI engine (`gui.a` / `gui.lib`) deliberately contains no decoder. This
|
|
9
|
+
* archive adds `<video>`/`<audio>` support: it bundles the FFmpeg-backed player
|
|
10
|
+
* from `runtime/ext_media/media.cpp` together with a minimal static FFmpeg, and
|
|
11
|
+
* the `media` extension links it only when the program asks for it. A program
|
|
12
|
+
* built with `--ext gui` alone therefore stays FFmpeg-free.
|
|
12
13
|
*
|
|
13
14
|
* Steps:
|
|
14
15
|
* 1. fetch the pinned FFmpeg release tarball into `vendor/ffmpeg`,
|
|
15
16
|
* 2. configure and build a minimal static FFmpeg into
|
|
16
17
|
* `vendor/ffmpeg-build/dist` (reused on later runs),
|
|
17
18
|
* 3. compile the player against those headers,
|
|
18
|
-
* 4. merge the player object and the FFmpeg libraries into
|
|
19
|
-
* (libtool on macOS, `ar -M` elsewhere).
|
|
19
|
+
* 4. merge the player object and the FFmpeg libraries into the archive
|
|
20
|
+
* (libtool on macOS, `ar -M`/`llvm-ar -M` elsewhere).
|
|
21
|
+
*
|
|
22
|
+
* Windows uses FFmpeg's own MSVC toolchain mode: `configure --toolchain=msvc
|
|
23
|
+
* --cc=clang-cl` produces COFF objects compiled against the static MSVC CRT,
|
|
24
|
+
* which is the ABI `gui.lib`, the xbintsc runtime and the final link use. The
|
|
25
|
+
* compiler chain is entirely Visual Studio (clang-cl, cl.exe, lib.exe and
|
|
26
|
+
* llvm-ar); no additional C/C++ toolchain is involved.
|
|
27
|
+
*
|
|
28
|
+
* FFmpeg's `configure` is a POSIX shell script and its Makefiles require GNU
|
|
29
|
+
* make, so those two build drivers remain. The shell comes from Git for Windows
|
|
30
|
+
* (already required to clone SDL3), and make is a native GNU make on PATH or
|
|
31
|
+
* `xbintsc_MAKE`; no additional POSIX environment is required. Because native
|
|
32
|
+
* make cannot pass the MSVC `/showIncludes` awk pipeline through the Windows
|
|
33
|
+
* command line unchanged, the generated `SRC_PATH` is rewritten to a
|
|
34
|
+
* drive-letter path and dependency generation is skipped. Headers/libraries are
|
|
35
|
+
* copied into the prefix instead of running `make install`.
|
|
20
36
|
*
|
|
21
37
|
* Environment:
|
|
22
38
|
* xbintsc_CXX C++ compiler override (default: clang++ next to clang)
|
|
23
39
|
* xbintsc_AR archiver override (default: llvm-ar next to clang, then ar)
|
|
40
|
+
* xbintsc_SHELL POSIX shell override (Windows; default: Git for Windows bash)
|
|
41
|
+
* xbintsc_MAKE GNU make override (Windows; default: `make` on PATH)
|
|
24
42
|
* FFMPEG_VERSION FFmpeg release (default: 7.1)
|
|
25
|
-
*
|
|
26
|
-
* Windows is not supported yet: FFmpeg needs its own `configure`/`make`, and an
|
|
27
|
-
* MSVC-compatible build has not been produced (see `doc/gui/known-issues.md`).
|
|
28
43
|
*/
|
|
29
44
|
|
|
30
|
-
import { existsSync, mkdirSync, renameSync, rmSync } from "node:fs";
|
|
45
|
+
import { copyFileSync, existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
31
46
|
import { availableParallelism } from "node:os";
|
|
32
47
|
import { spawnSync, type SpawnSyncReturns } from "node:child_process";
|
|
33
48
|
import { dirname, join, resolve } from "node:path";
|
|
34
49
|
import { fileURLToPath } from "node:url";
|
|
35
50
|
import { platformSlug } from "../src/driver/paths.js";
|
|
36
|
-
import { probeClang, realRunner } from "../src/driver/toolchain.js";
|
|
51
|
+
import { isMsvcTarget, probeClang, realRunner } from "../src/driver/toolchain.js";
|
|
37
52
|
import { resolveToolchain } from "../src/driver/toolchain-provider.js";
|
|
38
53
|
|
|
39
54
|
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
@@ -41,11 +56,16 @@ const runtimeDir = join(root, "runtime");
|
|
|
41
56
|
const sourceDir = join(runtimeDir, "ext_media");
|
|
42
57
|
const vendorDir = join(root, "vendor");
|
|
43
58
|
const ffmpegSrc = join(vendorDir, "ffmpeg");
|
|
44
|
-
const
|
|
59
|
+
const isWindows = process.platform === "win32";
|
|
60
|
+
/* The MSVC configure/build tree is kept apart from the POSIX one: a shared tree
|
|
61
|
+
* would carry `CC=clang`/`CC=clang-cl` and a POSIX/Windows `SRC_PATH` from the
|
|
62
|
+
* other platform into the next configure. */
|
|
63
|
+
const ffmpegBuild = join(vendorDir, isWindows ? "ffmpeg-build-msvc" : "ffmpeg-build");
|
|
45
64
|
const ffmpegInstall = join(ffmpegBuild, "dist");
|
|
46
65
|
const objDir = join(root, "build", "media-obj");
|
|
47
66
|
const outDir = join(runtimeDir, "lib", platformSlug());
|
|
48
|
-
const output = join(outDir, "media.a");
|
|
67
|
+
const output = join(outDir, isWindows ? "media.lib" : "media.a");
|
|
68
|
+
const object = join(objDir, isWindows ? "media.obj" : "media.o");
|
|
49
69
|
|
|
50
70
|
const FFMPEG_VERSION = process.env.FFMPEG_VERSION || "7.1";
|
|
51
71
|
const FFMPEG_URL = `https://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.xz`;
|
|
@@ -74,7 +94,7 @@ function fail(message: string): never {
|
|
|
74
94
|
function run(
|
|
75
95
|
command: string,
|
|
76
96
|
args: readonly string[],
|
|
77
|
-
options: { input?: string; quietStderr?: boolean; cwd?: string } = {},
|
|
97
|
+
options: { input?: string; quietStderr?: boolean; cwd?: string; env?: NodeJS.ProcessEnv } = {},
|
|
78
98
|
): SpawnSyncReturns<string> {
|
|
79
99
|
const quiet = options.quietStderr === true;
|
|
80
100
|
const result = spawnSync(command, args, {
|
|
@@ -82,6 +102,7 @@ function run(
|
|
|
82
102
|
encoding: "utf8",
|
|
83
103
|
input: options.input,
|
|
84
104
|
cwd: options.cwd,
|
|
105
|
+
env: options.env,
|
|
85
106
|
});
|
|
86
107
|
if (result.status !== 0) {
|
|
87
108
|
if (quiet && result.stderr) process.stderr.write(result.stderr);
|
|
@@ -104,7 +125,7 @@ function firstAvailable(candidates: readonly (string | undefined)[]): string | u
|
|
|
104
125
|
/** The tool that sits next to `clang` in the same LLVM installation. */
|
|
105
126
|
function siblingTool(clangPath: string, name: string): string | undefined {
|
|
106
127
|
if (!clangPath.includes("/") && !clangPath.includes("\\")) return undefined;
|
|
107
|
-
const candidate = join(dirname(clangPath), `${name}.exe`);
|
|
128
|
+
const candidate = join(dirname(clangPath), `${name}${isWindows ? ".exe" : ""}`);
|
|
108
129
|
if (existsSync(candidate)) return candidate;
|
|
109
130
|
const bare = join(dirname(clangPath), name);
|
|
110
131
|
return existsSync(bare) ? bare : undefined;
|
|
@@ -116,6 +137,12 @@ function findClangxx(clangPath: string): string {
|
|
|
116
137
|
if (override) {
|
|
117
138
|
const probe = probeClang(realRunner, override);
|
|
118
139
|
if (!probe.responds) fail(`xbintsc_CXX ${override} does not respond to --version`);
|
|
140
|
+
if (isWindows && (probe.version === undefined || (probe.target !== undefined && !isMsvcTarget(probe.target)))) {
|
|
141
|
+
fail(
|
|
142
|
+
`xbintsc_CXX ${override} is not an MSVC-targeting clang++ (target ${probe.target ?? "unknown"}); ` +
|
|
143
|
+
"the Windows media build requires one, for example x86_64-pc-windows-msvc.",
|
|
144
|
+
);
|
|
145
|
+
}
|
|
119
146
|
return override;
|
|
120
147
|
}
|
|
121
148
|
const sibling = siblingTool(clangPath, "clang++");
|
|
@@ -128,7 +155,9 @@ function findClangxx(clangPath: string): string {
|
|
|
128
155
|
/** Resolve the archiver that matches the compiler, preferring LLVM's own. */
|
|
129
156
|
function findArchiver(clangPath: string): string {
|
|
130
157
|
const sibling = siblingTool(clangPath, "llvm-ar");
|
|
131
|
-
|
|
158
|
+
/* Windows always uses llvm-ar: a non-LLVM `ar` there may write a different
|
|
159
|
+
* archive flavour than the COFF one the linker wants. */
|
|
160
|
+
const archiver = firstAvailable([process.env.xbintsc_AR, sibling, "llvm-ar", isWindows ? undefined : "ar"]);
|
|
132
161
|
if (!archiver) fail("no archiver found; install llvm-ar or set xbintsc_AR");
|
|
133
162
|
return archiver;
|
|
134
163
|
}
|
|
@@ -161,47 +190,284 @@ function ffmpegStaticLibraries(): string[] | undefined {
|
|
|
161
190
|
return libraries.every((library) => existsSync(library)) ? libraries : undefined;
|
|
162
191
|
}
|
|
163
192
|
|
|
164
|
-
|
|
193
|
+
/** True when `dist` holds both the libraries and the installed headers. */
|
|
194
|
+
function ffmpegInstalled(): boolean {
|
|
195
|
+
return ffmpegStaticLibraries() !== undefined && existsSync(join(ffmpegInstall, "include", "libavutil", "avutil.h"));
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/** Arguments shared by the POSIX and Windows FFmpeg configure runs. */
|
|
199
|
+
function ffmpegConfigureArgs(): string[] {
|
|
200
|
+
const prefix = isWindows ? ffmpegInstall.replace(/\\/g, "/") : ffmpegInstall;
|
|
201
|
+
const args = [
|
|
202
|
+
`--prefix=${prefix}`,
|
|
203
|
+
"--enable-static", "--disable-shared",
|
|
204
|
+
"--disable-programs", "--disable-doc",
|
|
205
|
+
"--disable-htmlpages", "--disable-manpages", "--disable-podpages", "--disable-txtpages",
|
|
206
|
+
"--disable-avdevice", "--disable-avfilter", "--disable-postproc",
|
|
207
|
+
"--disable-everything",
|
|
208
|
+
"--enable-avformat", "--enable-avcodec", "--enable-avutil", "--enable-swscale", "--enable-swresample",
|
|
209
|
+
"--disable-network", "--disable-autodetect", "--disable-x86asm", "--disable-debug",
|
|
210
|
+
...FFMPEG_COMPONENTS,
|
|
211
|
+
];
|
|
212
|
+
/* `-fPIC` is meaningless to the MSVC ABI; FFmpeg's msvc flag filter drops it,
|
|
213
|
+
* but omitting it keeps the configuration honest. */
|
|
214
|
+
if (!isWindows) args.splice(2, 0, "--enable-pic");
|
|
215
|
+
return args;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/* -- Windows: a POSIX shell + GNU make driving clang-cl -------------------- */
|
|
219
|
+
|
|
220
|
+
/** Drive-letter path in the `/d/dir/file` form the POSIX shell and configure use. */
|
|
221
|
+
function toPosixPath(path: string): string {
|
|
222
|
+
const absolute = resolve(path);
|
|
223
|
+
const match = /^([A-Za-z]):[\\/](.*)$/.exec(absolute);
|
|
224
|
+
if (!match) return absolute.replace(/\\/g, "/");
|
|
225
|
+
return `/${match[1].toLowerCase()}/${match[2].replace(/\\/g, "/")}`;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/** `D:\dir` form for the native make parser (it does not understand `/d/dir`). */
|
|
229
|
+
function toWindowsPath(path: string): string {
|
|
230
|
+
return resolve(path).replace(/\\/g, "/");
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/** Quote one word for a POSIX shell command line built by hand. */
|
|
234
|
+
function shellQuote(word: string): string {
|
|
235
|
+
return `'${word.replace(/'/g, `'\\''`)}'`;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/** Git for Windows' bash, which supplies the POSIX shell FFmpeg's configure needs. */
|
|
239
|
+
function findPosixShell(): string {
|
|
240
|
+
const programFiles = process.env.ProgramFiles ?? "C:\\Program Files";
|
|
241
|
+
const localAppData = process.env.LOCALAPPDATA ?? "";
|
|
242
|
+
const git = resolveOnPath("git");
|
|
243
|
+
const candidates = [
|
|
244
|
+
process.env.xbintsc_SHELL,
|
|
245
|
+
git ? resolve(dirname(git), "..", "bin", "bash.exe") : undefined,
|
|
246
|
+
join(programFiles, "Git", "bin", "bash.exe"),
|
|
247
|
+
join(localAppData, "Programs", "Git", "bin", "bash.exe"),
|
|
248
|
+
join(programFiles, "Git", "usr", "bin", "bash.exe"),
|
|
249
|
+
].filter((candidate): candidate is string => Boolean(candidate));
|
|
250
|
+
const shell = firstAvailable(candidates);
|
|
251
|
+
if (!shell) {
|
|
252
|
+
fail(
|
|
253
|
+
"the Windows media build needs a POSIX shell to run FFmpeg's configure; " +
|
|
254
|
+
"install Git for Windows (which also supplies git) or set xbintsc_SHELL.",
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
return shell;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/** First match for `name` on PATH, as an absolute path. */
|
|
261
|
+
function resolveOnPath(name: string): string | undefined {
|
|
262
|
+
const result = spawnSync("where.exe", [name], { encoding: "utf8" });
|
|
263
|
+
if (result.status !== 0) return undefined;
|
|
264
|
+
return result.stdout.split(/\r?\n/).map((line) => line.trim()).find((line) => line.length > 0);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/** Native GNU make to drive the FFmpeg build. */
|
|
268
|
+
function findWindowsMake(): string {
|
|
269
|
+
const candidates = [process.env.xbintsc_MAKE, resolveOnPath("make")].filter(
|
|
270
|
+
(candidate): candidate is string => Boolean(candidate),
|
|
271
|
+
);
|
|
272
|
+
for (const candidate of candidates) {
|
|
273
|
+
if (isRunnable(candidate)) return candidate;
|
|
274
|
+
}
|
|
275
|
+
fail(
|
|
276
|
+
"the Windows media build needs GNU make to run FFmpeg's Makefile; install it " +
|
|
277
|
+
"(`choco install make`) or set xbintsc_MAKE to a GNU make binary.",
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/** Resolve `clang-cl` from the same LLVM as the driver's clang. */
|
|
282
|
+
function findClangCl(clangPath: string): string {
|
|
283
|
+
const sibling = siblingTool(clangPath, "clang-cl");
|
|
284
|
+
if (sibling) return sibling;
|
|
285
|
+
const onPath = resolveOnPath("clang-cl");
|
|
286
|
+
if (onPath) return onPath;
|
|
287
|
+
fail(
|
|
288
|
+
`no clang-cl found next to ${clangPath} or on PATH; the Windows media build needs the LLVM bundled ` +
|
|
289
|
+
"with Visual Studio (VC\\Tools\\Llvm\\<arch>\\bin\\clang-cl.exe) so FFmpeg can use the MSVC ABI.",
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/** Installation path reported by `vswhere`, when it is available. */
|
|
294
|
+
function vswhereInstallation(): string | undefined {
|
|
295
|
+
const programFilesX86 = process.env["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)";
|
|
296
|
+
const vswhere = join(programFilesX86, "Microsoft Visual Studio", "Installer", "vswhere.exe");
|
|
297
|
+
if (!existsSync(vswhere)) return undefined;
|
|
298
|
+
const result = spawnSync(
|
|
299
|
+
vswhere,
|
|
300
|
+
[
|
|
301
|
+
"-latest", "-products", "*",
|
|
302
|
+
"-requires", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64",
|
|
303
|
+
"-property", "installationPath",
|
|
304
|
+
],
|
|
305
|
+
{ encoding: "utf8" },
|
|
306
|
+
);
|
|
307
|
+
const root = result.status === 0 ? result.stdout.split(/\r?\n/)[0]?.trim() : undefined;
|
|
308
|
+
return root && existsSync(root) ? root : undefined;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/** Directory holding `cl.exe` (and `lib.exe`), which FFmpeg's msvc toolchain probes. */
|
|
312
|
+
function findMsvcBin(clangPath: string): string {
|
|
313
|
+
const roots = [process.env.ProgramFiles, process.env["ProgramFiles(x86)"], process.env.ProgramW6432]
|
|
314
|
+
.filter((root): root is string => Boolean(root));
|
|
315
|
+
/* A clang from Visual Studio's own LLVM names the installation it belongs to;
|
|
316
|
+
* vswhere covers a clang from a separate LLVM when VS is installed elsewhere. */
|
|
317
|
+
const fromClang = /^(.*[\\/]Microsoft Visual Studio[\\/]\d{4}[\\/][^\\/]+)[\\/]VC[\\/]Tools[\\/]Llvm[\\/]/i.exec(
|
|
318
|
+
clangPath,
|
|
319
|
+
)?.[1];
|
|
320
|
+
const fromVswhere = vswhereInstallation();
|
|
321
|
+
const msvcDirs: string[] = [];
|
|
322
|
+
for (const extra of [fromClang, fromVswhere]) {
|
|
323
|
+
if (extra) msvcDirs.push(join(extra, "VC", "Tools", "MSVC"));
|
|
324
|
+
}
|
|
325
|
+
for (const root of roots) {
|
|
326
|
+
for (const year of ["2022", "2019"]) {
|
|
327
|
+
for (const edition of ["BuildTools", "Community", "Professional", "Enterprise"]) {
|
|
328
|
+
msvcDirs.push(join(root, "Microsoft Visual Studio", year, edition, "VC", "Tools", "MSVC"));
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
const host = process.arch === "arm64" ? "Hostarm64" : "Hostx64";
|
|
333
|
+
const target = process.arch === "arm64" ? "arm64" : "x64";
|
|
334
|
+
for (const msvc of msvcDirs) {
|
|
335
|
+
if (!existsSync(msvc)) continue;
|
|
336
|
+
const versions = readdirSync(msvc).sort((a, b) => b.localeCompare(a, undefined, { numeric: true }));
|
|
337
|
+
for (const version of versions) {
|
|
338
|
+
const bin = join(msvc, version, "bin", host, target);
|
|
339
|
+
if (existsSync(join(bin, "cl.exe"))) return bin;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
165
342
|
fail(
|
|
166
|
-
"the media
|
|
167
|
-
"
|
|
343
|
+
"the Windows media build needs the MSVC C++ toolchain (FFmpeg's configure probes cl.exe/lib.exe); " +
|
|
344
|
+
"install the 'Desktop development with C++' workload in Visual Studio or the Build Tools.",
|
|
168
345
|
);
|
|
169
346
|
}
|
|
170
347
|
|
|
348
|
+
interface WindowsBuildTools {
|
|
349
|
+
readonly shell: string;
|
|
350
|
+
readonly make: string;
|
|
351
|
+
readonly env: NodeJS.ProcessEnv;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/** Environment for configure/make: the resolved clang-cl and MSVC tools first. */
|
|
355
|
+
function windowsBuildEnv(shell: string, clangCl: string, msvcBin: string): NodeJS.ProcessEnv {
|
|
356
|
+
const env: NodeJS.ProcessEnv = { ...process.env };
|
|
357
|
+
const pathKey = Object.keys(env).find((key) => key.toUpperCase() === "PATH") ?? "Path";
|
|
358
|
+
const usrBin = resolve(dirname(shell), "..", "usr", "bin");
|
|
359
|
+
const parts = [dirname(clangCl), msvcBin, existsSync(usrBin) ? usrBin : "", env[pathKey] ?? ""];
|
|
360
|
+
env[pathKey] = parts.filter((part) => part.length > 0).join(";");
|
|
361
|
+
return env;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/** Rewrite the POSIX `SRC_PATH` configure wrote so a native make can parse it. */
|
|
365
|
+
function patchNativeMakePaths(): void {
|
|
366
|
+
const posixSource = toPosixPath(ffmpegSrc);
|
|
367
|
+
const posixInstall = toPosixPath(ffmpegInstall);
|
|
368
|
+
for (const file of [join(ffmpegBuild, "Makefile"), join(ffmpegBuild, "ffbuild", "config.mak")]) {
|
|
369
|
+
if (!existsSync(file)) continue;
|
|
370
|
+
const patched = readFileSync(file, "utf8")
|
|
371
|
+
.split(posixSource).join(toWindowsPath(ffmpegSrc))
|
|
372
|
+
.split(posixInstall).join(toWindowsPath(ffmpegInstall));
|
|
373
|
+
writeFileSync(file, patched);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/** Copy every public `.h` under `source` into `destination`, recursively. */
|
|
378
|
+
function copyHeaders(source: string, destination: string): void {
|
|
379
|
+
mkdirSync(destination, { recursive: true });
|
|
380
|
+
for (const entry of readdirSync(source, { withFileTypes: true })) {
|
|
381
|
+
const from = join(source, entry.name);
|
|
382
|
+
const to = join(destination, entry.name);
|
|
383
|
+
if (entry.isDirectory()) {
|
|
384
|
+
copyHeaders(from, to);
|
|
385
|
+
} else if (entry.isFile() && entry.name.endsWith(".h")) {
|
|
386
|
+
copyFileSync(from, to);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/** Copy FFmpeg headers and static libraries into the `dist` prefix. */
|
|
392
|
+
function installFfmpegWindows(): void {
|
|
393
|
+
const includeDir = join(ffmpegInstall, "include");
|
|
394
|
+
for (const name of FFMPEG_LIBRARY_NAMES) {
|
|
395
|
+
const library = name.replace(/\.a$/, "");
|
|
396
|
+
copyHeaders(join(ffmpegSrc, library), join(includeDir, library));
|
|
397
|
+
}
|
|
398
|
+
/* Generated headers live in the build tree, not in the sources. */
|
|
399
|
+
for (const generated of ["avconfig.h", "ffversion.h"]) {
|
|
400
|
+
const from = join(ffmpegBuild, "libavutil", generated);
|
|
401
|
+
if (existsSync(from)) copyFileSync(from, join(includeDir, "libavutil", generated));
|
|
402
|
+
}
|
|
403
|
+
const libDir = join(ffmpegInstall, "lib");
|
|
404
|
+
mkdirSync(libDir, { recursive: true });
|
|
405
|
+
for (const name of FFMPEG_LIBRARY_NAMES) {
|
|
406
|
+
copyFileSync(join(ffmpegBuild, name.replace(/\.a$/, ""), name), join(libDir, name));
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
function buildFfmpegWindows(shell: string, clangCl: string, msvcBin: string): void {
|
|
411
|
+
const make = findWindowsMake();
|
|
412
|
+
const tools: WindowsBuildTools = {
|
|
413
|
+
shell,
|
|
414
|
+
make,
|
|
415
|
+
env: windowsBuildEnv(shell, clangCl, msvcBin),
|
|
416
|
+
};
|
|
417
|
+
console.log(`xbintsc: configuring FFmpeg ${FFMPEG_VERSION} for the MSVC ABI with clang-cl`);
|
|
418
|
+
mkdirSync(ffmpegBuild, { recursive: true });
|
|
419
|
+
run(tools.shell, [
|
|
420
|
+
toPosixPath(join(ffmpegSrc, "configure")),
|
|
421
|
+
"--toolchain=msvc",
|
|
422
|
+
"--cc=clang-cl", "--cxx=clang-cl", "--ld=clang-cl", "--ar=lib.exe",
|
|
423
|
+
...ffmpegConfigureArgs(),
|
|
424
|
+
], { cwd: ffmpegBuild, env: tools.env });
|
|
425
|
+
|
|
426
|
+
/* Native make cannot pass FFmpeg's `/showIncludes` awk pipeline (the MSVC
|
|
427
|
+
* backslash escapes are consumed by the Windows command line); the `.d` files
|
|
428
|
+
* only affect incremental rebuilds, so generation is skipped. The source path
|
|
429
|
+
* configure wrote is POSIX-shaped and is rewritten for native make. */
|
|
430
|
+
patchNativeMakePaths();
|
|
431
|
+
const depOverrides = " CCDEP=true CXXDEP=true ASDEP=true HOSTCCDEP=true";
|
|
432
|
+
console.log(`xbintsc: building minimal static FFmpeg ${FFMPEG_VERSION} with clang-cl`);
|
|
433
|
+
run(tools.shell, ["-lc", `${shellQuote(tools.make)} -j ${availableParallelism()}${depOverrides}`], {
|
|
434
|
+
cwd: ffmpegBuild,
|
|
435
|
+
env: tools.env,
|
|
436
|
+
});
|
|
437
|
+
installFfmpegWindows();
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/* -- 1. FFmpeg source ------------------------------------------------------ */
|
|
441
|
+
|
|
442
|
+
ensureFfmpegSource();
|
|
443
|
+
|
|
171
444
|
/* One toolchain for the player and FFmpeg: the same clang the driver uses, its
|
|
172
445
|
* sibling clang++, and the matching llvm-ar. Mixing another C++ runtime or
|
|
173
446
|
* object format would break the final link. */
|
|
174
447
|
const clang = driverClang();
|
|
175
448
|
const clangxx = findClangxx(clang);
|
|
176
449
|
const archiver = findArchiver(clang);
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
450
|
+
const windowsTools = isWindows
|
|
451
|
+
? {
|
|
452
|
+
shell: findPosixShell(),
|
|
453
|
+
clangCl: findClangCl(clang),
|
|
454
|
+
msvcBin: findMsvcBin(clang),
|
|
455
|
+
}
|
|
456
|
+
: undefined;
|
|
181
457
|
|
|
182
458
|
/* -- 2. minimal static FFmpeg --------------------------------------------- */
|
|
183
459
|
|
|
184
|
-
|
|
185
|
-
if (
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
"
|
|
192
|
-
"
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
"--enable-avformat", "--enable-avcodec", "--enable-avutil", "--enable-swscale", "--enable-swresample",
|
|
196
|
-
"--disable-network", "--disable-autodetect", "--disable-x86asm", "--disable-debug", "--enable-pic",
|
|
197
|
-
`--cc=${clang}`,
|
|
198
|
-
`--cxx=${clangxx}`,
|
|
199
|
-
...FFMPEG_COMPONENTS,
|
|
200
|
-
], { cwd: ffmpegBuild });
|
|
201
|
-
run("make", ["-j", String(availableParallelism())], { cwd: ffmpegBuild });
|
|
202
|
-
run("make", ["install"], { cwd: ffmpegBuild });
|
|
203
|
-
ffmpegLibraries = ffmpegStaticLibraries();
|
|
204
|
-
if (!ffmpegLibraries) fail("FFmpeg build did not produce the expected static libraries");
|
|
460
|
+
if (!ffmpegInstalled()) {
|
|
461
|
+
if (windowsTools) {
|
|
462
|
+
buildFfmpegWindows(windowsTools.shell, windowsTools.clangCl, windowsTools.msvcBin);
|
|
463
|
+
} else {
|
|
464
|
+
console.log(`xbintsc: building minimal static FFmpeg ${FFMPEG_VERSION} with ${clang}`);
|
|
465
|
+
mkdirSync(ffmpegBuild, { recursive: true });
|
|
466
|
+
run(join(ffmpegSrc, "configure"), ffmpegConfigureArgs(), { cwd: ffmpegBuild });
|
|
467
|
+
run("make", ["-j", String(availableParallelism())], { cwd: ffmpegBuild });
|
|
468
|
+
run("make", ["install"], { cwd: ffmpegBuild });
|
|
469
|
+
}
|
|
470
|
+
if (!ffmpegInstalled()) fail("FFmpeg build did not produce the expected static libraries");
|
|
205
471
|
} else {
|
|
206
472
|
console.log(`xbintsc: reusing existing ${ffmpegInstall}/lib`);
|
|
207
473
|
}
|
|
@@ -212,30 +478,29 @@ if (!ffmpegLibraries) {
|
|
|
212
478
|
* because the *source* root contains a file literally named `version` that
|
|
213
479
|
* would shadow the C++ standard header for any `.cpp` that includes it. */
|
|
214
480
|
mkdirSync(objDir, { recursive: true });
|
|
215
|
-
const object = join(objDir, "media.o");
|
|
216
481
|
const playerSource = join(sourceDir, "media.cpp");
|
|
217
482
|
console.log("xbintsc: compiling media.cpp");
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
]);
|
|
483
|
+
const cxxFlags = ["-std=c++17", "-O2", "-Wall", "-Wextra", "-I", runtimeDir, "-I", join(ffmpegInstall, "include")];
|
|
484
|
+
/* The engine and the player are C++ with the static CRT (`libcpmt`), matching
|
|
485
|
+
* FFmpeg's clang-cl objects and the xbintsc runtime; see `scripts/build-gui.ts`. */
|
|
486
|
+
if (isWindows) cxxFlags.push("-Xclang", "--dependent-lib=libcpmt");
|
|
487
|
+
else cxxFlags.push("-fPIC");
|
|
488
|
+
run(clangxx, [...cxxFlags, "-c", playerSource, "-o", object]);
|
|
225
489
|
|
|
226
|
-
/* -- 4. merge into
|
|
490
|
+
/* -- 4. merge into the archive -------------------------------------------- */
|
|
227
491
|
|
|
228
492
|
mkdirSync(outDir, { recursive: true });
|
|
229
493
|
rmSync(output, { force: true });
|
|
230
494
|
if (process.platform === "darwin") {
|
|
231
|
-
run("libtool", ["-static", "-o", output, object, ...
|
|
495
|
+
run("libtool", ["-static", "-o", output, object, ...ffmpegStaticLibraries()!], { quietStderr: true });
|
|
232
496
|
} else {
|
|
233
|
-
/* `ar -M` (GNU/LLVM) merges archives through an MRI script.
|
|
497
|
+
/* `ar -M` (GNU/LLVM) merges archives through an MRI script. Windows paths are
|
|
498
|
+
* normalised to `/` so the MRI parser does not read `\` as an escape. */
|
|
234
499
|
const mri = (path: string): string => path.replace(/\\/g, "/");
|
|
235
500
|
const script = [
|
|
236
501
|
`create ${mri(output)}`,
|
|
237
502
|
`addmod ${mri(object)}`,
|
|
238
|
-
...
|
|
503
|
+
...ffmpegStaticLibraries()!.map((library) => `addlib ${mri(library)}`),
|
|
239
504
|
"save",
|
|
240
505
|
"end",
|
|
241
506
|
].join("\n");
|