|
1 | 1 | # cc-rs
|
2 | 2 |
|
3 |
| -A library to compile C/C++/assembly into a Rust library/application. |
4 |
| - |
5 |
| -[Documentation](https://docs.rs/cc) |
6 |
| - |
7 |
| -A simple library meant to be used as a build dependency with Cargo packages in |
8 |
| -order to build a set of C/C++ files into a static archive. This crate calls out |
9 |
| -to the most relevant compiler for a platform, for example using `cl` on MSVC. |
10 |
| - |
11 |
| -## Using cc-rs |
12 |
| - |
13 |
| -First, you'll want to both add a build script for your crate (`build.rs`) and |
14 |
| -also add this crate to your `Cargo.toml` via: |
15 |
| - |
16 |
| -```toml |
17 |
| -[build-dependencies] |
18 |
| -cc = "1.0" |
19 |
| -``` |
20 |
| - |
21 |
| -Next up, you'll want to write a build script like so: |
22 |
| - |
23 |
| -```rust,no_run |
24 |
| -// build.rs |
25 |
| -
|
26 |
| -fn main() { |
27 |
| - cc::Build::new() |
28 |
| - .file("foo.c") |
29 |
| - .file("bar.c") |
30 |
| - .compile("foo"); |
31 |
| -} |
32 |
| -``` |
33 |
| - |
34 |
| -And that's it! Running `cargo build` should take care of the rest and your Rust |
35 |
| -application will now have the C files `foo.c` and `bar.c` compiled into a file |
36 |
| -named `libfoo.a`. If the C files contain |
37 |
| - |
38 |
| -```c |
39 |
| -void foo_function(void) { ... } |
40 |
| -``` |
41 |
| -
|
42 |
| -and |
43 |
| -
|
44 |
| -```c |
45 |
| -int32_t bar_function(int32_t x) { ... } |
46 |
| -``` |
47 |
| - |
48 |
| -you can call them from Rust by declaring them in |
49 |
| -your Rust code like so: |
50 |
| - |
51 |
| -```rust,no_run |
52 |
| -extern "C" { |
53 |
| - fn foo_function(); |
54 |
| - fn bar_function(x: i32) -> i32; |
55 |
| -} |
56 |
| -
|
57 |
| -pub fn call() { |
58 |
| - unsafe { |
59 |
| - foo_function(); |
60 |
| - bar_function(42); |
61 |
| - } |
62 |
| -} |
63 |
| -
|
64 |
| -fn main() { |
65 |
| - // ... |
66 |
| -} |
67 |
| -``` |
68 |
| - |
69 |
| -See [the Rustonomicon](https://doc.rust-lang.org/nomicon/ffi.html) for more details. |
70 |
| - |
71 |
| -## External configuration via environment variables |
72 |
| - |
73 |
| -To control the programs and flags used for building, the builder can set a |
74 |
| -number of different environment variables. |
75 |
| - |
76 |
| -* `CFLAGS` - a series of space separated flags passed to compilers. Note that |
77 |
| - individual flags cannot currently contain spaces, so doing |
78 |
| - something like: `-L=foo\ bar` is not possible. |
79 |
| -* `CC` - the actual C compiler used. Note that this is used as an exact |
80 |
| - executable name, so (for example) no extra flags can be passed inside |
81 |
| - this variable, and the builder must ensure that there aren't any |
82 |
| - trailing spaces. This compiler must understand the `-c` flag. For |
83 |
| - certain `TARGET`s, it also is assumed to know about other flags (most |
84 |
| - common is `-fPIC`). |
85 |
| -* `AR` - the `ar` (archiver) executable to use to build the static library. |
86 |
| -* `CRATE_CC_NO_DEFAULTS` - the default compiler flags may cause conflicts in |
87 |
| - some cross compiling scenarios. Setting this variable |
88 |
| - will disable the generation of default compiler |
89 |
| - flags. |
90 |
| -* `CXX...` - see [C++ Support](#c-support). |
91 |
| - |
92 |
| -Furthermore, projects using this crate may specify custom environment variables |
93 |
| -to be inspected, for example via the `Build::try_flags_from_environment` |
94 |
| -function. Consult the project’s own documentation or its use of the `cc` crate |
95 |
| -for any additional variables it may use. |
96 |
| - |
97 |
| -Each of these variables can also be supplied with certain prefixes and suffixes, |
98 |
| -in the following prioritized order: |
99 |
| - |
100 |
| -1. `<var>_<target>` - for example, `CC_x86_64-unknown-linux-gnu` |
101 |
| -2. `<var>_<target_with_underscores>` - for example, `CC_x86_64_unknown_linux_gnu` |
102 |
| -3. `<build-kind>_<var>` - for example, `HOST_CC` or `TARGET_CFLAGS` |
103 |
| -4. `<var>` - a plain `CC`, `AR` as above. |
104 |
| - |
105 |
| -If none of these variables exist, cc-rs uses built-in defaults. |
106 |
| - |
107 |
| -In addition to the above optional environment variables, `cc-rs` has some |
108 |
| -functions with hard requirements on some variables supplied by [cargo's |
109 |
| -build-script driver][cargo] that it has the `TARGET`, `OUT_DIR`, `OPT_LEVEL`, |
110 |
| -and `HOST` variables. |
111 |
| - |
112 |
| -[cargo]: https://doc.rust-lang.org/cargo/reference/build-scripts.html#inputs-to-the-build-script |
113 |
| - |
114 |
| -## Optional features |
115 |
| - |
116 |
| -### Parallel |
117 |
| - |
118 |
| -Currently cc-rs supports parallel compilation (think `make -jN`) but this |
119 |
| -feature is turned off by default. To enable cc-rs to compile C/C++ in parallel, |
120 |
| -you can change your dependency to: |
121 |
| - |
122 |
| -```toml |
123 |
| -[build-dependencies] |
124 |
| -cc = { version = "1.0", features = ["parallel"] } |
125 |
| -``` |
126 |
| - |
127 |
| -By default cc-rs will limit parallelism to `$NUM_JOBS`, or if not present it |
128 |
| -will limit it to the number of cpus on the machine. If you are using cargo, |
129 |
| -use `-jN` option of `build`, `test` and `run` commands as `$NUM_JOBS` |
130 |
| -is supplied by cargo. |
131 |
| - |
132 |
| -## Compile-time Requirements |
133 |
| - |
134 |
| -To work properly this crate needs access to a C compiler when the build script |
135 |
| -is being run. This crate does not ship a C compiler with it. The compiler |
136 |
| -required varies per platform, but there are three broad categories: |
137 |
| - |
138 |
| -* Unix platforms require `cc` to be the C compiler. This can be found by |
139 |
| - installing cc/clang on Linux distributions and Xcode on macOS, for example. |
140 |
| -* Windows platforms targeting MSVC (e.g. your target triple ends in `-msvc`) |
141 |
| - require Visual Studio to be installed. `cc-rs` attempts to locate it, and |
142 |
| - if it fails, `cl.exe` is expected to be available in `PATH`. This can be |
143 |
| - set up by running the appropriate developer tools shell. |
144 |
| -* Windows platforms targeting MinGW (e.g. your target triple ends in `-gnu`) |
145 |
| - require `cc` to be available in `PATH`. We recommend the |
146 |
| - [MinGW-w64](https://www.mingw-w64.org/) distribution, which is using the |
147 |
| - [Win-builds](http://win-builds.org/) installation system. |
148 |
| - You may also acquire it via |
149 |
| - [MSYS2](https://www.msys2.org/), as explained [here][msys2-help]. Make sure |
150 |
| - to install the appropriate architecture corresponding to your installation of |
151 |
| - rustc. GCC from older [MinGW](http://www.mingw.org/) project is compatible |
152 |
| - only with 32-bit rust compiler. |
153 |
| - |
154 |
| -[msys2-help]: https://github.com/rust-lang/rust#building-on-windows |
155 |
| - |
156 |
| -## C++ support |
157 |
| - |
158 |
| -`cc-rs` supports C++ libraries compilation by using the `cpp` method on |
159 |
| -`Build`: |
160 |
| - |
161 |
| -```rust,no_run |
162 |
| -fn main() { |
163 |
| - cc::Build::new() |
164 |
| - .cpp(true) // Switch to C++ library compilation. |
165 |
| - .file("foo.cpp") |
166 |
| - .compile("foo"); |
167 |
| -} |
168 |
| -``` |
169 |
| - |
170 |
| -For C++ libraries, the `CXX` and `CXXFLAGS` environment variables are used instead of `CC` and `CFLAGS`. |
171 |
| - |
172 |
| -The C++ standard library may be linked to the crate target. By default it's `libc++` for macOS, FreeBSD, and OpenBSD, `libc++_shared` for Android, nothing for MSVC, and `libstdc++` for anything else. It can be changed in one of two ways: |
173 |
| - |
174 |
| -1. by using the `cpp_link_stdlib` method on `Build`: |
175 |
| - ```rust,no-run |
176 |
| - fn main() { |
177 |
| - cc::Build::new() |
178 |
| - .cpp(true) |
179 |
| - .file("foo.cpp") |
180 |
| - .cpp_link_stdlib("stdc++") // use libstdc++ |
181 |
| - .compile("foo"); |
182 |
| - } |
183 |
| - ``` |
184 |
| -2. by setting the `CXXSTDLIB` environment variable. |
185 |
| -
|
186 |
| -In particular, for Android you may want to [use `c++_static` if you have at most one shared library](https://developer.android.com/ndk/guides/cpp-support). |
187 |
| -
|
188 |
| -Remember that C++ does name mangling so `extern "C"` might be required to enable Rust linker to find your functions. |
189 |
| -
|
190 |
| -## CUDA C++ support |
191 |
| -
|
192 |
| -`cc-rs` also supports compiling CUDA C++ libraries by using the `cuda` method |
193 |
| -on `Build`: |
194 |
| -
|
195 |
| -```rust,no_run |
196 |
| -fn main() { |
197 |
| - cc::Build::new() |
198 |
| - // Switch to CUDA C++ library compilation using NVCC. |
199 |
| - .cuda(true) |
200 |
| - .cudart("static") |
201 |
| - // Generate code for Maxwell (GTX 970, 980, 980 Ti, Titan X). |
202 |
| - .flag("-gencode").flag("arch=compute_52,code=sm_52") |
203 |
| - // Generate code for Maxwell (Jetson TX1). |
204 |
| - .flag("-gencode").flag("arch=compute_53,code=sm_53") |
205 |
| - // Generate code for Pascal (GTX 1070, 1080, 1080 Ti, Titan Xp). |
206 |
| - .flag("-gencode").flag("arch=compute_61,code=sm_61") |
207 |
| - // Generate code for Pascal (Tesla P100). |
208 |
| - .flag("-gencode").flag("arch=compute_60,code=sm_60") |
209 |
| - // Generate code for Pascal (Jetson TX2). |
210 |
| - .flag("-gencode").flag("arch=compute_62,code=sm_62") |
211 |
| - // Generate code in parallel |
212 |
| - .flag("-t0") |
213 |
| - .file("bar.cu") |
214 |
| - .compile("bar"); |
215 |
| -} |
216 |
| -``` |
| 3 | +A library for [Cargo build scripts](https://doc.rust-lang.org/cargo/reference/build-scripts.html) |
| 4 | +to compile a set of C/C++/assembly/CUDA files into a static archive for Cargo |
| 5 | +to link into the crate being built. This crate does not compile code itself; |
| 6 | +it calls out to the default compiler for the platform. This crate will |
| 7 | +automatically detect situations such as cross compilation and |
| 8 | +various environment variables and will build code appropriately. |
| 9 | + |
| 10 | +Refer to the [documentation](https://docs.rs/cc) for detailed usage instructions. |
217 | 11 |
|
218 | 12 | ## License
|
219 | 13 |
|
|
0 commit comments