<commit_before>use {
    BackEnd,
    Borrowed,
    Draw,
    Field,
    Image,
    Matrix2d,
    Rectangle,
    RelativeRectangle,
    Transform2d,
    Value,
    View,
};
use vecmath::{
    identity,
    margin_rectangle,
    multiply,
    relative_rectangle,
    rotate_radians,
    scale,
    shear,
    translate,
};
use triangulation::{
    rect_tri_list_xy_f32,
    rect_tri_list_rgba_f32,
    rect_tri_list_uv_f32,
};

/// An image rectangle context.
pub struct ImageRectangleContext<'a> {
    /// Base/original transformation.
    pub base: Field<'a, Matrix2d>,
    /// Current transformation.
    pub transform: Field<'a, Matrix2d>,
    /// Current rectangle.
    pub rect: Field<'a, Rectangle>,
    /// Current color.
    pub image: Field<'a, Image>,
}

impl<'a> Transform2d<'a> for ImageRectangleContext<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> ImageRectangleContext<'a> {
        ImageRectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(&trans, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
            image: Borrowed(self.image.get()),
        }
    }

    #[inline(always)]
    fn trans_local(&'a self, x: f64, y: f64) -> ImageRectangleContext<'a> {
        ImageRectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(self.transform.get(), &trans))
            },
            rect: Borrowed(self.rect.get()),
            image: Borrowed(self.image.get()),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> ImageRectangleContext<'a> {
        ImageRectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(&rot, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
            image: Borrowed(self.image.get()),
        }
    }

    #[inline(always)]
    fn rot_rad_local(&'a self, angle: f64) -> ImageRectangleContext<'a> {
        ImageRectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(self.transform.get(), &rot))
            },
            rect: Borrowed(self.rect.get()),
            image: Borrowed(self.image.get()),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> ImageRectangleContext<'a> {
        ImageRectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(&scale, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
            image: Borrowed(self.image.get()),
        }
    }

    #[inline(always)]
    fn scale_local(&'a self, sx: f64, sy: f64) -> ImageRectangleContext<'a> {
        ImageRectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(self.transform.get(), &scale))
            },
            rect: Borrowed(self.rect.get()),
            image: Borrowed(self.image.get()),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> ImageRectangleContext<'a> {
        ImageRectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(&shear, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
            image: Borrowed(self.image.get()),
        }
    }

    #[inline(always)]
    fn shear_local(&'a self, sx: f64, sy: f64) -> ImageRectangleContext<'a> {
        ImageRectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(self.transform.get(), &shear))
            },
            rect: Borrowed(self.rect.get()),
            image: Borrowed(self.image.get()),
        }
    }
}

impl<'a> Draw<'a> for ImageRectangleContext<'a> {
    fn draw<B: BackEnd>(&'a self, back_end: &mut B) {
        if back_end.supports_single_texture()
        && back_end.supports_tri_list_xy_f32_rgba_f32_uv_f32() {
            let rect = self.rect.get();
            let color: [f32, ..4] = [1.0, 1.0, 1.0, 1.0];
            let texture_id = self.image.get().texture_id;
            // Complete transparency does not need to be rendered.
            if color[3] == 0.0 { return; }
            // Turn on alpha blending if not completely opaque or if the texture has alpha channel.
            let needs_alpha = color[3] != 1.0 || back_end.has_texture_alpha(texture_id);
            if needs_alpha { back_end.enable_alpha_blend(); }
            back_end.enable_single_texture(texture_id);
            back_end.tri_list_xy_f32_rgba_f32_uv_f32(
                rect_tri_list_xy_f32(self.transform.get(), rect),
                rect_tri_list_rgba_f32(color),
                rect_tri_list_uv_f32(self.image.get())
            );
            back_end.disable_single_texture();
            if needs_alpha { back_end.disable_alpha_blend(); }
        } else {
            unimplemented!();
        }
    }
}

impl<'a> RelativeRectangle<'a> for ImageRectangleContext<'a> {
    #[inline(always)]
    fn margin(&'a self, m: f64) -> ImageRectangleContext<'a> {
        ImageRectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            image: Borrowed(self.image.get()),
            rect: Value(margin_rectangle(self.rect.get(), m)),
        }
    }

    #[inline(always)]
    fn rel(&'a self, x: f64, y: f64) -> ImageRectangleContext<'a> {
        ImageRectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            image: Borrowed(self.image.get()),
            rect: Value(relative_rectangle(self.rect.get(), x, y)),
        }
    }
}

impl<'a> View<'a> for ImageRectangleContext<'a> {
    #[inline(always)]
    fn view(&'a self) -> ImageRectangleContext<'a> {
        ImageRectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.base.get()),
            rect: Borrowed(self.rect.get()),
            image: Borrowed(self.image.get()),
        }
    }

    #[inline(always)]
    fn reset(&'a self) -> ImageRectangleContext<'a> {
        ImageRectangleContext {
            base: Borrowed(self.base.get()),
            transform: Value(identity()),
            rect: Borrowed(self.rect.get()),
            image: Borrowed(self.image.get()),
        }
    }

    #[inline(always)]
    fn store_view(&'a self) -> ImageRectangleContext<'a> {
        ImageRectangleContext {
            base: Borrowed(self.transform.get()),
            transform: Borrowed(self.transform.get()),
            rect: Borrowed(self.rect.get()),
            image: Borrowed(self.image.get()),
        }
    }
}

<commit_msg>Fixed comment<commit_after>use {
    BackEnd,
    Borrowed,
    Draw,
    Field,
    Image,
    Matrix2d,
    Rectangle,
    RelativeRectangle,
    Transform2d,
    Value,
    View,
};
use vecmath::{
    identity,
    margin_rectangle,
    multiply,
    relative_rectangle,
    rotate_radians,
    scale,
    shear,
    translate,
};
use triangulation::{
    rect_tri_list_xy_f32,
    rect_tri_list_rgba_f32,
    rect_tri_list_uv_f32,
};

/// An image rectangle context.
pub struct ImageRectangleContext<'a> {
    /// Base/original transformation.
    pub base: Field<'a, Matrix2d>,
    /// Current transformation.
    pub transform: Field<'a, Matrix2d>,
    /// Current rectangle.
    pub rect: Field<'a, Rectangle>,
    /// Current image.
    pub image: Field<'a, Image>,
}

impl<'a> Transform2d<'a> for ImageRectangleContext<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> ImageRectangleContext<'a> {
        ImageRectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(&trans, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
            image: Borrowed(self.image.get()),
        }
    }

    #[inline(always)]
    fn trans_local(&'a self, x: f64, y: f64) -> ImageRectangleContext<'a> {
        ImageRectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(self.transform.get(), &trans))
            },
            rect: Borrowed(self.rect.get()),
            image: Borrowed(self.image.get()),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> ImageRectangleContext<'a> {
        ImageRectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(&rot, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
            image: Borrowed(self.image.get()),
        }
    }

    #[inline(always)]
    fn rot_rad_local(&'a self, angle: f64) -> ImageRectangleContext<'a> {
        ImageRectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(self.transform.get(), &rot))
            },
            rect: Borrowed(self.rect.get()),
            image: Borrowed(self.image.get()),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> ImageRectangleContext<'a> {
        ImageRectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(&scale, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
            image: Borrowed(self.image.get()),
        }
    }

    #[inline(always)]
    fn scale_local(&'a self, sx: f64, sy: f64) -> ImageRectangleContext<'a> {
        ImageRectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(self.transform.get(), &scale))
            },
            rect: Borrowed(self.rect.get()),
            image: Borrowed(self.image.get()),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> ImageRectangleContext<'a> {
        ImageRectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(&shear, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
            image: Borrowed(self.image.get()),
        }
    }

    #[inline(always)]
    fn shear_local(&'a self, sx: f64, sy: f64) -> ImageRectangleContext<'a> {
        ImageRectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(self.transform.get(), &shear))
            },
            rect: Borrowed(self.rect.get()),
            image: Borrowed(self.image.get()),
        }
    }
}

impl<'a> Draw<'a> for ImageRectangleContext<'a> {
    fn draw<B: BackEnd>(&'a self, back_end: &mut B) {
        if back_end.supports_single_texture()
        && back_end.supports_tri_list_xy_f32_rgba_f32_uv_f32() {
            let rect = self.rect.get();
            let color: [f32, ..4] = [1.0, 1.0, 1.0, 1.0];
            let texture_id = self.image.get().texture_id;
            // Complete transparency does not need to be rendered.
            if color[3] == 0.0 { return; }
            // Turn on alpha blending if not completely opaque or if the texture has alpha channel.
            let needs_alpha = color[3] != 1.0 || back_end.has_texture_alpha(texture_id);
            if needs_alpha { back_end.enable_alpha_blend(); }
            back_end.enable_single_texture(texture_id);
            back_end.tri_list_xy_f32_rgba_f32_uv_f32(
                rect_tri_list_xy_f32(self.transform.get(), rect),
                rect_tri_list_rgba_f32(color),
                rect_tri_list_uv_f32(self.image.get())
            );
            back_end.disable_single_texture();
            if needs_alpha { back_end.disable_alpha_blend(); }
        } else {
            unimplemented!();
        }
    }
}

impl<'a> RelativeRectangle<'a> for ImageRectangleContext<'a> {
    #[inline(always)]
    fn margin(&'a self, m: f64) -> ImageRectangleContext<'a> {
        ImageRectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            image: Borrowed(self.image.get()),
            rect: Value(margin_rectangle(self.rect.get(), m)),
        }
    }

    #[inline(always)]
    fn rel(&'a self, x: f64, y: f64) -> ImageRectangleContext<'a> {
        ImageRectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            image: Borrowed(self.image.get()),
            rect: Value(relative_rectangle(self.rect.get(), x, y)),
        }
    }
}

