FoxDev StudioFor Visual FoxPro 9 applications
Start here

Required tooling

What a machine needs to run FoxDev Studio, and what it needs to build the IDE, the virtual machine and the native pieces from source.

To run the IDE

Nothing beyond the package. The installer carries Electron, the compiled WebAssembly module and the native pieces, and the runtime a built application ships with is the same set of files.

Two of the pieces are Windows-only, because what they reach only exists there, and on another platform the runtime says so by name instead of failing as something else:

Piece What it is for Where it works
foxole.node COM automation: CREATEOBJECT("Excel.Application") and everything like it, through the foxole addon. Windows
fllhost.exe SET LIBRARY TO: a 32-bit process that holds a Visual FoxPro .fll and answers calls from the 64-bit runtime. Windows, and only where the Visual C++ 7.1 runtimes beside it can load.
koffi DECLARE ... DLL: a 64-bit library called in the same process. Everywhere the library itself runs.

Everything else - the compiler, the VM, the data engine, the designers, the HTTP server - is the same on every platform.

To build from source

The repository is github.com/FoxDevCommunity/FoxDevStudio. The build is driven by npm scripts, and each native piece is rebuilt only when its sources are newer than its output, so a checkout that has not touched Rust builds nothing in Rust.

Always

Tool Version Why
Node.js 24 The IDE is Electron 44 and the scripts are ES modules. The data engine's 64-bit offsets were verified on Node 24.
npm 11 Ships with Node. npm install fetches wasm-pack as a package, so there is nothing else to fetch for the wasm build.
Rust stable, with the wasm32-unknown-unknown target rust-toolchain.toml pins the channel and names the target; rustup reads it and installs both. The crate edition is 2024.

On Windows, for the native pieces

Tool Why
Visual Studio with the "Desktop development with C++" workload, x86 and x64 tools fllhost.exe is built for x86 with cl.exe, because every Visual FoxPro library is a 32-bit image whatever the machine is. foxole.node is a Rust cdylib built for x64. The build finds Visual Studio through vswhere and asks vcvarsall.bat for the x86 environment, so no shell setup is needed.
Visual FoxPro 9 Optional. Where vfp9.exe is present, the tests can ask it for the answers the runtime is measured against, and the library host can be built against Microsoft's own API samples. Without it the checked-in answers are used.

Without Visual C++, the two native builds print what they are skipping and exit cleanly. The IDE, the VM and every test that does not need COM or an .fll run as before. GitHub's Windows runner has the C++ tools, so the nightlies and releases carry both native pieces; the Visual C++ 7.1 runtimes the library host ships beside it are tracked in the repository, because no runner has a Visual FoxPro to take them from.

The commands

npm install
npm run dev          # Electron with hot reload
npm test             # Vitest + jsdom: the primary verification, no display needed
npm run typecheck
npm run lint
npm run build        # production bundles into out/
npm run package      # installers into release/ (Linux targets under WSL2)
npm run build:wasm   # rebuild the Rust VM (automatic when the crate changes)
npm run test:rust    # cargo test for the compiler and VM
npm run check        # typecheck + lint + vitest + cargo test + the argument-form check

npm run dev, npm run build and npm test run ensure-native first, which is the three ensure-* scripts in turn: wasm, then the COM addon, then the library host.

What the wasm build does

scripts/build-wasm.mjs runs wasm-pack build crates/foxvm --target web --release with the crate's wasm feature on, which turns on the wasm-bindgen exports. The module it produces is then inlined as base64 into src/wasm/foxvm/generated/foxvm_wasm.ts, and the renderer instantiates it with initSync rather than fetching it. That is deliberate: a packaged application loads its pages over file://, and the tests run under jsdom, and neither can fetch a .wasm from a URL. The release profile is opt-level = "s" with LTO and a single codegen unit, and wasm-opt is off.

The native cargo test does not turn the feature on, so the same crate is tested as ordinary Rust and shipped as wasm.

The command-line runner

crates/foxvm-cli builds foxvm, a headless runner over the same crate:

foxvm run file.prg       # run a program with a mock host: no forms, no dialogs
foxvm check file.prg     # compile and report diagnostics, as the editor's linter does
foxvm disasm file.prg    # print the bytecode, one instruction per line
foxvm audit dir          # compile every program under a folder and report what does not

It is the quickest way to see what the compiler makes of a program, and disasm is the companion to the bytecode page.

The layout, for orientation

crates/foxvm                Rust: lexer, parser, compiler, bytecode, VM, builtins, data engine, wasm exports
crates/foxvm-cli            the headless runner
crates/foxole               the COM addon (Windows)
src/wasm/foxvm              the compiled module, inlined as base64
src/shared/runtime          React-free: object model, scheduler, host contract, bundle format, HTTP service
src/main                    Electron main process: path-guarded file access, dialogs, sockets, native pieces
src/preload                 the sandboxed bridge exposing the typed FoxDevApi
src/renderer/src            the React IDE: designer/, editor/, explorer/, shell/, runtime/, player/
resources/native            foxole.node and fllhost.exe, unpacked from the asar because both need a real file
tests                       Vitest suites mirroring src; goldens measured against vfp9.exe
docs                        the language reference and coverage map, both generated