Struct Build

struct Build { ... }

A builder for compilation of a native library.

A Build is the main type of the cc crate and is used to control all the various configuration options and such of a compile. You'll find more documentation on each method itself.

Implementations

impl Build

fn is_flag_supported<impl AsRef<OsStr>: AsRef<OsStr>>(self: &Self, flag: impl AsRef<OsStr>) -> Result<bool, Error>

Run the compiler to test if it accepts the given flag.

For a convenience method for setting flags conditionally, see flag_if_supported().

It may return error if it's unable to run the compiler with a test file (e.g. the compiler is missing or a write to the out_dir failed).

Note: Once computed, the result of this call is stored in the known_flag_support field. If is_flag_supported(flag) is called again, the result will be read from the hash table.

fn try_compile(self: &Self, output: &str) -> Result<(), Error>

Run the compiler, generating the file output

This will return a result instead of panicking; see [Self::compile()] for the complete description.

fn compile(self: &Self, output: &str)

Run the compiler, generating the file output

Library name

The output string argument determines the file name for the compiled library. The Rust compiler will create an assembly named "lib"+output+".a". MSVC will create a file named output+".lib".

The choice of output is close to arbitrary, but:

  • must be nonempty,
  • must not contain a path separator (/),
  • must be unique across all compile invocations made by the same build script.

If your build script compiles a single source file, the base name of that source file would usually be reasonable:

cc::Build::new().file("blobstore.c").compile("blobstore");

Compiling multiple source files, some people use their crate's name, or their crate's name + "-cc".

Otherwise, please use your imagination.

For backwards compatibility, if output starts with "lib" and ends with ".a", a second "lib" prefix and ".a" suffix do not get added on, but this usage is deprecated; please omit lib and .a in the argument that you pass.

Panics

Panics if output is not formatted correctly or if one of the underlying compiler commands fails. It can also panic if it fails reading file names or creating directories.

fn compile_intermediates(self: &Self) -> Vec<PathBuf>

Run the compiler, generating intermediate files, but without linking them into an archive file.

This will return a list of compiled object files, in the same order as they were passed in as file/files methods.

fn try_compile_intermediates(self: &Self) -> Result<Vec<PathBuf>, Error>

Run the compiler, generating intermediate files, but without linking them into an archive file.

This will return a result instead of panicking; see compile_intermediates() for the complete description.

fn try_expand(self: &Self) -> Result<Vec<u8>, Error>

This will return a result instead of panicking; see [Self::expand()] for the complete description.

fn expand(self: &Self) -> Vec<u8>

Run the compiler, returning the macro-expanded version of the input files.

This is only relevant for C and C++ files.

Panics

Panics if more than one file is present in the config, or if compiler path has an invalid file name.

Example

let out = cc::Build::new().file("src/foo.c").expand();
fn get_compiler(self: &Self) -> Tool

Get the compiler that's in use for this configuration.

This function will return a Tool which represents the culmination of this configuration at a snapshot in time. The returned compiler can be inspected (e.g. the path, arguments, environment) to forward along to other tools, or the to_command method can be used to invoke the compiler itself.

This method will take into account all configuration such as debug information, optimization level, include directories, defines, etc. Additionally, the compiler binary in use follows the standard conventions for this path, e.g. looking at the explicitly set compiler, environment variables (a number of which are inspected here), and then falling back to the default configuration.

Panics

Panics if an error occurred while determining the architecture.

fn try_get_compiler(self: &Self) -> Result<Tool, Error>

Get the compiler that's in use for this configuration.

This will return a result instead of panicking; see get_compiler() for the complete description.

fn get_archiver(self: &Self) -> Command

Get the archiver (ar) that's in use for this configuration.

You can use Command::get_program to get just the path to the command.

This method will take into account all configuration such as debug information, optimization level, include directories, defines, etc. Additionally, the compiler binary in use follows the standard conventions for this path, e.g. looking at the explicitly set compiler, environment variables (a number of which are inspected here), and then falling back to the default configuration.

Panics

Panics if an error occurred while determining the architecture.

fn try_get_archiver(self: &Self) -> Result<Command, Error>

Get the archiver that's in use for this configuration.

This will return a result instead of panicking; see Self::get_archiver for the complete description.

