Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
02a0fb94
R
Rust
项目概览
int
/
Rust
大约 1 年 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
02a0fb94
编写于
9月 06, 2013
作者:
T
Tim Chevalier
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
rustpkg: Use workcache
rustpkg now uses the workcache library to avoid recompilation. Hooray!
上级
bb30f047
变更
15
展开全部
隐藏空白更改
内联
并排
Showing
15 changed file
with
668 addition
and
497 deletion
+668
-497
src/libextra/workcache.rs
src/libextra/workcache.rs
+7
-2
src/librustpkg/api.rs
src/librustpkg/api.rs
+103
-41
src/librustpkg/conditions.rs
src/librustpkg/conditions.rs
+6
-0
src/librustpkg/context.rs
src/librustpkg/context.rs
+37
-27
src/librustpkg/package_id.rs
src/librustpkg/package_id.rs
+0
-3
src/librustpkg/package_source.rs
src/librustpkg/package_source.rs
+154
-93
src/librustpkg/path_util.rs
src/librustpkg/path_util.rs
+7
-35
src/librustpkg/rustpkg.rs
src/librustpkg/rustpkg.rs
+149
-86
src/librustpkg/search.rs
src/librustpkg/search.rs
+0
-10
src/librustpkg/tests.rs
src/librustpkg/tests.rs
+46
-49
src/librustpkg/util.rs
src/librustpkg/util.rs
+85
-63
src/librustpkg/version.rs
src/librustpkg/version.rs
+6
-9
src/librustpkg/workcache_support.rs
src/librustpkg/workcache_support.rs
+58
-0
src/librustpkg/workspace.rs
src/librustpkg/workspace.rs
+1
-1
src/libsyntax/ast_util.rs
src/libsyntax/ast_util.rs
+9
-78
未找到文件。
src/libextra/workcache.rs
浏览文件 @
02a0fb94
...
...
@@ -493,7 +493,7 @@ pub fn unwrap(self) -> T {
#[test]
fn
test
()
{
use
std
::
io
::
WriterUtil
;
use
std
::
run
;
use
std
::
{
os
,
run
}
;
let
pth
=
Path
(
"foo.c"
);
{
...
...
@@ -501,7 +501,12 @@ fn test() {
r
.unwrap
()
.write_str
(
"int main() { return 0; }"
);
}
let
cx
=
Context
::
new
(
RWArc
::
new
(
Database
::
new
(
Path
(
"db.json"
))),
let
db_path
=
os
::
self_exe_path
()
.expect
(
"workcache::test failed"
)
.pop
()
.push
(
"db.json"
);
if
os
::
path_exists
(
&
db_path
)
{
os
::
remove_file
(
&
db_path
);
}
let
cx
=
Context
::
new
(
RWArc
::
new
(
Database
::
new
(
db_path
)),
RWArc
::
new
(
Logger
::
new
()),
Arc
::
new
(
TreeMap
::
new
()));
...
...
src/librustpkg/api.rs
浏览文件 @
02a0fb94
...
...
@@ -13,49 +13,101 @@
use
package_id
::
*
;
use
package_source
::
*
;
use
version
::
Version
;
use
workcache_support
::
*
;
use
extra
::
arc
::{
Arc
,
RWArc
};
use
extra
::
workcache
;
use
extra
::
workcache
::
*
;
use
std
::
os
;
use
std
::
hashmap
::
*
;
use
extra
::
treemap
::
TreeMap
;
/// Convenience functions intended for calling from pkg.rs
/// p is where to put the cache file for dependencies
pub
fn
default_ctxt
(
p
:
Path
)
->
BuildCtx
{
new_default_ctx
(
new_workcache_cx
(
&
p
),
p
)
}
fn
default_ctxt
(
p
:
@
Path
)
->
Ctx
{
Ctx
{
use_rust_path_hack
:
false
,
sysroot_opt
:
Some
(
p
),
json
:
false
,
dep_cache
:
@
mut
HashMap
::
new
()
pub
fn
new_default_ctx
(
c
:
Context
,
p
:
Path
)
->
BuildCtx
{
BuildCtx
{
cx
:
Ctx
{
use_rust_path_hack
:
false
,
sysroot_opt
:
p
},
workcache_cx
:
c
}
}
pub
fn
build_lib
(
sysroot
:
@
Path
,
root
:
Path
,
name
:
~
str
,
version
:
Version
,
lib
:
Path
)
{
fn
file_is_fresh
(
path
:
&
str
,
in_hash
:
&
str
)
->
bool
{
in_hash
==
digest_file_with_date
(
&
Path
(
path
))
}
let
pkg_src
=
PkgSrc
{
root
:
root
,
id
:
PkgId
{
version
:
version
,
..
PkgId
::
new
(
name
)},
libs
:
~
[
mk_crate
(
lib
)],
mains
:
~
[],
tests
:
~
[],
benchs
:
~
[]
};
pkg_src
.build
(
&
default_ctxt
(
sysroot
),
~
[]);
fn
binary_is_fresh
(
path
:
&
str
,
in_hash
:
&
str
)
->
bool
{
in_hash
==
digest_only_date
(
&
Path
(
path
))
}
pub
fn
build_exe
(
sysroot
:
@
Path
,
root
:
Path
,
name
:
~
str
,
version
:
Version
,
main
:
Path
)
{
let
pkg_src
=
PkgSrc
{
root
:
root
,
id
:
PkgId
{
version
:
version
,
..
PkgId
::
new
(
name
)},
libs
:
~
[],
mains
:
~
[
mk_crate
(
main
)],
tests
:
~
[],
benchs
:
~
[]
pub
fn
new_workcache_cx
(
p
:
&
Path
)
->
Context
{
let
db_file
=
p
.push
(
"rustpkg_db.json"
);
// ??? probably wrong
debug!
(
"Workcache database file: %s"
,
db_file
.to_str
());
let
db
=
RWArc
::
new
(
Database
::
new
(
db_file
));
let
lg
=
RWArc
::
new
(
Logger
::
new
());
let
cfg
=
Arc
::
new
(
TreeMap
::
new
());
let
mut
rslt
:
FreshnessMap
=
TreeMap
::
new
();
// Set up freshness functions for every type of dependency rustpkg
// knows about
rslt
.insert
(
~
"file"
,
file_is_fresh
);
rslt
.insert
(
~
"binary"
,
binary_is_fresh
);
workcache
::
Context
::
new_with_freshness
(
db
,
lg
,
cfg
,
Arc
::
new
(
rslt
))
}
pub
fn
build_lib
(
sysroot
:
Path
,
root
:
Path
,
name
:
~
str
,
version
:
Version
,
lib
:
Path
)
{
let
cx
=
default_ctxt
(
sysroot
);
let
subroot
=
root
.clone
();
let
subversion
=
version
.clone
();
let
sublib
=
lib
.clone
();
do
cx
.workcache_cx
.with_prep
(
name
)
|
prep
|
{
let
pkg_src
=
PkgSrc
{
workspace
:
subroot
.clone
(),
start_dir
:
subroot
.push
(
"src"
)
.push
(
name
),
id
:
PkgId
{
version
:
subversion
.clone
(),
..
PkgId
::
new
(
name
)},
libs
:
~
[
mk_crate
(
sublib
.clone
())],
mains
:
~
[],
tests
:
~
[],
benchs
:
~
[]
};
pkg_src
.declare_inputs
(
prep
);
let
subcx
=
cx
.clone
();
let
subsrc
=
pkg_src
.clone
();
do
prep
.exec
|
exec
|
{
subsrc
.clone
()
.build
(
exec
,
&
subcx
.clone
(),
~
[]);
}
};
pkg_src
.build
(
&
default_ctxt
(
sysroot
),
~
[]);
}
pub
fn
build_exe
(
sysroot
:
Path
,
root
:
Path
,
name
:
~
str
,
version
:
Version
,
main
:
Path
)
{
let
cx
=
default_ctxt
(
sysroot
);
let
subroot
=
root
.clone
();
let
submain
=
main
.clone
();
do
cx
.workcache_cx
.with_prep
(
name
)
|
prep
|
{
let
pkg_src
=
PkgSrc
{
workspace
:
subroot
.clone
(),
start_dir
:
subroot
.push
(
"src"
)
.push
(
name
),
id
:
PkgId
{
version
:
version
.clone
(),
..
PkgId
::
new
(
name
)},
libs
:
~
[],
mains
:
~
[
mk_crate
(
submain
.clone
())],
tests
:
~
[],
benchs
:
~
[]
};
pkg_src
.declare_inputs
(
prep
);
let
subsrc
=
pkg_src
.clone
();
let
subcx
=
cx
.clone
();
do
prep
.exec
|
exec
|
{
subsrc
.clone
()
.build
(
exec
,
&
subcx
.clone
(),
~
[]);
}
}
}
pub
fn
install_lib
(
sysroot
:
@
Path
,
pub
fn
install_lib
(
sysroot
:
Path
,
workspace
:
Path
,
name
:
~
str
,
lib_path
:
Path
,
...
...
@@ -65,23 +117,33 @@ pub fn install_lib(sysroot: @Path,
debug!
(
"workspace = %s"
,
workspace
.to_str
());
// make a PkgSrc
let
pkg_id
=
PkgId
{
version
:
version
,
..
PkgId
::
new
(
name
)};
let
pkg_src
=
PkgSrc
{
root
:
workspace
.clone
(),
id
:
pkg_id
.clone
(),
libs
:
~
[
mk_crate
(
lib_path
)],
mains
:
~
[],
tests
:
~
[],
benchs
:
~
[]
};
let
cx
=
default_ctxt
(
sysroot
);
pkg_src
.build
(
&
cx
,
~
[]);
let
subpath
=
lib_path
.clone
();
do
cx
.workcache_cx
.with_prep
(
pkg_id
.to_str
())
|
prep
|
{
let
pkg_src
=
PkgSrc
{
workspace
:
workspace
.clone
(),
start_dir
:
subpath
.push
(
"src"
)
.push
(
name
),
id
:
pkg_id
.clone
(),
libs
:
~
[
mk_crate
(
subpath
.clone
())],
mains
:
~
[],
tests
:
~
[],
benchs
:
~
[]
};
pkg_src
.declare_inputs
(
prep
);
let
subcx
=
cx
.clone
();
let
subpkg_src
=
pkg_src
.clone
();
do
prep
.exec
|
exec
|
{
subpkg_src
.clone
()
.build
(
exec
,
&
subcx
.clone
(),
~
[]);
}
}
cx
.install_no_build
(
&
workspace
,
&
pkg_id
);
}
pub
fn
install_exe
(
sysroot
:
@
Path
,
workspace
:
Path
,
name
:
~
str
,
version
:
Version
)
{
default_ctxt
(
sysroot
)
.install
(
&
workspace
,
&
PkgId
{
version
:
version
,
..
PkgId
::
new
(
name
)});
pub
fn
install_exe
(
sysroot
:
Path
,
workspace
:
Path
,
name
:
~
str
,
version
:
Version
)
{
let
cx
=
default_ctxt
(
sysroot
);
debug!
(
"install_exe calling with_prep"
);
let
pkgid
=
PkgId
{
version
:
version
,
..
PkgId
::
new
(
name
)};
cx
.install
(
PkgSrc
::
new
(
workspace
,
false
,
pkgid
));
}
fn
mk_crate
(
p
:
Path
)
->
Crate
{
...
...
src/librustpkg/conditions.rs
浏览文件 @
02a0fb94
...
...
@@ -12,11 +12,17 @@
pub
use
std
::
path
::
Path
;
pub
use
package_id
::
PkgId
;
pub
use
std
::
libc
;
pub
use
std
::
libc
::
stat
;
condition!
{
pub
bad_path
:
(
Path
,
~
str
)
->
Path
;
}
condition!
{
pub
bad_stat
:
(
Path
,
~
str
)
->
stat
;
}
condition!
{
pub
nonexistent_package
:
(
PkgId
,
~
str
)
->
Path
;
}
...
...
src/librustpkg/context.rs
浏览文件 @
02a0fb94
...
...
@@ -10,56 +10,66 @@
// Context data structure used by rustpkg
use
std
::
hashmap
::
HashMap
;
use
std
::
os
;
use
extra
::
workcache
;
#[deriving(Clone)]
pub
struct
Ctx
{
// If use_rust_path_hack is true, rustpkg searches for sources
// in *package* directories that are in the RUST_PATH (for example,
// FOO/src/bar-0.1 instead of FOO). The flag doesn't affect where
// rustpkg stores build artifacts.
use_rust_path_hack
:
bool
,
// Sysroot -- if this is None, uses rustc filesearch's
// idea of the default
sysroot_opt
:
Option
<@
Path
>
,
// I'm not sure what this is for
json
:
bool
,
// Cache of hashes of things already installed
// though I'm not sure why the value is a bool
dep_cache
:
@
mut
HashMap
<~
str
,
bool
>
,
// The root directory containing the Rust standard libraries
sysroot_opt
:
Path
}
#[deriving(Clone)]
pub
struct
BuildCtx
{
// Context for workcache
workcache_cx
:
workcache
::
Context
,
// Everything else
cx
:
Ctx
}
impl
BuildCtx
{
pub
fn
sysroot_opt
(
&
self
)
->
Path
{
self
.cx.sysroot_opt
.clone
()
}
pub
fn
sysroot_to_use
(
&
self
)
->
Path
{
self
.cx
.sysroot_to_use
()
}
}
impl
Ctx
{
pub
fn
sysroot_opt
(
&
self
)
->
Path
{
self
.sysroot_opt
.clone
()
}
}
impl
Ctx
{
/// Debugging
pub
fn
sysroot_opt_str
(
&
self
)
->
~
str
{
match
self
.sysroot_opt
{
None
=>
~
"[none]"
,
Some
(
p
)
=>
p
.to_str
()
}
self
.sysroot_opt
.to_str
()
}
// Hack so that rustpkg can run either out of a rustc target dir,
// or the host dir
pub
fn
sysroot_to_use
(
&
self
)
->
Option
<@
Path
>
{
if
!
in_target
(
self
.sysroot_opt
)
{
self
.sysroot_opt
pub
fn
sysroot_to_use
(
&
self
)
->
Path
{
if
!
in_target
(
&
self
.sysroot_opt
)
{
self
.sysroot_opt
.clone
()
}
else
{
self
.sysroot_opt
.
map
(|
p
|
{
@
p
.pop
()
.pop
()
.pop
()
}
)
self
.sysroot_opt
.
pop
()
.pop
()
.pop
(
)
}
}
}
}
/// We assume that if ../../rustc exists, then we're running
/// rustpkg from a Rust target directory. This is part of a
/// kludgy hack used to adjust the sysroot.
pub
fn
in_target
(
sysroot_opt
:
Option
<@
Path
>
)
->
bool
{
match
sysroot_opt
{
None
=>
false
,
Some
(
p
)
=>
{
debug!
(
"Checking whether %s is in target"
,
p
.to_str
());
os
::
path_is_dir
(
&
p
.pop
()
.pop
()
.push
(
"rustc"
))
}
}
pub
fn
in_target
(
sysroot_opt
:
&
Path
)
->
bool
{
debug!
(
"Checking whether %s is in target"
,
sysroot_opt
.to_str
());
os
::
path_is_dir
(
&
sysroot_opt
.pop
()
.pop
()
.push
(
"rustc"
))
}
src/librustpkg/package_id.rs
浏览文件 @
02a0fb94
...
...
@@ -51,12 +51,10 @@ pub fn new(s: &str) -> PkgId {
// Did the user request a specific version?
let
s
=
match
split_version
(
s
)
{
Some
((
path
,
v
))
=>
{
debug!
(
"s = %s, path = %s, v = %s"
,
s
,
path
,
v
.to_str
());
given_version
=
Some
(
v
);
path
}
None
=>
{
debug!
(
"%s has no explicit version"
,
s
);
s
}
};
...
...
@@ -81,7 +79,6 @@ pub fn new(s: &str) -> PkgId {
}
};
debug!
(
"path = %s"
,
path
.to_str
());
PkgId
{
path
:
path
.clone
(),
short_name
:
short_name
.to_owned
(),
...
...
src/librustpkg/package_source.rs
浏览文件 @
02a0fb94
...
...
@@ -18,14 +18,19 @@
use
crate
::
Crate
;
use
messages
::
*
;
use
source_control
::{
git_clone
,
git_clone_general
};
use
path_util
::{
pkgid_src_in_workspace
,
find_dir_using_rust_path_hack
,
default_workspace
};
use
path_util
::{
find_dir_using_rust_path_hack
,
default_workspace
};
use
util
::
compile_crate
;
use
workspace
::
is_workspace
;
use
workcache_support
;
use
extra
::
workcache
;
// An enumeration of the unpacked source of a package workspace.
// This contains a list of files found in the source workspace.
#[deriving(Clone)]
pub
struct
PkgSrc
{
root
:
Path
,
// root of where the package source code lives
workspace
:
Path
,
// root of where the package source code lives
start_dir
:
Path
,
// dir to start looking in for packages -- normally
// this is workspace/src/id but it may be just workspace
id
:
PkgId
,
libs
:
~
[
Crate
],
mains
:
~
[
Crate
],
...
...
@@ -33,57 +38,91 @@ pub struct PkgSrc {
benchs
:
~
[
Crate
],
}
impl
ToStr
for
PkgSrc
{
fn
to_str
(
&
self
)
->
~
str
{
fmt!
(
"Package ID %s in start dir %s [workspace = %s]"
,
self
.id
.to_str
(),
self
.start_dir
.to_str
(),
self
.workspace
.to_str
())
}
}
condition!
{
// #6009: should this be pub or not, when #8215 is fixed?
build_err
:
(
~
str
)
->
()
;
build_err
:
(
~
str
)
->
~
str
;
}
impl
PkgSrc
{
pub
fn
new
(
src_dir
:
&
Path
,
id
:
&
PkgId
)
->
PkgSrc
{
PkgSrc
{
root
:
(
*
src_dir
)
.clone
(),
id
:
(
*
id
)
.clone
(),
libs
:
~
[],
mains
:
~
[],
tests
:
~
[],
benchs
:
~
[]
}
}
pub
fn
new
(
workspace
:
Path
,
use_rust_path_hack
:
bool
,
id
:
PkgId
)
->
PkgSrc
{
use
conditions
::
nonexistent_package
::
cond
;
debug!
(
"Checking package source for package ID %s,
\
workspace = %s"
,
id
.to_str
(),
workspace
.to_str
());
fn
check_dir
(
&
self
,
cx
:
&
Ctx
)
->
Path
{
use
conditions
::
nonexistent_package
::
cond
;
let
mut
to_try
=
~
[];
if
use_rust_path_hack
{
to_try
.push
(
workspace
.clone
());
}
else
{
let
result
=
workspace
.push
(
"src"
)
.push_rel
(
&
id
.path
.pop
())
.push
(
fmt!
(
"%s-%s"
,
id
.short_name
,
id
.version
.to_str
()));
to_try
.push
(
result
);
to_try
.push
(
workspace
.push
(
"src"
)
.push_rel
(
&
id
.path
));
}
debug!
(
"
Pushing onto root: %s | %s"
,
self
.id.path
.to_str
(),
self
.root
.to_str
(
));
debug!
(
"
Checking dirs: %?"
,
to_try
.map
(|
s
|
s
.to_str
())
.connect
(
":"
));
let
dirs
=
pkgid_src_in_workspace
(
&
self
.id
,
&
self
.root
);
debug!
(
"Checking dirs: %?"
,
dirs
.map
(|
s
|
s
.to_str
())
.connect
(
":"
));
let
path
=
dirs
.iter
()
.find
(|
&
d
|
os
::
path_exists
(
d
));
let
path
=
to_try
.iter
()
.find
(|
&
d
|
os
::
path_exists
(
d
));
let
dir
=
match
path
{
let
dir
:
Path
=
match
path
{
Some
(
d
)
=>
(
*
d
)
.clone
(),
None
=>
{
match
self
.fetch_git
()
{
let
mut
ok_d
=
None
;
for
w
in
to_try
.iter
()
{
debug!
(
"Calling fetch_git on %s"
,
w
.to_str
());
let
gf
=
PkgSrc
::
fetch_git
(
w
,
&
id
);
for
p
in
gf
.iter
()
{
ok_d
=
Some
(
p
.clone
());
break
;
}
if
ok_d
.is_some
()
{
break
;
}
}
match
ok_d
{
Some
(
d
)
=>
d
,
None
=>
{
match
find_dir_using_rust_path_hack
(
cx
,
&
self
.id
)
{
Some
(
d
)
=>
d
,
None
=>
cond
.raise
((
self
.id
.clone
(),
~
"supplied path for package dir does not
\
exist, and couldn't interpret it as a URL fragment"
))
if
use_rust_path_hack
{
match
find_dir_using_rust_path_hack
(
&
id
)
{
Some
(
d
)
=>
d
,
None
=>
cond
.raise
((
id
.clone
(),
~
"supplied path for package dir does not
\
exist, and couldn't interpret it as a URL fragment"
))
}
}
else
{
cond
.raise
((
id
.clone
(),
~
"supplied path for package dir does not
\
exist, and couldn't interpret it as a URL fragment"
))
}
}
}
}
};
debug!
(
"For package id %s, returning %s"
,
self
.id
.to_str
(),
dir
.to_str
());
debug!
(
"For package id %s, returning %s"
,
id
.to_str
(),
dir
.to_str
());
if
!
os
::
path_is_dir
(
&
dir
)
{
cond
.raise
((
self
.
id
.clone
(),
~
"supplied path for package dir is a
\
cond
.raise
((
id
.clone
(),
~
"supplied path for package dir is a
\
non-directory"
));
}
dir
PkgSrc
{
workspace
:
workspace
,
start_dir
:
dir
,
id
:
id
,
libs
:
~
[],
mains
:
~
[],
tests
:
~
[],
benchs
:
~
[]
}
}
/// Try interpreting self's package id as a git repository, and try
...
...
@@ -91,7 +130,7 @@ fn check_dir(&self, cx: &Ctx) -> Path {
/// if this was successful, None otherwise. Similarly, if the package id
/// refers to a git repo on the local version, also check it out.
/// (right now we only support git)
pub
fn
fetch_git
(
&
self
)
->
Option
<
Path
>
{
pub
fn
fetch_git
(
local
:
&
Path
,
pkgid
:
&
PkgId
)
->
Option
<
Path
>
{
use
conditions
::
failed_to_create_temp_dir
::
cond
;
// We use a temporary directory because if the git clone fails,
...
...
@@ -103,38 +142,35 @@ pub fn fetch_git(&self) -> Option<Path> {
None
=>
cond
.raise
(
~
"Failed to create temporary directory for fetching git sources"
)
};
let
mut
local
=
self
.root
.push
(
"src"
);
local
=
local
.push
(
self
.id
.to_str
());
debug!
(
"Checking whether %s exists locally. Cwd = %s, does it? %?"
,
self
.id.path
.to_str
(),
debug!
(
"Checking whether %s (path = %s) exists locally. Cwd = %s, does it? %?"
,
pkgid
.to_str
(),
pkgid
.path
.to_str
(),
os
::
getcwd
()
.to_str
(),
os
::
path_exists
(
&
self
.
id.path
));
os
::
path_exists
(
&
pkg
id
.path
));
if
os
::
path_exists
(
&
self
.
id.path
)
{
if
os
::
path_exists
(
&
pkg
id
.path
)
{
debug!
(
"%s exists locally! Cloning it into %s"
,
self
.
id.path
.to_str
(),
local
.to_str
());
pkg
id
.path
.to_str
(),
local
.to_str
());
// Ok to use local here; we know it will succeed
git_clone
(
&
self
.id.path
,
&
local
,
&
self
.
id.version
);
return
Some
(
local
);
git_clone
(
&
pkgid
.path
,
local
,
&
pkg
id
.version
);
return
Some
(
local
.clone
()
);
}
if
self
.
id.path
.components
()
.len
()
<
2
{
if
pkg
id
.path
.components
()
.len
()
<
2
{
// If a non-URL, don't bother trying to fetch
return
None
;
}
let
url
=
fmt!
(
"https://%s"
,
self
.
id.path
.to_str
());
note
(
fmt
!
(
"Fetching package: git clone %s %s [version=%s]"
,
url
,
clone_target
.to_str
(),
self
.id.version
.to_str
()
));
let
url
=
fmt!
(
"https://%s"
,
pkg
id
.path
.to_str
());
debug
!
(
"Fetching package: git clone %s %s [version=%s]"
,
url
,
clone_target
.to_str
(),
pkgid
.version
.to_str
(
));
if
git_clone_general
(
url
,
&
clone_target
,
&
self
.
id.version
)
{
if
git_clone_general
(
url
,
&
clone_target
,
&
pkg
id
.version
)
{
// since the operation succeeded, move clone_target to local
if
!
os
::
rename_file
(
&
clone_target
,
&
local
)
{
if
!
os
::
rename_file
(
&
clone_target
,
local
)
{
None
}
else
{
Some
(
local
)
Some
(
local
.clone
()
)
}
}
else
{
...
...
@@ -143,10 +179,11 @@ pub fn fetch_git(&self) -> Option<Path> {
}
// If a file named "pkg.rs" in the
curren
t directory exists,
// If a file named "pkg.rs" in the
star
t directory exists,
// return the path for it. Otherwise, None
pub
fn
package_script_option
(
&
self
,
cwd
:
&
Path
)
->
Option
<
Path
>
{
let
maybe_path
=
cwd
.push
(
"pkg.rs"
);
pub
fn
package_script_option
(
&
self
)
->
Option
<
Path
>
{
let
maybe_path
=
self
.start_dir
.push
(
"pkg.rs"
);
debug!
(
"package_script_option: checking whether %s exists"
,
maybe_path
.to_str
());
if
os
::
path_exists
(
&
maybe_path
)
{
Some
(
maybe_path
)
}
...
...
@@ -166,20 +203,18 @@ fn push_crate(cs: &mut ~[Crate], prefix: uint, p: &Path) {
for
c
in
p
.components
.slice
(
prefix
,
p
.components
.len
())
.iter
()
{
sub
=
sub
.push
(
*
c
);
}
debug!
(
"
found
crate %s"
,
sub
.to_str
());
debug!
(
"
Will compile
crate %s"
,
sub
.to_str
());
cs
.push
(
Crate
::
new
(
&
sub
));
}
/// Infers crates to build. Called only in the case where there
/// is no custom build logic
pub
fn
find_crates
(
&
mut
self
,
cx
:
&
Ctx
)
{
pub
fn
find_crates
(
&
mut
self
)
{
use
conditions
::
missing_pkg_files
::
cond
;
let
dir
=
self
.check_dir
(
cx
);
debug!
(
"Called check_dir, I'm in %s"
,
dir
.to_str
());
let
prefix
=
dir
.components
.len
();
debug!
(
"Matching against %?"
,
self
.id.short_name
);
do
os
::
walk_dir
(
&
dir
)
|
pth
|
{
let
prefix
=
self
.start_dir.components
.len
();
debug!
(
"Matching against %s"
,
self
.id.short_name
);
do
os
::
walk_dir
(
&
self
.start_dir
)
|
pth
|
{
let
maybe_known_crate_set
=
match
pth
.filename
()
{
Some
(
filename
)
=>
match
filename
{
"lib.rs"
=>
Some
(
&
mut
self
.libs
),
...
...
@@ -207,7 +242,8 @@ pub fn find_crates(&mut self, cx: &Ctx) {
cond
.raise
(
self
.id
.clone
());
}
debug!
(
"found %u libs, %u mains, %u tests, %u benchs"
,
debug!
(
"In %s, found %u libs, %u mains, %u tests, %u benchs"
,
self
.start_dir
.to_str
(),
self
.libs
.len
(),
self
.mains
.len
(),
self
.tests
.len
(),
...
...
@@ -215,68 +251,93 @@ pub fn find_crates(&mut self, cx: &Ctx) {
}
fn
build_crates
(
&
self
,
ctx
:
&
Ctx
,
src_dir
:
&
Path
,
ctx
:
&
Build
Ctx
,
exec
:
&
mut
workcache
::
Exec
,
destination_dir
:
&
Path
,
crates
:
&
[
Crate
],
cfgs
:
&
[
~
str
],
what
:
OutputType
)
{
for
crate
in
crates
.iter
()
{
let
path
=
&
src_dir
.push_rel
(
&
crate
.file
)
.normalize
();
note
(
fmt!
(
"build_crates: compiling %s"
,
path
.to_str
()));
note
(
fmt!
(
"build_crates: using as workspace %s"
,
self
.root
.to_str
()));
let
result
=
compile_crate
(
ctx
,
&
self
.id
,
path
,
// compile_crate wants the destination workspace
destination_dir
,
crate
.flags
,
crate
.cfgs
+
cfgs
,
false
,
what
);
if
!
result
{
build_err
::
cond
.raise
(
fmt!
(
"build failure on %s"
,
path
.to_str
()));
let
path
=
self
.start_dir
.push_rel
(
&
crate
.file
)
.normalize
();
debug!
(
"build_crates: compiling %s"
,
path
.to_str
());
let
path_str
=
path
.to_str
();
let
cfgs
=
crate
.cfgs
+
cfgs
;
let
result
=
{
// compile_crate should return the path of the output artifact
match
compile_crate
(
ctx
,
exec
,
&
self
.id
,
&
path
,
destination_dir
,
crate
.flags
,
cfgs
,
false
,
what
)
.map
(|
p
|
p
.to_str
())
{
Some
(
p
)
=>
p
,
None
=>
build_err
::
cond
.raise
(
fmt!
(
"build failure on %s"
,
path_str
))
}
};
debug!
(
"Result of compiling %s was %s"
,
path_str
,
result
);
}
}
/// Declare all the crate files in the package source as inputs
pub
fn
declare_inputs
(
&
self
,
prep
:
&
mut
workcache
::
Prep
)
{
let
to_do
=
~
[
self
.libs
.clone
(),
self
.mains
.clone
(),
self
.tests
.clone
(),
self
.benchs
.clone
()];
for
cs
in
to_do
.iter
()
{
for
c
in
cs
.iter
()
{
let
path
=
self
.start_dir
.push_rel
(
&
c
.file
)
.normalize
();
debug!
(
"Declaring input: %s"
,
path
.to_str
());
prep
.declare_input
(
"file"
,
path
.to_str
(),
workcache_support
::
digest_file_with_date
(
&
path
.clone
()));
}
debug!
(
"Result of compiling %s was %?"
,
path
.to_str
(),
result
);
}
}
pub
fn
build
(
&
self
,
ctx
:
&
Ctx
,
cfgs
:
~
[
~
str
])
->
Path
{
// It would be better if build returned a Path, but then Path would have to derive
// Encodable.
pub
fn
build
(
&
self
,
exec
:
&
mut
workcache
::
Exec
,
ctx
:
&
BuildCtx
,
cfgs
:
~
[
~
str
])
->
~
str
{
use
conditions
::
not_a_workspace
::
cond
;
// Determine the destination workspace (which depends on whether
// we're using the rust_path_hack)
let
destination_workspace
=
if
is_workspace
(
&
self
.
root
)
{
debug!
(
"%s is indeed a workspace"
,
self
.
root
.to_str
());
self
.
root
.clone
()
let
destination_workspace
=
if
is_workspace
(
&
self
.
workspace
)
{
debug!
(
"%s is indeed a workspace"
,
self
.
workspace
.to_str
());
self
.
workspace
.clone
()
}
else
{
else
{
// It would be nice to have only one place in the code that checks
// for the use_rust_path_hack flag...
if
ctx
.use_rust_path_hack
{
if
ctx
.
cx.
use_rust_path_hack
{
let
rs
=
default_workspace
();
debug!
(
"Using hack: %s"
,
rs
.to_str
());
rs
}
else
{
cond
.raise
(
fmt!
(
"Package root %s is not a workspace; pass in --rust_path_hack
\
if you want to treat it as a package source"
,
self
.root
.to_str
()))
if you want to treat it as a package source"
,
self
.workspace
.to_str
()))
}
};
let
dir
=
self
.check_dir
(
ctx
);
debug!
(
"Building libs in %s, destination = %s"
,
dir
.to_str
(),
destination_workspace
.to_str
());
self
.build_crates
(
ctx
,
&
dir
,
&
destination_workspace
,
self
.libs
,
cfgs
,
Lib
);
let
libs
=
self
.libs
.clone
();
let
mains
=
self
.mains
.clone
();
let
tests
=
self
.tests
.clone
();
let
benchs
=
self
.benchs
.clone
();
debug!
(
"Building libs in %s, destination = %s"
,
destination_workspace
.to_str
(),
destination_workspace
.to_str
());
self
.build_crates
(
ctx
,
exec
,
&
destination_workspace
,
libs
,
cfgs
,
Lib
);
debug!
(
"Building mains"
);
self
.build_crates
(
ctx
,
&
dir
,
&
destination_workspace
,
self
.
mains
,
cfgs
,
Main
);
self
.build_crates
(
ctx
,
exec
,
&
destination_workspace
,
mains
,
cfgs
,
Main
);
debug!
(
"Building tests"
);
self
.build_crates
(
ctx
,
&
dir
,
&
destination_workspace
,
self
.
tests
,
cfgs
,
Test
);
self
.build_crates
(
ctx
,
exec
,
&
destination_workspace
,
tests
,
cfgs
,
Test
);
debug!
(
"Building benches"
);
self
.build_crates
(
ctx
,
&
dir
,
&
destination_workspace
,
self
.
benchs
,
cfgs
,
Bench
);
destination_workspace
self
.build_crates
(
ctx
,
exec
,
&
destination_workspace
,
benchs
,
cfgs
,
Bench
);
destination_workspace
.to_str
()
}
}
src/librustpkg/path_util.rs
浏览文件 @
02a0fb94
...
...
@@ -14,7 +14,6 @@
pub
use
target
::{
OutputType
,
Main
,
Lib
,
Test
,
Bench
,
Target
,
Build
,
Install
};
pub
use
version
::{
Version
,
NoVersion
,
split_version_general
,
try_parsing_version
};
pub
use
rustc
::
metadata
::
filesearch
::
rust_path
;
use
context
::
Ctx
;
use
std
::
libc
::
consts
::
os
::
posix88
::{
S_IRUSR
,
S_IWUSR
,
S_IXUSR
};
use
std
::
os
::
mkdir_recursive
;
...
...
@@ -62,12 +61,7 @@ pub fn workspace_contains_package_id_(pkgid: &PkgId, workspace: &Path,
let
mut
found
=
None
;
do
os
::
walk_dir
(
&
src_dir
)
|
p
|
{
debug!
(
"=> p = %s"
,
p
.to_str
());
if
os
::
path_is_dir
(
p
)
{
debug!
(
"p = %s, path = %s [%s]"
,
p
.to_str
(),
pkgid
.path
.to_str
(),
src_dir
.push_rel
(
&
pkgid
.path
)
.to_str
());
if
*
p
==
src_dir
.push_rel
(
&
pkgid
.path
)
||
{
let
pf
=
p
.filename
();
do
pf
.iter
()
.any
|
pf
|
{
...
...
@@ -75,8 +69,6 @@ pub fn workspace_contains_package_id_(pkgid: &PkgId, workspace: &Path,
match
split_version_general
(
g
,
'-'
)
{
None
=>
false
,
Some
((
ref
might_match
,
ref
vers
))
=>
{
debug!
(
"might_match = %s, vers = %s"
,
*
might_match
,
vers
.to_str
());
*
might_match
==
pkgid
.short_name
&&
(
pkgid
.version
==
*
vers
||
pkgid
.version
==
NoVersion
)
}
...
...
@@ -90,32 +82,15 @@ pub fn workspace_contains_package_id_(pkgid: &PkgId, workspace: &Path,
true
};
debug!
(
if
found
.is_some
()
{
fmt!
(
"Found %s in %s"
,
pkgid
.to_str
(),
workspace
.to_str
())
}
else
{
fmt!
(
"Didn't find %s in %s"
,
pkgid
.to_str
(),
workspace
.to_str
())
});
if
found
.is_some
()
{
debug!
(
"Found %s in %s"
,
pkgid
.to_str
(),
workspace
.to_str
());
}
else
{
debug!
(
"Didn't find %s in %s"
,
pkgid
.to_str
(),
workspace
.to_str
());
}
found
}
/// Returns a list of possible directories
/// for <pkgid>'s source files in <workspace>.
/// Doesn't check that any of them exist.
/// (for example, try both with and without the version)
pub
fn
pkgid_src_in_workspace
(
pkgid
:
&
PkgId
,
workspace
:
&
Path
)
->
~
[
Path
]
{
let
mut
results
=
~
[];
let
result
=
workspace
.push
(
"src"
)
.push
(
fmt!
(
"%s-%s"
,
pkgid
.path
.to_str
(),
pkgid
.version
.to_str
()));
results
.push
(
result
);
results
.push
(
workspace
.push
(
"src"
)
.push_rel
(
&
pkgid
.path
));
results
}
/// Returns a src for pkgid that does exist -- None if none of them do
pub
fn
first_pkgid_src_in_workspace
(
pkgid
:
&
PkgId
,
workspace
:
&
Path
)
->
Option
<
Path
>
{
let
rs
=
pkgid_src_in_workspace
(
pkgid
,
workspace
);
do
rs
.iter
()
.find
|
&
p
|
{
os
::
path_exists
(
p
)
}
.map
(|
p
|
(
**
p
)
.clone
())
}
/// Figure out what the executable name for <pkgid> in <workspace>'s build
/// directory is, and if the file exists, return it.
pub
fn
built_executable_in_workspace
(
pkgid
:
&
PkgId
,
workspace
:
&
Path
)
->
Option
<
Path
>
{
...
...
@@ -402,10 +377,7 @@ fn dir_has_file(dir: &Path, file: &str) -> bool {
os
::
path_exists
(
&
dir
.push
(
file
))
}
pub
fn
find_dir_using_rust_path_hack
(
cx
:
&
Ctx
,
p
:
&
PkgId
)
->
Option
<
Path
>
{
if
!
cx
.use_rust_path_hack
{
return
None
;
}
pub
fn
find_dir_using_rust_path_hack
(
p
:
&
PkgId
)
->
Option
<
Path
>
{
let
rp
=
rust_path
();
for
dir
in
rp
.iter
()
{
debug!
(
"In find_dir_using_rust_path_hack: checking dir %s"
,
dir
.to_str
());
...
...
src/librustpkg/rustpkg.rs
浏览文件 @
02a0fb94
此差异已折叠。
点击以展开。
src/librustpkg/search.rs
浏览文件 @
02a0fb94
...
...
@@ -11,16 +11,6 @@
use
path_util
::{
installed_library_in_workspace
,
rust_path
};
use
version
::
Version
;
/// If a library with path `p` matching pkg_id's name exists under sroot_opt,
/// return Some(p). Return None if there's no such path or if sroot_opt is None.
pub
fn
find_library_in_search_path
(
sroot_opt
:
Option
<@
Path
>
,
short_name
:
&
str
)
->
Option
<
Path
>
{
do
sroot_opt
.chain
|
sroot
|
{
debug!
(
"Will search for a library with short name %s in
\
%s"
,
short_name
,
(
sroot
.push
(
"lib"
))
.to_str
());
installed_library_in_workspace
(
short_name
,
sroot
)
}
}
/// If some workspace `p` in the RUST_PATH contains a package matching short_name,
/// return Some(p) (returns the first one of there are multiple matches.) Return
/// None if there's no such path.
...
...
src/librustpkg/tests.rs
浏览文件 @
02a0fb94
...
...
@@ -10,10 +10,13 @@
// rustpkg unit tests
use
context
::
Ctx
;
use
std
::
hashmap
::
HashMap
;
use
std
::{
io
,
libc
,
os
,
run
,
str
};
use
context
::{
BuildCtx
,
Ctx
};
use
std
::{
io
,
libc
,
os
,
run
,
str
,
task
};
use
extra
::
arc
::
Arc
;
use
extra
::
arc
::
RWArc
;
use
extra
::
tempfile
::
mkdtemp
;
use
extra
::
workcache
::{
Context
,
Database
,
Logger
};
use
extra
::
treemap
::
TreeMap
;
use
std
::
run
::
ProcessOutput
;
use
installed_packages
::
list_installed_packages
;
use
package_id
::{
PkgId
};
...
...
@@ -26,18 +29,23 @@
use
rustc
::
metadata
::
filesearch
::
rust_path
;
use
rustc
::
driver
::
driver
::
host_triple
;
use
target
::
*
;
use
package_source
::
PkgSrc
;
/// Returns the last-modified date as an Option
fn
datestamp
(
p
:
&
Path
)
->
Option
<
libc
::
time_t
>
{
p
.stat
()
.map
(|
stat
|
stat
.st_mtime
)
}
fn
fake_ctxt
(
sysroot_opt
:
Option
<@
Path
>
)
->
Ctx
{
Ctx
{
use_rust_path_hack
:
false
,
sysroot_opt
:
sysroot_opt
,
json
:
false
,
dep_cache
:
@
mut
HashMap
::
new
()
fn
fake_ctxt
(
sysroot_opt
:
Path
,
workspace
:
&
Path
)
->
BuildCtx
{
let
bcx
=
Context
::
new
(
RWArc
::
new
(
Database
::
new
(
workspace
.push
(
"rustpkg_db.json"
))),
RWArc
::
new
(
Logger
::
new
()),
Arc
::
new
(
TreeMap
::
new
()));
BuildCtx
{
workcache_cx
:
bcx
,
cx
:
Ctx
{
use_rust_path_hack
:
false
,
sysroot_opt
:
sysroot_opt
}
}
}
...
...
@@ -388,7 +396,7 @@ fn lib_output_file_name(workspace: &Path, parent: &str, short_name: &str) -> Pat
}
fn
output_file_name
(
workspace
:
&
Path
,
short_name
:
&
str
)
->
Path
{
workspace
.push
(
fmt!
(
"%s%s"
,
short_name
,
os
::
EXE_SUFFIX
))
workspace
.push
(
"build"
)
.push
(
short_name
)
.push
(
fmt!
(
"%s%s"
,
short_name
,
os
::
EXE_SUFFIX
))
}
fn
touch_source_file
(
workspace
:
&
Path
,
pkgid
:
&
PkgId
)
{
...
...
@@ -401,12 +409,11 @@ fn touch_source_file(workspace: &Path, pkgid: &PkgId) {
if
run
::
process_output
(
"touch"
,
[
p
.to_str
()])
.status
!=
0
{
let
_
=
cond
.raise
((
pkg_src_dir
.clone
(),
~
"Bad path"
));
}
break
;
}
}
}
/// Add a
blank line
at the end
/// Add a
comment
at the end
fn
frob_source_file
(
workspace
:
&
Path
,
pkgid
:
&
PkgId
)
{
use
conditions
::
bad_path
::
cond
;
let
pkg_src_dir
=
workspace
.push
(
"src"
)
.push
(
pkgid
.to_str
());
...
...
@@ -423,7 +430,7 @@ fn frob_source_file(workspace: &Path, pkgid: &PkgId) {
let
w
=
io
::
file_writer
(
p
,
&
[
io
::
Append
]);
match
w
{
Err
(
s
)
=>
{
let
_
=
cond
.raise
((
p
.clone
(),
fmt!
(
"Bad path: %s"
,
s
)));
}
Ok
(
w
)
=>
w
.write_line
(
""
)
Ok
(
w
)
=>
w
.write_line
(
"
/* hi */
"
)
}
}
None
=>
fail
!
(
fmt!
(
"frob_source_file failed to find a source file in %s"
,
...
...
@@ -450,12 +457,13 @@ fn test_install_valid() {
let
sysroot
=
test_sysroot
();
debug!
(
"sysroot = %s"
,
sysroot
.to_str
());
let
ctxt
=
fake_ctxt
(
Some
(
@
sysroot
));
let
temp_pkg_id
=
fake_pkg
();
let
temp_workspace
=
mk_temp_workspace
(
&
temp_pkg_id
.path
,
&
NoVersion
)
.pop
()
.pop
();
let
ctxt
=
fake_ctxt
(
sysroot
,
&
temp_workspace
);
debug!
(
"temp_workspace = %s"
,
temp_workspace
.to_str
());
// should have test, bench, lib, and main
ctxt
.install
(
&
temp_workspace
,
&
temp_pkg_id
);
let
src
=
PkgSrc
::
new
(
temp_workspace
.clone
(),
false
,
temp_pkg_id
.clone
());
ctxt
.install
(
src
);
// Check that all files exist
let
exec
=
target_executable_in_workspace
(
&
temp_pkg_id
,
&
temp_workspace
);
debug!
(
"exec = %s"
,
exec
.to_str
());
...
...
@@ -476,32 +484,19 @@ fn test_install_valid() {
#[test]
fn
test_install_invalid
()
{
use
conditions
::
nonexistent_package
::
cond
;
use
cond1
=
conditions
::
missing_pkg_files
::
cond
;
use
cond2
=
conditions
::
not_a_workspace
::
cond
;
let
ctxt
=
fake_ctxt
(
None
);
let
sysroot
=
test_sysroot
();
let
pkgid
=
fake_pkg
();
let
temp_workspace
=
mkdtemp
(
&
os
::
tmpdir
(),
"test"
)
.expect
(
"couldn't create temp dir"
);
let
mut
error_occurred
=
false
;
let
mut
error1_occurred
=
false
;
let
mut
error2_occurred
=
false
;
do
cond1
.trap
(|
_
|
{
error1_occurred
=
true
;
})
.inside
{
do
cond
.trap
(|
_
|
{
error_occurred
=
true
;
temp_workspace
.clone
()
})
.inside
{
do
cond2
.trap
(|
_
|
{
error2_occurred
=
true
;
temp_workspace
.clone
()
})
.inside
{
ctxt
.install
(
&
temp_workspace
,
&
pkgid
);
}
}
}
assert
!
(
error_occurred
&&
error1_occurred
&&
error2_occurred
);
let
ctxt
=
fake_ctxt
(
sysroot
,
&
temp_workspace
);
// Uses task::try because of #9001
let
result
=
do
task
::
try
{
let
pkg_src
=
PkgSrc
::
new
(
temp_workspace
.clone
(),
false
,
pkgid
.clone
());
ctxt
.install
(
pkg_src
);
};
// Not the best test -- doesn't test that we failed in the right way.
// Best we can do for now.
assert
!
(
result
==
Err
(()));
}
// Tests above should (maybe) be converted to shell out to rustpkg, too
...
...
@@ -898,7 +893,6 @@ fn install_check_duplicates() {
}
#[test]
#[ignore(reason
=
"Workcache not yet implemented -- see #7075"
)]
fn
no_rebuilding
()
{
let
p_id
=
PkgId
::
new
(
"foo"
);
let
workspace
=
create_local_package
(
&
p_id
);
...
...
@@ -912,24 +906,28 @@ fn no_rebuilding() {
}
#[test]
#[ignore(reason
=
"Workcache not yet implemented -- see #7075"
)]
fn
no_rebuilding_dep
()
{
let
p_id
=
PkgId
::
new
(
"foo"
);
let
dep_id
=
PkgId
::
new
(
"bar"
);
let
workspace
=
create_local_package_with_dep
(
&
p_id
,
&
dep_id
);
command_line_test
([
~
"build"
,
~
"foo"
],
&
workspace
);
let
bar_date
=
datestamp
(
&
lib_output_file_name
(
&
workspace
,
let
bar_date_1
=
datestamp
(
&
lib_output_file_name
(
&
workspace
,
".rust"
,
"bar"
));
let
foo_date_1
=
datestamp
(
&
output_file_name
(
&
workspace
,
"foo"
));
frob_source_file
(
&
workspace
,
&
p_id
);
command_line_test
([
~
"build"
,
~
"foo"
],
&
workspace
);
let
bar_date_2
=
datestamp
(
&
lib_output_file_name
(
&
workspace
,
".rust"
,
"bar"
));
let
foo_date
=
datestamp
(
&
output_file_name
(
&
workspace
,
"foo"
));
assert
!
(
bar_date
<
foo_date
);
let
foo_date_2
=
datestamp
(
&
output_file_name
(
&
workspace
,
"foo"
));
assert_eq!
(
bar_date_1
,
bar_date_2
);
assert
!
(
foo_date_1
<
foo_date_2
);
assert
!
(
foo_date_1
>
bar_date_1
);
}
// n.b. The following two tests are ignored; they worked "accidentally" before,
// when the behavior was "always rebuild libraries" (now it's "never rebuild
// libraries if they already exist"). They can be un-ignored once #7075 is done.
#[test]
#[ignore(reason
=
"Workcache not yet implemented -- see #7075"
)]
fn
do_rebuild_dep_dates_change
()
{
let
p_id
=
PkgId
::
new
(
"foo"
);
let
dep_id
=
PkgId
::
new
(
"bar"
);
...
...
@@ -946,7 +944,6 @@ fn do_rebuild_dep_dates_change() {
}
#[test]
#[ignore(reason
=
"Workcache not yet implemented -- see #7075"
)]
fn
do_rebuild_dep_only_contents_change
()
{
let
p_id
=
PkgId
::
new
(
"foo"
);
let
dep_id
=
PkgId
::
new
(
"bar"
);
...
...
src/librustpkg/util.rs
浏览文件 @
02a0fb94
...
...
@@ -9,6 +9,7 @@
// except according to those terms.
use
std
::
os
;
use
extra
::
workcache
;
use
rustc
::
driver
::{
driver
,
session
};
use
extra
::
getopts
::
groups
::
getopts
;
use
syntax
::
ast_util
::
*
;
...
...
@@ -18,12 +19,13 @@
use
syntax
::
attr
::
AttrMetaMethods
;
use
rustc
::
back
::
link
::
output_type_exe
;
use
rustc
::
driver
::
session
::{
lib_crate
,
bin_crate
};
use
context
::{
Ctx
,
in_target
};
use
context
::{
in_target
,
BuildCtx
};
use
package_id
::
PkgId
;
use
search
::{
find_library_in_search_path
,
find_installed_library_in_rust_path
};
use
path_util
::{
target_library_in_workspace
,
U_RWX
};
use
package_source
::
PkgSrc
;
use
path_util
::{
installed_library_in_workspace
,
U_RWX
};
pub
use
target
::{
OutputType
,
Main
,
Lib
,
Bench
,
Test
};
use
version
::
NoVersion
;
use
workcache_support
::{
digest_file_with_date
,
digest_only_date
}
;
// It would be nice to have the list of commands in just one place -- for example,
// you could update the match in rustpkg.rc but forget to update this list. I think
...
...
@@ -151,15 +153,15 @@ pub fn ready_crate(sess: session::Session,
@
fold
.fold_crate
(
crate
)
}
// FIXME (#4432): Use workcache to only compile when needed
pub
fn
compile_input
(
ctxt
:
&
Ctx
,
pub
fn
compile_input
(
ctxt
:
&
BuildCtx
,
exec
:
&
mut
workcache
::
Exec
,
pkg_id
:
&
PkgId
,
in_file
:
&
Path
,
workspace
:
&
Path
,
flags
:
&
[
~
str
],
cfgs
:
&
[
~
str
],
opt
:
bool
,
what
:
OutputType
)
->
bool
{
what
:
OutputType
)
->
Option
<
Path
>
{
assert
!
(
in_file
.components
.len
()
>
1
);
let
input
=
driver
::
file_input
((
*
in_file
)
.clone
());
...
...
@@ -173,7 +175,7 @@ pub fn compile_input(ctxt: &Ctx,
debug!
(
"flags: %s"
,
flags
.connect
(
" "
));
debug!
(
"cfgs: %s"
,
cfgs
.connect
(
" "
));
debug!
(
"
out_dir = %s"
,
out_dir
.to_str
());
debug!
(
"
compile_input's sysroot = %s"
,
ctxt
.sysroot_opt
()
.to_str
());
let
crate_type
=
match
what
{
Lib
=>
lib_crate
,
...
...
@@ -191,19 +193,19 @@ pub fn compile_input(ctxt: &Ctx,
driver
::
optgroups
())
.unwrap
();
// Hack so that rustpkg can run either out of a rustc target dir,
// or the host dir
let
sysroot_to_use
=
if
!
in_target
(
ctxt
.sysroot_opt
)
{
ctxt
.sysroot_opt
let
sysroot_to_use
=
@
if
!
in_target
(
&
ctxt
.sysroot_opt
()
)
{
ctxt
.sysroot_opt
()
}
else
{
ctxt
.sysroot_opt
.map
(|
p
|
{
@
p
.pop
()
.pop
()
.pop
()
}
)
ctxt
.sysroot_opt
()
.pop
()
.pop
()
.pop
(
)
};
debug!
(
"compile_input's sysroot = %
?"
,
ctxt
.sysroot_opt
_str
());
debug!
(
"sysroot_to_use = %
?"
,
sysroot_to_use
);
debug!
(
"compile_input's sysroot = %
s"
,
ctxt
.sysroot_opt
()
.to
_str
());
debug!
(
"sysroot_to_use = %
s"
,
sysroot_to_use
.to_str
()
);
let
options
=
@
session
::
options
{
crate_type
:
crate_type
,
optimize
:
if
opt
{
session
::
Aggressive
}
else
{
session
::
No
},
test
:
what
==
Test
||
what
==
Bench
,
maybe_sysroot
:
sysroot_to_use
,
maybe_sysroot
:
Some
(
sysroot_to_use
)
,
addl_lib_search_paths
:
@
mut
(
~
[
out_dir
.clone
()]),
// output_type should be conditional
output_type
:
output_type_exe
,
// Use this to get a library? That's weird
...
...
@@ -228,11 +230,11 @@ pub fn compile_input(ctxt: &Ctx,
// `extern mod` directives.
let
cfg
=
driver
::
build_configuration
(
sess
);
let
mut
crate
=
driver
::
phase_1_parse_input
(
sess
,
cfg
.clone
(),
&
input
);
crate
=
driver
::
phase_2_configure_and_expand
(
sess
,
cfg
,
crate
);
crate
=
driver
::
phase_2_configure_and_expand
(
sess
,
cfg
.clone
()
,
crate
);
// Not really right. Should search other workspaces too, and the installed
// database (which doesn't exist yet)
find_and_install_dependencies
(
ctxt
,
sess
,
workspace
,
crate
,
find_and_install_dependencies
(
ctxt
,
sess
,
exec
,
workspace
,
crate
,
|
p
|
{
debug!
(
"a dependency: %s"
,
p
.to_str
());
// Pass the directory containing a dependency
...
...
@@ -269,8 +271,7 @@ pub fn compile_input(ctxt: &Ctx,
debug!
(
"calling compile_crate_from_input, workspace = %s,
building_library = %?"
,
out_dir
.to_str
(),
sess
.building_library
);
compile_crate_from_input
(
&
input
,
&
out_dir
,
sess
,
crate
);
true
compile_crate_from_input
(
in_file
,
exec
,
&
out_dir
,
sess
,
crate
)
}
// Should use workcache to avoid recompiling when not necessary
...
...
@@ -278,17 +279,19 @@ pub fn compile_input(ctxt: &Ctx,
// If crate_opt is present, then finish compilation. If it's None, then
// call compile_upto and return the crate
// also, too many arguments
pub
fn
compile_crate_from_input
(
input
:
&
driver
::
input
,
pub
fn
compile_crate_from_input
(
input
:
&
Path
,
exec
:
&
mut
workcache
::
Exec
,
// should be of the form <workspace>/build/<pkg id's path>
out_dir
:
&
Path
,
sess
:
session
::
Session
,
crate
:
@
ast
::
Crate
)
{
crate
:
@
ast
::
Crate
)
->
Option
<
Path
>
{
debug!
(
"Calling build_output_filenames with %s, building library? %?"
,
out_dir
.to_str
(),
sess
.building_library
);
// bad copy
debug!
(
"out_dir = %s"
,
out_dir
.to_str
());
let
outputs
=
driver
::
build_output_filenames
(
input
,
&
Some
(
out_dir
.clone
()),
&
None
,
let
outputs
=
driver
::
build_output_filenames
(
&
driver
::
file_input
(
input
.clone
()),
&
Some
(
out_dir
.clone
()),
&
None
,
crate
.attrs
,
sess
);
debug!
(
"Outputs are out_filename: %s and obj_filename: %s and output type = %?"
,
...
...
@@ -304,8 +307,13 @@ pub fn compile_crate_from_input(input: &driver::input,
&
analysis
,
outputs
);
driver
::
phase_5_run_llvm_passes
(
sess
,
&
translation
,
outputs
);
if
driver
::
stop_after_phase_5
(
sess
)
{
return
;
}
if
driver
::
stop_after_phase_5
(
sess
)
{
return
Some
(
outputs
.out_filename
)
;
}
driver
::
phase_6_link_output
(
sess
,
&
translation
,
outputs
);
// Register dependency on the source file
exec
.discover_input
(
"file"
,
input
.to_str
(),
digest_file_with_date
(
input
));
Some
(
outputs
.out_filename
)
}
#[cfg(windows)]
...
...
@@ -318,76 +326,90 @@ pub fn exe_suffix() -> ~str { ~".exe" }
pub
fn
exe_suffix
()
->
~
str
{
~
""
}
// Called by build_crates
// FIXME (#4432): Use workcache to only compile when needed
pub
fn
compile_crate
(
ctxt
:
&
Ctx
,
pkg_id
:
&
PkgId
,
pub
fn
compile_crate
(
ctxt
:
&
BuildCtx
,
exec
:
&
mut
workcache
::
Exec
,
pkg_id
:
&
PkgId
,
crate
:
&
Path
,
workspace
:
&
Path
,
flags
:
&
[
~
str
],
cfgs
:
&
[
~
str
],
opt
:
bool
,
what
:
OutputType
)
->
bool
{
what
:
OutputType
)
->
Option
<
Path
>
{
debug!
(
"compile_crate: crate=%s, workspace=%s"
,
crate
.to_str
(),
workspace
.to_str
());
debug!
(
"compile_crate: short_name = %s, flags =..."
,
pkg_id
.to_str
());
for
fl
in
flags
.iter
()
{
debug!
(
"+++ %s"
,
*
fl
);
}
compile_input
(
ctxt
,
pkg_id
,
crate
,
workspace
,
flags
,
cfgs
,
opt
,
what
)
compile_input
(
ctxt
,
exec
,
pkg_id
,
crate
,
workspace
,
flags
,
cfgs
,
opt
,
what
)
}
/// Collect all `extern mod` directives in `c`, then
/// try to install their targets, failing if any target
/// can't be found.
pub
fn
find_and_install_dependencies
(
ctxt
:
&
Ctx
,
pub
fn
find_and_install_dependencies
(
ctxt
:
&
Build
Ctx
,
sess
:
session
::
Session
,
exec
:
&
mut
workcache
::
Exec
,
workspace
:
&
Path
,
c
:
&
ast
::
Crate
,
save
:
@
fn
(
Path
)
)
{
// :-(
debug!
(
"In find_and_install_dependencies..."
);
let
my_workspace
=
(
*
workspace
)
.clone
();
let
my_ctxt
=
*
ctxt
;
do
c
.each_view_item
()
|
vi
:
&
ast
::
view_item
|
{
debug!
(
"Finding and installing dependencies..."
);
do
c
.each_view_item
|
vi
|
{
debug!
(
"A view item!"
);
match
vi
.node
{
// ignore metadata, I guess
ast
::
view_item_extern_mod
(
lib_ident
,
path_opt
,
_
,
_
)
=>
{
match
my_ctxt
.sysroot_opt
{
Some
(
ref
x
)
=>
debug!
(
"*** sysroot: %s"
,
x
.to_str
()),
None
=>
debug!
(
"No sysroot given"
)
};
let
lib_name
=
match
path_opt
{
// ???
let
lib_name
=
match
path_opt
{
Some
(
p
)
=>
p
,
None
=>
sess
.str_of
(
lib_ident
)
};
match
find_library_in_search_path
(
my_ctxt
.sysroot_opt
,
lib_name
)
{
Some
(
installed_path
)
=>
{
match
installed_library_in_workspace
(
lib_name
,
&
ctxt
.sysroot_opt
()
)
{
Some
(
ref
installed_path
)
=>
{
debug!
(
"It exists: %s"
,
installed_path
.to_str
());
// Say that [path for c] has a discovered dependency on
// installed_path
// For binary files, we only hash the datestamp, not the contents.
// I'm not sure what the right thing is.
// Now we know that this crate has a discovered dependency on
// installed_path
exec
.discover_input
(
"binary"
,
installed_path
.to_str
(),
digest_only_date
(
installed_path
));
}
None
=>
{
// FIXME #8711: need to parse version out of path_opt
match
find_installed_library_in_rust_path
(
lib_name
,
&
NoVersion
)
{
Some
(
installed_path
)
=>
{
debug!
(
"Found library %s, not rebuilding it"
,
installed_path
.to_str
());
// Once workcache is implemented, we'll actually check
// whether or not the library at installed_path is fresh
save
(
installed_path
.pop
());
debug!
(
"Trying to install library %s, rebuilding it"
,
lib_name
.to_str
());
// Try to install it
let
pkg_id
=
PkgId
::
new
(
lib_name
);
let
(
outputs_disc
,
inputs_disc
)
=
ctxt
.install
(
PkgSrc
::
new
(
workspace
.clone
(),
false
,
pkg_id
));
debug!
(
"Installed %s, returned %? dependencies and
\
%? transitive dependencies"
,
lib_name
,
outputs_disc
.len
(),
inputs_disc
.len
());
for
dep
in
outputs_disc
.iter
()
{
debug!
(
"Discovering a binary input: %s"
,
dep
.to_str
());
exec
.discover_input
(
"binary"
,
dep
.to_str
(),
digest_only_date
(
dep
));
}
for
&
(
ref
what
,
ref
dep
)
in
inputs_disc
.iter
()
{
if
*
what
==
~
"file"
{
exec
.discover_input
(
*
what
,
*
dep
,
digest_file_with_date
(
&
Path
(
*
dep
)));
}
None
=>
{
debug!
(
"Trying to install library %s, rebuilding it"
,
lib_name
.to_str
());
// Try to install it
let
pkg_id
=
PkgId
::
new
(
lib_name
);
my_ctxt
.install
(
&
my_workspace
,
&
pkg_id
);
// Also, add an additional search path
debug!
(
"let installed_path..."
)
let
installed_path
=
target_library_in_workspace
(
&
pkg_id
,
&
my_workspace
)
.pop
();
debug!
(
"Great, I installed %s, and it's in %s"
,
lib_name
,
installed_path
.to_str
());
save
(
installed_path
);
}
else
if
*
what
==
~
"binary"
{
exec
.discover_input
(
*
what
,
*
dep
,
digest_only_date
(
&
Path
(
*
dep
)));
}
else
{
fail
!
(
"Bad kind: %s"
,
*
what
);
}
}
// Also, add an additional search path
let
installed_library
=
installed_library_in_workspace
(
lib_name
,
workspace
)
.expect
(
fmt!
(
"rustpkg failed to install dependency %s"
,
lib_name
));
let
install_dir
=
installed_library
.pop
();
debug!
(
"Installed %s into %s"
,
lib_name
,
install_dir
.to_str
());
save
(
install_dir
);
}
}
}
}
}}
// Ignore `use`s
_
=>
()
}
...
...
src/librustpkg/version.rs
浏览文件 @
02a0fb94
...
...
@@ -99,12 +99,14 @@ pub fn try_getting_local_version(local_path: &Path) -> Option<Version> {
let
rustpath
=
rust_path
();
for
rp
in
rustpath
.iter
()
{
let
local_path
=
rp
.push_rel
(
local_path
);
debug!
(
"in try_getting_local_version"
);
let
git_dir
=
local_path
.push
(
".git"
);
if
!
os
::
path_is_dir
(
&
git_dir
)
{
loop
;
}
let
outp
=
run
::
process_output
(
"git"
,
[
fmt!
(
"--git-dir=%s"
,
local_path
.push
(
".git"
)
.to_str
()),
~
"tag"
,
~
"-l"
]);
[
fmt!
(
"--git-dir=%s"
,
git_dir
.to_str
()),
~
"tag"
,
~
"-l"
]);
debug!
(
"git --git-dir=%s tag -l ~~~> %?"
,
local_path
.push
(
".git"
)
.to_str
(),
outp
.status
);
debug!
(
"git --git-dir=%s tag -l ~~~> %?"
,
git_dir
.to_str
(),
outp
.status
);
if
outp
.status
!=
0
{
loop
;
...
...
@@ -129,9 +131,7 @@ pub fn try_getting_local_version(local_path: &Path) -> Option<Version> {
/// and the most recent tag in that repo denotes a version, return it;
/// otherwise, `None`
pub
fn
try_getting_version
(
remote_path
:
&
Path
)
->
Option
<
Version
>
{
debug!
(
"try_getting_version: %s"
,
remote_path
.to_str
());
if
is_url_like
(
remote_path
)
{
debug!
(
"Trying to fetch its sources.."
);
let
tmp_dir
=
mkdtemp
(
&
os
::
tmpdir
(),
"test"
)
.expect
(
"try_getting_version: couldn't create temp dir"
);
debug!
(
"(to get version) executing {git clone https://%s %s}"
,
...
...
@@ -218,14 +218,11 @@ pub fn split_version<'a>(s: &'a str) -> Option<(&'a str, Version)> {
pub
fn
split_version_general
<
'a
>
(
s
:
&
'a
str
,
sep
:
char
)
->
Option
<
(
&
'a
str
,
Version
)
>
{
match
s
.rfind
(
sep
)
{
Some
(
i
)
=>
{
debug!
(
"in %s, i = %?"
,
s
,
i
);
let
path
=
s
.slice
(
0
,
i
);
debug!
(
"path = %s"
,
path
);
// n.b. for now, assuming an exact revision is intended, not a SemVer
Some
((
path
,
ExactRevision
(
s
.slice
(
i
+
1
,
s
.len
())
.to_owned
())))
}
None
=>
{
debug!
(
"%s doesn't look like an explicit-version thing"
,
s
);
None
}
}
...
...
src/librustpkg/workcache_support.rs
0 → 100644
浏览文件 @
02a0fb94
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use
extra
::
sha1
::
Sha1
;
use
extra
::
digest
::
Digest
;
use
extra
::
workcache
;
use
std
::
io
;
/// Hashes the file contents along with the last-modified time
pub
fn
digest_file_with_date
(
path
:
&
Path
)
->
~
str
{
use
conditions
::
bad_path
::
cond
;
use
cond1
=
conditions
::
bad_stat
::
cond
;
let
mut
sha
=
~
Sha1
::
new
();
let
s
=
io
::
read_whole_file_str
(
path
);
match
s
{
Ok
(
s
)
=>
{
(
*
sha
)
.input_str
(
s
);
let
st
=
match
path
.stat
()
{
Some
(
st
)
=>
st
,
None
=>
cond1
.raise
((
path
.clone
(),
fmt!
(
"Couldn't get file access time"
)))
};
(
*
sha
)
.input_str
(
st
.st_mtime
.to_str
());
(
*
sha
)
.result_str
()
}
Err
(
e
)
=>
cond
.raise
((
path
.clone
(),
fmt!
(
"Couldn't read file: %s"
,
e
)))
.to_str
()
}
}
/// Hashes only the last-modified time
pub
fn
digest_only_date
(
path
:
&
Path
)
->
~
str
{
use
cond
=
conditions
::
bad_stat
::
cond
;
let
mut
sha
=
~
Sha1
::
new
();
let
st
=
match
path
.stat
()
{
Some
(
st
)
=>
st
,
None
=>
cond
.raise
((
path
.clone
(),
fmt!
(
"Couldn't get file access time"
)))
};
(
*
sha
)
.input_str
(
st
.st_mtime
.to_str
());
(
*
sha
)
.result_str
()
}
/// Adds multiple discovered outputs
pub
fn
discover_outputs
(
e
:
&
mut
workcache
::
Exec
,
outputs
:
~
[
Path
])
{
debug!
(
"Discovering %? outputs"
,
outputs
.len
());
for
p
in
outputs
.iter
()
{
debug!
(
"Discovering output! %s"
,
p
.to_str
());
// For now, assume that all discovered outputs are binaries
e
.discover_output
(
"binary"
,
p
.to_str
(),
digest_only_date
(
p
));
}
}
src/librustpkg/workspace.rs
浏览文件 @
02a0fb94
...
...
@@ -43,7 +43,7 @@ pub fn pkg_parent_workspaces(cx: &Ctx, pkgid: &PkgId) -> ~[Path] {
.filter
(|
ws
|
workspace_contains_package_id
(
pkgid
,
ws
))
.collect
();
if
cx
.use_rust_path_hack
{
rs
+
option_to_vec
(
find_dir_using_rust_path_hack
(
cx
,
pkgid
))
rs
+
option_to_vec
(
find_dir_using_rust_path_hack
(
pkgid
))
}
else
{
rs
...
...
src/libsyntax/ast_util.rs
浏览文件 @
02a0fb94
...
...
@@ -14,7 +14,7 @@
use
codemap
::{
Span
,
dummy_sp
};
use
opt_vec
;
use
parse
::
token
;
use
visit
::{
SimpleVisitor
,
SimpleVisitorVisitor
,
Visitor
};
use
visit
::{
SimpleVisitor
,
Visitor
};
use
visit
;
use
std
::
hashmap
::
HashMap
;
...
...
@@ -684,94 +684,25 @@ pub fn walk_pat(pat: @Pat, it: &fn(@Pat) -> bool) -> bool {
}
pub
trait
EachViewItem
{
fn
each_view_item
(
&
self
,
f
:
@
fn
(
&
ast
::
view_item
)
->
bool
)
->
bool
;
fn
each_view_item
(
&
self
,
f
:
&
fn
(
&
ast
::
view_item
)
->
bool
)
->
bool
;
}
struct
EachViewItemData
{
callback
:
@
fn
(
&
ast
::
view_item
)
->
bool
,
struct
EachViewItemData
<
'self
>
{
callback
:
&
'self
fn
(
&
ast
::
view_item
)
->
bool
,
}
impl
SimpleVisitor
for
EachViewItemData
{
fn
visit_mod
(
&
mut
self
,
_
:
&
_
mod
,
_
:
Span
,
_
:
NodeId
)
{
// XXX: Default method.
}
fn
visit_view_item
(
&
mut
self
,
view_item
:
&
view_item
)
{
impl
<
'self
>
Visitor
<
()
>
for
EachViewItemData
<
'self
>
{
fn
visit_view_item
(
&
mut
self
,
view_item
:
&
ast
::
view_item
,
_
:
())
{
let
_
=
(
self
.callback
)(
view_item
);
}
fn
visit_foreign_item
(
&
mut
self
,
_
:
@
foreign_item
)
{
// XXX: Default method.
}
fn
visit_item
(
&
mut
self
,
_
:
@
item
)
{
// XXX: Default method.
}
fn
visit_local
(
&
mut
self
,
_
:
@
Local
)
{
// XXX: Default method.
}
fn
visit_block
(
&
mut
self
,
_
:
&
Block
)
{
// XXX: Default method.
}
fn
visit_stmt
(
&
mut
self
,
_
:
@
Stmt
)
{
// XXX: Default method.
}
fn
visit_arm
(
&
mut
self
,
_
:
&
Arm
)
{
// XXX: Default method.
}
fn
visit_pat
(
&
mut
self
,
_
:
@
Pat
)
{
// XXX: Default method.
}
fn
visit_decl
(
&
mut
self
,
_
:
@
Decl
)
{
// XXX: Default method.
}
fn
visit_expr
(
&
mut
self
,
_
:
@
Expr
)
{
// XXX: Default method.
}
fn
visit_expr_post
(
&
mut
self
,
_
:
@
Expr
)
{
// XXX: Default method.
}
fn
visit_ty
(
&
mut
self
,
_
:
&
Ty
)
{
// XXX: Default method.
}
fn
visit_generics
(
&
mut
self
,
_
:
&
Generics
)
{
// XXX: Default method.
}
fn
visit_fn
(
&
mut
self
,
_
:
&
visit
::
fn_kind
,
_
:
&
fn_decl
,
_
:
&
Block
,
_
:
Span
,
_
:
NodeId
)
{
// XXX: Default method.
}
fn
visit_ty_method
(
&
mut
self
,
_
:
&
TypeMethod
)
{
// XXX: Default method.
}
fn
visit_trait_method
(
&
mut
self
,
_
:
&
trait_method
)
{
// XXX: Default method.
}
fn
visit_struct_def
(
&
mut
self
,
_
:
@
struct_def
,
_
:
Ident
,
_
:
&
Generics
,
_
:
NodeId
)
{
// XXX: Default method.
}
fn
visit_struct_field
(
&
mut
self
,
_
:
@
struct_field
)
{
// XXX: Default method.
}
fn
visit_struct_method
(
&
mut
self
,
_
:
@
method
)
{
// XXX: Default method.
}
}
impl
EachViewItem
for
ast
::
Crate
{
fn
each_view_item
(
&
self
,
f
:
@
fn
(
&
ast
::
view_item
)
->
bool
)
->
bool
{
let
data
=
@
mut
EachViewItemData
{
fn
each_view_item
(
&
self
,
f
:
&
fn
(
&
ast
::
view_item
)
->
bool
)
->
bool
{
let
mut
visit
=
EachViewItemData
{
callback
:
f
,
};
let
visitor
=
@
mut
SimpleVisitorVisitor
{
simple_visitor
:
data
as
@
mut
SimpleVisitor
,
};
visit
::
walk_crate
(
visitor
,
self
,
());
visit
::
walk_crate
(
&
mut
visit
,
self
,
());
true
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录