about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/librustpkg/rustpkg.rc190
-rw-r--r--src/librustpkg/util.rs78
2 files changed, 200 insertions, 68 deletions
diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc
index bf1301868af..86802c65781 100644
--- a/src/librustpkg/rustpkg.rc
+++ b/src/librustpkg/rustpkg.rc
@@ -281,7 +281,13 @@ impl Ctx {
 
         match cmd {
             ~"build" => {
-                self.build(&os::getcwd(), true, false, false);
+                if args.len() < 1 {
+                    return usage::build();
+                }
+                let pkgid = PkgId::new(args[0]);
+                let mut src = PkgSrc::new(&Path("."), &pkgid);
+                src.find_crates();
+                src.build(&Path("."));
             }
             ~"clean" => {
                 self.clean();
@@ -927,7 +933,7 @@ pub fn main() {
 
 /// A crate is a unit of Rust code to be compiled into a binary or library
 pub struct Crate {
-    file: ~str,
+    file: Path,
     flags: ~[~str],
     cfgs: ~[~str]
 }
@@ -959,28 +965,37 @@ pub fn run(listeners: ~[Listener]) {
 }
 
 pub impl Crate {
-    pub fn flag(&self, flag: ~str) -> Crate {
+
+    static fn new(p: &Path) -> Crate {
+        Crate {
+            file: copy *p,
+            flags: ~[],
+            cfgs: ~[]
+        }
+    }
+
+    fn flag(&self, flag: ~str) -> Crate {
         Crate {
             flags: vec::append(copy self.flags, ~[flag]),
             .. copy *self
         }
     }
 
-    pub fn flags(&self, flags: ~[~str]) -> Crate {
+    fn flags(&self, flags: ~[~str]) -> Crate {
         Crate {
             flags: vec::append(copy self.flags, flags),
             .. copy *self
         }
     }
 
-    pub fn cfg(&self, cfg: ~str) -> Crate {
+    fn cfg(&self, cfg: ~str) -> Crate {
         Crate {
             cfgs: vec::append(copy self.cfgs, ~[cfg]),
             .. copy *self
         }
     }
 
-    pub fn cfgs(&self, cfgs: ~[~str]) -> Crate {
+    fn cfgs(&self, cfgs: ~[~str]) -> Crate {
         Crate {
             cfgs: vec::append(copy self.cfgs, cfgs),
             .. copy *self
@@ -988,15 +1003,6 @@ pub impl Crate {
     }
 }
 
-/// Create a crate target from a source file
-pub fn Crate(file: ~str) -> Crate {
-    Crate {
-        file: file,
-        flags: ~[],
-        cfgs: ~[]
-    }
-}
-
 /**
  * Get the working directory of the package script.
  * Assumes that the package script has been compiled
@@ -1026,7 +1032,7 @@ pub fn build(crates: ~[Crate]) -> bool {
     let test = args[3] == ~"true";
 
     for crates.each |&crate| {
-        let path = &dir.push_rel(&Path(crate.file)).normalize();
+        let path = &dir.push_rel(&crate.file).normalize();
 
         util::note(fmt!("compiling %s", path.to_str()));
 
@@ -1043,3 +1049,155 @@ pub fn build(crates: ~[Crate]) -> bool {
 
     success
 }
+
+
+// Path-fragment identifier of a package such as 
+// 'github.com/graydon/test'; must be a relative
+// path with >=1 component.
+struct PkgId {
+    path: Path
+}
+
+condition! {
+    bad_pkg_id: (::core::path::Path, ~str) -> ::PkgId;
+}
+
+impl PkgId {
+    static fn new(s: &str) -> PkgId {
+        use bad_pkg_id::cond;
+
+        let p = Path(s);
+        if p.is_absolute {
+            return cond.raise((p, ~"absolute pkgid"));
+        }
+        if p.components.len() < 1 {
+            return cond.raise((p, ~"0-length pkgid"));
+        }
+        PkgId {
+            path: p
+        }
+    }
+}
+
+
+// An enumeration of the unpacked source of a package workspace.
+// This contains a list of files found in the source workspace.
+pub struct PkgSrc {
+    root: Path,
+    id: PkgId,
+    libs: ~[Crate],
+    mains: ~[Crate],
+    tests: ~[Crate],
+    benchs: ~[Crate],
+}
+
+condition! {
+    bad_path: (::core::path::Path, ~str) -> ::core::path::Path;
+}
+
+condition! {
+    build_err: (~str) -> ();
+}
+
+impl PkgSrc {
+
+
+    static fn new(fs_root: &Path, id: &PkgId) -> PkgSrc {
+        PkgSrc {
+            root: copy *fs_root,
+            id: copy *id,
+            libs: ~[],
+            mains: ~[],
+            tests: ~[],
+            benchs: ~[]
+        }
+    }
+
+
+    fn check_dir(&self) -> Path {
+        use bad_path::cond;
+
+        let dir = self.root.push_rel(&self.id.path).normalize();
+
+        if ! os::path_exists(&dir) {
+            return cond.raise((dir, ~"missing package dir"));
+        }
+              
+        if ! os::path_is_dir(&dir) {
+            return cond.raise((dir, ~"missing package dir"));
+        }
+
+        dir
+    }
+
+
+    fn has_pkg_file(&self) -> bool {
+        let dir = self.check_dir();
+        dir.push("pkg.rs").exists()
+    }
+
+
+    static fn push_crate(cs: &mut ~[Crate], prefix: uint, p: &Path) {
+        assert p.components.len() > prefix;
+        let mut sub = Path("");
+        for vec::slice(p.components, prefix,
+                       p.components.len()).each |c| {
+            sub = sub.push(*c);
+        }
+        debug!("found crate %s", sub.to_str());
+        cs.push(Crate::new(&sub));
+    }
+
+    fn find_crates(&mut self) {
+        use PkgSrc::push_crate;
+        assert ! self.has_pkg_file();
+        let dir = self.check_dir();
+        let prefix = dir.components.len();
+        for os::walk_dir(&dir) |pth| {
+            match pth.filename() {
+                Some(~"lib.rs") => push_crate(&mut self.libs,
+                                              prefix, pth),
+                Some(~"main.rs") => push_crate(&mut self.mains,
+                                               prefix, pth),
+                Some(~"test.rs") => push_crate(&mut self.tests,
+                                               prefix, pth),
+                Some(~"bench.rs") => push_crate(&mut self.benchs,
+                                                prefix, pth),
+                _ => ()
+            }
+        }
+        debug!("found %u libs, %u mains, %u tests, %u benchs",
+               self.libs.len(),
+               self.mains.len(),
+               self.tests.len(),
+               self.benchs.len())
+    }
+
+
+    static fn build_crates(dst_dir: &Path,
+                           src_dir: &Path,
+                           crates: &[Crate],
+                           test: bool) {
+
+        for crates.each |&crate| {
+            let path = &src_dir.push_rel(&crate.file).normalize();
+            util::note(fmt!("compiling %s", path.to_str()));
+            if ! util::compile_crate(None, path,
+                                     dst_dir,
+                                     crate.flags,
+                                     crate.cfgs,
+                                     false, test) {
+                build_err::cond.raise(fmt!("build failure on %s",
+                                           path.to_str()));
+            }
+        }
+    }
+
+    fn build(&self, dst_dir: &Path) {
+        let dir = self.check_dir();
+        PkgSrc::build_crates(dst_dir, &dir, self.libs, false);
+        PkgSrc::build_crates(dst_dir, &dir, self.mains, false);
+        PkgSrc::build_crates(dst_dir, &dir, self.tests, true);
+        PkgSrc::build_crates(dst_dir, &dir, self.benchs, true);
+    }
+}
\ No newline at end of file
diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs
index 9d3751c3de2..776ca398268 100644
--- a/src/librustpkg/util.rs
+++ b/src/librustpkg/util.rs
@@ -597,11 +597,23 @@ pub fn remove_pkg(pkg: &Package) -> bool {
     true
 }
 
-pub fn compile_input(sysroot: Option<Path>, input: driver::input, dir: &Path,
-               flags: ~[~str], cfgs: ~[~str], opt: bool, test: bool) -> bool {
-    let lib_dir = dir.push(~"lib");
-    let bin_dir = dir.push(~"bin");
-    let test_dir = dir.push(~"test");
+pub fn compile_input(sysroot: Option<Path>,
+                     in_file: &Path,
+                     out_dir: &Path,
+                     flags: ~[~str],
+                     cfgs: ~[~str],
+                     opt: bool,
+                     test: bool) -> bool {
+
+    assert in_file.components.len() > 1;
+    let input = driver::file_input(copy *in_file);
+    let short_name = in_file.pop().filename().get();
+    let out_file = out_dir.push(os::dll_filename(short_name));
+
+    debug!("compiling %s into %s",
+           in_file.to_str(),
+           out_file.to_str());
+
     let binary = os::args()[0];
     let matches = getopts(flags, driver::optgroups()).get();
     let options = @session::options {
@@ -630,15 +642,12 @@ pub fn compile_input(sysroot: Option<Path>, input: driver::input, dir: &Path,
 
     let mut name = None;
     let mut vers = None;
-    let mut uuid = None;
     let mut crate_type = None;
 
     fn load_link_attr(mis: ~[@ast::meta_item]) -> (Option<~str>,
-                                                   Option<~str>,
                                                    Option<~str>) {
         let mut name = None;
         let mut vers = None;
-        let mut uuid = None;
 
         for mis.each |a| {
             match a.node {
@@ -647,7 +656,6 @@ pub fn compile_input(sysroot: Option<Path>, input: driver::input, dir: &Path,
                     match *v {
                         ~"name" => name = Some(*s),
                         ~"vers" => vers = Some(*s),
-                        ~"uuid" => uuid = Some(*s),
                         _ => { }
                     }
                 }
@@ -655,7 +663,7 @@ pub fn compile_input(sysroot: Option<Path>, input: driver::input, dir: &Path,
             }
         }
 
-        (name, vers, uuid)
+        (name, vers)
     }
 
     for crate.node.attrs.each |a| {
@@ -670,11 +678,10 @@ pub fn compile_input(sysroot: Option<Path>, input: driver::input, dir: &Path,
             ast::meta_list(v, mis) => {
                 match *v {
                     ~"link" => {
-                        let (n, v, u) = load_link_attr(mis);
+                        let (n, v) = load_link_attr(mis);
 
                         name = n;
                         vers = v;
-                        uuid = u;
                     }
                     _ => {}
                 }
@@ -683,16 +690,6 @@ pub fn compile_input(sysroot: Option<Path>, input: driver::input, dir: &Path,
         }
     }
 
-    if name.is_none() || vers.is_none() || uuid.is_none() {
-        error(~"link attr without (name, vers, uuid) values");
-
-        return false;
-    }
-
-    let name = name.get();
-    let vers = vers.get();
-    let uuid = uuid.get();
-
     let is_bin = match crate_type {
         Some(crate_type) => {
             match crate_type {
@@ -712,29 +709,14 @@ pub fn compile_input(sysroot: Option<Path>, input: driver::input, dir: &Path,
         }
     };
 
-    if test {
-        need_dir(&test_dir);
-
-        outputs = driver::build_output_filenames(input, &Some(test_dir),
-                                                 &None, sess)
-    }
-    else if is_bin {
-        need_dir(&bin_dir);
-
-        let path = bin_dir.push(fmt!("%s-%s-%s%s", name,
-                                                   hash(name + uuid + vers),
-                                                   vers, exe_suffix()));
-        outputs = driver::build_output_filenames(input, &None, &Some(path),
-                                                 sess);
-    } else {
-        need_dir(&lib_dir);
-
-        outputs = driver::build_output_filenames(input, &Some(lib_dir),
-                                                 &None, sess)
-    }
+    outputs = driver::build_output_filenames(input,
+                                             &Some(copy *out_dir),
+                                             &Some(out_file),
+                                             sess);
 
     driver::compile_rest(sess, cfg, driver::cu_everything,
-                         Some(outputs), Some(crate));
+                         Some(outputs),
+                         Some(crate));
 
     true
 }
@@ -753,15 +735,7 @@ pub fn exe_suffix() -> ~str { ~"" }
 pub fn compile_crate(sysroot: Option<Path>, crate: &Path, dir: &Path,
                      flags: ~[~str], cfgs: ~[~str], opt: bool,
                      test: bool) -> bool {
-    compile_input(sysroot, driver::file_input(*crate), dir, flags, cfgs,
-                  opt, test)
-}
-
-pub fn compile_str(sysroot: Option<Path>, code: ~str, dir: &Path,
-                   flags: ~[~str], cfgs: ~[~str], opt: bool,
-                   test: bool) -> bool {
-    compile_input(sysroot, driver::str_input(code), dir, flags, cfgs,
-                  opt, test)
+    compile_input(sysroot, crate, dir, flags, cfgs, opt, test)
 }
 
 #[cfg(windows)]