fn get_ranlib(self: &Self) -> Command

Get the ranlib that's in use for this configuration.

You can use Command::get_program to get just the path to the command.

This method will take into account all configuration such as debug information, optimization level, include directories, defines, etc. Additionally, the compiler binary in use follows the standard conventions for this path, e.g. looking at the explicitly set compiler, environment variables (a number of which are inspected here), and then falling back to the default configuration.

Panics

Panics if an error occurred while determining the architecture.

fn try_get_ranlib(self: &Self) -> Result<Command, Error>

Get the ranlib that's in use for this configuration.

This will return a result instead of panicking; see Self::get_ranlib for the complete description.

impl Build

fn new() -> Build

Construct a new instance of a blank set of configuration.

This builder is finished with the compile function.

fn include<P: AsRef<Path>>(self: &mut Self, dir: P) -> &mut Build

Add a directory to the -I or include path for headers

Example

use std::path::Path;

let library_path = Path::new("/path/to/library");

cc::Build::new()
    .file("src/foo.c")
    .include(library_path)
    .include("src")
    .compile("foo");
fn includes<P>(self: &mut Self, dirs: P) -> &mut Build
where
    P: IntoIterator,
    <P as >::Item: AsRef<Path>

Add multiple directories to the -I include path.

Example

# use std::path::Path;
# let condition = true;
#
let mut extra_dir = None;
if condition {
    extra_dir = Some(Path::new("/path/to"));
}

cc::Build::new()
    .file("src/foo.c")
    .includes(extra_dir)
    .compile("foo");
fn define<'a, V: Into<Option<&'a str>>>(self: &mut Self, var: &str, val: V) -> &mut Build

Specify a -D variable with an optional value.

Example

cc::Build::new()
    .file("src/foo.c")
    .define("FOO", "BAR")
    .define("BAZ", None)
    .compile("foo");
fn object<P: AsRef<Path>>(self: &mut Self, obj: P) -> &mut Build

Add an arbitrary object file to link in

fn objects<P>(self: &mut Self, objs: P) -> &mut Build
where
    P: IntoIterator,
    <P as >::Item: AsRef<Path>

Add arbitrary object files to link in

fn flag<impl AsRef<OsStr>: AsRef<OsStr>>(self: &mut Self, flag: impl AsRef<OsStr>) -> &mut Build

Add an arbitrary flag to the invocation of the compiler

Example

cc::Build::new()
    .file("src/foo.c")
    .flag("-ffunction-sections")
    .compile("foo");
fn flags<Iter>(self: &mut Self, flags: Iter) -> &mut Build
where
    Iter: IntoIterator,
    <Iter as >::Item: AsRef<OsStr>

Add multiple flags to the invocation of the compiler. This is equivalent to calling flag for each item in the iterator.

Example

cc::Build::new()
    .file("src/foo.c")
    .flags(["-Wall", "-Wextra"])
    .compile("foo");
fn remove_flag(self: &mut Self, flag: &str) -> &mut Build

Removes a compiler flag that was added by Build::flag.

Will not remove flags added by other means (default flags, flags from env, and so on).

Example

cc::Build::new()
    .file("src/foo.c")
    .flag("unwanted_flag")
    .remove_flag("unwanted_flag");
fn ar_flag<impl AsRef<OsStr>: AsRef<OsStr>>(self: &mut Self, flag: impl AsRef<OsStr>) -> &mut Build

Add a flag to the invocation of the ar

Example

cc::Build::new()
    .file("src/foo.c")
    .file("src/bar.c")
    .ar_flag("/NODEFAULTLIB:libc.dll")
    .compile("foo");
fn asm_flag<impl AsRef<OsStr>: AsRef<OsStr>>(self: &mut Self, flag: impl AsRef<OsStr>) -> &mut Build

Add a flag that will only be used with assembly files.

The flag will be applied to input files with either a .s or .asm extension (case insensitive).

Example

cc::Build::new()
    .asm_flag("-Wa,-defsym,abc=1")
    .file("src/foo.S")  // The asm flag will be applied here
    .file("src/bar.c")  // The asm flag will not be applied here
    .compile("foo");
fn flag_if_supported<impl AsRef<OsStr>: AsRef<OsStr>>(self: &mut Self, flag: impl AsRef<OsStr>) -> &mut Build