impl<'a> View<'a> for ImageRectangleContext<'a> {
    #[inline(always)]
    fn view(&'a self) -> ImageRectangleContext<'a> {
        ImageRectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.base.get()),
            rect: Borrowed(self.rect.get()),
            image: Borrowed(self.image.get()),
        }
    }

    #[inline(always)]
    fn reset(&'a self) -> ImageRectangleContext<'a> {
        ImageRectangleContext {
            base: Borrowed(self.base.get()),
            transform: Value(identity()),
            rect: Borrowed(self.rect.get()),
            image: Borrowed(self.image.get()),
        }
    }

    #[inline(always)]
    fn store_view(&'a self) -> ImageRectangleContext<'a> {
        ImageRectangleContext {
            base: Borrowed(self.transform.get()),
            transform: Borrowed(self.transform.get()),
            rect: Borrowed(self.rect.get()),
            image: Borrowed(self.image.get()),
        }
    }
}

<|endoftext|>


<commit_before>extern mod std;

use std::run;
use std::str;
use std::option::Option;
use std::trie::TrieSet;
use std::libc::{execvp, perror};
//use std::c_str::ptr;
use std::vec;
use std::ptr;
use std::os;

fn detached_session_number(line: &str) -> Option<uint> {
    if line.ends_with("(attached)") {
        None
    } else {
        line.split(':').next().and_then(|s| from_str(s))
    }
}

fn detached_sessions(output: ~str) -> TrieSet {
    output.lines().filter_map(|line| {
            detached_session_number(line)
    }).collect()
}

fn exec_program(program: &str, args: &[~str]) {
    program.with_c_str(|c_program| {
            // I don't much care about the ownership of the strings here
            // at this point, so let's just fail if execvp isn't working.
            unsafe {
                let mut c_args = args.map(|arg| { arg.to_c_str().unwrap() });
                c_args.push(ptr::null());
                execvp(c_program, vec::raw::to_ptr(c_args));
                perror("Running tmux failed:".to_c_str().unwrap());
            }
        });
    fail!(format!("Couldn't exec {:s}", program));
}

fn prepare_environment() {
    let path = match os::getenv("PATH") {
        Some(path) => path + ":/usr/local/bin",
        _ => ~"/bin:/usr/bin:/usr/local/bin"
    };
    os::setenv("PATH", path);
}

fn start_server() {
    let program = run::process_output("tmux", &[~"start-server"]);
    if !program.status.success() {
        fail!(format!("Could not start tmux server: exited with an error status: {:?}", program.status));
    }
}

fn main() {
    prepare_environment();

    start_server();
    let program = run::process_output("tmux", &[~"list-sessions"]);
    if !program.status.success() {
        fail!(format!("Tmux exited with an error status: {:?}", program.status));
    }
    let output = str::from_utf8(program.output).to_owned();
    let sessions = detached_sessions(output);
    match sessions.iter().next() {
        Some(n) => {
            let session = n.to_str();
            exec_program("tmux", &[~"tmux", ~"attach-session", ~"-t", session]);
        }
        _ => { exec_program("tmux", &[~"tmux"]); }
    }
}

#[test]
fn test_session_number_with_numbers(){
    match(detached_session_number("11: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65]")) {
        Some(11) => (),
        Some(n) => fail!(format!("Should have returned 11, got {:u}!", n)),
        None => fail!("Should have returned something, got nothing"),
    }
}

#[test]
fn test_session_number_with_strings(){
    match(detached_session_number("oink: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65]")) {
        Some(n) => fail!(format!("Should have returned None, got {:u}!", n)),
        None => ()
    }
}

#[test]
fn test_session_number_with_attached_session(){
    match(detached_session_number("1: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65] (attached)")) {
        Some(n) => fail!(format!("Should have returned None, got {:u}!", n)),
        None => ()
    }
}

#[test]
fn test_detached_sessions() {
    let set = detached_sessions(~"3: foo (attached)\n2: bar\n15: oink\n4: baz (attached)\nfoo: baz");
    // attached sessions:
    assert!(!set.contains(&3));
    assert!(!set.contains(&4));

    // detached sessions should be present:
    assert!(set.contains(&15));
    assert!(set.contains(&2));

    // missing session:
    assert!(!set.contains(&1));
}
<commit_msg>OMG redo everything for rust 0.11<commit_after>extern crate std;
extern crate libc;

use std::io::Command;
use std::str;
use std::option::Option;
use std::collections::TrieSet;
use libc::{execvp, perror};
//use std::c_str::ptr;
use std::ptr;
use std::os;

fn detached_session_number(line: &str) -> Option<uint> {
    if line.ends_with("(attached)") {
        None
    } else {
        line.split(':').next().and_then(|s| from_str(s))
    }
}

fn detached_sessions(output: &str) -> TrieSet {
    output.lines().filter_map(|line| {
            detached_session_number(line)
    }).collect()
}

fn exec_program(program: &str, args: &[&str]) {
    program.with_c_str(|c_program| {
            // I don't much care about the ownership of the strings here
            // at this point, so let's just fail if execvp isn't working.
            unsafe {
                let mut c_args = vec![];
                for &arg in args.iter() {
                    c_args.push(arg.to_c_str().unwrap());
                }
                c_args.push(ptr::null());
                execvp(c_program, c_args.as_ptr());
                perror("Running tmux failed:".to_c_str().unwrap());
            }
        });
    fail!("Couldn't exec {:s}", program);
}

fn prepare_environment() {
    let path = match os::getenv("PATH") {
        Some(path) => path + ":/usr/local/bin",
        _ => "/bin:/usr/bin:/usr/local/bin".to_str()
    };
    os::setenv("PATH", path.as_slice());
}

fn start_server() {
    match Command::new("tmux").arg("start-server").status() {
        Ok(status) => status,
        Err(e) => fail!("Could not start tmux server: exited with an error status: {}", e),
    };
}

fn main() {
    prepare_environment();

    start_server();
    let session_output = Command::new("tmux").arg("list-sessions").output();
    match session_output {
        Ok(o) => {
            match str::from_utf8(o.output.as_slice()) {
                Some(output) => {
                    let sessions = detached_sessions(output);
                    match sessions.iter().next() {
                        Some(n) => {
                            let my_str = n.to_str();
                            let session = my_str.as_slice();
                            let mut args: Vec<&str> = vec!["tmux", "attach-session", "-t"];
                            args.push(session);
                            exec_program("tmux", args.as_slice());
                        }
                        _ => { exec_program("tmux", ["tmux"]); }
                    }
                },
                None => fail!("Could not parse the utf-8 returned by tmux!"),
            }
        },
        Err(e) => fail!("Tmux exited with an error status: {}", e),
    };
}

#[test]
fn test_session_number_with_numbers(){
    match(detached_session_number("11: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65]")) {
        Some(11) => (),
        Some(n) => fail!(format!("Should have returned 11, got {:u}!", n)),
        None => fail!("Should have returned something, got nothing"),
    }
}

#[test]
fn test_session_number_with_strings(){
    match(detached_session_number("oink: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65]")) {
        Some(n) => fail!(format!("Should have returned None, got {:u}!", n)),
        None => ()
    }
}

#[test]
fn test_session_number_with_attached_session(){
    match(detached_session_number("1: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65] (attached)")) {
        Some(n) => fail!(format!("Should have returned None, got {:u}!", n)),
        None => ()
    }
}

#[test]
fn test_detached_sessions() {
    let set = detached_sessions("3: foo (attached)\n2: bar\n15: oink\n4: baz (attached)\nfoo: baz");
    // attached sessions:
    assert!(!set.contains(&3));
    assert!(!set.contains(&4));

    // detached sessions should be present:
    assert!(set.contains(&15));
    assert!(set.contains(&2));

    // missing session:
    assert!(!set.contains(&1));
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::process::Command;
use std::env;

fn main() {
    assert!(Command::new("make")
        .args(&["-R", "-f", "makefile.cargo", "-j4"])
        .status()
        .unwrap()
        .success());
    let out_dir = env::var("OUT_DIR").unwrap();
    println!("cargo:rustc-flags=-L native={}", out_dir);
    println!("cargo:outdir={}", out_dir);
}
<commit_msg>Use NUM_JOBS to control make -j<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::process::Command;
use std::env;

fn main() {
    assert!(Command::new("make")
        .args(&["-R", "-f", "makefile.cargo", &format!("-j{}", env::var("NUM_JOBS").unwrap())])
        .status()
        .unwrap()
        .success());
    let out_dir = env::var("OUT_DIR").unwrap();
    println!("cargo:rustc-flags=-L native={}", out_dir);
    println!("cargo:outdir={}", out_dir);
}
<|endoftext|>


<commit_before>extern crate gcc;

use std::fs;
use std::io;
use std::env;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::ffi::OsString;

trait CommandExt {
    fn execute(&mut self) -> io::Result<()>;
}

impl CommandExt for Command {
    /// Execute the command and return an error if it exited with a failure status.
    fn execute(&mut self) -> io::Result<()> {
        let status = try!(self.status());
        if status.success() {
            Ok(())
        } else {
            Err(io::Error::new(io::ErrorKind::Other, format!("The command\n\
            \t{:?}\n\
            did not run successfully.", self)))
        }
    }
}

/// The command to build lua, with switches for different OSes.
fn build_lua(tooling: &gcc::Tool, dir: &Path) -> io::Result<()> {
    // calculate the Lua platform name
    let platform = match env::var("TARGET").unwrap().split('-').nth(2).unwrap() {
        "windows" => "mingw",
        "macos" => "macosx",
        "linux" => "linux",
        "freebsd" => "freebsd",
        "dragonfly" => "bsd",
        // fall back to the "generic" system
        _ => "generic",
    };

    // build the CC and MYCFLAGS parameters
    let mut cc = OsString::from("CC=");
    cc.push(tooling.path());
    let mut cflags = OsString::from("MYCFLAGS=");
    for arg in tooling.args() {
        cflags.push(arg);
        cflags.push(" ");
    }

    // call the makefile
    let mut command = Command::new("make");
    for &(ref key, ref val) in tooling.env() {
        command.env(key, val);
    }
    command.current_dir(dir)
        .arg(platform)
        .arg(cc)
        .arg(cflags)
        .execute()
}

/// The command to fetch a URL (e.g. with wget) specialized for different
/// OSes.
#[cfg(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "macos")))]
fn fetch_in_dir(url: &str, cwd: &Path) -> io::Result<()> {
    Command::new("wget").arg(url).current_dir(cwd).execute()
}

#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
fn fetch_in_dir(url: &str, cwd: &Path) -> io::Result<()> {
    Command::new("fetch").arg(url).current_dir(cwd).execute()
}

#[cfg(target_os = "macos")]
fn fetch_in_dir(url: &str, cwd: &Path) -> io::Result<()> {
    Command::new("curl").arg("-O").arg(url).current_dir(cwd).execute()
}

/// If a static Lua is not yet available from a prior run of this script, this
/// will download Lua and build it. The cargo configuration text to link
/// statically against lua.a is then printed to stdout.
fn prebuild() -> io::Result<()> {
    let lua_version = match env::var_os("LUA_VERSION") {
        Some(lua_version) => lua_version,
        None => From::from("5.3.3"),
    };
    let lua_version = lua_version.to_str().unwrap();
    let lua_dir = format!("lua-{}", lua_version);
    let lua_tarball = format!("{}.tar.gz", lua_dir);
    let build_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let tooling = gcc::Config::new().get_compiler();

    // Ensure the presence of liblua.a
    if !fs::metadata(build_dir.join(&format!("{}/src/liblua.a", lua_dir))).is_ok() {
        try!(fs::create_dir_all(&build_dir));

        // Download lua if it hasn't been already
        if !fs::metadata(build_dir.join(&lua_tarball)).is_ok() {
            match env::var_os("LUA_LOCAL_SOURCE") {
                Some(lua_source_path) => {
                    try!(Command::new("cp")
                         .arg(&PathBuf::from(lua_source_path).join(&lua_tarball))
                         .arg(".")
                         .current_dir(&build_dir)
                         .execute());
                }
                None => {
                    try!(fetch_in_dir(&format!(
                        "http://www.lua.org/ftp/{}", lua_tarball), &build_dir));
                }
            }
            try!(Command::new("tar")
                .arg("xzf")
                .arg(&lua_tarball)
                .current_dir(&build_dir)
                .execute());
        }
        // Compile lua
        try!(build_lua(&tooling, &build_dir.join(&lua_dir)));
    }

    // Ensure the presence of glue.rs
    if !fs::metadata(build_dir.join("glue.rs")).is_ok() {
        // Compile glue.c
        let glue = build_dir.join("glue");
        try!(Command::new("gcc")
            .arg("-I").arg(build_dir.join(&format!("{}/src", lua_dir)))
            .arg("src/glue/glue.c")
            .arg("-o").arg(&glue)
            .execute());
        try!(Command::new(glue)
            .arg(build_dir.join("glue.rs"))
            .execute());
    }

    // Output build information
    println!("cargo:rustc-link-lib=static=lua");
    println!("cargo:rustc-link-search=native={}/{}/src", build_dir.to_str().unwrap(), lua_dir);

    Ok(())
}

fn main() {
    match prebuild() {
        Err(e) => panic!("Error: {}", e),
        Ok(()) => (),
    }
}
<commit_msg>Use bundled or provided source when compiling Lua<commit_after>extern crate gcc;

use std::fs;
use std::io;
use std::env;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::ffi::OsString;

trait CommandExt {
    fn execute(&mut self) -> io::Result<()>;
}

impl CommandExt for Command {
    /// Execute the command and return an error if it exited with a failure status.
    fn execute(&mut self) -> io::Result<()> {
        let status = try!(self.status());
        if status.success() {
            Ok(())
        } else {
            Err(io::Error::new(io::ErrorKind::Other, format!("The command\n\
            \t{:?}\n\
            did not run successfully.", self)))
        }
    }
}

/// The command to build lua, with switches for different OSes.
fn build_lua(tooling: &gcc::Tool, source: &Path, build: &Path) -> io::Result<()> {
    // calculate the Lua platform name
    let platform = match env::var("TARGET").unwrap().split('-').nth(2).unwrap() {
        "windows" => "mingw",
        "macos" => "macosx",
        "linux" => "linux",
        "freebsd" => "freebsd",
        "dragonfly" => "bsd",
        // fall back to the "generic" system
        _ => "generic",
    };

    // extract CC and MYCFLAGS from the detected tooling
    let cc = tooling.path();
    let mut cflags = OsString::new();
    for arg in tooling.args() {
        cflags.push(arg);
        cflags.push(" ");
    }

    // VPATH is used to invoke "make" from the directory where we want Lua to
    // be built into, but read the sources from the provided source directory.
    // Setting MAKE to match the command we invoke means that the VPATH and
    // Makefile path will be carried over when the Makefile invokes itself.
    let makefile = source.join("Makefile");
    let make = OsString::from(format!("make -e -f {:?}", makefile.to_string_lossy().replace("\\", "/")));

    // call the makefile
    let mut command = Command::new("make");
    for &(ref key, ref val) in tooling.env() {
        command.env(key, val);
    }
    command.current_dir(build)
        .env("VPATH", source.to_string_lossy().replace("\\", "/"))
        .env("MAKE", make)
        .env("CC", cc)
        .env("MYCFLAGS", cflags)
        .arg("-e")
        .arg("-f").arg(makefile)
        .arg(platform)
        .execute()
}

/// If a static Lua is not yet available from a prior run of this script, this
/// will download Lua and build it. The cargo configuration text to link
/// statically against lua.a is then printed to stdout.
fn prebuild() -> io::Result<()> {
    let lua_dir = match env::var_os("LUA_LOCAL_SOURCE") {
        // If LUA_LOCAL_SOURCE is set, use it
        Some(dir) => PathBuf::from(dir),
        // Otherwise, pull from lua-source/src in the crate root
        None => {
            let mut dir = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap());
            dir.push("lua-source/src");
            dir
        }
    };
    let build_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let mut config = gcc::Config::new();

    println!("cargo:rustc-link-lib=static=lua");
    if lua_dir.join("liblua.a").exists() {
        // If liblua.a is already in lua_dir, use it
        println!("cargo:rustc-link-search=native={}", lua_dir.display());
    } else {
        // Otherwise, build from lua_dir into build_dir
        if !build_dir.join("liblua.a").exists() {
            let tooling = config.get_compiler();
            try!(fs::create_dir_all(&build_dir));
            try!(build_lua(&tooling, &lua_dir, &build_dir));
        }
        println!("cargo:rustc-link-search=native={}", build_dir.display());
    }

    // Ensure the presence of glue.rs
    if !build_dir.join("glue.rs").exists() {
        // Compile and run glue.c
        let glue = build_dir.join("glue");
        try!(config.include(&lua_dir).get_compiler().to_command()
            .arg("-I").arg(&lua_dir)
            .arg("src/glue/glue.c")
            .arg("-o").arg(&glue)
            .execute());
        try!(Command::new(glue)
            .arg(build_dir.join("glue.rs"))
            .execute());
    }

    Ok(())
}

fn main() {
    match prebuild() {
        Err(e) => panic!("Error: {}", e),
        Ok(()) => (),
    }
}
<|endoftext|>


<commit_before>extern crate gcc;

fn main() {
    gcc::Config::new()
        .cpp(true)
        .file("native/opencv-wrapper.cc")
        .include("native")
        .flag("--std=c++11")
        .compile("libopencv-wrapper.a");

    println!("cargo:rustc-link-search=native=-L/usr/local/lib");
    println!("cargo:rustc-link-lib=opencv_core");
    println!("cargo:rustc-link-lib=opencv_imgcodecs");
    println!("cargo:rustc-link-lib=opencv_imgproc");
    println!("cargo:rustc-link-lib=opencv_highgui");
    println!("cargo:rustc-link-lib=opencv_videoio");
    println!("cargo:rustc-link-lib=opencv_objdetect");
    println!("cargo:rustc-link-lib=opencv_video");
}
<commit_msg>fix(build): add include path; update lib path<commit_after>extern crate gcc;

fn main() {
    gcc::Config::new()
        .cpp(true)
        .file("native/opencv-wrapper.cc")
	.include("/usr/local/include")
        .include("native")
        .flag("--std=c++11")
        .compile("libopencv-wrapper.a");

    println!("cargo:rustc-link-search=native=/usr/local/lib");
    println!("cargo:rustc-link-lib=opencv_core");
    println!("cargo:rustc-link-lib=opencv_imgcodecs");
    println!("cargo:rustc-link-lib=opencv_imgproc");
    println!("cargo:rustc-link-lib=opencv_highgui");
    println!("cargo:rustc-link-lib=opencv_videoio");
    println!("cargo:rustc-link-lib=opencv_objdetect");
    println!("cargo:rustc-link-lib=opencv_video");
}
<|endoftext|>


<commit_before>extern crate pkg_config;
use std::process::Command;
use std::path::PathBuf;
use std::env;
use std::fs;

macro_rules! sio {
    ($expr:expr) => { format!("libsoundio-{}", $expr) }
}

macro_rules! err_exists {
    ($expr:expr, $msg:expr) => {
        match $expr {
            Ok(val) => val,
            Err(err) => {
                match err.kind() {
                    ::std::io::ErrorKind::AlreadyExists => (),
                    _ => panic!(format!("{}: {}", $msg, err)),
                }
            }
        }
    }
}

fn lib_available(name: &str) -> bool {
    match pkg_config::find_library(name) {
        Ok(_) => true,
        Err(_) => {
            let res = Command::new("ldconfig").arg("--print-cache").output().unwrap();
            if res.status.success() {
                String::from_utf8(res.stdout).unwrap().contains(name)
            } else {
                false
            }
        }
    }
}

fn windows(_: String) {
    // TODO: Use precompiled binary!
    unimplemented!();
}

fn osx(_: String) {
    // TODO: I down't own any apple hardware to test this.
    unimplemented!();
}

fn linux(target: String) {
    if !lib_available("soundio") {
        build(target);
    } else {
        // TODO: remove else branch
        build(target);
    }
}

fn main() {
    let target = env::var("TARGET").unwrap();
    if target.contains("windows") {
        windows(target)
    } else if target.contains("apple") {
        osx(target)
    } else {
        // assume the rest is linux
        linux(target)
    }
}

fn sio_url(ext: &'static str) -> String {
    format!("http://libsound.io/release/{}.{}", sio!("1.1.0"), ext)
}

fn build(target: String) {
    let host = env::var("HOST").unwrap();
    let dst_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
    let lib_dir = dst_dir.join("lib");
    let include_dir = dst_dir.join("include");
    err_exists!(fs::create_dir(&lib_dir), &lib_dir.display());
    err_exists!(fs::create_dir(&include_dir), &include_dir.display());

    // set cargo flags
    println!("cargo:rustc-link-lib=dylib={}", "soundio"); // -l
    println!("cargo:rustc-link-search=native={}", &lib_dir.display()); // -L
    println!("cargo:include={}", &include_dir.display());
    println!("cargo:root={}", &dst_dir.display());

    // download and extract libsoundio source
    Command::new("curl")
        .current_dir(&dst_dir)
        .args(&["--location", "--remote-name"])
        .arg(sio_url("tar.gz"))
        .output()
        .unwrap();
    Command::new("tar")
        .current_dir(&dst_dir)
        .arg("-xvzf")
        .arg(format!("{}.{}", sio!("1.1.0"), "tar.gz"))
        .output()
        .unwrap();

    // create build dir
    let soundio_root = dst_dir.join(sio!("1.1.0"));
    let build_dir = soundio_root.join("build");
    err_exists!(fs::create_dir(&build_dir), &build_dir.display());

    // run cmake
    Command::new("cmake")
        .current_dir(&build_dir)
        .arg("-DCMAKE_BUILD_TYPE=Debug")
        .arg("-DCMAKE_INSTALL_LIBDIR:PATH=lib")
        .arg(format!("-DCMAKE_INSTALL_PREFIX:PATH={}", &dst_dir.display()))
        .arg("-DBUILD_EXAMPLE_PROGRAMS:BOOL=OFF")
        .arg("-DBUILD_TESTS:BOOL=OFF")
        .arg("-DBUILD_STATIC_LIBS:BOOL=OFF")
        .arg("-DBUILD_SHARED_LIBS:BOOL=ON")
        .arg("-DENABLE_JACK:BOOL=OFF")
        .arg("-DENABLE_PULSEAUDIO:BOOL=OFF")
        .arg("-DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON")
        .arg("..")
        .output()
        .unwrap();

    // make install
    Command::new("make")
        .current_dir(&build_dir)
        .arg("install")
        .output()
        .unwrap();

    // remove builddir
    fs::remove_dir_all(build_dir).unwrap();
}
<commit_msg>Panic on unknown extension<commit_after>extern crate pkg_config;
use std::process::Command;
use std::path::PathBuf;
use std::env;
use std::fs;

macro_rules! sio {
    ($expr:expr) => { format!("libsoundio-{}", $expr) }
}

macro_rules! err_exists {
    ($expr:expr, $msg:expr) => {
        match $expr {
            Ok(val) => val,
            Err(err) => {
                match err.kind() {
                    ::std::io::ErrorKind::AlreadyExists => (),
                    _ => panic!(format!("{}: {}", $msg, err)),
                }
            }
        }
    }
}

fn lib_available(name: &str) -> bool {
    match pkg_config::find_library(name) {
        Ok(_) => true,
        Err(_) => {
            let res = Command::new("ldconfig").arg("--print-cache").output().unwrap();
            if res.status.success() {
                String::from_utf8(res.stdout).unwrap().contains(name)
            } else {
                false
            }
        }
    }
}

fn windows(_: String) {
    // TODO: Use precompiled binary!
    unimplemented!();
}

fn osx(_: String) {
    // TODO: I down't own any apple hardware to test this.
    unimplemented!();
}

fn linux(target: String) {
    if !lib_available("soundio") {
        build(target);
    } else {
        // TODO: remove else branch
        build(target);
    }
}

fn main() {
    let target = env::var("TARGET").unwrap();
    if target.contains("windows") {
        windows(target)
    } else if target.contains("apple") {
        osx(target)
    } else {
        // assume the rest is linux
        linux(target)
    }
}

fn sio_url(ext: &'static str) -> String {
    match ext {
        "tar.gz" | "zip" => format!("http://libsound.io/release/{}.{}", sio!("1.1.0"), ext),
        _ => panic!(format!("No release for format: {}", ext)),
    }
}

fn build(target: String) {
    let host = env::var("HOST").unwrap();
    let dst_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
    let lib_dir = dst_dir.join("lib");
    let include_dir = dst_dir.join("include");
    err_exists!(fs::create_dir(&lib_dir), &lib_dir.display());
    err_exists!(fs::create_dir(&include_dir), &include_dir.display());

    // set cargo flags
    println!("cargo:rustc-link-lib=dylib={}", "soundio"); // -l
    println!("cargo:rustc-link-search=native={}", &lib_dir.display()); // -L
    println!("cargo:include={}", &include_dir.display());
    println!("cargo:root={}", &dst_dir.display());

    // download and extract libsoundio source
    Command::new("curl")
        .current_dir(&dst_dir)
        .args(&["--location", "--remote-name"])
        .arg(sio_url("tar.gz"))
        .output()
        .unwrap();
    Command::new("tar")
        .current_dir(&dst_dir)
        .arg("-xvzf")
        .arg(format!("{}.{}", sio!("1.1.0"), "tar.gz"))
        .output()
        .unwrap();

    // create build dir
    let soundio_root = dst_dir.join(sio!("1.1.0"));
    let build_dir = soundio_root.join("build");
    err_exists!(fs::create_dir(&build_dir), &build_dir.display());

    // run cmake
    Command::new("cmake")
        .current_dir(&build_dir)
        .arg("-DCMAKE_BUILD_TYPE=Debug")
        .arg("-DCMAKE_INSTALL_LIBDIR:PATH=lib")
        .arg(format!("-DCMAKE_INSTALL_PREFIX:PATH={}", &dst_dir.display()))
        .arg("-DBUILD_EXAMPLE_PROGRAMS:BOOL=OFF")
        .arg("-DBUILD_TESTS:BOOL=OFF")
        .arg("-DBUILD_STATIC_LIBS:BOOL=OFF")
        .arg("-DBUILD_SHARED_LIBS:BOOL=ON")
        .arg("-DENABLE_JACK:BOOL=OFF")
        .arg("-DENABLE_PULSEAUDIO:BOOL=OFF")
        .arg("-DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON")
        .arg("..")
        .output()
        .unwrap();

    // make install
    Command::new("make")
        .current_dir(&build_dir)
        .arg("install")
        .output()
        .unwrap();

    // remove builddir
    fs::remove_dir_all(build_dir).unwrap();
}
<|endoftext|>


<commit_before>extern crate gcc;

use std::fs::File;
use std::path::Path;
use std::io::Write;
use std::process::Command;
use std::env;

fn main() {
    if cfg!(target_os = "linux") || cfg!(target_os = "macos") || cfg!(target_os = "windows") {
        env::set_var("CC", "gcc");
        env::set_var("AS", "gcc -c");
        if cfg!(target_os = "linux") {
            env::set_var("AR", "ar");
        }
    } else if cfg!(target_os = "freebsd") || cfg!(target_os = "openbsd") {
        env::set_var("CC", "cc");
        env::set_var("AS", "cc -c");
        env::set_var("AR", "ar");
    }

    let sse3 = if cfg!(target_os = "windows") {
        cfg!(feature = "sse")
    } else {
        let output = if cfg!(target_os = "freebsd") || cfg!(target_os = "openbsd") {
            // /usr/bin/grep -o SSSE3 /var/run/dmesg.boot | /usr/bin/head -1
            Command::new("/usr/bin/grep")
                .arg("-o")
                .arg("SSE3")
                .arg("/var/run/dmesg.boot")
                .output()
                .unwrap()
        } else if cfg!(target_os = "macos") {
            // /usr/sbin/sysctl machdep.cpu.features | grep -m 1 -ow SSSE3
            Command::new("/usr/sbin/sysctl")
                .arg("machdep.cpu.features")
                .output()
                .unwrap()
        } else {
            // /bin/grep -m 1 -o ssse3 /proc/cpuinfo
            Command::new("/bin/grep")
                .arg("-m")
                .arg("1")
                .arg("-o")
                .arg("ssse3")
                .arg("/proc/cpuinfo")
                .output()
                .unwrap()
        };
        let output = std::str::from_utf8(&output.stdout[..]).unwrap().trim();

        if cfg!(target_os = "freebsd") || cfg!(target_os = "openbsd") || cfg!(target_os = "macos") {
            output.contains("SSSE3")
        } else {
            output == "ssse3"
        }
    };

    let mut cflags = "-g -Wall -Wextra -Wno-unused-parameter".to_owned();
    if !cfg!(feature = "no-sse") && sse3 {
        cflags = cflags + " -mssse3";
    }
    if cfg!(feature = "no-sse") && cfg!(target_os = "macos") {
        cflags = cflags + " -march=x86-64";
    }
    cflags = cflags + " -O2";

    env::set_var("CFLAGS", cflags);

    let mut config = gcc::Config::new();
    config.file("src/c/src/bitstring.c")
          .file("src/c/src/encparams.c")
          .file("src/c/src/hash.c")
          .file("src/c/src/idxgen.c")
          .file("src/c/src/key.c")
          .file("src/c/src/mgf.c")
          .file("src/c/src/ntru.c")
          .file("src/c/src/poly.c")
          .file("src/c/src/rand.c")
          .file("src/c/src/arith.c")
          .file("src/c/src/sha1.c")
          .file("src/c/src/sha2.c")
          .file("src/c/src/nist_ctr_drbg.c")
          .file("src/c/src/rijndael.c")
          .file("src/c/src/rijndael-alg-fst.c");

    if sse3 &&
       (cfg!(target_pointer_width = "64") || cfg!(target_os = "macos") ||
        cfg!(target_os = "windows")) {
        let out = if cfg!(target_os = "windows") {
            Command::new("c:\\mingw\\msys\\1.0\\bin\\perl")
                .arg("src/c/src/sha1-mb-x86_64.pl")
                .arg("elf")
                .output()
                .unwrap()
        } else {
            Command::new("/usr/bin/perl")
                .arg("src/c/src/sha1-mb-x86_64.pl")
                .arg("elf")
                .output()
                .unwrap()
        };
        let out = std::str::from_utf8(&out.stdout[..]).unwrap().trim();

        let p = Path::new("src/c/src/sha1-mb-x86_64.s");
        let mut f = File::create(&p).unwrap();
        f.write(out.as_bytes()).unwrap();

        println!("{}", out);
        panic!();

        if cfg!(target_os = "linux") || cfg!(target_os = "macos") {
            Command::new("gcc")
                .arg("-c")
                .arg("src/c/src/sha1-mb-x86_64.s")
                .arg("-o")
                .arg("src/c/src/sha1-mb-x86_64.o")
                .output()
                .unwrap();
        } else if cfg!(target_os = "freebsd") || cfg!(target_os = "openbsd") {
            Command::new("cc")
                .arg("-c")
                .arg("src/c/src/sha1-mb-x86_64.s")
                .arg("-o")
                .arg("src/c/src/sha1-mb-x86_64.o")
                .output()
                .unwrap();
        }

        let out = if cfg!(target_os = "windows") {
            Command::new("c:\\mingw\\msys\\1.0\\bin\\perl")
                .arg("src/c/src/sha256-mb-x86_64.pl")
                .arg("elf")
                .output()
                .unwrap()
        } else {
            Command::new("/usr/bin/perl")
                .arg("src/c/src/sha256-mb-x86_64.pl")
                .arg("elf")
                .output()
                .unwrap()
        };
        let out = std::str::from_utf8(&out.stdout[..]).unwrap().trim();

        let p = Path::new("src/c/src/sha256-mb-x86_64.s");
        let mut f = File::create(&p).unwrap();
        f.write(out.as_bytes()).unwrap();

        if cfg!(target_os = "linux") || cfg!(target_os = "macos") {
            Command::new("gcc")
                .arg("-c")
                .arg("src/c/src/sha256-mb-x86_64.s")
                .arg("-o")
                .arg("src/c/src/sha256-mb-x86_64.o")
                .output()
                .unwrap();
        } else if cfg!(target_os = "freebsd") || cfg!(target_os = "openbsd") {
            Command::new("cc")
                .arg("-c")
                .arg("src/c/src/sha256-mb-x86_64.s")
                .arg("-o")
                .arg("src/c/src/sha256-mb-x86_64.o")
                .output()
                .unwrap();
        }

        config.object("src/c/src/sha1-mb-x86_64.o").object("src/c/src/sha256-mb-x86_64.o");
    }

    config.include("src/c/src").compile("libntru.a");

    if !cfg!(feature = "no-sse") && sse3 {
        println!("cargo:rustc-cfg=SSE3")
    }
}
<commit_msg>Trying to avoid some possible issues with a smaller build script<commit_after>extern crate gcc;

use std::fs::File;
use std::path::Path;
use std::io::Write;
use std::process::Command;
use std::env;

fn main() {
    if cfg!(target_os = "linux") || cfg!(target_os = "macos") || cfg!(target_os = "windows") {
        env::set_var("CC", "gcc");
        env::set_var("AS", "gcc -c");
        if cfg!(target_os = "linux") {
            env::set_var("AR", "ar");
        }
    } else if cfg!(target_os = "freebsd") || cfg!(target_os = "openbsd") {
        env::set_var("CC", "cc");
        env::set_var("AS", "cc -c");
        env::set_var("AR", "ar");
    }

    let sse3 = if cfg!(target_os = "windows") {
        cfg!(feature = "sse")
    } else {
        let output = if cfg!(target_os = "freebsd") || cfg!(target_os = "openbsd") {
            // /usr/bin/grep -o SSSE3 /var/run/dmesg.boot | /usr/bin/head -1
            Command::new("/usr/bin/grep")
                .arg("-o")
                .arg("SSE3")
                .arg("/var/run/dmesg.boot")
                .output()
                .unwrap()
        } else if cfg!(target_os = "macos") {
            // /usr/sbin/sysctl machdep.cpu.features | grep -m 1 -ow SSSE3
            Command::new("/usr/sbin/sysctl")
                .arg("machdep.cpu.features")
                .output()
                .unwrap()
        } else {
            // /bin/grep -m 1 -o ssse3 /proc/cpuinfo
            Command::new("/bin/grep")
                .arg("-m")
                .arg("1")
                .arg("-o")
                .arg("ssse3")
                .arg("/proc/cpuinfo")
                .output()
                .unwrap()
        };
        let output = std::str::from_utf8(&output.stdout[..]).unwrap().trim();

        if cfg!(target_os = "freebsd") || cfg!(target_os = "openbsd") || cfg!(target_os = "macos") {
            output.contains("SSSE3")
        } else {
            output == "ssse3"
        }
    };

    let mut cflags = "-g -Wall -Wextra -Wno-unused-parameter".to_owned();
    if !cfg!(feature = "no-sse") && sse3 {
        cflags = cflags + " -mssse3";
    }
    if cfg!(feature = "no-sse") && cfg!(target_os = "macos") {
        cflags = cflags + " -march=x86-64";
    }
    cflags = cflags + " -O2";

    env::set_var("CFLAGS", cflags);

    let mut config = gcc::Config::new();
    config.file("src/c/src/bitstring.c")
          .file("src/c/src/encparams.c")
          .file("src/c/src/hash.c")
          .file("src/c/src/idxgen.c")
          .file("src/c/src/key.c")
          .file("src/c/src/mgf.c")
          .file("src/c/src/ntru.c")
          .file("src/c/src/poly.c")
          .file("src/c/src/rand.c")
          .file("src/c/src/arith.c")
          .file("src/c/src/sha1.c")
          .file("src/c/src/sha2.c")
          .file("src/c/src/nist_ctr_drbg.c")
          .file("src/c/src/rijndael.c")
          .file("src/c/src/rijndael-alg-fst.c");

    if sse3 &&
       (cfg!(target_pointer_width = "64") || cfg!(target_os = "macos") ||
        cfg!(target_os = "windows")) {
        let out = if cfg!(target_os = "windows") {
            Command::new("c:\\mingw\\msys\\1.0\\bin\\perl")
                .arg("src/c/src/sha1-mb-x86_64.pl")
                .arg("elf")
                .output()
                .unwrap()
        } else {
            Command::new("/usr/bin/perl")
                .arg("src/c/src/sha1-mb-x86_64.pl")
                .arg("elf")
                .output()
                .unwrap()
        };
        let out = std::str::from_utf8(&out.stdout[..]).unwrap().trim();

        let p = Path::new("src/c/src/sha1-mb-x86_64.s");
        let mut f = File::create(&p).unwrap();
        f.write(out.as_bytes()).unwrap();

        Command::new(env::var("CC").unwrap())
            .arg("-c")
            .arg("src/c/src/sha1-mb-x86_64.s")
            .arg("-o")
            .arg("src/c/src/sha1-mb-x86_64.o")
            .output()
            .unwrap();

        let out = if cfg!(target_os = "windows") {
            Command::new("c:\\mingw\\msys\\1.0\\bin\\perl")
                .arg("src/c/src/sha256-mb-x86_64.pl")
                .arg("elf")
                .output()
                .unwrap()
        } else {
            Command::new("/usr/bin/perl")
                .arg("src/c/src/sha256-mb-x86_64.pl")
                .arg("elf")
                .output()
                .unwrap()
        };
        let out = std::str::from_utf8(&out.stdout[..]).unwrap().trim();

        let p = Path::new("src/c/src/sha256-mb-x86_64.s");
        let mut f = File::create(&p).unwrap();
        f.write(out.as_bytes()).unwrap();

        Command::new(env::var("CC").unwrap())
            .arg("-c")
            .arg("src/c/src/sha256-mb-x86_64.s")
            .arg("-o")
            .arg("src/c/src/sha256-mb-x86_64.o")
            .output()
            .unwrap();

        config.object("src/c/src/sha1-mb-x86_64.o").object("src/c/src/sha256-mb-x86_64.o");
    }

    config.include("src/c/src").compile("libntru.a");

    if !cfg!(feature = "no-sse") && sse3 {
        println!("cargo:rustc-cfg=SSE3")
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::fs;
use std::os::unix::fs::symlink;
use std::path::{Path, PathBuf};

extern crate bindgen;
extern crate gcc;

fn main() {

    let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());

    let mut builder = gcc::Config::new();

    #[cfg(feature="cmsis_os")]
    let bindings = bindgen::Builder::default()
        .header("./ChibiOS/os/common/abstractions/cmsis_os/cmsis_os.h")
        .ctypes_prefix("cty");

    #[cfg(feature="cmsis_os")]
    builder.include("./ChibiOS/os/common/abstractions/cmsis_os");

    // from os/rt/rt.mk, KERNSRC
    let os_src_files = [
        "./ChibiOS/os/rt/src/chsys.c",
        "./ChibiOS/os/rt/src/chdebug.c",
        "./ChibiOS/os/rt/src/chtrace.c",
        "./ChibiOS/os/rt/src/chvt.c",
        "./ChibiOS/os/rt/src/chschd.c",
        "./ChibiOS/os/rt/src/chthreads.c",
        "./ChibiOS/os/rt/src/chtm.c",
        "./ChibiOS/os/rt/src/chstats.c",
        "./ChibiOS/os/rt/src/chregistry.c",
        "./ChibiOS/os/rt/src/chsem.c",
        "./ChibiOS/os/rt/src/chmtx.c",
        "./ChibiOS/os/rt/src/chcond.c",
        "./ChibiOS/os/rt/src/chevents.c",
        "./ChibiOS/os/rt/src/chmsg.c",
        "./ChibiOS/os/rt/src/chdynamic.c",
        "./ChibiOS/os/common/oslib/src/chmboxes.c",
        "./ChibiOS/os/common/oslib/src/chmemcore.c",
        "./ChibiOS/os/common/oslib/src/chheap.c",
        "./ChibiOS/os/common/oslib/src/chmempools.c",
    ];

    for os_src_file in os_src_files.iter() {
        builder.file(os_src_file);
    }

    #[cfg(feature="cmsis_os")]
    builder.file("./ChibiOS/os/common/abstractions/cmsis_os/cmsis_os.c");

    #[cfg(feature="stm32f407xg")]
    let port_src_files = [
        "./ChibiOS/os/common/ports/ARMCMx/chcore.c",
        "./ChibiOS/os/common/ports/ARMCMx/chcore_v7m.c",
        "./ChibiOS/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v7m.S",
        "./ChibiOS/os/common/startup/ARMCMx/compilers/GCC/crt0_v7m.S",
        "./ChibiOS/os/common/startup/ARMCMx/compilers/GCC/crt1.c",
    ];

    #[cfg(feature="stm32f051x8")]
    let port_src_files = [
        "./ChibiOS/os/common/ports/ARMCMx/chcore.c",
        "./ChibiOS/os/common/ports/ARMCMx/chcore_v6m.c",
        "./ChibiOS/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v6m.S",
        "./ChibiOS/os/common/startup/ARMCMx/compilers/GCC/crt0_v6m.S",
        "./ChibiOS/os/common/startup/ARMCMx/compilers/GCC/crt1.c",
    ];

    for port_src_file in port_src_files.iter() {
        builder.file(port_src_file);
    }

    let flags = [
        "-mno-thumb-interwork", // CFLAGS, because USB_THUMB is set
        "-ffunction-sections",  // from os/common/startup/ARMCMx/compilers/GCC/rules.mk
        "-fdata-sections",      // from os/common/startup/ARMCMx/compilers/GCC/rules.mk
        "-fno-common",          // from os/common/startup/ARMCMx/compilers/GCC/rules.mk
        "-fomit-frame-pointer",
        "-falign-functions=16",
    ];

    for flag in flags.iter() {
        builder.flag(flag);
    }

    let include_dirs = [
        "./",                               // for chconf.h
        "./ChibiOS/os/license",
        "./ChibiOS/os/various",
        "./ChibiOS/os/rt/include",            // KERNINC, from os/rt/rt.mk
        "./ChibiOS/os/common/oslib/include",  // KERNINC, from os/rt/rt.mk
    ];

    for include_dir in include_dirs.iter() {
        builder.include(include_dir);
    }

    #[cfg(feature="cmsis_os")]
    let bindings = bindings.clang_args(include_dirs.iter().map(|d| format!("-I{}", d)));

    #[cfg(feature="stm32f407xg")]
    let port_include_dirs = [
        "ChibiOS/os/common/ports/ARMCMx",                  // PORTINC, from os/common/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk
        "ChibiOS/os/common/ports/ARMCMx/compilers/GCC",    // PORTINC, from os/common/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk
        "ChibiOS/os/common/startup/ARMCMx/compilers/GCC",      // STARTUPINC, from os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk
        "ChibiOS/os/common/startup/ARMCMx/devices/STM32F4xx",  // STARTUPINC, from os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk
        "ChibiOS/os/common/ext/CMSIS/include",                 // STARTUPINC, from os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk
        "ChibiOS/os/common/ext/CMSIS/ST/STM32F4xx",            // STARTUPINC, from os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk
    ];

    #[cfg(feature="stm32f051x8")]
    let port_include_dirs = [
        "ChibiOS/os/common/ports/ARMCMx",                  // PORTINC, from os/common/ports/ARMCMx/compilers/GCC/mk/port_v6m.mk
        "ChibiOS/os/common/ports/ARMCMx/compilers/GCC",    // PORTINC, from os/common/ports/ARMCMx/compilers/GCC/mk/port_v6m.mk
        "ChibiOS/os/common/startup/ARMCMx/compilers/GCC",       // STARTUPINC, from os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f0xx.mk
        "ChibiOS/os/common/startup/ARMCMx/devices/STM32F0xx",   // STARTUPINC, from os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f0xx.mk
        "ChibiOS/os/common/ext/CMSIS/include",                  // STARTUPINC, from os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f0xx.mk
        "ChibiOS/os/common/ext/CMSIS/ST/STM32F0xx",             // STARTUPINC, from os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f0xx.mk
    ];

    for include_dir in port_include_dirs.iter() {
        builder.include(include_dir);
    }

    #[cfg(feature="cmsis_os")]
    let bindings = bindings.clang_args(port_include_dirs.iter().map(|d| format!("-I{}", d)));

    let defines = [
        ("THUMB_PRESENT", None),                              // CFLAGS, because USE_THUMB is set, rules.mk
        ("THUMB_NO_INTERWORKING", None),                      // CFLAGS, because USB_THUMB is set, rules.mk
    ];

    for &(def_key, def_val) in defines.iter() {
        builder.define(def_key, def_val);
    }

    #[cfg(feature="stm32f407xg")]
    let port_defines = [
        ("STM32F407xx", None),      // UDEFS from RT-ARMCM4-GENERIC demo Makefile
        ("THUMB", None),
    ];

    #[cfg(feature="stm32f051x8")]
    let port_defines = [
        ("STM32F051x8", None),      // UDEFS from RT-ARMCM0-GENERIC demo Makefile
        ("THUMB", None),
    ];

    for &(def_key, def_val) in port_defines.iter() {
        builder.define(def_key, def_val);
    }

    builder.archiver("arm-none-eabi-ar");
    builder.compile("libchibios.a");

    // ld path from os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk
    let ld_path = Path::new("./ChibiOS/os/common/startup/ARMCMx/compilers/GCC/ld/");

    #[cfg(feature="stm32f051x8")]
    let ld_file = "STM32F051x8.ld";

    #[cfg(feature="stm32f407xg")]
    let ld_file = "STM32F407xG.ld";

    fs::remove_file(ld_path.join("layout.ld")).expect("could not remove old linker file symlink");
    symlink(ld_file, ld_path.join("layout.ld")).expect("Could not create linker file symlink!");

    #[cfg(feature="cmsis_os")]
    {
        #[cfg(feature="stm32f407xg")]
        let bindings = bindings.clang_arg("-DSTM32F407xG");
        #[cfg(feature="stm32f051x8")]
        let bindings = bindings.clang_arg("-DSTM32F051x8");
        bindings
            .generate()
            .expect("unable to generate cmsis bindings")
            .write_to_file(out_dir.join("cmsis_os.rs"))
            .expect("unable to write cmsis bindings");
        std::process::Command::new("sed")
            .args(["-i", "", "-e", r"s/::std::os::raw::(c_\w+)/::libc::\1/g", out_dir.join("cmsis_os.rs").to_str().unwrap()].iter())
            .output()
            .expect("filed to munge bindings file");
        std::process::Command::new("sed")
            .args(["-i", "", "-e", "s/::std::/::core::/g", out_dir.join("cmsis_os.rs").to_str().unwrap()].iter())
            .output()
            .expect("filed to munge bindings file");
    }

    println!("cargo:rustc-link-search=native={}", ld_path.to_str().unwrap());
    println!("cargo:rustc-link-search=native={}", out_dir.to_str().unwrap());
    println!("cargo:rerun-if-changed=build.rs");
}
<commit_msg>Don't die when the ldscript symlink doesn't exist yet<commit_after>use std::env;
use std::fs;
use std::os::unix::fs::symlink;
use std::path::{Path, PathBuf};

extern crate bindgen;
extern crate gcc;

fn main() {

    let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());

    let mut builder = gcc::Config::new();

    #[cfg(feature="cmsis_os")]
    let bindings = bindgen::Builder::default()
        .header("./ChibiOS/os/common/abstractions/cmsis_os/cmsis_os.h")
        .ctypes_prefix("cty");

    #[cfg(feature = "cmsis_os")] builder.include("./ChibiOS/os/common/abstractions/cmsis_os");

    // from os/rt/rt.mk, KERNSRC
    let os_src_files = [
        "./ChibiOS/os/rt/src/chsys.c",
        "./ChibiOS/os/rt/src/chdebug.c",
        "./ChibiOS/os/rt/src/chtrace.c",
        "./ChibiOS/os/rt/src/chvt.c",
        "./ChibiOS/os/rt/src/chschd.c",
        "./ChibiOS/os/rt/src/chthreads.c",
        "./ChibiOS/os/rt/src/chtm.c",
        "./ChibiOS/os/rt/src/chstats.c",
        "./ChibiOS/os/rt/src/chregistry.c",
        "./ChibiOS/os/rt/src/chsem.c",
        "./ChibiOS/os/rt/src/chmtx.c",
        "./ChibiOS/os/rt/src/chcond.c",
        "./ChibiOS/os/rt/src/chevents.c",
        "./ChibiOS/os/rt/src/chmsg.c",
        "./ChibiOS/os/rt/src/chdynamic.c",
        "./ChibiOS/os/common/oslib/src/chmboxes.c",
        "./ChibiOS/os/common/oslib/src/chmemcore.c",
        "./ChibiOS/os/common/oslib/src/chheap.c",
        "./ChibiOS/os/common/oslib/src/chmempools.c",
    ];

    for os_src_file in os_src_files.iter() {
        builder.file(os_src_file);
    }

    #[cfg(feature = "cmsis_os")]
    builder.file("./ChibiOS/os/common/abstractions/cmsis_os/cmsis_os.c");

    #[cfg(feature="stm32f407xg")]
    let port_src_files = [
        "./ChibiOS/os/common/ports/ARMCMx/chcore.c",
        "./ChibiOS/os/common/ports/ARMCMx/chcore_v7m.c",
        "./ChibiOS/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v7m.S",
        "./ChibiOS/os/common/startup/ARMCMx/compilers/GCC/crt0_v7m.S",
        "./ChibiOS/os/common/startup/ARMCMx/compilers/GCC/crt1.c",
    ];

    #[cfg(feature="stm32f051x8")]
    let port_src_files = [
        "./ChibiOS/os/common/ports/ARMCMx/chcore.c",
        "./ChibiOS/os/common/ports/ARMCMx/chcore_v6m.c",
        "./ChibiOS/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v6m.S",
        "./ChibiOS/os/common/startup/ARMCMx/compilers/GCC/crt0_v6m.S",
        "./ChibiOS/os/common/startup/ARMCMx/compilers/GCC/crt1.c",
    ];

    for port_src_file in port_src_files.iter() {
        builder.file(port_src_file);
    }

    let flags = [
        "-mno-thumb-interwork", // CFLAGS, because USB_THUMB is set
        "-ffunction-sections", // from os/common/startup/ARMCMx/compilers/GCC/rules.mk
        "-fdata-sections", // from os/common/startup/ARMCMx/compilers/GCC/rules.mk
        "-fno-common", // from os/common/startup/ARMCMx/compilers/GCC/rules.mk
        "-fomit-frame-pointer",
        "-falign-functions=16",
    ];

    for flag in flags.iter() {
        builder.flag(flag);
    }

    let include_dirs = [
        "./",                               // for chconf.h
        "./ChibiOS/os/license",
        "./ChibiOS/os/various",
        "./ChibiOS/os/rt/include",            // KERNINC, from os/rt/rt.mk
        "./ChibiOS/os/common/oslib/include",  // KERNINC, from os/rt/rt.mk
    ];

    for include_dir in include_dirs.iter() {
        builder.include(include_dir);
    }

    #[cfg(feature="cmsis_os")]
    let bindings = bindings.clang_args(include_dirs.iter().map(|d| format!("-I{}", d)));

    #[cfg(feature="stm32f407xg")]
    let port_include_dirs = [
        "ChibiOS/os/common/ports/ARMCMx",                  // PORTINC, from os/common/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk
        "ChibiOS/os/common/ports/ARMCMx/compilers/GCC",    // PORTINC, from os/common/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk
        "ChibiOS/os/common/startup/ARMCMx/compilers/GCC",      // STARTUPINC, from os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk
        "ChibiOS/os/common/startup/ARMCMx/devices/STM32F4xx",  // STARTUPINC, from os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk
        "ChibiOS/os/common/ext/CMSIS/include",                 // STARTUPINC, from os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk
        "ChibiOS/os/common/ext/CMSIS/ST/STM32F4xx",            // STARTUPINC, from os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk
    ];

    #[cfg(feature="stm32f051x8")]
    let port_include_dirs = [
        "ChibiOS/os/common/ports/ARMCMx",                  // PORTINC, from os/common/ports/ARMCMx/compilers/GCC/mk/port_v6m.mk
        "ChibiOS/os/common/ports/ARMCMx/compilers/GCC",    // PORTINC, from os/common/ports/ARMCMx/compilers/GCC/mk/port_v6m.mk
        "ChibiOS/os/common/startup/ARMCMx/compilers/GCC",       // STARTUPINC, from os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f0xx.mk
        "ChibiOS/os/common/startup/ARMCMx/devices/STM32F0xx",   // STARTUPINC, from os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f0xx.mk
        "ChibiOS/os/common/ext/CMSIS/include",                  // STARTUPINC, from os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f0xx.mk
        "ChibiOS/os/common/ext/CMSIS/ST/STM32F0xx",             // STARTUPINC, from os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f0xx.mk
    ];

    for include_dir in port_include_dirs.iter() {
        builder.include(include_dir);
    }

    #[cfg(feature="cmsis_os")]
    let bindings = bindings.clang_args(port_include_dirs.iter().map(|d| format!("-I{}", d)));

    let defines = [
        ("THUMB_PRESENT", None),                              // CFLAGS, because USE_THUMB is set, rules.mk
        ("THUMB_NO_INTERWORKING", None),                      // CFLAGS, because USB_THUMB is set, rules.mk
    ];

    for &(def_key, def_val) in defines.iter() {
        builder.define(def_key, def_val);
    }

    #[cfg(feature="stm32f407xg")]
    let port_defines = [
        ("STM32F407xx", None), // UDEFS from RT-ARMCM4-GENERIC demo Makefile
        ("THUMB", None),
    ];

    #[cfg(feature="stm32f051x8")]
    let port_defines = [
        ("STM32F051x8", None), // UDEFS from RT-ARMCM0-GENERIC demo Makefile
        ("THUMB", None),
    ];

    for &(def_key, def_val) in port_defines.iter() {
        builder.define(def_key, def_val);
    }

    builder.archiver("arm-none-eabi-ar");
    builder.compile("libchibios.a");

    // ld path from os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk
    let ld_path = Path::new("./ChibiOS/os/common/startup/ARMCMx/compilers/GCC/ld/");

    #[cfg(feature="stm32f051x8")]
    let ld_file = "STM32F051x8.ld";

    #[cfg(feature="stm32f407xg")]
    let ld_file = "STM32F407xG.ld";

    match fs::remove_file(ld_path.join("layout.ld")) {
        Err(_) => println!("could not remove old linker file symlink"),
        _ => {}
    };
    symlink(ld_file, ld_path.join("layout.ld")).expect("Could not create symlink!");

    #[cfg(feature = "cmsis_os")]
    {
        #[cfg(feature="stm32f407xg")]
        let bindings = bindings.clang_arg("-DSTM32F407xG");
        #[cfg(feature="stm32f051x8")]
        let bindings = bindings.clang_arg("-DSTM32F051x8");
        bindings
            .generate()
            .expect("unable to generate cmsis bindings")
            .write_to_file(out_dir.join("cmsis_os.rs"))
            .expect("unable to write cmsis bindings");
        std::process::Command::new("sed")
            .args(
                [
                    "-i",
                    "",
                    "-e",
                    r"s/::std::os::raw::(c_\w+)/::libc::\1/g",
                    out_dir.join("cmsis_os.rs").to_str().unwrap(),
                ].iter(),
            )
            .output()
            .expect("filed to munge bindings file");
        std::process::Command::new("sed")
            .args(
                [
                    "-i",
                    "",
                    "-e",
                    "s/::std::/::core::/g",
                    out_dir.join("cmsis_os.rs").to_str().unwrap(),
                ].iter(),
            )
            .output()
            .expect("filed to munge bindings file");
    }

    println!(
        "cargo:rustc-link-search=native={}",
        ld_path.to_str().unwrap()
    );
    println!(
        "cargo:rustc-link-search=native={}",
        out_dir.to_str().unwrap()
    );
    println!("cargo:rerun-if-changed=build.rs");
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use autocxx_parser::IncludeCpp;
use proc_macro2::{Ident, Span};
use proc_macro_error::{abort, proc_macro_error};
use quote::{quote, ToTokens};
use syn::parse::{Parse, ParseStream, Parser};
use syn::{parse_macro_input, Fields, ItemStruct, Result as ParseResult};

struct SelfOwned(bool);

impl Parse for SelfOwned {
    fn parse(input: ParseStream) -> ParseResult<Self> {
        let id = input.parse::<Option<Ident>>()?;
        match id {
            Some(id) if id == "self_owned" => Ok(Self(true)),
            Some(id) => Err(syn::Error::new_spanned(
                id.into_token_stream(),
                "Expected self_owned",
            )),
            None => Ok(Self(false)),
        }
    }
}

/// Implementation of the `include_cpp` macro. See documentation for `autocxx` crate.
#[proc_macro_error]
#[proc_macro]
pub fn include_cpp_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let include_cpp = parse_macro_input!(input as IncludeCpp);
    proc_macro::TokenStream::from(include_cpp.generate_rs())
}

/// Attribute to state that a Rust `struct` is a C++ subclass.
/// This adds an additional field to the struct which autocxx uses to
/// track a C++ instantiation of this Rust subclass.
#[proc_macro_error]
#[proc_macro_attribute]
pub fn is_subclass(
    attr: proc_macro::TokenStream,
    item: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
    let mut s: ItemStruct =
        syn::parse(item).unwrap_or_else(|_| abort!(Span::call_site(), "Expected a struct"));
    let id = &s.ident;
    let cpp_ident = Ident::new(&format!("{}Cpp", id.to_string()), Span::call_site());
    match &mut s.fields {
        Fields::Named(fields) => {
            let input = quote! {
                cpp_peer: autocxx::subclass::CppSubclassCppPeerHolder<ffi:: #cpp_ident>
            };
            let parser = syn::Field::parse_named;
            let f = parser.parse2(input).unwrap();
            fields.named.push(f);
        }
        _ => abort!(Span::call_site(), "Expect a struct with named fields"),
    }
    let self_owned: SelfOwned = syn::parse(attr)
        .unwrap_or_else(|_| abort!(Span::call_site(), "Unable to parse attributes"));
    let self_owned_bit = if self_owned.0 {
        Some(quote! {
            impl autocxx::subclass::CppSubclassSelfOwned<ffi::#cpp_ident> for #id {}
        })
    } else {
        None
    };
    let toks = quote! {
        #s

        impl autocxx::subclass::CppSubclass<ffi::#cpp_ident> for #id {
            fn peer_holder_mut(&mut self) -> &mut autocxx::subclass::CppSubclassCppPeerHolder<ffi::#cpp_ident> {
                &mut self.cpp_peer
            }
            fn peer_holder(&self) -> &autocxx::subclass::CppSubclassCppPeerHolder<ffi::#cpp_ident> {
                &self.cpp_peer
            }
        }

        #self_owned_bit
    };
    toks.into()
}
<commit_msg>Better error.<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use autocxx_parser::IncludeCpp;
use proc_macro2::{Ident, Span};
use proc_macro_error::{abort, proc_macro_error};
use quote::{quote, ToTokens};
use syn::parse::{Parse, ParseStream, Parser};
use syn::{parse_macro_input, Fields, ItemStruct, Result as ParseResult};

