Codegen Options

All of these options are passed to rustc via the -C flag, short for "codegen." You can see a version of this list for your exact compiler by running rustc -C help.

ar

This option is deprecated and does nothing.

code-model

This option lets you choose which code model to use.
Code models put constraints on address ranges that the program and its symbols may use.
With smaller address ranges machine instructions may be able to use more compact addressing modes.

The specific ranges depend on target architectures and addressing modes available to them.
For x86 more detailed description of its code models can be found in System V Application Binary Interface specification.

Supported values for this option are:

Supported values can also be discovered by running rustc --print code-models.

codegen-units

This flag controls the maximum number of code generation units the crate is split into. It takes an integer greater than 0.

When a crate is split into multiple codegen units, LLVM is able to process them in parallel. Increasing parallelism may speed up compile times, but may also produce slower code. Setting this to 1 may improve the performance of generated code, but may be slower to compile.

The default value, if not specified, is 16 for non-incremental builds. For incremental builds the default is 256 which allows caching to be more granular.

collapse-macro-debuginfo

This flag controls whether code locations from a macro definition are collapsed into a single location associated with that macro's call site, when generating debuginfo for this crate.

This option, if passed, overrides both default collapsing behavior and #[collapse_debuginfo] attributes in code.

control-flow-guard

This flag controls whether LLVM enables the Windows Control Flow Guard platform security feature. This flag is currently ignored for non-Windows targets. It takes one of the following values:

debug-assertions

This flag lets you turn cfg(debug_assertions) conditional compilation on or off. It takes one of the following values:

If not specified, debug assertions are automatically enabled only if the opt-level is 0.

debuginfo

This flag controls the generation of debug information. It takes one of the following values:

Note: The -g flag is an alias for -C debuginfo=2.

default-linker-libraries

This flag controls whether or not the linker includes its default libraries. It takes one of the following values:

For example, for gcc flavor linkers, this issues the -nodefaultlibs flag to the linker.

dlltool

On windows-gnu targets, this flag controls which dlltool rustc invokes to generate import libraries when using the raw-dylib link kind. It takes a path to the dlltool executable. If this flag is not specified, a dlltool executable will be inferred based on the host environment and target.

dwarf-version

This option controls the version of DWARF that the compiler emits, on platforms that use DWARF to encode debug information. It takes one of the following values:

DWARF version 1 is not supported.

embed-bitcode

This flag controls whether or not the compiler embeds LLVM bitcode into object files. It takes one of the following values:

LLVM bitcode is required when rustc is performing link-time optimization (LTO). Embedded bitcode will appear in rustc-generated object files inside of a section whose name is defined by the target platform. Most of the time this is .llvmbc.

