Skip to content

Commit 39e4108

Browse files
committed
Build docs for all targets
Thanks to @nagisa's advice in #16 we can build documentation for all targets now!
1 parent c7b210b commit 39e4108

File tree

6 files changed

+174
-68
lines changed

6 files changed

+174
-68
lines changed

src/bin/cratesfyi.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,11 @@ pub fn main() {
3232
.arg(Arg::with_name("CRATE_VERSION")
3333
.index(2)
3434
.required(false)
35-
.help("Crate version")))
35+
.help("Crate version"))
36+
.arg(Arg::with_name("TARGET")
37+
.index(3)
38+
.required(false)
39+
.help("The target platform to compile for")))
3640
.subcommand(SubCommand::with_name("build")
3741
.about("Builds documentation in a chroot environment")
3842
.arg(Arg::with_name("PREFIX")
@@ -110,7 +114,8 @@ pub fn main() {
110114
if let Some(matches) = matches.subcommand_matches("doc") {
111115
let name = matches.value_of("CRATE_NAME").unwrap();
112116
let version = matches.value_of("CRATE_VERSION");
113-
if let Err(e) = build_doc(name, version) {
117+
let target = matches.value_of("TARGET");
118+
if let Err(e) = build_doc(name, version, target) {
114119
panic!("{:#?}", e);
115120
}
116121
} else if let Some(matches) = matches.subcommand_matches("build") {

src/db/add_package.rs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ use time;
2424
pub fn add_package_into_database(conn: &Connection,
2525
pkg: &Package,
2626
res: &ChrootBuilderResult,
27-
files: Option<Json>)
27+
files: Option<Json>,
28+
doc_targets: Vec<String>)
2829
-> Result<i32, DocBuilderError> {
2930
debug!("Adding package into database");
3031
let crate_id = try!(initialize_package_in_database(&conn, &pkg));
@@ -38,13 +39,16 @@ pub fn add_package_into_database(conn: &Connection,
3839
&[&crate_id, &format!("{}", pkg.manifest().version())]));
3940

4041
if rows.len() == 0 {
41-
let rows = try!(conn.query("INSERT INTO releases ( crate_id, version, release_time, \
42-
dependencies, target_name, yanked, build_status, \
43-
rustdoc_status, test_status, license, repository_url, \
44-
homepage_url, description, description_long, readme, \
45-
authors, keywords, have_examples, downloads, files ) \
42+
let rows = try!(conn.query("INSERT INTO releases (
43+
crate_id, version, release_time, \
44+
dependencies, target_name, yanked, build_status, \
45+
rustdoc_status, test_status, license, repository_url, \
46+
homepage_url, description, description_long, readme, \
47+
authors, keywords, have_examples, downloads, files, \
48+
doc_targets \
49+
) \
4650
VALUES ( $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, \
47-
$11, $12, $13, $14, $15, $16, $17, $18, $19, $20 ) \
51+
$11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21 ) \
4852
RETURNING id",
4953
&[&crate_id,
5054
&format!("{}", pkg.manifest().version()),
@@ -65,7 +69,8 @@ pub fn add_package_into_database(conn: &Connection,
6569
&pkg.manifest().metadata().keywords.to_json(),
6670
&res.have_examples,
6771
&downloads,
68-
&files]));
72+
&files,
73+
&doc_targets.to_json()]));
6974
// return id
7075
rows.get(0).get(0)
7176

@@ -75,7 +80,8 @@ pub fn add_package_into_database(conn: &Connection,
7580
$8, test_status = $9, license = $10, repository_url = $11, \
7681
homepage_url = $12, description = $13, description_long = $14, \
7782
readme = $15, authors = $16, keywords = $17, have_examples = $18, \
78-
downloads = $19, files = $20 WHERE crate_id = $1 AND version = $2",
83+
downloads = $19, files = $20, doc_targets = $21 \
84+
WHERE crate_id = $1 AND version = $2",
7985
&[&crate_id,
8086
&format!("{}", pkg.manifest().version()),
8187
&release_time,
@@ -95,7 +101,8 @@ pub fn add_package_into_database(conn: &Connection,
95101
&pkg.manifest().metadata().keywords.to_json(),
96102
&res.have_examples,
97103
&downloads,
98-
&files]));
104+
&files,
105+
&doc_targets.to_json()]));
99106
rows.get(0).get(0)
100107
}
101108
};

src/db/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ pub fn create_tables(conn: &Connection) -> Result<(), Error> {
5959
have_examples BOOL DEFAULT FALSE, \
6060
downloads INT DEFAULT 0, \
6161
files JSON, \
62+
doc_targets JSON DEFAULT '[]', \
6263
UNIQUE (crate_id, version) \
6364
)",
6465
"CREATE TABLE authors ( \
@@ -116,6 +117,11 @@ pub fn create_tables(conn: &Connection) -> Result<(), Error> {
116117
date_updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, \
117118
content BYTEA \
118119
)",
120+
"CREATE TABLE config ( \
121+
name VARCHAR(100) NOT NULL PRIMARY KEY, \
122+
value JSON NOT NULL \
123+
)",
124+
"INSERT INTO config VALUES ('database_version', '1'::json)",
119125
];
120126