struct SelfOwned(bool);

impl Parse for SelfOwned {
    fn parse(input: ParseStream) -> ParseResult<Self> {
        let id = input.parse::<Option<Ident>>()?;
        match id {
            Some(id) if id == "self_owned" => Ok(Self(true)),
            Some(id) => Err(syn::Error::new_spanned(
                id.into_token_stream(),
                "Expected self_owned",
            )),
            None => Ok(Self(false)),
        }
    }
}

/// Implementation of the `include_cpp` macro. See documentation for `autocxx` crate.
#[proc_macro_error]
#[proc_macro]
pub fn include_cpp_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let include_cpp = parse_macro_input!(input as IncludeCpp);
    proc_macro::TokenStream::from(include_cpp.generate_rs())
}

/// Attribute to state that a Rust `struct` is a C++ subclass.
/// This adds an additional field to the struct which autocxx uses to
/// track a C++ instantiation of this Rust subclass.
#[proc_macro_error]
#[proc_macro_attribute]
pub fn is_subclass(
    attr: proc_macro::TokenStream,
    item: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
    let mut s: ItemStruct =
        syn::parse(item).unwrap_or_else(|_| abort!(Span::call_site(), "Expected a struct"));
    let id = &s.ident;
    let cpp_ident = Ident::new(&format!("{}Cpp", id.to_string()), Span::call_site());
    match &mut s.fields {
        Fields::Named(fields) => {
            let input = quote! {
                cpp_peer: autocxx::subclass::CppSubclassCppPeerHolder<ffi:: #cpp_ident>
            };
            let parser = syn::Field::parse_named;
            let f = parser.parse2(input).unwrap();
            fields.named.push(f);
        }
        _ => abort!(Span::call_site(), "Expect a struct with named fields - use struct A{} as opposed to struct A; or struct A()"),
    }
    let self_owned: SelfOwned = syn::parse(attr)
        .unwrap_or_else(|_| abort!(Span::call_site(), "Unable to parse attributes"));
    let self_owned_bit = if self_owned.0 {
        Some(quote! {
            impl autocxx::subclass::CppSubclassSelfOwned<ffi::#cpp_ident> for #id {}
        })
    } else {
        None
    };
    let toks = quote! {
        #s

        impl autocxx::subclass::CppSubclass<ffi::#cpp_ident> for #id {
            fn peer_holder_mut(&mut self) -> &mut autocxx::subclass::CppSubclassCppPeerHolder<ffi::#cpp_ident> {
                &mut self.cpp_peer
            }
            fn peer_holder(&self) -> &autocxx::subclass::CppSubclassCppPeerHolder<ffi::#cpp_ident> {
                &self.cpp_peer
            }
        }

        #self_owned_bit
    };
    toks.into()
}
<|endoftext|>


