Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
FROM ubuntu:22.04

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y \
luajit \
libluajit-5.1-dev \
build-essential \
git
cmake \
ninja-build \
curl \
&& rm -rf /var/lib/apt/lists/*

RUN curl -fsSL https://github.com/lde-org/lde/releases/download/nightly/lde-linux-x86-64 \
-o /usr/local/bin/lde \
&& chmod +x /usr/local/bin/lde \
&& lde --setup
89 changes: 26 additions & 63 deletions .github/workflows/bootstrap.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,18 @@ jobs:
matrix:
include:
# - os: ubuntu-22.04
# artifact: luajit-linux-x86-64-gnu
# outfile: lde-linux-x86-64
# sea_cc: gcc
# - os: ubuntu-22.04-arm
# artifact: luajit-linux-aarch64-gnu
# outfile: lde-linux-aarch64
# sea_cc: gcc
# - os: windows-latest
# artifact: luajit-windows-x86-64-gnu
# outfile: lde-windows-x86-64
# sea_cc: gcc
# - os: windows-11-arm
# artifact: luajit-windows-aarch64-gnu
# outfile: lde-windows-aarch64
# sea_cc: clang
# - os: macos-15
# artifact: luajit-macos-aarch64
# outfile: lde-macos-aarch64
# sea_cc: gcc
# - os: macos-15-intel
# artifact: luajit-macos-x86-64
# outfile: lde-macos-x86-64
# sea_cc: gcc
- os: ubuntu-22.04
artifact: luajit-linux-x86-64-gnu
- os: ubuntu-22.04-arm
outfile: lde-android-aarch64
android: true

Expand All @@ -47,63 +34,39 @@ jobs:
- name: Checkout code
uses: actions/checkout@v6

- name: Cache LuaJIT
id: cache-luajit
- name: Fix workspace permissions (Android)
if: matrix.android
run: chmod -R a+rw ${{ github.workspace }}

- name: Cache test image (Android)
if: matrix.android
id: cache-android-image
uses: actions/cache@v5
with:
path: ${{ matrix.artifact }}
key: ${{ matrix.artifact }}-latest

- name: Download LuaJIT
if: steps.cache-luajit.outputs.cache-hit != 'true'
run: |
curl -L -o luajit.tar.gz https://github.com/lde-org/lj-dist/releases/download/latest/${{ matrix.artifact }}.tar.gz
tar -xzf luajit.tar.gz
path: /tmp/termux-android.tar
key: termux-android-v3

- name: Install llvm-mingw (Windows ARM64)
if: matrix.os == 'windows-11-arm'
shell: pwsh
run: |
curl -L -o llvm-mingw.zip https://github.com/mstorsjo/llvm-mingw/releases/download/20260311/llvm-mingw-20260311-ucrt-aarch64.zip
Expand-Archive -Path llvm-mingw.zip -DestinationPath .
echo "$env:GITHUB_WORKSPACE\llvm-mingw-20260311-ucrt-aarch64\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append

- name: Build lde (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
cd packages/lde
$env:BOOTSTRAP=1
$env:SEA_CC="${{ matrix.sea_cc }}"
& "$env:GITHUB_WORKSPACE/${{ matrix.artifact }}/luajit.exe" ./src/init.lua compile --outfile ${{ matrix.outfile }}.exe

- name: Set up Android NDK compiler
- name: Build lde (Android)
if: matrix.android
run: |
echo "SEA_CC=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang" >> $GITHUB_ENV
if [[ "${{ steps.cache-android-image.outputs.cache-hit }}" != "true" ]]; then
docker run --privileged --platform linux/arm64 \
--name termux-build termux/termux-docker:aarch64 \
bash -c "apt update && apt install -y luajit clang cmake ninja openssl git"
docker commit termux-build termux-android:latest
docker rm termux-build
docker save termux-android:latest -o /tmp/termux-android.tar
fi

- name: Build lde (Unix)
if: runner.os != 'Windows'
run: |
cd packages/lde
BOOTSTRAP=1 SEA_CC="${SEA_CC:-${{ matrix.sea_cc }}}" $GITHUB_WORKSPACE/${{ matrix.artifact }}/luajit ./src/init.lua compile --outfile ${{ matrix.outfile }}
docker load -i /tmp/termux-android.tar

- name: Upload nightly release asset (Windows)
if: runner.os == 'Windows'
uses: softprops/action-gh-release@v2
with:
tag_name: nightly
name: Nightly Build
prerelease: true
body: |
Automated nightly build from master.
Commit: ${{ github.sha }}
Run: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
files: packages/lde/${{ matrix.outfile }}.exe
fail_on_unmatched_files: true
docker run --rm --privileged --platform linux/arm64 \
-v ${{ github.workspace }}:/workspace \
-w /workspace \
termux-android:latest \
bash -c "cd /workspace/packages/lde && BOOTSTRAP=1 luajit /workspace/packages/lde/src/init.lua compile --outfile /workspace/packages/lde/${{ matrix.outfile }}"

- name: Upload nightly release asset (Unix)
if: runner.os != 'Windows'
- name: Upload nightly release asset
uses: softprops/action-gh-release@v2
with:
tag_name: nightly
Expand Down
4 changes: 0 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,6 @@ jobs:
shell: pwsh
run: echo "SEA_CC=aarch64-w64-mingw32-clang" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append

- name: Install macOS build deps
if: startsWith(matrix.os, 'macos')
run: brew install autoconf automake libtool

- uses: lde-org/setup-lde@master
with:
version: nightly
Expand Down
24 changes: 13 additions & 11 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ packages/
lde/ # The CLI binary itself (entry: src/init.lua)
lde-core/ # Core library: Package, Lockfile, runtime, install logic
lde-test/ # Built-in test framework
ansi/clap/env/fs/git/http/json/path/process2/semver/util/ # Internal packages
ansi/clap/env/fs/git/http/json/path/process/semver/util/ # Internal packages
sea/ # Single-executable assembly (compiles bundles into binaries)
archive/ # Archive extraction support
luarocks/ # LuaRocks integration
Expand Down Expand Up @@ -37,6 +37,7 @@ The key: **the require name is the key in `lde.json` `dependencies`, not the pac
During `lde test`, the runner automatically exposes the package's `tests/` directory as `target/tests` (symlinked or copied). This means test files can `require("tests.lib.something")` to share helpers across test files.

Example from `packages/lde/tests/main.test.lua`:

```lua
local ldecli = require("tests.lib.ldecli")
```
Expand Down Expand Up @@ -107,6 +108,7 @@ This outputs `packages/lde/lde` (or `lde.exe` on Windows). To install it, copy i
## Runtime Isolation (`lde-core.runtime`)

`lde run` / `lde test` execute scripts in an isolated environment:

- `package.loaded` is cleared of non-builtins before and restored after each run.
- A fresh `_G` metatable is created per execution (`setfenv`).
- `ffi.cdef` is patched to silently ignore "attempt to redefine" errors (safe for repeated runs in the same process).
Expand All @@ -116,16 +118,16 @@ This means multiple `lde run` calls in the same process don't pollute each other

## Key Packages

| Package | Purpose |
|---|---|
| `lde-core` | `Package`, `Lockfile`, install/build/run/test/compile logic |
| `lde-test` | Test framework (`require("lde-test")` in test files) |
| `clap` | CLI argument parsing (`args:option()`, `args:flag()`, `args:pop()`) |
| `ansi` | Colored terminal output (`ansi.printf("{red}msg")`) |
| `fs` | Filesystem ops (`read`, `write`, `mkdir`, `mklink`, `scan`, `stat`) |
| `process2` | Process execution (`process.exec(bin, args, opts)`) |
| `sea` | Compiles a bundled Lua string + native libs into a self-contained binary |
| `env` | Env vars, cwd, `env.execPath()` |
| Package | Purpose |
| ---------- | ------------------------------------------------------------------------ |
| `lde-core` | `Package`, `Lockfile`, install/build/run/test/compile logic |
| `lde-test` | Test framework (`require("lde-test")` in test files) |
| `clap` | CLI argument parsing (`args:option()`, `args:flag()`, `args:pop()`) |
| `ansi` | Colored terminal output (`ansi.printf("{red}msg")`) |
| `fs` | Filesystem ops (`read`, `write`, `mkdir`, `mklink`, `scan`, `stat`) |
| `process` | Process execution (`process.exec(bin, args, opts)`) |
| `sea` | Compiles a bundled Lua string + native libs into a self-contained binary |
| `env` | Env vars, cwd, `env.execPath()` |

## Monorepo Conventions

Expand Down
6 changes: 3 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ packages/
lde/ # The CLI binary itself (entry: src/init.lua)
lde-core/ # Core library: Package, Lockfile, runtime, install logic
lde-test/ # Built-in test framework
ansi/clap/env/fs/git/http/json/path/process2/semver/util/ # Internal packages
ansi/clap/env/fs/git/http/json/path/process/semver/util/ # Internal packages
sea/ # Single-executable assembly (compiles bundles into binaries)
archive/ # Archive extraction support
luarocks/ # LuaRocks integration
Expand Down Expand Up @@ -213,7 +213,7 @@ args:drain(start) -- returns and removes all remaining args (or from i
args:count() -- number of remaining args
```

### `process2`
### `process`

```lua
-- Blocking execution
Expand All @@ -228,7 +228,7 @@ child:kill(force)
-- opts: { cwd, env, stdin, stdout, stderr }
-- stdout/stderr: "pipe" (default for exec), "inherit", "null"

process2.platform -- "linux", "darwin", "win32", "unix"
process.platform -- "linux", "darwin", "win32", "unix"
```

### `env`
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/lde.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "benchmarks",
"version": "0.1.0",
"dependencies": {
"process2": { "path": "../packages/process2" },
"process": { "git": "https://github.com/lde-org/process" },
"ansi": { "path": "../packages/ansi" }
}
}
11 changes: 7 additions & 4 deletions benchmarks/src/init.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
local ffi = require("ffi")

local process = require("process2")
local process = require("process")
local ansi = require("ansi")

---@type fun(): number
Expand Down Expand Up @@ -91,7 +91,8 @@ local function runBenchmarks(tool, tmpdir)
bench("install busted (cold)", function()
local code, _, stderr
if tool == "lde" then
code, _, stderr = process.exec("lde", { "--tree", tmpdir .. "/lde", "install", "rocks:busted" }, { stdout = "null" })
code, _, stderr = process.exec("lde", { "--tree", tmpdir .. "/lde", "install", "rocks:busted" },
{ stdout = "null" })
elseif tool == "luarocks" then
code, _, stderr = process.exec("luarocks", { "--tree", tmpdir .. "/rocks", "install", "busted" })
elseif tool == "lx" then
Expand All @@ -103,7 +104,8 @@ local function runBenchmarks(tool, tmpdir)
bench("install busted (warm)", function()
local code, _, stderr
if tool == "lde" then
code, _, stderr = process.exec("lde", { "--tree", tmpdir .. "/lde", "install", "rocks:busted" }, { stdout = "null" })
code, _, stderr = process.exec("lde", { "--tree", tmpdir .. "/lde", "install", "rocks:busted" },
{ stdout = "null" })
elseif tool == "luarocks" then
code, _, stderr = process.exec("luarocks", { "--tree", tmpdir .. "/rocks", "install", "busted" })
elseif tool == "lx" then
Expand All @@ -115,7 +117,8 @@ local function runBenchmarks(tool, tmpdir)
bench("build C rock (luafilesystem)", function()
local code, _, stderr
if tool == "lde" then
code, _, stderr = process.exec("lde", { "--tree", tmpdir .. "/lde", "install", "rocks:luafilesystem" }, { stdout = "null" })
code, _, stderr = process.exec("lde", { "--tree", tmpdir .. "/lde", "install", "rocks:luafilesystem" },
{ stdout = "null" })
elseif tool == "luarocks" then
code, _, stderr = process.exec("luarocks", { "--tree", tmpdir .. "/rocks", "install", "luafilesystem" })
elseif tool == "lx" then
Expand Down
2 changes: 0 additions & 2 deletions packages/archive/.gitignore

This file was deleted.

16 changes: 0 additions & 16 deletions packages/archive/lde.json

This file was deleted.

Loading
Loading