Add an arbitrary flag to the invocation of the compiler if it supports it

Example

cc::Build::new()
    .file("src/foo.c")
    .flag_if_supported("-Wlogical-op") // only supported by GCC
    .flag_if_supported("-Wunreachable-code") // only supported by clang
    .compile("foo");
fn try_flags_from_environment(self: &mut Self, environ_key: &str) -> Result<&mut Build, Error>

Add flags from the specified environment variable.

Normally the cc crate will consult with the standard set of environment variables (such as CFLAGS and CXXFLAGS) to construct the compiler invocation. Use of this method provides additional levers for the end user to use when configuring the build process.

Just like the standard variables, this method will search for an environment variable with appropriate target prefixes, when appropriate.

Examples

This method is particularly beneficial in introducing the ability to specify crate-specific flags.

cc::Build::new()
    .file("src/foo.c")
    .try_flags_from_environment(concat!(env!("CARGO_PKG_NAME"), "_CFLAGS"))
    .expect("the environment variable must be specified and UTF-8")
    .compile("foo");
fn shared_flag(self: &mut Self, shared_flag: bool) -> &mut Build

Set the -shared flag.

This will typically be ignored by the compiler when calling [Self::compile()] since it only produces static libraries.

Example

// This will create a library named "liblibfoo.so.a"
cc::Build::new()
    .file("src/foo.c")
    .shared_flag(true)
    .compile("libfoo.so");
fn static_flag(self: &mut Self, static_flag: bool) -> &mut Build

Set the -static flag.

This will typically be ignored by the compiler when calling [Self::compile()] since it only produces static libraries.

Example

cc::Build::new()
    .file("src/foo.c")
    .shared_flag(true)
    .static_flag(true)
    .compile("foo");
fn no_default_flags(self: &mut Self, no_default_flags: bool) -> &mut Build

Disables the generation of default compiler flags. The default compiler flags may cause conflicts in some cross compiling scenarios.

Setting the CRATE_CC_NO_DEFAULTS environment variable has the same effect as setting this to true. The presence of the environment variable and the value of no_default_flags will be OR'd together.

fn file<P: AsRef<Path>>(self: &mut Self, p: P) -> &mut Build

Add a file which will be compiled

fn files<P>(self: &mut Self, p: P) -> &mut Build
where
    P: IntoIterator,
    <P as >::Item: AsRef<Path>

Add files which will be compiled

fn get_files(self: &Self) -> impl Iterator<Item = &Path>

Get the files which will be compiled

fn cpp(self: &mut Self, cpp: bool) -> &mut Build

Set C++ support.

The other cpp_* options will only become active if this is set to true.

The name of the C++ standard library to link is decided by:

  1. If cpp_link_stdlib is set, use its value.
  2. Else if the CXXSTDLIB environment variable is set, use its value.
  3. Else the default is c++ for OS X and BSDs, c++_shared for Android, None for MSVC and stdc++ for anything else.
fn cuda(self: &mut Self, cuda: bool) -> &mut Build

Set CUDA C++ support.

Enabling CUDA will invoke the CUDA compiler, NVCC. While NVCC accepts the most common compiler flags, e.g. -std=c++17, some project-specific flags might have to be prefixed with "-Xcompiler" flag, for example as .flag("-Xcompiler").flag("-fpermissive"). See the documentation for nvcc, the CUDA compiler driver, at https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/ for more information.

If enabled, this also implicitly enables C++ support.

fn cudart(self: &mut Self, cudart: &str) -> &mut Build

Link CUDA run-time.

This option mimics the --cudart NVCC command-line option. Just like the original it accepts {none|shared|static}, with default being static. The method has to be invoked after .cuda(true), or not at all, if the default is right for the project.

fn ccbin(self: &mut Self, ccbin: bool) -> &mut Build

Set CUDA host compiler.

By default, a -ccbin flag will be passed to NVCC to specify the underlying host compiler. The value of -ccbin is the same as the chosen C++ compiler. This is not always desired, because NVCC might not support that compiler. In this case, you can remove the -ccbin flag so that NVCC will choose the host compiler by itself.

fn std(self: &mut Self, std: &str) -> &mut Build

Specify the C or C++ language standard version.