<commit_before>use std::libc::*;
use std::{cast, ptr, str, to_bytes, uint, vec};

pub use ll = clangll;
use clangll::*;

// Cursor
pub struct Cursor(CXCursor);

pub type CursorVisitor<'self> = &'self fn(c: &Cursor, p: &Cursor) -> Enum_CXChildVisitResult;

impl Cursor {
    // common
    pub fn spelling(&self) -> ~str {
        unsafe {
            String(clang_getCursorSpelling(**self)).to_str()
        }
    }

    pub fn kind(&self) -> Enum_CXCursorKind {
        unsafe {
            clang_getCursorKind(**self)
        }
    }

    pub fn location(&self) -> SourceLocation {
        unsafe {
            SourceLocation(clang_getCursorLocation(**self))
        }
    }

    pub fn cur_type(&self) -> Type {
        unsafe {
            Type(clang_getCursorType(**self))
        }
    }

    pub fn definition(&self) -> Cursor {
        unsafe {
            Cursor(clang_getCursorDefinition(**self))
        }
    }

    pub fn visit(&self, func: CursorVisitor) {
        unsafe {
            let data = cast::transmute::<&CursorVisitor, CXClientData>(&func);
            clang_visitChildren(**self, visit_children, data);
        };
    }

    // enum
    pub fn enum_type(&self) -> Type {
        unsafe {
            Type(clang_getEnumDeclIntegerType(**self))
        }
    }

