Skip to content

Dagor config build - #3594

Merged
borisbat merged 12 commits into
GaijinEntertainment:masterfrom
aleksisch:dagor-config-build
Jul 31, 2026
Merged

Dagor config build#3594
borisbat merged 12 commits into
GaijinEntertainment:masterfrom
aleksisch:dagor-config-build

Conversation

@aleksisch

Copy link
Copy Markdown
Collaborator

No description provided.

@aleksisch
aleksisch force-pushed the dagor-config-build branch 5 times, most recently from 9f9d8b2 to 78de195 Compare July 30, 2026 21:20
@borisbat
borisbat requested a review from Copilot July 30, 2026 22:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds “Dagor config” compile-coverage to ensure daScript/daslang builds cleanly under DagorEngine-style build constraints (EASTL + dag::Vector + ska maps, no filesystem/environment on console-like builds), while making the test suite resilient to fast-math/finite-math host builds and tightening a couple of runtime correctness guards.

Changes:

  • Introduce a centralized C++ environment-access rail (env_cfg) and update core call sites to use it (Dagor config poisons direct getenv/setenv usage).
  • Add/refresh CI for a Dagor-flavored build (pc + “no_fileio” variant) using a sparse DagorEngine checkout and host-toolchain compilation.
  • Make several tests robust to host fast-math / finite-math-only builds and to configurable vector-print separators; add coverage for a constant_expression + inliner locked-name edge case.

Reviewed changes

Copilot reviewed 34 out of 34 changed files in this pull request and generated no comments.

Show a summary per file
File Description
tests/math/inf_and_nan.das Skip IEEE NaN/Inf semantics checks on finite-math-only hosts where builtins fold.
tests/language/optimization_auto_inline_functions.das Add coverage for locked-name dispatch interactions with auto-inlining.
tests/language/_inline_constant_expression_helper.das New helper module reproducing constant_expression locked-name cloning scenario.
tests/jit_tests/arithmetics.das Skip vector-vs-scalar division bit-equality test on fast-math hosts.
tests/flatten/test_flatten_ctor.das Switch exact/approx comparison depending on host reciprocal-division behavior.
tests/flatten/no_aot/test_flatten_fold.das Make shader-corpus folding test tolerant of vendored builds lacking examples/.
tests/decs/test_objects.das Use VEC_SEP in expected vector formatting to match configurable separators.
tests/debug/deval.das Use VEC_SEP in expected float3 formatting to match configurable separators.
tests/daslib/test_toml.das Skip non-finite TOML round-trip tests on finite-math-only hosts; add require math.
tests/ast/test_lineinfo_ranges.das Resolve fixture path via get_das_root() for robustness across CWDs.
src/misc/job_que.cpp Route env reads through env_cfg accessors (Dagor getenv poisoning compatibility).
src/misc/gc_node.cpp Route env reads through env_cfg accessors.
src/misc/env_cfg.cpp New TU: the only allowed direct getenv/setenv access; PS-target stubs.
src/hal/project_specific_crash_handler.cpp Ensure crash-handler-only code is guarded by platform-support macro.
src/hal/crash_handler.cpp Guard <csignal> and other headers so unsupported/no-libc configs still compile.
src/builtin/module_builtin_fio.cpp Route env reads/writes through env_cfg (incl. COLUMNS, set_env_variable).
src/ast/ast_inline.cpp Treat constant_expression clones (no fromGeneric) as a locked-name splice fence.
src/ast/ast_gc_report.cpp Route env reads through env_cfg.
skills/environment_variables.md Document the new env_cfg accessor rail and why direct getenv is prohibited.
modules/dasClipboard/src/dasClipboard.cpp Route DISPLAY check through das_getenv to comply with getenv poisoning.
install/skills.list Stop shipping environment_variables skill in SDK; clarify rationale in comments.
install/CLAUDE.md Remove environment_variables skill from shipped SDK skill index.
include/daScript/simulate/aot.h Add safety init for Prologue flags; add swizzle size static_assert.
include/daScript/misc/env_cfg.h New header declaring env accessors used across core C++ code.
doc/source/reference/environment_variables.rst Update note: env vars list is published via doc include; skill is repo-only.
daslib/rst_comment.das Rename debug arg to avoid unused warnings while preserving behavior.
CMakeLists.txt Add env_cfg sources/headers to build and release install include list.
cmake/das_config_eastl/no_libc/csignal Add <csignal> shadow that errors to enforce correct guarding in no-libc builds.
cmake/das_config_eastl/eastl_glue.cpp Remove now-unneeded glue TU (Dagor EASTL fork supplies required sources).
cmake/das_config_eastl/daScript/das_config.h Rework EASTL config to match Dagor’s containers/settings + poison getenv rail.
cmake/das_config_eastl/dag/dag_config.h Add minimal dag_config.h shim for dag::Vector usage without Dagor kernel deps.
CLAUDE.md Clarify environment_variables skill scope and doc publication path (repo-only).
ci/build_eastl_config.sh New script building Dagor-config variants (pc + no_fileio) with sparse Dagor headers.
.github/workflows/build_eastl.yml Revamp build_eastl workflow to run the Dagor-config builds via the new script.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@aleksisch
aleksisch force-pushed the dagor-config-build branch from 5c31e56 to b8426fb Compare July 31, 2026 11:34
Every environment variable core reads now has one accessor declared in
include/daScript/misc/env_cfg.h, implemented in src/misc/env_cfg.cpp.
The name strings live in exactly one translation unit, so there is a
single place to answer "what does daslang read from the environment".