The use of -C embed-bitcode=no can significantly improve compile times and reduce generated file sizes if your compilation does not actually need bitcode (e.g. if you're not performing LTO). For these reasons, Cargo uses -C embed-bitcode=no whenever possible. Likewise, if you are building directly with rustc we recommend using -C embed-bitcode=no whenever you are not using LTO.

If combined with -C lto, -C embed-bitcode=no will cause rustc to abort at start-up, because the combination is invalid.

Note: if you're building Rust code with LTO then you probably don't even need the embed-bitcode option turned on. You'll likely want to use -Clinker-plugin-lto instead which skips generating object files entirely and simply replaces object files with LLVM bitcode. The only purpose for -Cembed-bitcode is when you're generating an rlib that is both being used with and without LTO. For example Rust's standard library ships with embedded bitcode since users link to it both with and without LTO.

This also may make you wonder why the default is yes for this option. The reason for that is that it's how it was for rustc 1.44 and prior. In 1.45 this option was added to turn off what had always been the default.

extra-filename

This option allows you to put extra data in each output filename. It takes a string to add as a suffix to the filename. See the --emit flag for more information.

force-frame-pointers

This flag forces the use of frame pointers. It takes one of the following values:

The default behaviour, if frame pointers are not force-enabled, depends on the target.

force-unwind-tables

This flag forces the generation of unwind tables. It takes one of the following values:

The default if not specified depends on the target.

incremental

This flag allows you to enable incremental compilation, which allows rustc to save information after compiling a crate to be reused when recompiling the crate, improving re-compile times. This takes a path to a directory where incremental files will be stored.

Using incremental compilation inhibits certain optimizations (for example by increasing the amount of codegen units) and is therefore not recommended for release builds.

inline-threshold

This option is deprecated and does nothing.

Consider using -Cllvm-args=--inline-threshold=....

instrument-coverage

This option enables instrumentation-based code coverage support. See the chapter on instrumentation-based code coverage for more information.

Note that while the -C instrument-coverage option is stable, the profile data format produced by the resulting instrumentation may change, and may not work with coverage tools other than those built and shipped with the compiler.

link-arg

This flag lets you append a single extra argument to the linker invocation.

"Append" is significant; you can pass this flag multiple times to add multiple arguments.

On Unix-like targets that use cc as the linker driver, use -Clink-arg=-Wl,$ARG to pass an argument to the actual linker.

link-args

This flag lets you append multiple extra arguments to the linker invocation. The options should be separated by spaces.

link-dead-code

Tries to generate and link dead code that would otherwise not be generated or linked. It takes one of the following values:

This flag was historically used to help improve some older forms of code coverage measurement. Its use is not recommended.

link-self-contained

This flag controls whether the linker will use libraries and objects shipped with Rust instead of those in the system. It also controls which binary is used for the linker itself. This allows overriding cases when detection fails or the user wants to use shipped libraries.

You can enable or disable the usage of any self-contained components using one of the following values:

It is also possible to enable or disable specific self-contained components in a more granular way. You can pass a comma-separated list of self-contained components, individually enabled (+component) or disabled (-component).

Currently, only the linker granular option is stabilized, and only on the x86_64-unknown-linux-gnu target:

Note that only the -linker opt-out is stable on the x86_64-unknown-linux-gnu target: +linker is already the default on this target.

Implementation notes

On the x86_64-unknown-linux-gnu target, when using the default linker flavor (using cc as the linker driver) and linker features (to try using lld), rustc will try to use the self-contained linker by passing a -B /path/to/sysroot/ link argument to the driver to find rust-lld in the sysroot. For backwards-compatibility, and to limit name and PATH collisions, this is done using a shim executable (the lld-wrapper tool) that forwards execution to the rust-lld executable itself.

linker

This flag controls which linker rustc invokes to link your code. It takes a path to the linker executable. If this flag is not specified, the linker will be inferred based on the target. See also the linker-flavor flag for another way to specify the linker.

Note that on Unix-like targets (for example, *-unknown-linux-gnu or *-unknown-freebsd) the C compiler (for example cc or clang) is used as the "linker" here, serving as a linker driver. It will invoke the actual linker with all the necessary flags to be able to link against the system libraries like libc.

linker-features

The -Clinker-features flag allows enabling or disabling specific features used during linking.

These feature flags are a flexible extension mechanism that is complementary to linker flavors, designed to avoid the combinatorial explosion of having to create a new set of flavors for each linker feature we'd want to use.

The flag accepts a comma-separated list of features, individually enabled (+feature) or disabled (-feature).

Currently only one is stable, and only on the x86_64-unknown-linux-gnu target:

For example, use:

Note that only the -lld opt-out is stable on the x86_64-unknown-linux-gnu target: +lld is already the default on this target.

Implementation notes

On the x86_64-unknown-linux-gnu target, when using the default linker flavor (using cc as the linker driver), rustc will try to use lld by passing a -fuse-ld=lld link argument to the driver. rustc will also try to detect if that causes an error during linking (for example, if GCC is too old to understand the flag, and returns an error) and will then retry linking without this argument, as a fallback.

If the user also passes a -Clink-arg=-fuse-ld=$value, both will be given to the linker driver but the user's will be passed last, and would generally have priority over rustc's.

linker-flavor

This flag controls the linker flavor used by rustc. If a linker is given with the -C linker flag, then the linker flavor is inferred from the value provided. If no linker is given then the linker flavor is used to determine the linker to use. Every rustc target defaults to some linker flavor. Valid options are:

linker-plugin-lto

This flag defers LTO optimizations to the linker. See linker-plugin-LTO for more details. It takes one of the following values:

More specifically this flag will cause the compiler to replace its typical object file output with LLVM bitcode files. For example an rlib produced with -Clinker-plugin-lto will still have *.o files in it, but they'll all be LLVM bitcode instead of actual machine code. It is expected that the native platform linker is capable of loading these LLVM bitcode files and generating code at link time (typically after performing optimizations).

Note that rustc can also read its own object files produced with -Clinker-plugin-lto. If an rlib is only ever going to get used later with a -Clto compilation then you can pass -Clinker-plugin-lto to speed up compilation and avoid generating object files that aren't used.

llvm-args

This flag can be used to pass a list of arguments directly to LLVM.

The list must be separated by spaces.

Pass --help to see a list of options.

Because this flag directly talks to LLVM, it is not subject to the usual stability guarantees of rustc's CLI interface.

lto

This flag controls whether LLVM uses link time optimizations to produce better optimized code, using whole-program analysis, at the cost of longer linking time. It takes one of the following values:

If -C lto is not specified, then the compiler will attempt to perform "thin local LTO" which performs "thin" LTO on the local crate only across its codegen units. When -C lto is not specified, LTO is disabled if codegen units is 1 or optimizations are disabled (-C opt-level=0). That is:

See also linker-plugin-lto for cross-language LTO.

metadata

This option allows you to control the metadata used for symbol mangling. This takes a space-separated list of strings. Mangled symbols will incorporate a hash of the metadata. This may be used, for example, to differentiate symbols between two different versions of the same crate being linked.

no-prepopulate-passes

This flag tells the pass manager to use an empty list of passes, instead of the usual pre-populated list of passes.

When combined with -O --emit llvm-ir, it can be used to see the optimized LLVM IR emitted by rustc before any optimizations are applied by LLVM.

no-redzone

This flag allows you to disable the red zone. It takes one of the following values:

The default behaviour, if the flag is not specified, depends on the target.

no-stack-check

This option is deprecated and does nothing.

no-vectorize-loops

This flag disables loop vectorization.

no-vectorize-slp

This flag disables vectorization using superword-level parallelism.

opt-level

This flag controls the optimization level.

Note: The -O flag is an alias for -C opt-level=3.

The default is 0.

overflow-checks

This flag allows you to control the behavior of runtime integer overflow. When overflow-checks are enabled, a panic will occur on overflow. This flag takes one of the following values:

If not specified, overflow checks are enabled if debug-assertions are enabled, disabled otherwise.

panic

This option lets you control what happens when the code panics.

If not specified, the default depends on the target.

If any crate in the crate graph uses abort, the final binary (bin, dylib, cdylib, staticlib) must also use abort. If std is used as a dylib with unwind, the final binary must also use unwind.

passes

This flag can be used to add extra LLVM passes to the compilation.

The list must be separated by spaces.

See also the no-prepopulate-passes flag.

Because this flag directly talks to LLVM, it not subject to the usual stability guarantees of rustc's CLI interface.

prefer-dynamic

By default, rustc prefers to statically link dependencies. This option will indicate that dynamic linking should be used if possible if both a static and dynamic versions of a library are available.

There is an internal algorithm for determining whether or not it is possible to statically or dynamically link with a dependency.

This flag takes one of the following values:

profile-generate

This flag allows for creating instrumented binaries that will collect profiling data for use with profile-guided optimization (PGO). The flag takes an optional argument which is the path to a directory into which the instrumented binary will emit the collected data. See the chapter on profile-guided optimization for more information.

profile-use

This flag specifies the profiling data file to be used for profile-guided optimization (PGO). The flag takes a mandatory argument which is the path to a valid .profdata file. See the chapter on profile-guided optimization for more information.

relocation-model

This option controls generation of position-independent code (PIC).

Supported values for this option are:

Primary relocation models

Special relocation models

Supported values can also be discovered by running rustc --print relocation-models.

Linking effects

In addition to codegen effects, relocation-model has effects during linking.

If the relocation model is pic and the current target supports position-independent executables (PIE), the linker will be instructed (-pie) to produce one.
If the target doesn't support both position-independent and statically linked executables, then -C target-feature=+crt-static "wins" over -C relocation-model=pic, and the linker is instructed (-static) to produce a statically linked but not position-independent executable.

relro-level

This flag controls what level of RELRO (Relocation Read-Only) is enabled. RELRO is an exploit mitigation which makes the Global Offset Table (GOT) read-only.

Supported values for this option are:

This flag is ignored on platforms where RELRO is not supported (targets which do not use the ELF binary format), such as Windows or macOS. Each rustc target has its own default for RELRO. rustc enables Full RELRO by default on platforms where it is supported.

remark

This flag lets you print remarks for optimization passes.

The list of passes should be separated by spaces.

all will remark on every pass.

rpath

This flag controls whether rustc sets an rpath for the binary. It takes one of the following values:

This flag only does something on Unix-like platforms (Mach-O and ELF), it is ignored on other platforms.

If enabled, rustc will add output-relative (using @load_path on Mach-O and $ORIGIN on ELF respectively) rpaths to all dylib dependencies.

For example, for the following directory structure, with libdep.so being a dylib crate compiled with -Cprefer-dynamic:

dep
 |- libdep.so
a.rs

rustc a.rs --extern dep=dep/libdep.so -Crpath will, on x86-64 Linux, result in approximately the following DT_RUNPATH: $ORIGIN/dep:$ORIGIN/$RELATIVE_PATH_TO_SYSROOT/lib/rustlib/x86_64-unknown-linux-gnu/lib (where RELATIVE_PATH_TO_SYSROOT depends on the build directory location).

This is primarily useful for local development, to ensure that all the dylib dependencies can be found appropriately.

To set the rpath to a different value (which can be useful for distribution), -Clink-arg with a platform-specific linker argument can be used to set the rpath directly.

save-temps

This flag controls whether temporary files generated during compilation are deleted once compilation finishes. It takes one of the following values:

soft-float

This option controls whether rustc generates code that emulates floating point instructions in software. It takes one of the following values:

This flag only works on *eabihf targets and is unsound and deprecated.

split-debuginfo

This option controls the emission of "split debuginfo" for debug information that rustc generates. The default behavior of this option is platform-specific, and not all possible values for this option work on all platforms. Possible values are:

Note that all three options are supported on Linux and Apple platforms, packed is supported on Windows-MSVC, and all other platforms support off. Attempting to use an unsupported option requires using the nightly channel with the -Z unstable-options flag.

strip

The option -C strip=val controls stripping of debuginfo and similar auxiliary data from binaries during linking.

Supported values for this option are:

Note that, at any level, removing debuginfo only necessarily impacts "friendly" introspection. -Cstrip cannot be relied on as a meaningful security or obfuscation measure, as disassemblers and decompilers can extract considerable information even in the absence of symbols.

symbol-mangling-version

This option controls the name mangling format for encoding Rust item names for the purpose of generating object code and linking.

Supported values for this option are:

The default, if not specified, will use a compiler-chosen default which may change in the future.

See the Symbol Mangling chapter for details on symbol mangling and the mangling format.

target-cpu

This instructs rustc to generate code specifically for a particular processor.

You can run rustc --print target-cpus to see the valid options to pass and the default target CPU for the current build target. Each target has a default base CPU. Special values include:

target-feature

Individual targets will support different features; this flag lets you control enabling or disabling a feature. Each feature should be prefixed with a + to enable it or - to disable it.

Features from multiple -C target-feature options are combined.
Multiple features can be specified in a single option by separating them with commas - -C target-feature=+x,-y.
If some feature is specified more than once with both + and -, then values passed later override values passed earlier.
For example, -C target-feature=+x,-y,+z -Ctarget-feature=-x,+y is equivalent to -C target-feature=-x,+y,+z.

To see the valid options and an example of use, run rustc --print target-features.

Using this flag is unsafe and might result in undefined runtime behavior.

See also the target_feature attribute for controlling features per-function.

This also supports the feature +crt-static and -crt-static to control static C runtime linkage.

Each target and target-cpu has a default set of enabled features.

tune-cpu

This instructs rustc to schedule code specifically for a particular processor. This does not affect the compatibility (instruction sets or ABI), but should make your code slightly more efficient on the selected CPU.

The valid options are the same as those for target-cpu. The default is None, which LLVM translates as the target-cpu.

This is an unstable option. Use -Z tune-cpu=machine to specify a value.

Due to limitations in LLVM (12.0.0-git9218f92), this option is currently effective only for x86 targets.