    pub fn enum_val(&self) -> int {
        unsafe {
            clang_getEnumConstantDeclValue(**self) as int
        }
    }

    // typedef
    pub fn typedef_type(&self) -> Type {
        unsafe {
            Type(clang_getTypedefDeclUnderlyingType(**self))
        }
    }

    // function, variable
    pub fn linkage(&self) -> Enum_CXLinkageKind {
        unsafe {
            clang_getCursorLinkage(**self)
        }
    }

    // function
    pub fn args(&self) -> ~[Cursor] {
        unsafe {
            let num = clang_Cursor_getNumArguments(**self) as uint;
            let mut args = ~[];
            for uint::range(0, num) |i| {
                args.push(Cursor(clang_Cursor_getArgument(**self, i as c_uint)));
            }
            return args;
        }
    }

    pub fn ret_type(&self) -> Type {
        unsafe {
            Type(clang_getCursorResultType(**self))
        }
    }
}

extern fn visit_children(cur: CXCursor, parent: ll::CXCursor,
                         data: CXClientData) -> ll::Enum_CXChildVisitResult {
    unsafe {
        let func = cast::transmute::<CXClientData, &CursorVisitor>(data);
        return (*func)(&Cursor(cur), &Cursor(parent));
    }
}

impl Eq for Cursor {
    fn eq(&self, other: &Cursor) -> bool {
        unsafe {
            clang_equalCursors(**self, **other) == 1
        }
    }