These values are common to modern versions of GCC, Clang and MSVC:

  • c11 for ISO/IEC 9899:2011
  • c17 for ISO/IEC 9899:2018
  • c++14 for ISO/IEC 14882:2014
  • c++17 for ISO/IEC 14882:2017
  • c++20 for ISO/IEC 14882:2020

Other values have less broad support, e.g. MSVC does not support c++11 (c++14 is the minimum), c89 (omit the flag instead) or c99.

For compiling C++ code, you should also set .cpp(true).

The default is that no standard flag is passed to the compiler, so the language version will be the compiler's default.

Example

cc::Build::new()
    .file("src/modern.cpp")
    .cpp(true)
    .std("c++17")
    .compile("modern");
fn warnings_into_errors(self: &mut Self, warnings_into_errors: bool) -> &mut Build

Set warnings into errors flag.

Disabled by default.

Warning: turning warnings into errors only make sense if you are a developer of the crate using cc-rs. Some warnings only appear on some architecture or specific version of the compiler. Any user of this crate, or any other crate depending on it, could fail during compile time.

Example

cc::Build::new()
    .file("src/foo.c")
    .warnings_into_errors(true)
    .compile("libfoo.a");
fn warnings(self: &mut Self, warnings: bool) -> &mut Build

Set warnings flags.

Adds some flags:

  • "-Wall" for MSVC.
  • "-Wall", "-Wextra" for GNU and Clang.

Enabled by default.

Example

cc::Build::new()
    .file("src/foo.c")
    .warnings(false)
    .compile("libfoo.a");
fn extra_warnings(self: &mut Self, warnings: bool) -> &mut Build

Set extra warnings flags.

Adds some flags:

  • nothing for MSVC.
  • "-Wextra" for GNU and Clang.

Enabled by default.

Example

// Disables -Wextra, -Wall remains enabled:
cc::Build::new()
    .file("src/foo.c")
    .extra_warnings(false)
    .compile("libfoo.a");
fn cpp_link_stdlib<'a, V: Into<Option<&'a str>>>(self: &mut Self, cpp_link_stdlib: V) -> &mut Build

Set the standard library to link against when compiling with C++ support.

If the CXXSTDLIB environment variable is set, its value will override the default value, but not the value explicitly set by calling this function.

A value of None indicates that no automatic linking should happen, otherwise cargo will link against the specified library.

The given library name must not contain the lib prefix.

Common values:

  • stdc++ for GNU
  • c++ for Clang
  • c++_shared or c++_static for Android

Example

cc::Build::new()
    .file("src/foo.c")
    .shared_flag(true)
    .cpp_link_stdlib("stdc++")
    .compile("libfoo.so");
fn cpp_link_stdlib_static(self: &mut Self, is_static: bool) -> &mut Build

Force linker to statically link C++ stdlib. By default cc-rs will emit rustc-link flag to link against system C++ stdlib (e.g. libstdc++.so, libc++.so) Provide value of true if linking against system library is not desired

Note that for wasm32 target C++ stdlib will always be linked statically

Example

cc::Build::new()
    .file("src/foo.cpp")
    .cpp(true)
    .cpp_link_stdlib("stdc++")
    .cpp_link_stdlib_static(true)
    .compile("foo");
fn cpp_set_stdlib<'a, V: Into<Option<&'a str>>>(self: &mut Self, cpp_set_stdlib: V) -> &mut Build

Force the C++ compiler to use the specified standard library.

Setting this option will automatically set cpp_link_stdlib to the same value.

The default value of this option is always None.

This option has no effect when compiling for a Visual Studio based target.

This option sets the -stdlib flag, which is only supported by some compilers (clang, icc) but not by others (gcc). The library will not detect which compiler is used, as such it is the responsibility of the caller to ensure that this option is only used in conjunction with a compiler which supports the -stdlib flag.

A value of None indicates that no specific C++ standard library should be used, otherwise -stdlib is added to the compile invocation.

The given library name must not contain the lib prefix.

Common values:

  • stdc++ for GNU
  • c++ for Clang

Example

cc::Build::new()
    .file("src/foo.c")
    .cpp_set_stdlib("c++")
    .compile("libfoo.a");
fn target(self: &mut Self, target: &str) -> &mut Build