121127
for query in queries.into_iter() {

src/docbuilder/chroot_builder.rs

Lines changed: 109 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,23 @@ impl DocBuilder {
7171

7272
// copy sources and documentation
7373
let file_list = try!(self.add_sources_into_database(&conn, &pkg));
74-
if res.have_doc {
75-
try!(self.copy_documentation(&pkg, &res.rustc_version));
74+
let successfully_targets = if res.have_doc {
75+
try!(self.copy_documentation(&pkg, &res.rustc_version, None));
76+
let successfully_targets = self.build_package_for_all_targets(&pkg);
77+
for target in &successfully_targets {
78+
try!(self.copy_documentation(&pkg, &res.rustc_version, Some(target)));
79+
}
7680
try!(self.add_documentation_into_database(&conn, &pkg));
77-
}
78-
79-
let release_id = try!(add_package_into_database(&conn, &pkg, &res, Some(file_list)));
81+
successfully_targets
82+
} else {
83+
Vec::new()
84+
};
85+
86+
let release_id = try!(add_package_into_database(&conn,
87+
&pkg,
88+
&res,
89+
Some(file_list),
90+
successfully_targets));
8091
try!(add_build_into_database(&conn, &release_id, &res));
8192

8293
// remove documentation, source and build directory after we are done
@@ -121,13 +132,70 @@ impl DocBuilder {
121132
}
122133

123134

135+
136+
/// Builds documentation of crate for every target and returns Vec of successfully targets
137+
fn build_package_for_all_targets(&self, package: &Package) -> Vec<String> {
138+
let targets = ["aarch64-apple-ios",
139+
"aarch64-linux-android",
140+
"aarch64-unknown-linux-gnu",
141+
"arm-linux-androideabi",
142+
"arm-unknown-linux-gnueabi",
143+
"arm-unknown-linux-gnueabihf",
144+
"armv7-apple-ios",
145+
"armv7-linux-androideabi",
146+
"armv7-unknown-linux-gnueabihf",
147+
"armv7s-apple-ios",
148+
"i386-apple-ios",
149+
"i586-pc-windows-msvc",
150+
"i586-unknown-linux-gnu",
151+
"i686-apple-darwin",
152+
"i686-linux-android",
153+
"i686-pc-windows-gnu",
154+
"i686-pc-windows-msvc",
155+
"i686-unknown-freebsd",
156+
"i686-unknown-linux-gnu",
157+
"i686-unknown-linux-musl",
158+
"mips-unknown-linux-gnu",
159+
"mips-unknown-linux-musl",
160+
"mipsel-unknown-linux-gnu",
161+
"mipsel-unknown-linux-musl",
162+
"powerpc-unknown-linux-gnu",
163+
"powerpc64-unknown-linux-gnu",
164+
"powerpc64le-unknown-linux-gnu",
165+
"x86_64-apple-darwin",
166+
"x86_64-apple-ios",
167+
"x86_64-pc-windows-gnu",
168+
"x86_64-pc-windows-msvc",
169+
"x86_64-rumprun-netbsd",
170+
"x86_64-unknown-freebsd",
171+
"x86_64-unknown-linux-gnu",
172+
"x86_64-unknown-linux-musl",
173+
"x86_64-unknown-netbsd"];
174+
175+
let mut successfuly_targets = Vec::new();
176+
177+
for target in targets.iter() {
178+
debug!("Building {} for {}", canonical_name(&package), target);
179+
let cmd = format!("cratesfyi doc {} ={} {}",
180+
package.manifest().name(),
181+
package.manifest().version(),
182+
target);
183+
if let Ok(_) = self.chroot_command(cmd) {
184+
successfuly_targets.push(target.to_string());
185+
}
186+
}
187+
successfuly_targets
188+
}
189+
190+
124191
/// Copies source files of a package into source_path
125192
#[allow(dead_code)] // I've been using this function before storing files in database
126193
fn copy_sources(&self, package: &Package) -> Result<(), DocBuilderError> {
127194
debug!("Copying sources");
128-
let destination = PathBuf::from(&self.options.sources_path).join(format!("{}/{}",
129-
package.manifest().name(),
130-
package.manifest().version()));
195+
let destination =
196+
PathBuf::from(&self.options.sources_path).join(format!("{}/{}",
197+
package.manifest().name(),
198+
package.manifest().version()));
131199
// unwrap is safe here, this function will be always called after get_package
132200
match copy_dir(source_path(&package).unwrap(), &destination) {
133201
Ok(_) => Ok(()),
@@ -139,19 +207,23 @@ impl DocBuilder {
139207
/// Copies documentation to destination directory
140208
fn copy_documentation(&self,
141209
package: &Package,
142-
rustc_version: &str)
210+
rustc_version: &str,
211+
target: Option<&str>)
143212
-> Result<(), DocBuilderError> {
144-
debug!("Copying documentation");
145213
let crate_doc_path = PathBuf::from(&self.options.chroot_path)
146-
.join("home")
147-
.join(&self.options.chroot_user)
148-
.join(canonical_name(&package));
149-
let destination = PathBuf::from(&self.options.destination).join(format!("{}/{}",
214+
.join("home")
215+
.join(&self.options.chroot_user)
216+
.join(canonical_name(&package))
217+
.join(target.unwrap_or(""));
218+
let destination = PathBuf::from(&self.options.destination)
219+
.join(format!("{}/{}",
150220
package.manifest().name(),
151-
package.manifest().version()));
221+
package.manifest().version()))
222+
.join(target.unwrap_or(""));
152223
copy_doc_dir(crate_doc_path,
153224
destination,
154-
parse_rustc_version(rustc_version).trim())
225+
parse_rustc_version(rustc_version).trim(),
226+
target.is_some())
155227
.map_err(DocBuilderError::Io)
156228
}
157229

@@ -168,7 +240,7 @@ impl DocBuilder {
168240
debug!("Cleaning package");
169241
use std::fs::remove_dir_all;
170242
let documentation_path = PathBuf::from(&self.options.destination)
171-
.join(package.manifest().name());
243+
.join(package.manifest().name());
172244
let source_path = source_path(&package).unwrap();
173245
// Some crates don't have documentation, so we don't care if removing_dir_all fails
174246
let _ = self.remove_build_dir(&package);
@@ -181,17 +253,17 @@ impl DocBuilder {
181253
/// Runs a command in a chroot environment
182254
fn chroot_command<T: AsRef<str>>(&self, cmd: T) -> CommandResult {
183255
command_result(Command::new("sudo")
184-
.arg("lxc-attach")
185-
.arg("-n")
186-
.arg(&self.options.container_name)
187-
.arg("--")
188-
.arg("su")
189-
.arg("-")
190-
.arg(&self.options.chroot_user)
191-
.arg("-c")
192-
.arg(cmd.as_ref())
193-
.output()
194-
.unwrap())
256+
.arg("lxc-attach")
257+
.arg("-n")
258+
.arg(&self.options.container_name)
259+
.arg("--")
260+
.arg("su")
261+
.arg("-")
262+
.arg(&self.options.chroot_user)
263+
.arg("-c")
264+
.arg(cmd.as_ref())
265+
.output()
266+
.unwrap())
195267
}
196268

197269

@@ -201,11 +273,11 @@ impl DocBuilder {
201273
/// crate. Package must be successfully built in chroot environment first.
202274
fn have_documentation(&self, package: &Package) -> bool {
203275
let crate_doc_path = PathBuf::from(&self.options.chroot_path)
204-
.join("home")
205-
.join(&self.options.chroot_user)
206-
.join(canonical_name(&package))
207-
.join("doc")
208-
.join(package.targets()[0].name().to_string());
276+
.join("home")
277+
.join(&self.options.chroot_user)
278+
.join(canonical_name(&package))
279+
.join("doc")
280+
.join(package.targets()[0].name().to_string());
209281
crate_doc_path.exists()
210282
}
211283

@@ -222,11 +294,11 @@ impl DocBuilder {
222294
// It is safe to use expect here
223295
// chroot environment must always have rustc and cratesfyi installed
224296
(String::from(self.chroot_command("rustc --version")
225-
.expect("Failed to get rustc version")
226-
.trim()),
297+
.expect("Failed to get rustc version")
298+
.trim()),
227299
String::from(self.chroot_command("cratesfyi --version")
228-
.expect("Failed to get cratesfyi version")
229-
.trim()))
300+
.expect("Failed to get cratesfyi version")
301+
.trim()))
230302
}
231303

232304

src/utils/build_doc.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use cargo::{ops, ChainError};
2020
// idea is to make cargo to download
2121
// and build a crate and its documentation
2222
// instead of doing it manually like in the previous version of cratesfyi
23-
pub fn build_doc(name: &str, vers: Option<&str>) -> CargoResult<Package> {
23+
pub fn build_doc(name: &str, vers: Option<&str>, target: Option<&str>) -> CargoResult<Package> {
2424
let config = try!(Config::default());
2525
let source_id = try!(SourceId::for_central(&config));
2626

@@ -46,7 +46,7 @@ pub fn build_doc(name: &str, vers: Option<&str>) -> CargoResult<Package> {
4646
let opts = ops::CompileOptions {
4747
config: &config,
4848
jobs: None,
49-
target: None,
49+
target: target,
5050
features: &[],
5151
no_default_features: false,
5252
spec: &[],
@@ -117,10 +117,10 @@ mod test {
117117
#[ignore]
118118
fn test_build_doc() {
119119
// FIXME: Need to remove directory after we are finished
120-
let doc = build_doc("rand", None);
120+
let doc = build_doc("rand", None, None);
121121
assert!(doc.is_ok());
122122

123-
let doc = build_doc("SOMECRATEWICHWILLBENVEREXISTS", None);
123+
let doc = build_doc("SOMECRATEWICHWILLBENVEREXISTS", None, None);
124124
assert!(doc.is_err());
125125
}
126126

0 commit comments

Comments
 (0)