    fn ne(&self, other: &Cursor) -> bool {
        return !self.eq(other);
    }
}

impl IterBytes for Cursor {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
        [(self.kind as int),
         (self.xdata as int),
         (self.data[0] as int),
         (self.data[1] as int),
         (self.data[2] as int)
        ].iter_bytes(lsb0, f)
    }
}

// type
pub struct Type(CXType);

impl Type {
    // common
    pub fn kind(&self) -> Enum_CXTypeKind {
        return (*self).kind;
    }

    pub fn declaration(&self) -> Cursor {
        unsafe {
            Cursor(clang_getTypeDeclaration(**self))
        }
    }

    pub fn is_const(&self) -> bool {
        unsafe {
            clang_isConstQualifiedType(**self) == 1
        }
    }

    // pointer
    pub fn pointee_type(&self) -> Type {
        unsafe {
            Type(clang_getPointeeType(**self))
        }
    }

    // array
    pub fn elem_type(&self) -> Type {
        unsafe {
            Type(clang_getArrayElementType(**self))
        }
    }

    pub fn array_size(&self) -> uint {
        unsafe {
            clang_getArraySize(**self) as uint
        }
    }

    // typedef
    pub fn canonical_type(&self) -> Type {
        unsafe {
            Type(clang_getCanonicalType(**self))
        }
    }