Configures the rustc target this configuration will be compiling for.

This will fail if using a target not in a pre-compiled list taken from rustc +nightly --print target-list. The list will be updated periodically.

You should avoid setting this in build scripts, target information will instead be retrieved from the environment variables TARGET and CARGO_CFG_TARGET_* that Cargo sets.

Example

cc::Build::new()
    .file("src/foo.c")
    .target("aarch64-linux-android")
    .compile("foo");
fn host(self: &mut Self, host: &str) -> &mut Build

Configures the host assumed by this configuration.

This option is automatically scraped from the HOST environment variable by build scripts, so it's not required to call this function.

Example

cc::Build::new()
    .file("src/foo.c")
    .host("arm-linux-gnueabihf")
    .compile("foo");
fn opt_level(self: &mut Self, opt_level: u32) -> &mut Build

Configures the optimization level of the generated object files.

This option is automatically scraped from the OPT_LEVEL environment variable by build scripts, so it's not required to call this function.

fn opt_level_str(self: &mut Self, opt_level: &str) -> &mut Build

Configures the optimization level of the generated object files.

This option is automatically scraped from the OPT_LEVEL environment variable by build scripts, so it's not required to call this function.

fn debug(self: &mut Self, debug: bool) -> &mut Build

Configures whether the compiler will emit debug information when generating object files.

This option is automatically scraped from the DEBUG environment variable by build scripts, so it's not required to call this function.

fn debug_str(self: &mut Self, debug: &str) -> &mut Build

Configures whether the compiler will emit debug information when generating object files.

This should be one of the values accepted by Cargo's debug profile setting, which cc-rs will try to map to the appropriate C compiler flag.

This option is automatically scraped from the DEBUG environment variable by build scripts, so it's not required to call this function.

fn force_frame_pointer(self: &mut Self, force: bool) -> &mut Build

Configures whether the compiler will emit instructions to store frame pointers during codegen.

This option is automatically enabled when debug information is emitted. Otherwise the target platform compiler's default will be used. You can use this option to force a specific setting.

fn out_dir<P: AsRef<Path>>(self: &mut Self, out_dir: P) -> &mut Build

Configures the output directory where all object files and static libraries will be located.

This option is automatically scraped from the OUT_DIR environment variable by build scripts, so it's not required to call this function.

fn compiler<P: AsRef<Path>>(self: &mut Self, compiler: P) -> &mut Build

Configures the compiler to be used to produce output.

This option is automatically determined from the target platform or a number of environment variables, so it's not required to call this function.

fn archiver<P: AsRef<Path>>(self: &mut Self, archiver: P) -> &mut Build

Configures the tool used to assemble archives.

This option is automatically determined from the target platform or a number of environment variables, so it's not required to call this function.

fn ranlib<P: AsRef<Path>>(self: &mut Self, ranlib: P) -> &mut Build

Configures the tool used to index archives.

This option is automatically determined from the target platform or a number of environment variables, so it's not required to call this function.

fn cargo_metadata(self: &mut Self, cargo_metadata: bool) -> &mut Build

Define whether metadata should be emitted for cargo allowing it to automatically link the binary. Defaults to true.

The emitted metadata is:

  • rustc-link-lib=static=compiled lib
  • rustc-link-search=native=target folder
  • When target is MSVC, the ATL-MFC libs are added via rustc-link-search=native=
  • When C++ is enabled, the C++ stdlib is added via rustc-link-lib
  • If emit_rerun_if_env_changed is not false, rerun-if-env-changed=env
fn cargo_warnings(self: &mut Self, cargo_warnings: bool) -> &mut Build

Define whether compile warnings should be emitted for cargo. Defaults to true.

If disabled, compiler messages will not be printed. Issues unrelated to the compilation will always produce cargo warnings regardless of this setting.

fn cargo_debug(self: &mut Self, cargo_debug: bool) -> &mut Build

Define whether debug information should be emitted for cargo. Defaults to whether or not the environment variable CC_ENABLE_DEBUG_OUTPUT is set.

If enabled, the compiler will emit debug information when generating object files, such as the command invoked and the exit status.

fn cargo_output(self: &mut Self, cargo_output: bool) -> &mut Build