das_getenv and the DAS_TARGET_PS guard move out of platform.h, which was
carrying an env accessor and <stdlib.h> for every translation unit in the
project. The generic has_env_variable / get_env_variable bindings now go
through das_getenv too, which fixes their PS inconsistency.

Parsing, caching and defaults are unchanged at every call site - this is
a name-for-string substitution. The accessor is get_dasenv_ plus the
variable in lowercase without its DAS_ prefix (DAS_GC_STAGE_REPORT ->
get_dasenv_gc_stage_report) and returns the raw const char *; a variable
daslang does not own keeps its own name (COLUMNS -> get_columns).

Writes get the same treatment: das_setenv, a no-op on PS, replaces the
setenv / _putenv_s pair the set_env_variable binding called directly, and
dasClipboard's DISPLAY probe goes through das_getenv instead of
std::getenv.
DAS_CRASH_HANDLER_PLATFORM_SUPPORTED is 0 whenever the host brings its own
handler (DAS_USE_BASE_CRASH_HANDLER=0, dagor) or the platform is not one of
win/linux/apple, and the whole body of crash_handler.cpp is behind it. Two
things still escaped:

<csignal> and friends were included unconditionally. PS5's libc has no
<csignal> at all, so the PS5 lane died with "'csignal' file not found"
before reaching any code that would have been compiled out anyway.

The frame-count constant and print_das_stack_walk / das_crash_frame_filter
were declared unconditionally while their only callers sit inside the
guard, which -Werror rejects as unused.

Both now sit behind the same condition as their users.
@aleksisch
aleksisch force-pushed the dagor-config-build branch from b8426fb to 0fdfe5f Compare July 31, 2026 15:46
aleksisch added 10 commits July 31, 2026 20:05
The build_eastl lane used upstream EA EASTL with eastl::vector, which
misses the two things that actually break dagor bumps: dag::Vector as
das::vector (uint32_t size_type, assign() casts iterators to raw
pointers) and ska::flat_hash_map as das_map with DAS_CUSTOM_HASH left
undefined. Replaying past fixes as regressions, the old lane caught the
std:: churn but not the reverse-iterator assign from 27ebece - that
one only fails inside dag_vector.h.

Take the headers from a sparse DagorEngine checkout (dag, eastl,
ska_hash_map, dagorInclude/util) instead of vendoring copies, so the
lane tracks dagor drift on its own. Dagor's EASTL fork ships the
operator new[] glue and EA::StdC::Vsnprintf, so eastl_glue.cpp goes
away.

Two variants. pc builds daslang_static - dagor links daScript
statically, and the shared-module build hits a ska bug where
empty_default_table()'s hidden-visibility local static gets one copy per
module, so a table freed in another module frees .rodata. no_fileio
passes _TARGET_PC=0 and DAS_TARGET_PS=1 and builds the static lib only:
no filesystem, no environment, which is the feature set a console build
gets. Both run on the host toolchain - console SDKs cannot run in public
CI, so this covers the source, not the platform.

Two things a host libc may not have are made to fail here rather than in
a console lane. getenv/setenv/putenv are poisoned outside env_cfg.cpp,
which opts out via DAS_ALLOW_GETENV; that is what found the two direct
callers fixed in the env_cfg commit. <csignal> is shadowed by a header
that #errors: the PS SDK ships <signal.h> but not the C++ wrapper, and an
unguarded include there cost a PS5 build.
A [constant_expression] specialization is cloned into the module that
first resolves the call and dispatched as
`__::<instance>`constant_expression`<hash>`. Function::clone does not
copy fromGeneric, so the locked-name fallback has no origin to
re-resolve through, and splicing such a body into another module leaves
that call unresolvable there (error[30341], reported at the callee's
line). Exempt locked names only when they carry fromGeneric; otherwise
the site declines like any other `__::` dispatch.

Only auto inlining reaches these bodies (a block argument is what pulls
them in), so `options disable_auto_inline` was the only workaround.
DEBUG_COMMENT_READER is a compile-time false constant, so the only read
of s folds away and LINT012 fires on every module that pulls rst_comment
in. Rename to _s; an annotation would sit on a [macro_function] the
comment reader itself walks.
The swizzle helper writes sizeof...(f) elements into ResT and relied on
call sites matching the widths (PVS V557). State the contract instead.
das_stack_prologue set info/fileName/stackSize and left functionLine and
the flags bitfield alone. Stack memory is not zeroed (a dev build fills
it with 0x7ffdcdcd), so a stale is_jit bit sends getStackWalk into
StackWalkerTextWriter::onCallJIT, which dereferences pp->functionLine:
any panic or error report raised from AOT code segfaults inside the
handler instead of printing. Reproduced in dagor's das_ecs_test, where
a plain "division by zero" from AOT code crashed the process; both
fields are now initialized at entry.