    // function
    pub fn is_variadic(&self) -> bool {
        unsafe {
            clang_isFunctionTypeVariadic(**self) == 1
        }
    }

    pub fn arg_types(&self) -> ~[Type] {
        unsafe {
            let num = clang_getNumArgTypes(**self) as uint;
            let mut args = ~[];
            for uint::range(0, num) |i| {
                args.push(Type(clang_getArgType(**self, i as c_uint)));
            }
            return args;
        }
    }

    pub fn ret_type(&self) -> Type {
        unsafe {
            Type(clang_getResultType(**self))
        }
    }
}

// SourceLocation
pub struct SourceLocation(CXSourceLocation);

impl SourceLocation {
    pub fn location(&self) -> (File, uint, uint, uint) {
        unsafe {
            let mut file = ptr::mut_null();
            let mut line = 0;
            let mut col = 0;
            let mut off = 0;
            clang_getSpellingLocation(**self, ptr::to_mut_unsafe_ptr(&mut file),
                                          ptr::to_mut_unsafe_ptr(&mut line),
                                          ptr::to_mut_unsafe_ptr(&mut col),
                                          ptr::to_mut_unsafe_ptr(&mut off));
            return (File(file), line as uint, col as uint, off as uint);
        }
    }
}

// File
pub struct File(CXFile);

impl File {
    pub fn name(&self) -> ~str {
        unsafe {
            String(clang_getFileName(**self)).to_str()
        }
    }
}

// String
pub struct String(CXString);

impl ToStr for String {
    fn to_str(&self) -> ~str {
        unsafe {
            let c_str = clang_getCString(**self) as *c_char;
            str::raw::from_c_str(c_str)
        }
    }
}

// Index
pub struct Index(CXIndex);

impl Index {
    pub fn create(pch: bool, diag: bool) -> Index {
        unsafe {
            Index(clang_createIndex(pch as c_int, diag as c_int))
        }
    }

    pub fn dispose(&self) {
        unsafe {
            clang_disposeIndex(**self);
        }
    }
}

// TranslationUnit
pub struct TranslationUnit(CXTranslationUnit);

impl TranslationUnit {
    pub fn parse(ix: &Index, file: &str, cmd_args: &[~str],
                 unsaved: &[UnsavedFile], opts: uint) -> TranslationUnit {
        let fname = str::as_c_str(file, |f| f);
        let c_args = cmd_args.map(|s| str::as_c_str(*s, |cs| cs));
        let mut c_unsaved = unsaved.map(|f| **f);
        let tu = unsafe {
            clang_parseTranslationUnit(**ix, fname,
                                       vec::raw::to_ptr(c_args),
                                       c_args.len() as c_int,
                                       vec::raw::to_mut_ptr(c_unsaved),
                                       c_unsaved.len() as c_uint,
                                       opts as c_uint)
        };
        TranslationUnit(tu)
    }

    pub fn diags(&self) -> ~[Diagnostic] {
        unsafe {
            let num = clang_getNumDiagnostics(**self) as uint;
            let mut diags = ~[];
            for uint::range(0, num) |i| {
                diags.push(Diagnostic(clang_getDiagnostic(**self, i as c_uint)));
            }
            return diags;
        }
    }

    pub fn cursor(&self) -> Cursor {
        unsafe {
            Cursor(clang_getTranslationUnitCursor(**self))
        }
    }

    pub fn dispose(&self) {
        unsafe {
            clang_disposeTranslationUnit(**self);
        }
    }
}

// Diagnostic
pub struct Diagnostic(CXDiagnostic);

impl Diagnostic {
    pub fn default_opts() -> uint {
        unsafe {
            clang_defaultDiagnosticDisplayOptions() as uint
        }
    }

    pub fn format(&self, opts: uint) -> ~str {
        unsafe {
            String(clang_formatDiagnostic(**self, opts as c_uint)).to_str()
        }
    }

    pub fn severity(&self) -> Enum_CXDiagnosticSeverity {
        unsafe {
            clang_getDiagnosticSeverity(**self)
        }
    }
}

// UnsavedFile
pub struct UnsavedFile(Struct_CXUnsavedFile);
<commit_msg>fix build<commit_after>use std::libc::*;
use std::{cast, ptr, str, to_bytes, uint, vec};

pub use ll = clangll;
use clangll::*;

// Cursor
pub struct Cursor(CXCursor);

pub type CursorVisitor<'self> = &'self fn(c: &Cursor, p: &Cursor) -> Enum_CXChildVisitResult;

impl Cursor {
    // common
    pub fn spelling(&self) -> ~str {
        unsafe {
            String(clang_getCursorSpelling(**self)).to_str()
        }
    }

    pub fn kind(&self) -> Enum_CXCursorKind {
        unsafe {
            clang_getCursorKind(**self)
        }
    }

    pub fn location(&self) -> SourceLocation {
        unsafe {
            SourceLocation(clang_getCursorLocation(**self))
        }
    }

    pub fn cur_type(&self) -> Type {
        unsafe {
            Type(clang_getCursorType(**self))
        }
    }

    pub fn definition(&self) -> Cursor {
        unsafe {
            Cursor(clang_getCursorDefinition(**self))
        }
    }

    pub fn visit(&self, func: CursorVisitor) {
        unsafe {
            let data = cast::transmute::<&CursorVisitor, CXClientData>(&func);
            clang_visitChildren(**self, visit_children, data);
        };
    }

    // enum
    pub fn enum_type(&self) -> Type {
        unsafe {
            Type(clang_getEnumDeclIntegerType(**self))
        }
    }

    pub fn enum_val(&self) -> int {
        unsafe {
            clang_getEnumConstantDeclValue(**self) as int
        }
    }

    // typedef
    pub fn typedef_type(&self) -> Type {
        unsafe {
            Type(clang_getTypedefDeclUnderlyingType(**self))
        }
    }

    // function, variable
    pub fn linkage(&self) -> Enum_CXLinkageKind {
        unsafe {
            clang_getCursorLinkage(**self)
        }
    }

    // function
    pub fn args(&self) -> ~[Cursor] {
        unsafe {
            let num = clang_Cursor_getNumArguments(**self) as uint;
            let mut args = ~[];
            for uint::range(0, num) |i| {
                args.push(Cursor(clang_Cursor_getArgument(**self, i as c_uint)));
            }
            return args;
        }
    }

    pub fn ret_type(&self) -> Type {
        unsafe {
            Type(clang_getCursorResultType(**self))
        }
    }
}

extern fn visit_children(cur: CXCursor, parent: ll::CXCursor,
                         data: CXClientData) -> ll::Enum_CXChildVisitResult {
    unsafe {
        let func = cast::transmute::<CXClientData, &CursorVisitor>(data);
        return (*func)(&Cursor(cur), &Cursor(parent));
    }
}

impl Eq for Cursor {
    fn eq(&self, other: &Cursor) -> bool {
        unsafe {
            clang_equalCursors(**self, **other) == 1
        }
    }

    fn ne(&self, other: &Cursor) -> bool {
        return !self.eq(other);
    }
}

impl IterBytes for Cursor {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
        [(self.kind as int),
         (self.xdata as int),
         (self.data[0] as int),
         (self.data[1] as int),
         (self.data[2] as int)
        ].iter_bytes(lsb0, f)
    }
}

// type
pub struct Type(CXType);

impl Type {
    // common
    pub fn kind(&self) -> Enum_CXTypeKind {
        return (*self).kind;
    }

    pub fn declaration(&self) -> Cursor {
        unsafe {
            Cursor(clang_getTypeDeclaration(**self))
        }
    }

    pub fn is_const(&self) -> bool {
        unsafe {
            clang_isConstQualifiedType(**self) == 1
        }
    }

    // pointer
    pub fn pointee_type(&self) -> Type {
        unsafe {
            Type(clang_getPointeeType(**self))
        }
    }

    // array
    pub fn elem_type(&self) -> Type {
        unsafe {
            Type(clang_getArrayElementType(**self))
        }
    }

    pub fn array_size(&self) -> uint {
        unsafe {
            clang_getArraySize(**self) as uint
        }
    }

    // typedef
    pub fn canonical_type(&self) -> Type {
        unsafe {
            Type(clang_getCanonicalType(**self))
        }
    }

    // function
    pub fn is_variadic(&self) -> bool {
        unsafe {
            clang_isFunctionTypeVariadic(**self) == 1
        }
    }

    pub fn arg_types(&self) -> ~[Type] {
        unsafe {
            let num = clang_getNumArgTypes(**self) as uint;
            let mut args = ~[];
            for uint::range(0, num) |i| {
                args.push(Type(clang_getArgType(**self, i as c_uint)));
            }
            return args;
        }
    }

    pub fn ret_type(&self) -> Type {
        unsafe {
            Type(clang_getResultType(**self))
        }
    }
}

// SourceLocation
pub struct SourceLocation(CXSourceLocation);

impl SourceLocation {
    pub fn location(&self) -> (File, uint, uint, uint) {
        unsafe {
            let mut file = ptr::mut_null();
            let mut line = 0;
            let mut col = 0;
            let mut off = 0;
            clang_getSpellingLocation(**self, ptr::to_mut_unsafe_ptr(&mut file),
                                          ptr::to_mut_unsafe_ptr(&mut line),
                                          ptr::to_mut_unsafe_ptr(&mut col),
                                          ptr::to_mut_unsafe_ptr(&mut off));
            return (File(file), line as uint, col as uint, off as uint);
        }
    }
}

// File
pub struct File(CXFile);

impl File {
    pub fn name(&self) -> ~str {
        unsafe {
            String(clang_getFileName(**self)).to_str()
        }
    }
}

// String
pub struct String(CXString);

impl ToStr for String {
    fn to_str(&self) -> ~str {
        unsafe {
            let c_str = clang_getCString(**self) as *c_char;
            str::raw::from_c_str(c_str)
        }
    }
}

// Index
pub struct Index(CXIndex);

impl Index {
    pub fn create(pch: bool, diag: bool) -> Index {
        unsafe {
            Index(clang_createIndex(pch as c_int, diag as c_int))
        }
    }

    pub fn dispose(&self) {
        unsafe {
            clang_disposeIndex(**self);
        }
    }
}

// TranslationUnit
pub struct TranslationUnit(CXTranslationUnit);

impl TranslationUnit {
    pub fn parse(ix: &Index, file: &str, cmd_args: &[~str],
                 unsaved: &[UnsavedFile], opts: uint) -> TranslationUnit {
        let fname = file.as_c_str(|f| f);
        let c_args = cmd_args.map(|s| (*s).as_c_str(|cs| cs));
        let mut c_unsaved = unsaved.map(|f| **f);
        let tu = unsafe {
            clang_parseTranslationUnit(**ix, fname,
                                       vec::raw::to_ptr(c_args),
                                       c_args.len() as c_int,
                                       vec::raw::to_mut_ptr(c_unsaved),
                                       c_unsaved.len() as c_uint,
                                       opts as c_uint)
        };
        TranslationUnit(tu)
    }

    pub fn diags(&self) -> ~[Diagnostic] {
        unsafe {
            let num = clang_getNumDiagnostics(**self) as uint;
            let mut diags = ~[];
            for uint::range(0, num) |i| {
                diags.push(Diagnostic(clang_getDiagnostic(**self, i as c_uint)));
            }
            return diags;
        }
    }

    pub fn cursor(&self) -> Cursor {
        unsafe {
            Cursor(clang_getTranslationUnitCursor(**self))
        }
    }

    pub fn dispose(&self) {
        unsafe {
            clang_disposeTranslationUnit(**self);
        }
    }
}

// Diagnostic
pub struct Diagnostic(CXDiagnostic);

impl Diagnostic {
    pub fn default_opts() -> uint {
        unsafe {
            clang_defaultDiagnosticDisplayOptions() as uint
        }
    }

    pub fn format(&self, opts: uint) -> ~str {
        unsafe {
            String(clang_formatDiagnostic(**self, opts as c_uint)).to_str()
        }
    }

    pub fn severity(&self) -> Enum_CXDiagnosticSeverity {
        unsafe {
            clang_getDiagnosticSeverity(**self)
        }
    }
}

// UnsavedFile
pub struct UnsavedFile(Struct_CXUnsavedFile);
<|endoftext|>