@@ -210,7 +210,8 @@ impl RustwideBuilder {
210
210
}
211
211
212
212
info ! ( "copying essential files for {}" , self . rustc_version) ;
213
- let source = build. host_target_dir ( ) . join ( "doc" ) ;
213
+ assert ! ( !metadata. proc_macro) ;
214
+ let source = build. host_target_dir ( ) . join ( HOST_TARGET ) . join ( "doc" ) ;
214
215
let dest = tempfile:: Builder :: new ( )
215
216
. prefix ( "essential-files" )
216
217
. tempdir ( ) ?;
@@ -350,14 +351,23 @@ impl RustwideBuilder {
350
351
if res. result . successful {
351
352
if let Some ( name) = res. cargo_metadata . root ( ) . library_name ( ) {
352
353
let host_target = build. host_target_dir ( ) ;
353
- has_docs = host_target. join ( "doc" ) . join ( name) . is_dir ( ) ;
354
+ has_docs = host_target
355
+ . join ( default_target)
356
+ . join ( "doc" )
357
+ . join ( name)
358
+ . is_dir ( ) ;
354
359
}
355
360
}
356
361
357
362
let mut algs = HashSet :: new ( ) ;
358
363
if has_docs {
359
364
debug ! ( "adding documentation for the default target to the database" ) ;
360
- self . copy_docs ( & build. host_target_dir ( ) , local_storage. path ( ) , "" , true ) ?;
365
+ self . copy_docs (
366
+ & build. host_target_dir ( ) ,
367
+ local_storage. path ( ) ,
368
+ default_target,
369
+ true ,
370
+ ) ?;
361
371
362
372
successful_targets. push ( res. target . clone ( ) ) ;
363
373
@@ -593,17 +603,20 @@ impl RustwideBuilder {
593
603
. is_ok ( )
594
604
} ) ;
595
605
596
- // If we're passed a default_target which requires a cross-compile,
597
- // cargo will put the output in `target/<target>/doc`.
598
- // However, if this is the default build, we don't want it there,
599
- // we want it in `target/doc`.
600
- // NOTE: don't rename this if the build failed, because `target/<target>/doc` won't exist.
601
- if successful && target != HOST_TARGET && is_default_target {
602
- // mv target/$target/doc target/doc
606
+ // For proc-macros, cargo will put the output in `target/doc`.
607
+ // Move it to the target-specific directory for consistency with other builds.
608
+ // NOTE: don't rename this if the build failed, because `target/doc` won't exist.
609
+ if successful && metadata. proc_macro {
610
+ assert ! (
611
+ is_default_target && target == HOST_TARGET ,
612
+ "can't handle cross-compiling macros"
613
+ ) ;
614
+ // mv target/doc target/$target/doc
603
615
let target_dir = build. host_target_dir ( ) ;
604
- let old_dir = target_dir. join ( target ) . join ( "doc" ) ;
605
- let new_dir = target_dir. join ( "doc" ) ;
616
+ let old_dir = target_dir. join ( "doc" ) ;
617
+ let new_dir = target_dir. join ( target ) . join ( "doc" ) ;
606
618
debug ! ( "rename {} to {}" , old_dir. display( ) , new_dir. display( ) ) ;
619
+ std:: fs:: create_dir ( target_dir. join ( target) ) ?;
607
620
std:: fs:: rename ( old_dir, new_dir) ?;
608
621
}
609
622
@@ -656,7 +669,16 @@ impl RustwideBuilder {
656
669
if let Some ( cpu_limit) = self . config . build_cpu_limit {
657
670
cargo_args. push ( format ! ( "-j{}" , cpu_limit) ) ;
658
671
}
659
- if target != HOST_TARGET {
672
+ // Cargo has a series of frightening bugs around cross-compiling proc-macros:
673
+ // - Passing `--target` causes RUSTDOCFLAGS to fail to be passed 🤦
674
+ // - Passing `--target` will *create* `target/{target-name}/doc` but will put the docs in `target/doc` anyway
675
+ // As a result, it's not possible for us to support cross-compiling proc-macros.
676
+ // However, all these caveats unfortunately still apply when `{target-name}` is the host.
677
+ // So, only pass `--target` for crates that aren't proc-macros.
678
+ //
679
+ // Originally, this had a simpler check `target != HOST_TARGET`, but *that* was buggy when `HOST_TARGET` wasn't the same as the default target.
680
+ // Rather than trying to keep track of it all, only special case proc-macros, which are what we actually care about.
681
+ if !metadata. proc_macro {
660
682
cargo_args. push ( "--target" . into ( ) ) ;
661
683
cargo_args. push ( target. into ( ) ) ;
662
684
} ;
@@ -702,7 +724,7 @@ impl RustwideBuilder {
702
724
dest = dest. join ( target) ;
703
725
}
704
726
705
- info ! ( "{} {}" , source. display( ) , dest. display( ) ) ;
727
+ info ! ( "copy {} to {}" , source. display( ) , dest. display( ) ) ;
706
728
copy_dir_all ( source, dest) . map_err ( Into :: into)
707
729
}
708
730
@@ -835,11 +857,11 @@ mod tests {
835
857
836
858
// doc archive exists
837
859
let doc_archive = rustdoc_archive_path ( crate_, version) ;
838
- assert ! ( storage. exists( & doc_archive) ?) ;
860
+ assert ! ( storage. exists( & doc_archive) ?, "{}" , doc_archive ) ;
839
861
840
862
// source archive exists
841
863
let source_archive = source_archive_path ( crate_, version) ;
842
- assert ! ( storage. exists( & source_archive) ?) ;
864
+ assert ! ( storage. exists( & source_archive) ?, "{}" , source_archive ) ;
843
865
844
866
// default target was built and is accessible
845
867
assert ! ( storage. exists_in_archive( & doc_archive, & format!( "{}/index.html" , crate_path) ) ?) ;
@@ -935,4 +957,66 @@ mod tests {
935
957
Ok ( ( ) )
936
958
} )
937
959
}
960
+
961
+ #[ test]
962
+ #[ ignore]
963
+ fn test_proc_macro ( ) {
964
+ wrapper ( |env| {
965
+ let crate_ = "thiserror-impl" ;
966
+ let version = "1.0.26" ;
967
+ let mut builder = RustwideBuilder :: init ( env) . unwrap ( ) ;
968
+ assert ! ( builder. build_package( crate_, version, PackageKind :: CratesIo ) ?) ;
969
+
970
+ let storage = env. storage ( ) ;
971
+
972
+ // doc archive exists
973
+ let doc_archive = rustdoc_archive_path ( crate_, version) ;
974
+ assert ! ( storage. exists( & doc_archive) ?) ;
975
+
976
+ // source archive exists
977
+ let source_archive = source_archive_path ( crate_, version) ;
978
+ assert ! ( storage. exists( & source_archive) ?) ;
979
+
980
+ Ok ( ( ) )
981
+ } ) ;
982
+ }
983
+
984
+ #[ test]
985
+ #[ ignore]
986
+ fn test_cross_compile_non_host_default ( ) {
987
+ wrapper ( |env| {
988
+ let crate_ = "xingapi" ;
989
+ let version = "0.3.3" ;
990
+ let mut builder = RustwideBuilder :: init ( env) . unwrap ( ) ;
991
+ assert ! ( builder. build_package( crate_, version, PackageKind :: CratesIo ) ?) ;
992
+
993
+ let storage = env. storage ( ) ;
994
+
995
+ // doc archive exists
996
+ let doc_archive = rustdoc_archive_path ( crate_, version) ;
997
+ assert ! ( storage. exists( & doc_archive) ?, "{}" , doc_archive) ;
998
+
999
+ // source archive exists
1000
+ let source_archive = source_archive_path ( crate_, version) ;
1001
+ assert ! ( storage. exists( & source_archive) ?, "{}" , source_archive) ;
1002
+
1003
+ let target = "x86_64-unknown-linux-gnu" ;
1004
+ let crate_path = crate_. replace ( "-" , "_" ) ;
1005
+ let target_docs_present = storage. exists_in_archive (
1006
+ & doc_archive,
1007
+ & format ! ( "{}/{}/index.html" , target, crate_path) ,
1008
+ ) ?;
1009
+
1010
+ let web = env. frontend ( ) ;
1011
+ let target_url = format ! (
1012
+ "/{}/{}/{}/{}/index.html" ,
1013
+ crate_, version, target, crate_path
1014
+ ) ;
1015
+
1016
+ assert ! ( target_docs_present) ;
1017
+ assert_success ( & target_url, web) ?;
1018
+
1019
+ Ok ( ( ) )
1020
+ } ) ;
1021
+ }
938
1022
}
0 commit comments