Skip to content

Embedded C compiler and linker via LLVM

Use embedded Clang and LLVM to compile freestanding C17 into object files or LLVM IR, or link and invoke a native function in memory through ORC LLJIT.

On this page

elide cc embeds Clang compilation and LLVM’s ORC LLJIT execution pipeline. Compile one freestanding C17 translation unit for the current host, emit an object file or textual LLVM IR, or link and invoke a native function in memory. These operations require no separate compiler installation.

Frontend scope

Native tools are part of Elide 1.6.2. The initial CLI exposes object output, LLVM IR output and in-memory JIT execution. It does not expose executable or shared-library output, system headers, include paths, library selection or cross-compilation.

Compile a C source file

answer.c:

long long answer(void) {
  return 42;
}

Compile it to a native object file:

elide cc -- -c answer.c -o answer.o

answer.o is a host-native relocatable object. To produce an executable or shared library from it, pass it to a full compiler driver or linker; the current cc CLI does not expose those output modes.

Without -o, Elide writes the source basename with an .o extension in the current working directory: elide cc -- -c src/answer.c produces ./answer.o.

Inspect LLVM IR

Select both -S and -emit-llvm to write textual LLVM IR:

elide cc -- -S -emit-llvm answer.c -o answer.ll

Without -o, the output is answer.ll in the current directory. -S alone does not emit assembly, and -c -emit-llvm does not emit bitcode; these combinations are rejected.

Invoke a native function

Compile the same source to LLVM IR, JIT-compile and link it in memory, then invoke answer:

elide cc -- --run answer answer.c
42

The entry point must be defined with the C calling convention, no arguments, no varargs and an LLVM i64 return type, represented here by long long. int, floating-point, pointer and void return types are rejected for the entry point.

Elide prints the signed 64-bit result and exits successfully. The returned value does not become the shell exit status: returning 42 still gives exit status 0. --run creates no object or executable file and cannot be combined with -c, -S, -emit-llvm or -o.

ORC LLJIT owns compilation, in-memory linking and symbol lookup for that invocation. The JIT and its code are released after the call; functions and native addresses do not persist across commands. The CLI does not expose argument passing or external library loading. Native code executes with the process’s privileges; invalid memory access or other native faults can terminate the process.

Options

Pass compiler arguments after --:

OptionBehavior
-cWrite a native object file.
-S -emit-llvmWrite textual LLVM IR.
-o PATHSet the object or IR output path.
--run SYMBOLCompile, link in memory and invoke a no-argument function returning long long.
--help, -hShow the embedded compiler’s help.
elide cc -- --help

Exactly one source file and one output mode are required. Other compiler-driver options, including -I, -D, -l, -O and --target, are not accepted. The command refuses to overwrite its source with its output.

Headers and toolchain boundaries

The embedded compiler uses freestanding C17 with standard include discovery disabled. Write self-contained translation units; installed host headers and bundled Native Image sysroots are not exposed through cc. Adding SDKROOT does not enable system includes in this command.

Elide also packages a full Clang driver, LLD and target resources for Native Image. That driver handles Native Image’s C compilation and final executable or shared-library link; elide cc -- --run uses ORC LLJIT for in-memory linking. On macOS, Native Image requires an explicit SDKROOT until the distribution includes an Apple SDK. The freestanding examples above need no Apple SDK.

To generate Java bindings for an existing C library, use jextract, or compile bindings directly with Java C header bindings.

Availability

Elide distributionEmbedded cc
macOS arm64Supported.
Dynamically linked Linux amd64 or arm64Supported.
Fully static Linux / musl ElideNot included.
WindowsNot included.

The supported distributions include native tools alongside the JVM toolchain and load the compiler payload when needed. A custom build made with --no-jvm-toolchain omits both. Having JVM tools on Windows or a fully static build does not imply that cc or jextract is available.

A dynamically linked Linux Elide can still build a musl-targeted Native Image when its distribution includes the appropriate sysroot; that is separate from running native tools inside a fully static Elide binary.

Was this page helpful?