The two test fixes make files pass regardless of who embeds them:

- test_lineinfo_ranges read its fixture through a cwd-relative path, so
  it only worked when dastest ran from the repo root. A host that runs
  the suite from the tests directory (dagor CI does) got an empty fread
  and a failure. Anchor it to get_das_root() like the flatten tests do.
- deval and test_objects hardcoded "1,2,3" for a printed float3, which
  bakes in DAS_PRINT_VEC_SEPARATROR. A host that overrides that macro
  (dagor uses ", ") had to patch these two files after every sync, and
  the patch was silently reverted by the next one. Build the expectation
  from the VEC_SEP constant the runtime already exports instead.

Touching deval.das subjects it to the changed-file lint, so it also drops
two unused requires and moves each t |> run body into its own function
(the old one was 88 lines, over the STYLE038 limit).
An embedder may compile the runtime with flags the suite silently assumed
away, and may vendor the sources without examples/. Five tests asserted
semantics that host never asked for, so they failed for the host's own
configuration rather than for a defect. Each now detects the situation at
runtime, which keeps the strict assertions on an IEEE build and does not
need a build-system opt-out on the embedder's side.

-ffinite-math-only folds the is_finite / is_nan builtins and the nan
comparisons to constants: math/inf_and_nan and the three non-finite
tests in daslib/test_toml probe for it (is_finite(inf) || !is_nan(nan))
and skip.

-ffast-math lets a/b become a*(1/b) and flushes denormals, so a vector
divide stops being bit-equal to its scalar reference. The probe compares
the two paths through module-level vars, so nothing folds at compile
time. flatten/test_flatten_ctor keeps the exact compare on an IEEE host
and uses the approximate one otherwise; jit_tests/arithmetics skips its
vector-vs-scalar fuzz, where the divergence reaches -0 vs -2.4e-06 on
denormal inputs and no tolerance would be honest.

flatten/no_aot/test_flatten_fold walked examples/flatten and asserted a
shader count; it now reports the corpus as absent instead of failing.

Touching these files subjects them to the changed-file lint, so the
deliberate patterns they already carried are annotated: the inf/nan
constructions (LINT006/LINT007), the generic TT(1) casts (PERF020), and
the two flat t |> run lists that exceed STYLE038's length limit.
v[i] on a vector and the fp16 lane ops read the lane by casting a vec4f
value to CTYPE*/float16_t*, which is a strict aliasing violation. gcc under
-fstrict-aliasing sees no CTYPE-typed store into that object and reports it
as read uninitialized (26 errors in dagor's jam build, which keeps strict
aliasing on); the optimizer is equally free to act on the same conclusion.
Read through a union instead, the form already used for the int64/double
lane accessors in vectypes.h and cast.h. The fp16 SetOp write side keeps
its cast: there the destination is a char* into script memory, not a pun of
a value.

Our cmake builds passed -fno-strict-aliasing unconditionally, so no lane
could see any of this. DAS_STRICT_ALIASING keeps the optimization on and
build_eastl now builds with gcc and sets it, so the next such pun fails in
CI rather than in a consumer. The warning stays suppressed - the tree has
~190 other punning sites, which are a separate cleanup - and with the gate
on that suppression has to be per target, since -Wall re-enables it and
cmake de-duplicates a directory-level copy back to the early position.
test_json_output built a shell command line and ran it through popen. On
windows that goes to cmd.exe /c, which strips the first and last quote of
a line starting with a quote, so the quotes around argv[0] were lost. With
a relative forward-slash argv[0] (../../../../tools/util/das-dev in the
dagor CI lane) cmd then took ".." as the command name, the child never
ran, no JSON was written and read_json("") panicked.

run_and_capture passes argv straight to popen_argv (CreateProcess, no
shell), so quoting and path separators stop mattering.
This reverts commit 0dda3ec.

The guard is right about the mechanism - a module-less file compiled as its
own AOT unit runs markExecutableSymbolUse + removeUnusedSymbols, so every
function nothing in that file calls is stripped and requiring modules call
into the interpreter - but it cannot be an error for hosts that require by
path. dagor requires thousands of module-less .das files that way, and its
loader accepts a `module` directive only on a *_common / *_events / *_macro
file name, so the fix it asks for is a tree-wide rename, not a one-line
edit.

Keep the dead name check until this can be reported as a warning (or gated
behind its own policy) rather than a hard error.
bionic declares no pthread_setaffinity_np, so the linux branch of
SetCurrentThreadAffinityCpu did not compile for android. sched_setaffinity
with pid 0 targets the calling thread, which is what the pthread_self call
asked for, and it exists on glibc and bionic alike.
@aleksisch
aleksisch force-pushed the dagor-config-build branch from 3121b96 to 3fe7096 Compare July 31, 2026 17:10
@borisbat
borisbat merged commit 56b1cbe into GaijinEntertainment:master Jul 31, 2026
37 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants