android target + APK pipeline; LSP imports honor stdlib paths

Android (toolchain):
  --target android / --target android-arm64 → aarch64-linux-android21.
  target.zig discovers $ANDROID_NDK_HOME (or scans
  ~/Library/Android/sdk/ndk/* for the newest), invokes the NDK clang
  with -shared -fPIC and links libsxhello.so against -llog -landroid
  -lEGL -lGLESv3 -lm -ldl. native_app_glue.c from the NDK is compiled
  and linked alongside the sx .o so apps can use the conventional
  android_main(struct android_app*) shape; -u ANativeActivity_onCreate
  keeps glue's symbol live.

Android (APK):
  --apk <out> wraps the .so into a debug-signed installable APK.
  target.zig discovers the SDK at $ANDROID_HOME (or
  ~/Library/Android/sdk), picks the newest build-tools + platforms,
  generates a NativeActivity AndroidManifest.xml from --bundle-id,
  packages via aapt2 link, appends the lib/ tree, zipalign, then
  apksigner against ~/.android/debug.keystore (auto-generated via
  keytool on first use). One command end-to-end:
      sx build --target android --apk out.apk \\
          --bundle-id co.swipelab.foo main.sx
  Verified on Pixel 7 Pro: install + launch reaches android_main.

Compiler (entry-point linkage):
  Top-level fn defs default to LLVM internal linkage and are lazily
  lowered (only `main` was eagerly lowered before). Added
  isExportedEntryName() — a small allowlist for names the OS loader
  calls: `main`, `android_main`, `ANativeActivity_onCreate`,
  `JNI_OnLoad`. These get eagerly lowered AND keep external linkage,
  so they actually land in .dynsym.

LSP (imports):
  DocumentStore now takes the install-discovered stdlib_paths and
  forwards them into resolveImportPath, mirroring the compiler. Before
  this, every `#import "modules/..."` resolved through the stdlib path
  failed silently inside the LSP and identifiers from those modules
  showed as `undefined variable`. Repro on label.sx: 1 false positive
  before, 0 after.
This commit is contained in:
agra
2026-05-18 23:09:55 +03:00
parent f41a121a29
commit f66cda6d11
5 changed files with 384 additions and 15 deletions

View File

@@ -47,13 +47,19 @@ pub const DocumentStore = struct {
io: std.Io,
/// Workspace root path (from initialize). Used to absolutify CWD-relative import paths.
root_path: []const u8 = "",
/// Install-discovered stdlib search paths. Mirrors the compiler's
/// `--lib-path` resolution so `#import "modules/std.sx"` etc. find the
/// shipped library files even when the workspace is something other
/// than the sx repo (e.g. /Users/agra/projects/game).
stdlib_paths: []const []const u8 = &.{},
/// All loaded documents keyed by resolved file path.
by_path: std.StringHashMap(*Document),
pub fn init(allocator: std.mem.Allocator, io: std.Io) DocumentStore {
pub fn init(allocator: std.mem.Allocator, io: std.Io, stdlib_paths: []const []const u8) DocumentStore {
return .{
.allocator = allocator,
.io = io,
.stdlib_paths = stdlib_paths,
.by_path = std.StringHashMap(*Document).init(allocator),
};
}
@@ -184,7 +190,7 @@ pub const DocumentStore = struct {
for (root.data.root.decls) |decl| {
if (decl.data != .import_decl) continue;
const imp = decl.data.import_decl;
const resolved_path = try sx.imports.resolveImportPath(self.allocator, self.io, base_dir, imp.path, self.rootPathOpt(), &.{});
const resolved_path = try sx.imports.resolveImportPath(self.allocator, self.io, base_dir, imp.path, self.rootPathOpt(), self.stdlib_paths);
try import_list.append(self.allocator, .{
.ns = imp.name,
.path = resolved_path,