Define whether compiler output (to stdout) should be emitted. Defaults to true (forward compiler stdout to this process' stdout)

Some compilers emit errors to stdout, so if you really need stdout to be clean you should also set this to false.

fn link_lib_modifier<impl AsRef<OsStr>: AsRef<OsStr>>(self: &mut Self, link_lib_modifier: impl AsRef<OsStr>) -> &mut Build

Adds a native library modifier that will be added to the rustc-link-lib=static:MODIFIERS=LIBRARY_NAME metadata line emitted for cargo if cargo_metadata is enabled. See https://doc.rust-lang.org/rustc/command-line-arguments.html#-l-link-the-generated-crate-to-a-native-library for the list of modifiers accepted by rustc.

fn pic(self: &mut Self, pic: bool) -> &mut Build

Configures whether the compiler will emit position independent code.

This option defaults to false for windows-gnu and bare metal targets and to true for all other targets.

fn use_plt(self: &mut Self, use_plt: bool) -> &mut Build

Configures whether the Procedure Linkage Table is used for indirect calls into shared libraries.

The PLT is used to provide features like lazy binding, but introduces a small performance loss due to extra pointer indirection. Setting use_plt to false can provide a small performance increase.

Note that skipping the PLT requires a recent version of GCC/Clang.

This only applies to ELF targets. It has no effect on other platforms.

fn emit_rerun_if_env_changed(self: &mut Self, emit_rerun_if_env_changed: bool) -> &mut Build

Define whether metadata should be emitted for cargo to only trigger rebuild when detected environment changes, by default build script is always run on every compilation if no rerun cargo metadata is emitted.

NOTE that cc does not emit metadata to detect changes for PATH, since it could be changed every compilation yet does not affect the result of compilation (i.e. rust-analyzer adds temporary directory to PATH).

cc in general, has no way detecting changes to compiler, as there are so many ways to change it and sidestep the detection, for example the compiler might be wrapped in a script so detecting change of the file, or using checksum won't work.

We recommend users to decide for themselves, if they want rebuild if the compiler has been upgraded or changed, and how to detect that.

This has no effect if the cargo_metadata option is false.

This option defaults to true.

fn static_crt(self: &mut Self, static_crt: bool) -> &mut Build

Configures whether the /MT flag or the /MD flag will be passed to msvc build tools.

This option defaults to false, and affect only msvc targets.

fn shell_escaped_flags(self: &mut Self, shell_escaped_flags: bool) -> &mut Build

Configure whether *FLAGS variables are parsed using shlex, similarly to make and cmake.

This option defaults to false.

fn inherit_rustflags(self: &mut Self, inherit_rustflags: bool) -> &mut Build

Configure whether cc should automatically inherit compatible flags passed to rustc from CARGO_ENCODED_RUSTFLAGS.

This option defaults to true.

fn prefer_clang_cl_over_msvc(self: &mut Self, prefer_clang_cl_over_msvc: bool) -> &mut Build

Prefer to use clang-cl over msvc.

This option defaults to false.

impl Clone for Build

fn clone(self: &Self) -> Build

impl Debug for Build

fn fmt(self: &Self, f: &mut $crate::fmt::Formatter<'_>) -> $crate::fmt::Result

impl Default for Build

fn default() -> Build

impl Freeze for Build

impl RefUnwindSafe for Build

impl Send for Build

impl Sync for Build

impl Unpin for Build

impl UnwindSafe for Build

impl<T> Any for Build

fn type_id(self: &Self) -> TypeId

impl<T> Borrow for Build

fn borrow(self: &Self) -> &T

impl<T> BorrowMut for Build

fn borrow_mut(self: &mut Self) -> &mut T

impl<T> CloneToUninit for Build

unsafe fn clone_to_uninit(self: &Self, dest: *mut u8)

impl<T> From for Build

fn from(t: T) -> T

Returns the argument unchanged.

impl<T> ToOwned for Build

fn to_owned(self: &Self) -> T
fn clone_into(self: &Self, target: &mut T)

impl<T, U> Into for Build

fn into(self: Self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of [From]<T> for U chooses to do.

impl<T, U> TryFrom for Build

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

impl<T, U> TryInto for Build

fn try_into(self: Self) -> Result<U, <U as TryFrom<T>>::Error>