Build systems
Eclipse Atesor™ finds the build system of a repository from marker files, with no LLM call. The build system selects the default build plan, the dependency scan, the package test command and the tunes of performance mode. This page lists each build system that the code detects, how Atesor detects it, the default commands, and the support level.
What is the support level of each build system?
Section titled “What is the support level of each build system?”| Build system | Ecosystem | Support level |
|---|---|---|
cmake |
C, C++ | Full |
make |
C, C++ | Full |
autotools |
C, C++ | Full |
go |
Go modules, and GOPATH-style Go | Full |
meson |
C, C++ | Fallback |
cargo |
Rust | Fallback |
npm |
Node.js | Guarded |
pip |
Python | Detected only |
gradle |
JVM | Detected only |
maven |
JVM | Detected only |
bazel |
multi-language | Detected only |
The levels mean this:
- Full: Atesor has a default build plan that needs no LLM call. It also has a fallback plan and a package test command.
- Fallback: The LLM scout writes the build plan. If the scout fails, Atesor uses a built-in fallback plan. Atesor finds the package test command.
- Guarded: The LLM scout writes the build plan. Detection and the builder have extra checks for this ecosystem. If the scout fails, Atesor uses the discovery plan.
- Detected only: Atesor detects the build system and tells the LLM scout. The scout writes the plan. If the scout fails, Atesor uses the discovery plan.
All levels share the same sandbox, the same build and fix loop, and the same artifact verification. Refer to How it works.
How does Atesor detect the build system?
Section titled “How does Atesor detect the build system?”ScriptedOperations.detect_build_system() in src/scripted_ops.py looks for these files in the repository root, in this order:
| Build system | Marker files |
|---|---|
cmake |
CMakeLists.txt |
autotools |
configure.ac, configure.in, configure |
make |
Makefile, GNUmakefile |
meson |
meson.build |
cargo |
Cargo.toml |
npm |
package.json |
pip |
setup.py, pyproject.toml |
go |
go.mod |
gradle |
build.gradle, build.gradle.kts |
maven |
pom.xml |
bazel |
BUILD, BUILD.bazel, WORKSPACE |
Each marker gives a confidence value:
CMakeLists.txt,Cargo.toml,configure.acandgo.modgive 0.95.configuregives 0.85, but never lowers a value that is already higher.- Each other marker adds 0.3 to its build system, up to 0.9.
Rules for the result:
- The build system with the highest confidence wins. On a tie, the build system that comes first in the table wins.
package.jsoncounts only when the root also haspackage-lock.json, orpackage.jsondeclares abuildscript.- When Atesor finds both
goandnpm,gowins. - When the primary marker file is in a subdirectory, Atesor records that directory as
module_dir. The scout and the builder use it.
What if the root has no marker file?
Section titled “What if the root has no marker file?”Atesor tries these steps in order, and stops at the first match:
- Atesor searches all subdirectories for
go.modandCargo.toml. It skips vendored and test directories such asvendor,third_party,node_modules,test,tests,examplesanddocs. A Go module wins over a Cargo module. Confidence: 0.90. - Atesor searches the directories 1 and 2 levels below the root for
CMakeLists.txt,meson.build,configure.ac,configure.in,MakefileandGNUmakefile. It skips the same vendored and test directories. The shallowest file wins, then the first file in this list. Confidence: 0.75. - Atesor looks for
.gofiles without ago.mod. A match givesgo(GOPATH style), and the plan addsgo mod init. Confidence: 0.65. - No match gives
unknown, with confidence 0.0.
For a Go module in a subdirectory, Atesor prefers the directory with the strongest signs of a program: a main.go file, a cmd/ directory, and a .go file with package main.
When does Atesor use the default plan?
Section titled “When does Atesor use the default plan?”After detection, the analyst agent reads the build files with an LLM. Then heuristic_plan_node() in src/graph.py decides between the default plan and the LLM scout. Atesor uses the default plan only when all of these conditions are true:
- The build system is
cmake,make,autotoolsorgo. - The confidence is 0.5 or more.
- The analyst did not set
needs_custom_plan. - The scan found no
criticalarch-specific code, and fewer than 3highfindings.
The analyst can replace the detected build system and confidence with its own. This happens when the analyst read the files with an LLM, names a build system other than unknown, and has a confidence equal to or higher than the detection confidence. In all other cases, the LLM scout writes the plan.
With --optimize, a verified entry in the recipe cache replaces this decision. The cached build plan becomes the plan, with confidence 1.0. The analyst, the default plan and the scout do not run before the first build. When the entry has no command, Atesor plans as usual. --force turns this off. Refer to Command-line options.
What are the default build commands?
Section titled “What are the default build commands?”Each plan starts with a setup phase. It runs one install command for the active sandbox: <update> && <install> <packages>. The packages come from canonical names that the platform profile maps to distribution packages. The default plan also adds the dependencies that the analyst and the scan found, when the profile knows them. The setup command has up to 15 names in total. The fallback plans install only the packages in their table.
Default plans (no LLM)
Section titled “Default plans (no LLM)”| Build system | Setup packages (canonical) | Configure | Build |
|---|---|---|---|
cmake |
cmake, gcc |
mkdir -p build && cd build && cmake .. -DCMAKE_BUILD_TYPE=Release |
cd build && make -j$(nproc) |
make |
gcc |
none | make -j$(nproc) |
autotools |
gcc, autotools, pkgconfig |
./configure |
make -j$(nproc) |
go |
git |
none | go mod tidy, then the Go build command |
The Go build command comes from the search for the main package:
go build -buildvcs=false ./<dir>for amainpackage in a subdirectory of the module. Atesor preferscmd/<repository name>, then the othercmd/directories, then the module root.go build -buildvcs=false .for amainpackage in the module root, for a GOPATH-style repository, and when the search finds nomainpackage.go build -buildvcs=false ./...when Atesor has no search result, for example when the analyst changes the build system togo.- For a repository without
go.mod, the phase starts withgo mod init <module>andgo mod tidy.<module>is the repository URL withouthttps://.
Fallback plans (after a scout failure)
Section titled “Fallback plans (after a scout failure)”When the LLM scout gives no valid plan, create_fallback_build_plan() in src/graph.py uses the detected build system:
| Build system | Setup packages (canonical) | Configure | Build |
|---|---|---|---|
cmake |
gcc, cmake |
mkdir -p build, then cd build && cmake .. -DCMAKE_BUILD_TYPE=Release |
cd build && make -j$(nproc) |
make |
gcc |
none | make -j$(nproc) |
autotools |
gcc, autotools, pkgconfig |
./configure |
make -j$(nproc) |
go |
git |
none | go mod tidy (and go mod init when needed), then the Go build command |
meson |
gcc, meson, ninja |
meson setup builddir |
ninja -C builddir |
cargo |
rust |
none | cargo build --release |
| other | none | none | make -j$(nproc) |
- For
autotoolswithout a committedconfigure, the configure phase runsautoreconf -fibefore./configure. - The
autotoolssetup phase also copies the gettext.m4files intom4/. - In the
gofallback plan,go build .becomesgo build -buildvcs=false ./.... Another Go build command stays as the search gave it. The sandbox images setGOFLAGS=-buildvcs=false. - For other build systems, a
discoverphase runsls -laon the build files that exist, or a shortfindfor them. Then the plan runsmake -j$(nproc).
Which package test command does Atesor run?
Section titled “Which package test command does Atesor run?”After a successful build, Atesor runs the tests of the package one time. The result goes into the report and the zip manifest. It never changes the result of the port. _detect_test_command() in src/graph.py checks these cases in order:
- In
build/,_build/orbuilddir/: aCTestTestfile.cmakefile givesctest --test-dir <dir> --output-on-failure. - In the same directories: a
meson-infodirectory givesmeson test -C <dir> --print-errorlogs. - A root
go.modgivesgo test ./..., when the plan isgoor the root has noMakefile. - A root
Cargo.tomlgivescargo test --release, when the plan iscargoorrust, or the root has noMakefile. - A root
Makefilewith acheck:target givesmake check. Else atest:target givesmake test.
Without a match, the result is skipped. The time limit is 600 seconds. Refer to Environment variables for ATESOR_PACKAGE_TEST_TIMEOUT.
A build plan from the LLM scout never runs tests. Atesor removes these commands from the scout plan, because the package tests run after the build:
ctest,pytestandpython -m pytest.go test,cargo test,meson testandnpm test.make,gmakeorninjawith the targetcheck,testortests.cmake --buildwith--target check,--target testor--target tests.
Atesor ignores a leading cd <dir> && and leading NAME=value words when it reads a command. A phase that has no command left goes out of the plan. A scout plan with only test commands counts as a scout failure, so Atesor uses the fallback plan.
What else does Atesor do for each build system?
Section titled “What else does Atesor do for each build system?”The scan reads the dependencies of some build systems from their files, with no LLM call:
| Build system | Dependency scan |
|---|---|
cmake |
find_package(), pkg_check_modules() and pkg_search_module() in CMakeLists.txt |
make |
-l<name> flags in Makefile |
go |
require lines in go.mod |
cargo |
[dependencies] in Cargo.toml |
npm |
dependencies and devDependencies in package.json |
pip |
requirements.txt |
autotools, meson, gradle, maven, bazel |
none |
The builder also changes or retries some commands with no LLM call. This table shows examples for each build system. Refer to Recovery heuristics for the full list.
| Build system | Examples of builder adjustments |
|---|---|
cmake |
When a bare make finds no makefile next to CMakeLists.txt, Atesor retries with cmake -S . -B build -DCMAKE_BUILD_TYPE=Release && cmake --build build -j1. When the CMake cache has a stale compiler path, Atesor deletes build/ and sets /usr/bin/gcc and /usr/bin/g++. |
make |
When the root has no makefile, a plain make runs in the shallowest subdirectory that has one, 1 or 2 levels below the root. |
autotools |
When the repository has no committed configure, Atesor runs a bootstrap before ./configure. |
go |
Atesor adds -buildvcs=false to go build and go install, and removes it from other Go commands. It retries with -mod=mod or after go mod tidy for some module errors. |
meson |
ninja runs with -j1 after a suspected out-of-memory kill. |
cargo |
cargo runs with -j 1 and CARGO_BUILD_JOBS=1 after a suspected out-of-memory kill. |
npm |
The npm run <script> guard. npm install, npm ci and npm run get --jobs 1 after a suspected out-of-memory kill. |
pip |
pip install runs with MAKEFLAGS=-j1 after a suspected out-of-memory kill. |
The autotools bootstrap uses the first case that applies:
- The repository has
autogen.sh,buildconf,buildconf.shorbootstrap. Atesor runssh <script>. - The repository has
configure.acorconfigure.in, andm4/gettext.m4. Atesor copies the gettext.m4files intom4/, then runsaclocal -I m4 -I /usr/share/aclocal && autoconf. - The repository has
configure.acorconfigure.in. Atesor runsautoreconf -fi.
The npm run <script> guard works like this:
- When
package.jsondoes not declare the script, Atesor uses the first declared script ofbuild,prod,compileanddist. - When none of them exists, Atesor skips the command.
After a suspected out-of-memory kill, Atesor also runs make with -j1 and MAKEFLAGS=-j1, and Go with -p 1 and GOMAXPROCS=1. Exit code 137 always counts as an out-of-memory kill.
Performance mode (--optimize) also reads the build system of the plan. It treats go as Go, cargo and rust as Rust, and every other build system as C or C++. The language selects the tunes:
- C and C++: core tuning (
-mtune), machine ISA (-march), vector ISA, optimization level, link-time optimization and a second compiler, all through wrapper scripts. Then profile-guided optimization on top of the best tune. - Go: the
GORISCV64level, then profile-guided optimization. - Rust:
RUSTFLAGSwith a target CPU or target features, then link-time optimization.
A tune repeats the commands of the verified build in a copy of the tree. It does not repeat package installs, install steps, source control steps and writes outside the tree. Refer to Performance mode.
Which tool packages does each sandbox install?
Section titled “Which tool packages does each sandbox install?”The platform profiles in src/platforms.py map canonical names to distribution packages:
| Canonical name | Alpine | Debian and Ubuntu |
|---|---|---|
cmake |
cmake |
cmake |
make |
make |
make |
ninja |
ninja |
ninja-build |
meson |
meson |
meson |
autotools |
automake autoconf libtool |
autoconf automake libtool |
gcc, g++ |
build-base |
build-essential |
pkgconfig |
pkgconf |
pkg-config |
python3 |
python3 py3-pip |
python3 python3-pip python3-dev |
node |
nodejs npm |
nodejs npm |
java |
openjdk17 |
openjdk-17-jdk |
git |
git |
git |
go |
go |
no entry |
rust |
no entry | no entry |
All three sandbox images contain Go 1.26.5 in /usr/local/go and Rust 1.99.0 from rustup in /root/.cargo. The profiles have no rust entry and the Debian profile has no go entry, so that a distribution package does not hide the newer toolchain. Dockerfile.native also installs clang-19, lld-19, llvm-19 and libclang-rt-19-dev for the second compiler and the clang profiles of performance mode. Refer to Sandboxes and Add a platform.