This guide is for the people who build, deploy, embed, and extend Julia: operators compiling Julia from source, packagers and distributors, developers embedding libjulia in larger applications, HPC administrators tuning Julia across clusters, and contributors who need a map of the runtime's internals. It documents Julia's architecture, its build system, configuration surface, security-relevant behavior, and the organization of its C/C++ core.
For installing and using the julia program day-to-day, see the companion User Guide. This document deliberately goes deeper: it is meant to be exhaustive enough that an engineer (or an AI) could understand how Julia is structured and reproduce its build and deployment.
Note
This guide describes the Julia source tree at version
1.14.0-DEV(commit2614585). Julia is released under the MIT license (© 2009–2025 Jeff Bezanson, Stefan Karpinski, Viral B. Shah, and contributors).
Table of Contents
- Executive Summary
- System Architecture
- Repository Structure
- System Requirements
- Building Julia from Source
- Build Configuration Reference (
Make.user) - The Runtime in Depth
- System Images, Package Images, and AOT (
juliac) - Embedding
libjulia - Configuration & Environment Surface
- Operations
- Security Analysis
- Code Quality & Conventions
- Testing Strategy
- Troubleshooting (Build & Deploy)
- Potential Improvements
- Contributing
- Quick Reference
1. Executive Summary
Julia is a programming-language implementation: a compiler, a runtime, a standard library, and a command-line front end, distributed together. Architecturally it is a polyglot project:
- The language core and runtime are written in C and C++ (
src/) — the type system, multiple-dispatch method tables, the LLVM-based code generator, garbage collectors, task scheduler, and the embedding API. - The standard library (
base/andstdlib/) is written largely in Julia itself, which is possible because the runtime bootstraps a working Julia early in the build. - A front-end parser lives in the bundled
flispScheme interpreter (src/flisp) plus the newerJuliaSyntax/JuliaLoweringcomponents. - A thin C loader (
cli/) is what users actually invoke asjulia; it locates and loads the runtime shared libraries and jumps into them.
The defining design choices an administrator must understand:
| Choice | Operational consequence |
|---|---|
| JIT compilation via LLVM | First use of a function is compiled; "time-to-first-result" latency is real and is mitigated by caching (system images, package images, precompilation). |
| System image | Julia starts from a pre-compiled snapshot of Base + stdlib. Building, customizing, and shipping these images is a core deployment lever. |
Three-library split (libjulia, libjulia-internal, libjulia-codegen) |
Code generation can be separated from the runtime; libjulia-codegen is optional and deletable to save space. |
| Self-contained depot | All package/cache/config state lives under ~/.julia (configurable). Uninstalling is "delete two directories." |
| BinaryBuilder dependencies | The build downloads pre-built external libraries by default; air-gapped builds must opt out (USE_BINARYBUILDER=0). |
Important
The single most consequential operational concept in Julia is the system image. Almost every performance, startup-latency, deployment, and HPC-portability decision routes through how the sysimage is built and targeted (
-J,--output-*,--trim,JULIA_CPU_TARGET). Read Section 8 carefully.
2. System Architecture
2.1 The launch / loading chain
The julia binary is not the runtime — it is a small RPATH-style relative-path loader (cli/loader_exe.c, cli/loader_lib.c). Its job is to open the runtime libraries in the correct order and hand control to them.
┌──────────────────────────────────────────┐
user runs `julia` │ julia (loader executable, cli/) │
───────────────────► │ main() → jl_load_repl() │
└───────────────┬────────────────────────────┘
│ dlopen() DEP_LIBS, in order:
│
┌────────────────────────┼─────────────────────────────┐
▼ ▼ ▼
┌───────────────┐ ┌──────────────────┐ ┌────────────────────┐
│ libstdc++ │ │ libjulia-internal │ │ libjulia-codegen │
│ (probed: use │ │ (the runtime: │ │ (LLVM code gen; │
│ system one if │ │ GC, types, │ │ OPTIONAL — falls │
│ newer, else │ │ dispatch, tasks) │ │ back to internal) │
│ bundled) │ └──────────────────┘ └────────────────────┘
└───────────────┘ │
│ re-export runtime symbols,
│ jl_init_options(), set up fast TLS
▼
jl_repl_entrypoint(argc, argv)
│
▼
REPL / script / -e expression
Key facts grounded in cli/loader_lib.c:
DEP_LIBSis a colon-separated, order-sensitive list of dependent libraries;libjuliamust be last. Libraries prefixed@are "special" and handled with custom logic. There are exactly three special libraries:libstdc++,libjulia-internal,libjulia-codegen.- libstdc++ probing: on Linux, the loader probes for a system libstdc++ newer than the bundled one and prefers it (to stay compatible with third-party dynamic libraries that link the system C++ runtime). This is controlled by
JULIA_PROBE_LIBSTDCXX(1/yes/0/no). - Optional codegen: if
libjulia-codegencannot be found, the loader sets it tolibjulia-internaland uses a fallback function table — Julia can then run already-compiled code but cannot generate new code. - Fast TLS: on Linux/FreeBSD the loader sets up a static thread-local-storage key for the per-thread GC stack (
jl_pgcstack), guarded by an atomic semaphore so it is installed exactly once. - Windows: the loader bundles its own minimal libc shims (
cli/loader_win_utils.c) —malloc/freeover the process heap, UTF-16↔WTF-8 conversion, command-line splitting — so it can run without depending on libgcc.
2.2 The runtime libraries (src/)
The runtime is a large C/C++ codebase. The file inventory itself is a clean architecture map; the largest and most load-bearing translation units:
| Concern | Primary source | Role |
|---|---|---|
| Code generation | codegen.cpp, cgutils.cpp, intrinsics.cpp |
Lower Julia IR to LLVM IR; emit native code |
| JIT | jitlayers.cpp, aotcompile.cpp, cgmemmgr.cpp |
ORC-style JIT layers; ahead-of-time compilation; code memory management |
| Type system | jltypes.c, datatype.c, subtype.c, typemap.c |
Types, datatype layout, the subtyping algorithm, dispatch type maps |
| Multiple dispatch | gf.c, method.c |
Generic functions, method tables, specialization & dispatch |
| Builtins & intrinsics | builtins.c, runtime_intrinsics.c |
Core operations and numeric intrinsics |
| Garbage collection | gc-stock.c, gc-mmtk.c, gc-debug.c, gc-heap-snapshot.c |
Two collectors: the stock GC and an MMTk-based GC; debugging & heap snapshots |
| Tasks & threads | task.c, threading.c |
Green-thread tasks (coroutines), the threadpool scheduler |
| System image | staticdata.c, staticdata_utils.c, ircode.c |
Serialize/deserialize the compiled session image; IR (de)serialization |
| Startup & API | init.c, jlapi.c, jloptions.c |
Process init, the embedding C API, command-line option parsing |
| FFI | ccall.cpp |
ccall/@ccall foreign-function interface to C/Fortran |
| Interpreter | interpreter.c, toplevel.c |
Interpret IR (used during bootstrap and where JIT is disabled); top-level eval |
| Signals & stack | signals-unix.c, signals-mach.c, stackwalk.c |
Signal handling per platform; backtraces |
| AST / parser bridge | ast.c, src/flisp/ |
Bridge to the flisp-based front end |
| CPU dispatch | processor.cpp, llvm-multiversioning.cpp |
Multi-versioning of code for different CPU feature sets |
Note
The presence of both
gc-stock.candgc-mmtk.creflects that Julia supports a pluggable GC: the long-standing stock collector and an alternative built on the MMTk memory-management toolkit, selected at build time.
2.3 The compiler front end
Julia's surface syntax is parsed and lowered through a chain that includes the embedded flisp Scheme interpreter (src/flisp/, a complete femtolisp implementation) and the newer JuliaSyntax and JuliaLowering components (in-tree at the repository root). Parsed and lowered code becomes Julia IR, which the interpreter runs directly or the codegen path compiles via LLVM.
2.4 The standard library
base/ is the Base module — the always-available core, written in Julia. stdlib/ holds the bundled standard-library packages (e.g. Dates, Random, LinearAlgebra machinery, REPL, Printf, Sockets, Logging, Markdown, TOML, Test, Profile, InteractiveUtils, LibGit2, plus a large set of *_jll artifact packages wrapping external binaries such as OpenBLAS_jll, LLVM, MPFR_jll, GMP_jll, LibCURL_jll, OpenSSL_jll, Zstd_jll). The *_jll packages are how Julia ships and locates its bundled native dependencies at runtime.
3. Repository Structure
| Directory | Contents |
|---|---|
base/ |
The Base module — core standard library, written in Julia |
Compiler/ |
The compiler (type inference / optimization) as a relocatable component |
JuliaSyntax/ |
Modern parser |
JuliaLowering/ |
Lowering (desugaring) component |
cli/ |
The command-line launcher / loader (C) |
contrib/ |
Miscellaneous scripts and platform install helpers (mac/, windows/, build helpers) |
deps/ |
External dependencies and their build glue |
doc/ |
The user manual (doc/src/), developer docs (doc/src/devdocs/), and the julia.1 man page (doc/man/) |
etc/ |
The default startup.jl |
src/ |
The language core and runtime (C/C++ + flisp) |
stdlib/ |
Bundled standard-library packages |
test/ |
Test suites (including embedding/, gcext/, trimming/, clangsa/, llvmpasses/) |
Tip
Julia's Makefiles define automatic
print-<VARNAME>rules. For examplemake print-JULIA_PRECOMPILEprints the value ofJULIA_PRECOMPILE. This is the fastest way to introspect any build variable.
4. System Requirements
4.1 Disk and memory (build)
- ~5 GiB disk if building all dependencies (the README cites ~2 GiB for a basic build; the detailed build doc cites ~5 GiB when building all dependencies).
- ~4 GiB virtual memory during the build.
4.2 Toolchain
Building Julia requires a working C/C++ toolchain and GNU make. External libraries (LLVM, OpenBLAS, LibGit2, GMP, MPFR, PCRE2, SuiteSparse, libuv, etc.) are downloaded pre-built by default via BinaryBuilder; building them yourself requires the corresponding system toolchains.
Caution
The build will fail badly if any parent directory of the build tree contains spaces or shell metacharacters such as
$or:in its name. This is a limitation of GNU make. Keep the source path simple (e.g./home/user/julia).
Note
On macOS, run
xcode-select --installto provide the command-line tools; otherwise you may hit missing-header/library errors such asld: library not found for -lcrt1.10.6.o.
4.3 Supported platforms
The Julia project publishes official binaries and a tiered support matrix at https://julialang.org/downloads/support. The recommended runtime install on all platforms is Juliaup (see the User Guide).
5. Building Julia from Source
5.1 Acquire the source
git clone https://github.com/JuliaLang/julia.git
cd julia
By default you are on the latest unstable development branch. For production, check out a released tag:
git checkout v1.13.0 # replace with the desired release tag
Tip
Behind a firewall? Force HTTPS for git submodule/dependency fetches:
git config --global url."https://".insteadOf git://and set
https_proxy/http_proxyas needed.
5.2 Build
make
For a parallel build, pass the job count:
make -j 8
The first build downloads pre-built external dependencies automatically. When it completes, a julia symlink appears in the build directory (the real executable is under <build-directory>/usr/bin):
./julia
5.3 Verify
make testall
You should see a series of running tests complete without error.
5.4 Out-of-tree builds
make O=/path/to/builddir configure
make -C /path/to/builddir
Out-of-tree build directories share the source files and deps/srccache, and each can carry its own Make.user.
5.5 Install
Set a prefix in Make.user:
prefix=/opt/julia
then:
make install
Warning
If a Julia install already exists in the target prefix, delete it before
make install.
5.6 Air-gapped / self-built dependencies
To build every dependency from source (no network during build), put this in Make.user:
USE_BINARYBUILDER=0
5.7 Updating an existing tree
cd julia
git pull && make
If bootstrap fails after a large update, make clean && make (or, more rarely, make cleanall && make) usually resolves it.
5.8 Distribution artifacts
The top-level Makefile exposes targets for producing distributable artifacts:
| Target | Produces |
|---|---|
make binary-dist |
A binary distribution tarball (runs distclean first) |
make source-dist / make full-source-dist / make light-source-dist |
Source distributions |
make exe |
A standalone executable bundle |
make app / make darwinframework |
macOS .app / framework (see contrib/mac/) |
make win-extras |
Windows packaging extras |
See doc/src/devdocs/build/distributing.md for platform-specific packaging notes.
6. Build Configuration Reference (Make.user)
Build options are set in a Make.user file placed at the source root (or per out-of-tree build directory). Never edit Make.inc for this purpose — it documents the available variables at its top, but Make.user is the override mechanism.
Operationally important build variables:
| Variable | Effect |
|---|---|
prefix=<dir> |
Install location for make install |
USE_BINARYBUILDER=0 |
Build all external dependencies from source instead of downloading pre-built |
O=<dir> (on the make command line) |
Configure an out-of-tree build directory |
JULIA_CPU_TARGET=<targets> |
CPU multi-versioning target string baked into the build (see Section 8.4) |
JULIA_PRECOMPILE |
Whether to precompile the system image during build (inspect with make print-JULIA_PRECOMPILE) |
WITH_GC_DEBUG_ENV |
Enable GC-debug environment hooks (e.g. JULIA_GC_WAIT_FOR_DEBUGGER) |
USE_INTEL_JITEVENTS / USE_OPROFILE_JITEVENTS / USE_PERF_JITEVENTS |
Enable JIT-profiling integration (VTune / OProfile / Perf) |
JULIA_BUILD_MODE |
release or debug (the default target builds one of these) |
Tip
make debugandmake releasebuild the debug and release runtimes respectively;makealone builds whicheverJULIA_BUILD_MODEselects. The debug runtime islibjulia-debugand the executable isjulia-debug.
Dependency-wipe targets are invaluable when an external library is in a bad state:
make -C deps clean-llvm # rebuild LLVM from the cached source dist
make -C deps distclean-llvm # also re-download the LLVM source dist
7. The Runtime in Depth
7.1 Startup sequence
- The OS runs the loader (
cli/loader_exe.cmain). On Windows the entry ismainCRTStartup, which convertswchar_targuments to UTF-8 first. - The loader's constructor (
jl_load_libjulia_internal) opensDEP_LIBSin order, performing libstdc++ probing and re-exporting runtime symbols, then callsjl_init_options. - Fast TLS for the per-thread GC stack is installed (Linux/FreeBSD).
jl_load_repllooks up and jumps tojl_repl_entrypointinsidelibjulia-internal.- The runtime initializes (
init.c), loads the system image (Base + stdlib, pre-compiled), processes command-line options (jloptions.c), and dispatches to the REPL, a script, or an-eexpression.
7.2 Compilation pipeline
source text
│ flisp / JuliaSyntax (parse)
▼
surface AST
│ JuliaLowering (desugar → lowered IR)
▼
lowered Julia IR
│ Compiler/ (type inference, optimization)
▼
typed, optimized IR
│ codegen.cpp → LLVM IR → jitlayers.cpp (ORC JIT) [libjulia-codegen]
▼
native machine code ──► executed; cached in memory and (optionally) on disk
The first call of a function for a given argument-type signature triggers specialization + compilation; the result is reused. Disk caches (system images, package images, precompilation files) persist this work across sessions.
7.3 Garbage collection
Julia ships a generational, non-moving stock collector (gc-stock.c) and an alternative MMTk-based collector (gc-mmtk.c), chosen at build time. GC parallelism is controlled by --gcthreads=N[,M] / JULIA_NUM_GC_THREADS, and memory pressure by --heap-size-hint / JULIA_HEAP_SIZE_HINT. GC debugging facilities live in gc-debug.c; heap snapshots in gc-heap-snapshot.c (triggerable via JULIA_PROFILE_PEEK_HEAP_SNAPSHOT).
7.4 Tasks and threading
Julia tasks (task.c) are stackful coroutines scheduled across OS threads (threading.c). There are two threadpools: :default for compute and :interactive for latency-sensitive work, sized via -t N,M / JULIA_NUM_THREADS=N,M. JULIA_EXCLUSIVE affinitizes default-pool threads for dedicated machines; JULIA_THREAD_SLEEP_THRESHOLD tunes spin-then-sleep behavior.
7.5 Foreign-function interface
ccall.cpp implements ccall/@ccall, Julia's zero-overhead C/Fortran FFI. This is also the mechanism by which the *_jll artifact packages call into bundled native libraries.
8. System Images, Package Images, and AOT (juliac)
This is the heart of Julia deployment and performance tuning.
8.1 System images
A system image is a serialized snapshot of a compiled Julia world: Base, the standard library, and their compiled methods (staticdata.c handles (de)serialization). Julia starts from a default system image; -J/--sysimage <file> selects a different one.
Generate images and other static outputs with these julia switches:
| Switch | Output |
|---|---|
--output-ji <name> |
System image data file (.ji) |
--output-o <name> |
Object file including system image data |
--output-bc / --output-unopt-bc |
(Unoptimized) LLVM bitcode |
--output-asm |
Assembly |
--output-incremental={yes|no*} |
Incremental vs. complete output |
--strip-metadata |
Drop docstrings and source locations from the image |
--strip-ir |
Drop compiled-function IR from the image |
Tip
A custom system image that pre-compiles your application's hot paths is the most effective way to eliminate first-call latency in production and HPC jobs. The community tool PackageCompiler.jl wraps this workflow.
8.2 Package images (pkgimages)
Package images cache native code per package on disk. They are controlled by --pkgimages={yes*|no|existing} and --permalloc-pkgimg. JULIA_MAX_NUM_PRECOMPILE_FILES (default 10) bounds how many cached variants of a single package are kept.
8.3 Trimming and juliac
--trim={no*|safe|unsafe|unsafe-warn} builds a system image containing only code provably reachable from methods marked by entrypoint, enabling much smaller binaries. The in-tree juliac tooling (contrib/juliac/, installed as juliac.jl plus build scripts) drives the ahead-of-time compilation path (aotcompile.cpp).
--trim mode |
Dynamic call sites |
|---|---|
no (default) |
Full image, nothing trimmed |
safe |
Compile-time error on dynamic call sites |
unsafe |
Allowed; binary may be missing code and can error at runtime |
unsafe-warn |
Allowed with compile-time warnings; may error at runtime |
Warning
unsafe/unsafe-warntrimming can produce binaries that throw at runtime due to code that was trimmed away. Validate trimmed binaries against a representative workload before shipping.
8.4 CPU targeting & multi-versioning
Julia can emit multiple versions of code for different CPU feature sets (processor.cpp, llvm-multiversioning.cpp). Two distinct controls:
-C/--cpu-targetaffects in-memory JIT codegen for the current session.julia -C helplists valid targets.JULIA_CPU_TARGETaffects disk-cached images (system and package images) only — not the in-session JIT.
The target string is ;-separated; each entry is a CPU/architecture name plus optional comma-separated features. Special keywords: sysimage (reuse the running sysimage's target), clone_all (force-clone all functions), base(N) (base-target index), opt_size (-Os), min_size (-Oz).
Important
On heterogeneous HPC clusters where nodes have different processors, set
JULIA_CPU_TARGETto a target that is valid on the least capable node (or usesysimage) so cached code runs everywhere. Package images can only target the same or more specific features than their base system image.
9. Embedding libjulia
Julia exposes a C API (jlapi.c, header src/julia.h) so it can be embedded in larger C/C++ (or, via the C ABI, Rust/Python/C#) applications.
9.1 Minimal embedding (Unix)
#include <julia.h>
JULIA_DEFINE_FAST_TLS // define exactly once, in an executable (not a shared library)
int main(int argc, char *argv[])
{
jl_init(); // set up the Julia context
jl_eval_string("print(sqrt(2.0))"); // run Julia code
jl_atexit_hook(0); // flush writes, run finalizers
return 0;
}
Compile and link against libjulia (with Julia installed at $JULIA_DIR):
gcc -o test -fPIC -I$JULIA_DIR/include/julia -L$JULIA_DIR/lib \
-Wl,-rpath,$JULIA_DIR/lib test.c -ljulia
Note
jl_init()auto-detects the install location. Usejl_init_with_image_file/jl_init_with_image_handleto pin a custom location or system image.- Dynamically linking
libjuliacurrently requiresRTLD_GLOBAL.- If embedded Julia must see symbols from the host executable (Linux), add
-Wl,--export-dynamic.cli/loader_exe.citself is a worked example of settingjl_optionswhile linkinglibjulia;test/embedding/contains a full example program.
9.2 julia-config.jl
The julia-config.jl script (in Julia's shared data directory) emits the exact compiler/linker flags an embedding program needs for this distribution. Use it instead of hard-coding flags.
9.3 GC extensions
The test/gcext/ suite and the runtime's GC-extension hooks let embedders register foreign roots with the collector — relevant when the host application holds references to Julia objects.
10. Configuration & Environment Surface
Julia has no central config file for the runtime; configuration is expressed through (a) command-line switches, (b) environment variables, and (c) the user's startup.jl. The User Guide contains the complete switch and environment-variable reference. The admin-relevant highlights:
10.1 Path and depot control
| Variable | Operational role |
|---|---|
JULIA_DEPOT_PATH |
Where all package/cache/config/history state lives. Use a trailing : to override the user depot while keeping bundled resources; key for shared/read-only deployments. Set before startup. |
JULIA_LOAD_PATH |
Which environments/packages are loadable. Set before startup. |
JULIA_PROJECT |
The initial active environment. Set before startup. |
JULIA_BINDIR |
Override the detected executable directory (Sys.BINDIR). |
JULIA_HISTORY |
Relocate the REPL history file. |
10.2 Read-only / immutable deployments
For images deployed on read-only filesystems (containers, HPC scratch policies):
julia --compiled-modules=existing --pkgimages=existing --startup-file=no
This uses existing caches without attempting to write new ones. Point JULIA_DEPOT_PATH at a writable scratch location if any writes are needed.
10.3 Package server / network policy
| Variable | Use |
|---|---|
JULIA_PKG_SERVER |
Set the registry/package server URL; "" bypasses the PkgServer protocol |
JULIA_PKG_SERVER_REGISTRY_PREFERENCE |
conservative (firewall-safe default) vs. eager |
JULIA_PKG_OFFLINE |
Fully offline package operation |
JULIA_PKG_USE_CLI_GIT |
Use system git instead of libgit2 |
JULIA_SSL_CA_ROOTS_PATH, JULIA_*_VERIFY_HOSTS |
TLS/SSH host-verification policy |
10.4 Startup files (run order)
startup.jl is loaded from $JULIA_DEPOT_PATH/config/startup.jl (or ~/.julia/config/startup.jl). System-wide startup is searched at $JULIA_BINDIR/$SYSCONFDIR/julia/startup.jl and $JULIA_BINDIR/../etc/julia/startup.jl.
Caution
__init__()functions of modules baked into a system image (via PackageCompiler) run beforestartup.jl. Environment variables those modules read must be set before the process starts, not instartup.jl.
11. Operations
11.1 Deployment checklist
- [ ] Decide install method: Juliaup for interactive/dev, a pinned binary tarball or custom system image for production/HPC.
- [ ] Pin the Julia version (release tag or sysimage build).
- [ ] Set
JULIA_DEPOT_PATHto a writable, appropriately-sized location (caches and artifacts grow). - [ ] Set
JULIA_CPU_TARGETfor the target hardware (or the least-capable node on a heterogeneous cluster). - [ ] Decide on a custom system image to remove first-call latency for your workload.
- [ ] Configure package-server/network policy for the deployment's network posture.
- [ ] For containers/read-only roots: use
--compiled-modules=existing --pkgimages=existing. - [ ] Lock a consistent launch command (flags affect caching — see below).
11.2 Startup / shutdown
- Start:
julia [flags]. There is no daemon; each invocation is a process. For services, keep a long-lived process (the JIT warms up over time). - Stop:
exit()/exit(code)from Julia, Ctrl+D interactively, or a normal signal.--handle-signals={yes*|no}controls Julia's own signal handlers.
11.3 Logging and diagnostics
| Need | Mechanism |
|---|---|
| Debug logging for a module | JULIA_DEBUG=ModuleName |
| What is being compiled (and how long) | --trace-compile=stderr --trace-compile-timing |
| What is being dispatched | --trace-dispatch=stderr |
| Top-level expression tracing | --trace-eval=loc |
| Subsystem timing zones | JULIA_TIMING_SUBSYSTEMS=+GC,-INFERENCE |
| Heap snapshot | JULIA_PROFILE_PEEK_HEAP_SNAPSHOT |
| Per-task metrics | --task-metrics=yes |
| Allocation / coverage profiling | --track-allocation, --code-coverage |
Note
CI debug environment variables auto-enable
--trace-eval(location mode) and verbose test output, so re-running a failed CI job with debug logging needs no script changes.
11.4 Caching hygiene
Because optimization-affecting flags (-O, -g, --check-bounds) change generated code, changing them between runs invalidates and regenerates caches. Pin a single launch command per deployment to keep precompilation/pkgimage caches warm. Pkg's automatic artifact/package GC (disable with JULIA_PKG_GC_AUTO=false, Julia 1.12+) reclaims depot space.
11.5 Backup / state
The only persistent state Julia writes is under the depot (~/.julia by default): installed packages, registries, artifacts, compiled caches, config, and REPL history. Back up Project.toml + Manifest.toml for reproducibility; the rest of the depot is reconstructible from those plus the registries.
12. Security Analysis
Note
This section assesses the security-relevant behavior of the Julia implementation and toolchain as observed in the source tree. It is not a vulnerability assessment of any particular deployment.
12.1 Trust model
Julia executes arbitrary code by design — it is a programming language. There is no sandbox around user code: a .jl script, an -e expression, an include, or a loaded package can do anything the OS user can (file I/O, network, ccall into native code, spawning processes via shell mode / run). Treat running untrusted Julia code exactly as you would treat running an untrusted native binary.
12.2 Code loading & supply chain
- Package server / registries: packages are fetched from
JULIA_PKG_SERVER(defaulthttps://pkg.julialang.org). Artifact integrity is verified by hash;JULIA_PKG_IGNORE_HASHES=1disables that verification and should be used only as a last resort. - TLS/SSH host verification: governed by
JULIA_SSL_CA_ROOTS_PATHand theJULIA_*_VERIFY_HOSTSfamily. The defaultconservativeregistry preference is the firewall- and supply-chain-safer choice;eagerpublishes resources that haven't necessarily been processed by the storage servers. Manifest.tomlpinning is the primary supply-chain control: it records exact resolved versions and hashes, making environments reproducible and auditable.
12.3 Native library loading
The loader (cli/loader_lib.c) loads dependent libraries by relative path from the library directory (RPATH-style), reducing reliance on ambient LD_LIBRARY_PATH. On Linux it may prefer a system libstdc++ if it is newer (controllable via JULIA_PROBE_LIBSTDCXX), and it emulates the dynamic linker's library search (LD_LIBRARY_PATH → /etc/ld.so.cache → default libdirs) when probing for a system libstdc++. Operators who need fully hermetic loading can disable probing.
12.4 Memory safety
The runtime is C/C++ and is therefore subject to the usual memory-safety considerations of native code. The project maintains substantial defensive infrastructure:
- Clang Static Analyzer integration (
src/clangsa/,test/clangsa/) with custom checkers for Julia's GC-rooting invariants. - Sanitizer build support: AddressSanitizer (
contrib/asan/), ThreadSanitizer (contrib/tsan/), and MemorySanitizer wiring in the loader. The loader disablesRTLD_DEEPBINDand tweaks fork behavior under ASan/TSan. - GC-extension and gcext tests (
test/gcext/) exercise foreign-root registration.
12.5 Reporting vulnerabilities
Security issues are reported per the project's SECURITY.md. General bugs go to the GitHub issue tracker; a reproducible bug-report session can be captured with julia --bug-report=KIND.
13. Code Quality & Conventions
- License header: every source file carries
// This file is a part of Julia. License is MIT: https://julialang.org/license.contrib/add_license_to_files.jladds it. - Whitespace policy: enforced by
contrib/check-whitespace.jl; the build targetmake check-whitespace(andmake fix-whitespace) gate it.make testandmake testallboth runcheck-whitespacefirst. - C/C++ core, Julia stdlib: the deliberate split keeps the performance-critical, GC-aware machinery in C/C++ while the broad, evolving standard library is written in Julia and bootstrapped during the build.
- Multi-platform code is heavily
#ifdef-guarded (_OS_WINDOWS_,_OS_LINUX_,_OS_DARWIN_,_CPU_X86_64_, etc.), and Windows runs with bundled libc shims to avoid a libgcc dependency. - X-macro pattern: exported-symbol lists are generated via X-macros (
jl_exported_funcs.inc,jl_exported_data.inc) consumed incli/jl_exports.h— a single source of truth re-expanded for declarations, address tables, and name tables.
14. Testing Strategy
The test/ tree is driven by make test / make testall (and make testall1), which run runtests.jl with --check-bounds=yes --startup-file=no --depwarn=error. The test Makefile enumerates test groups dynamically.
| Test area | Directory | Exercises |
|---|---|---|
| Test groups | test/ (e.g. unicode, strings, compiler, Compiler, JuliaSyntax, JuliaLowering) |
Core language & compiler |
| Stdlib tests | stdlib/*/test/ |
Each standard-library package |
| Embedding | test/embedding/ |
The C embedding API end-to-end |
| GC extensions | test/gcext/ |
Foreign-root registration |
| Trimming / AOT | test/trimming/ |
--trim binaries |
| Static analysis | test/clangsa/ |
Clang Static Analyzer GC-rooting checks |
| LLVM passes | test/llvmpasses/ |
Custom LLVM optimization passes |
| Relocation | test/relocatedepot, RelocationTestPkg1–4 |
Depot relocatability |
Useful invocations:
make test # core tests
make testall # everything
make test-Dates # a single stdlib's tests (pattern: test-<Name>)
make -C test embedding # the embedding suite
Tip
The Revise-based flow (
make test ... revise=true,make revise-<group>) lets you re-test changes without rebuilding the system image.
15. Troubleshooting (Build & Deploy)
Error: bootstrap fails building the system image
- Cause: accumulated Base changes broke the bootstrap, or stale dependency builds.
- Solution:
make clean && make; if it persists,make cleanall && make. The build prints exactly this hint on such failures. - Prevention: rebuild after large
git pulls; avoid mixing incompatible dependency versions.
Error: library not found for -lcrt1.10.6.o (macOS)
- Cause: missing/outdated Xcode command-line tools after a macOS update.
- Solution:
xcode-select --install. - Prevention: reinstall the CLT after OS upgrades.
Error: CMake Error: ... CMakeCache.txt directory ... is different ...
- Cause: the source directory was moved after a dependency was configured.
- Solution: delete the offending dependency under
deps/so it reconfigures. - Prevention: don't relocate the source tree mid-build; use out-of-tree builds (
O=) for movable build dirs.
Problem: the build fails immediately with cryptic make errors
- Cause: a parent directory of the build tree contains a space or a shell metacharacter (
$,:). - Solution: move the source tree to a path with none of those characters.
- Prevention: keep build paths simple and ASCII.
Problem: build cannot reach the network
- Cause: default BinaryBuilder dependency downloads are blocked.
- Solution: set
USE_BINARYBUILDER=0inMake.userto build dependencies from source, or pre-seeddeps/srccache. - Prevention: for air-gapped CI, bake a
Make.userwithUSE_BINARYBUILDER=0and a populated srccache.
Problem: cached code keeps regenerating in production
- Cause: launch flags affecting codegen (
-O,-g,--check-bounds) vary between runs, or the depot is read-only. - Solution: pin one launch command; for read-only roots use
--compiled-modules=existing --pkgimages=existingand a writableJULIA_DEPOT_PATH. - Prevention: treat the launch command as part of the deployment artifact.
Problem: a custom/trimmed binary throws at runtime
- Cause:
--trim=unsafe/unsafe-warnremoved code reached via a dynamic call site. - Solution: rebuild with
--trim=safeto surface the offending sites at compile time, or mark the needed entry points. - Prevention: validate trimmed binaries against a representative workload before release.
Problem: third-party native libraries fail to load alongside Julia (Linux)
- Cause: libstdc++ version mismatch between the bundled and system copies.
- Solution: Julia's loader probes for and prefers a newer system libstdc++ automatically; control it with
JULIA_PROBE_LIBSTDCXX(1/0). - Prevention: ensure the system libstdc++ is current, or disable probing for fully hermetic loading.
Problem: GC waits forever / want to attach a debugger on a GC crash
- Cause:
JULIA_GC_WAIT_FOR_DEBUGGERis set, but it only works on a GC-debug build. - Solution: build with
WITH_GC_DEBUG_ENV=1; then set the variable and attach your debugger.
16. Potential Improvements
Observations for maintainers and integrators, derived from the source layout:
- First-call latency remains the headline ergonomic cost of the JIT model. The trajectory (precompilation → pkgimages →
--trim/juliacAOT) is clearly toward smaller, faster-starting artifacts; investing in custom system images is the most reliable operator-side mitigation today. - Dual GC (
gc-stock.c+gc-mmtk.c) signals an in-progress collector strategy; deployments sensitive to pause behavior should track which collector their build selects and benchmark both. - Optional codegen library (
libjulia-codegen) enables shipping run-only distributions (delete codegen to save space) — useful for locked-down or size-constrained deployments where new code generation is unnecessary. - CPU multi-versioning is powerful but easy to misconfigure on heterogeneous clusters; documenting an organization-standard
JULIA_CPU_TARGETper hardware tier avoids "illegal instruction" surprises.
17. Contributing
The project welcomes contributions from developers of all experience levels — bug fixes, documentation, tests, and performance work. New contributors should start with CONTRIBUTING.md.
Important
If a pull request contains substantial contributions from a generative AI tool, the project asks that you disclose this with details and review all changes before opening. This also applies to issues, discussions, and comments.
Local workflow:
git clone https://github.com/JuliaLang/julia.git
cd julia
make -j$(nproc)
make check-whitespace # gate your change passes whitespace policy
make testall # or a targeted test group, e.g. make test-strings
Documentation is built with Documenter.jl: make docs (HTML into doc/_build/), and doctests run via make -C doc doctest=true.
18. Quick Reference
18.1 Build commands
| Command | Purpose |
|---|---|
make / make -j N |
Build (parallel) |
make debug / make release |
Build a specific runtime variant |
make install (with prefix= in Make.user) |
Install |
make testall |
Run the full test suite |
make test-<Name> |
Run one test group / stdlib |
make docs |
Build the HTML manual |
make clean / make cleanall |
Clean (light / deep) |
make binary-dist |
Produce a binary distribution |
make print-<VAR> |
Print a build variable |
make -C deps clean-<dep> |
Rebuild one dependency |
18.2 Key build variables (Make.user)
| Variable | Purpose |
|---|---|
prefix=<dir> |
Install location |
USE_BINARYBUILDER=0 |
Build deps from source (air-gapped) |
JULIA_CPU_TARGET=<targets> |
Baked-in CPU multi-versioning |
O=<dir> (cmdline) |
Out-of-tree build dir |
WITH_GC_DEBUG_ENV=1 |
Enable GC-debug env hooks |
USE_*_JITEVENTS=1 |
JIT-profiling integration |
18.3 Runtime libraries
| Library | Role |
|---|---|
julia (loader) |
Locates and loads the runtime, jumps to jl_repl_entrypoint |
libjulia |
Public shared library (embedding target) |
libjulia-internal |
The runtime: types, dispatch, GC, tasks, sysimage |
libjulia-codegen |
LLVM code generation (optional; falls back to internal) |
libjulia-debug / julia-debug |
Debug-build variants |
18.4 Source map (where to look)
| To understand… | Read… |
|---|---|
| Launch/loading | cli/loader_exe.c, cli/loader_lib.c |
| Option parsing | src/jloptions.c, src/jloptions.h |
| Embedding API | src/jlapi.c, src/julia.h |
| Codegen / JIT | src/codegen.cpp, src/jitlayers.cpp, src/aotcompile.cpp |
| Type system / dispatch | src/jltypes.c, src/subtype.c, src/gf.c, src/method.c |
| GC | src/gc-stock.c, src/gc-mmtk.c |
| Tasks / threads | src/task.c, src/threading.c |
| System image | src/staticdata.c |
| CLI reference | doc/man/julia.1, doc/src/manual/command-line-interface.md |
| Env-var reference | doc/src/manual/environment-variables.md |
| Build instructions | README.md, doc/src/devdocs/build/build.md |
18.5 Official resources
| Resource | URL |
|---|---|
| Homepage | https://julialang.org |
| Documentation | https://docs.julialang.org |
| Install | https://julialang.org/install/ |
| Packages / Pkg docs | https://julialang.org/packages/ · https://pkgdocs.julialang.org |
| Source | https://github.com/JuliaLang/julia |
| Issues | https://github.com/JuliaLang/julia/issues |
| Discourse / Zulip / Slack | linked from https://julialang.org |