Browse Source

Merge branch 'master' into master

cmd
Raphaël Huchet 8 years ago
committed by GitHub
parent
commit
12dc0bab96
  1. 9
      README.md
  2. 52
      src/lib.rs

9
README.md

@ -35,13 +35,16 @@ Next up, you'll want to write a build script like so:
extern crate gcc; extern crate gcc;
fn main() { fn main() {
gcc::compile_library("libfoo.a", &["foo.c", "bar.c"]); gcc::Config::new()
.files(["foo.c", "bar.c"])
.compile("foo");
} }
``` ```
And that's it! Running `cargo build` should take care of the rest and your Rust And that's it! Running `cargo build` should take care of the rest and your Rust
application will now have the C files `foo.c` and `bar.c` compiled into it. You application will now have the C files `foo.c` and `bar.c` compiled into a file
can call the functions in Rust by declaring functions in your Rust code like so: named libfoo.a. You can call the functions in Rust by declaring functions in
your Rust code like so:
``` ```
extern { extern {

52
src/lib.rs

@ -10,25 +10,16 @@
//! //!
//! The purpose of this crate is to provide the utility functions necessary to //! The purpose of this crate is to provide the utility functions necessary to
//! compile C code into a static archive which is then linked into a Rust crate. //! compile C code into a static archive which is then linked into a Rust crate.
//! The top-level `compile_library` function serves as a convenience and more //! Configuration is available through the `Config` builder.
//! advanced configuration is available through the `Config` builder.
//! //!
//! This crate will automatically detect situations such as cross compilation or //! This crate will automatically detect situations such as cross compilation or
//! other environment variables set by Cargo and will build code appropriately. //! other environment variables set by Cargo and will build code appropriately.
//! //!
//! # Examples //! [`Config`]: struct.Config.html
//!
//! Use the default configuration:
//! //!
//! ```no_run //! # Examples
//! extern crate gcc;
//!
//! fn main() {
//! gcc::compile_library("libfoo.a", &["src/foo.c"]);
//! }
//! ```
//! //!
//! Use more advanced configuration: //! Use the `Config` builder to compile `src/foo.c`:
//! //!
//! ```no_run //! ```no_run
//! extern crate gcc; //! extern crate gcc;
@ -38,7 +29,7 @@
//! .file("src/foo.c") //! .file("src/foo.c")
//! .define("FOO", Some("bar")) //! .define("FOO", Some("bar"))
//! .include("src") //! .include("src")
//! .compile("libfoo.a"); //! .compile("foo");
//! } //! }
//! ``` //! ```
@ -168,8 +159,10 @@ impl ToolFamily {
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// gcc::compile_library("libfoo.a", &["foo.c", "bar.c"]); /// gcc::compile_library("foo", &["foo.c", "bar.c"]);
/// ``` /// ```
#[deprecated]
#[doc(hidden)]
pub fn compile_library(output: &str, files: &[&str]) { pub fn compile_library(output: &str, files: &[&str]) {
let mut c = Config::new(); let mut c = Config::new();
for f in files.iter() { for f in files.iter() {
@ -181,7 +174,9 @@ pub fn compile_library(output: &str, files: &[&str]) {
impl Config { impl Config {
/// Construct a new instance of a blank set of configuration. /// Construct a new instance of a blank set of configuration.
/// ///
/// This builder is finished with the `compile` function. /// This builder is finished with the [`compile`] function.
///
/// [`compile`]: struct.Config.html#method.compile
pub fn new() -> Config { pub fn new() -> Config {
Config { Config {
include_directories: Vec::new(), include_directories: Vec::new(),
@ -221,7 +216,7 @@ impl Config {
/// .file("src/foo.c") /// .file("src/foo.c")
/// .include(library_path) /// .include(library_path)
/// .include("src") /// .include("src")
/// .compile("libfoo.a"); /// .compile("foo");
/// ``` /// ```
pub fn include<P: AsRef<Path>>(&mut self, dir: P) -> &mut Config { pub fn include<P: AsRef<Path>>(&mut self, dir: P) -> &mut Config {
self.include_directories.push(dir.as_ref().to_path_buf()); self.include_directories.push(dir.as_ref().to_path_buf());
@ -237,7 +232,7 @@ impl Config {
/// .file("src/foo.c") /// .file("src/foo.c")
/// .define("FOO", Some("BAR")) /// .define("FOO", Some("BAR"))
/// .define("BAZ", None) /// .define("BAZ", None)
/// .compile("libfoo.a"); /// .compile("foo");
/// ``` /// ```
pub fn define(&mut self, var: &str, val: Option<&str>) -> &mut Config { pub fn define(&mut self, var: &str, val: Option<&str>) -> &mut Config {
self.definitions.push((var.to_string(), val.map(|s| s.to_string()))); self.definitions.push((var.to_string(), val.map(|s| s.to_string())));
@ -258,7 +253,7 @@ impl Config {
/// gcc::Config::new() /// gcc::Config::new()
/// .file("src/foo.c") /// .file("src/foo.c")
/// .flag("-ffunction-sections") /// .flag("-ffunction-sections")
/// .compile("libfoo.a"); /// .compile("foo");
/// ``` /// ```
pub fn flag(&mut self, flag: &str) -> &mut Config { pub fn flag(&mut self, flag: &str) -> &mut Config {
self.flags.push(flag.to_string()); self.flags.push(flag.to_string());
@ -296,7 +291,7 @@ impl Config {
/// .file("src/foo.c") /// .file("src/foo.c")
/// .shared_flag(true) /// .shared_flag(true)
/// .static_flag(true) /// .static_flag(true)
/// .compile("libfoo.so"); /// .compile("foo");
/// ``` /// ```
pub fn static_flag(&mut self, static_flag: bool) -> &mut Config { pub fn static_flag(&mut self, static_flag: bool) -> &mut Config {
self.static_flag = Some(static_flag); self.static_flag = Some(static_flag);
@ -381,7 +376,7 @@ impl Config {
/// gcc::Config::new() /// gcc::Config::new()
/// .file("src/foo.c") /// .file("src/foo.c")
/// .target("aarch64-linux-android") /// .target("aarch64-linux-android")
/// .compile("libfoo.so"); /// .compile("foo");
/// ``` /// ```
pub fn target(&mut self, target: &str) -> &mut Config { pub fn target(&mut self, target: &str) -> &mut Config {
self.target = Some(target.to_string()); self.target = Some(target.to_string());
@ -392,14 +387,14 @@ impl Config {
/// ///
/// This option is automatically scraped from the `HOST` environment /// This option is automatically scraped from the `HOST` environment
/// variable by build scripts, so it's not required to call this function. /// variable by build scripts, so it's not required to call this function.
/// ///
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// gcc::Config::new() /// gcc::Config::new()
/// .file("src/foo.c") /// .file("src/foo.c")
/// .host("arm-linux-gnueabihf") /// .host("arm-linux-gnueabihf")
/// .compile("libfoo.so"); /// .compile("foo");
/// ``` /// ```
pub fn host(&mut self, host: &str) -> &mut Config { pub fn host(&mut self, host: &str) -> &mut Config {
self.host = Some(host.to_string()); self.host = Some(host.to_string());
@ -500,7 +495,10 @@ impl Config {
/// Run the compiler, generating the file `output` /// Run the compiler, generating the file `output`
/// ///
/// The name `output` must begin with `lib` and end with `.a` /// The name `output` should be the name of the library. For backwards compatibility,
/// the `output` may start with `lib` and end with `.a`. The Rust compilier will create
/// the assembly with the lib prefix and .a extension. MSVC will create a file without prefix,
/// ending with `.lib`.
/// ///
/// # Panics /// # Panics
/// ///
@ -508,9 +506,9 @@ impl Config {
/// compiler commands fails. It can also panic if it fails reading file names /// compiler commands fails. It can also panic if it fails reading file names
/// or creating directories. /// or creating directories.
pub fn compile(&self, output: &str) { pub fn compile(&self, output: &str) {
assert!(output.starts_with("lib")); let name_start = if output.starts_with("lib") { 3 } else { 0 };
assert!(output.ends_with(".a")); let name_end = if output.ends_with(".a") { output.len() - 2 } else { output.len() };
let lib_name = &output[3..output.len() - 2]; let lib_name = &output[name_start..name_end];
let dst = self.get_out_dir(); let dst = self.get_out_dir();
let mut objects = Vec::new(); let mut objects = Vec::new();

Loading…
Cancel
Save