| ... | ... | @@ -19,7 +19,7 @@ use serde_derive::Deserialize; |
| 19 | 19 | #[cfg(feature = "tracing")] |
| 20 | 20 | use tracing::span; |
| 21 | 21 | |
| 22 | | use crate::core::build_steps::gcc::{Gcc, GccOutput, GccTargetPair, add_cg_gcc_cargo_flags}; |
| 22 | use crate::core::build_steps::gcc::{Gcc, GccOutput, GccTargetPair}; |
| 23 | 23 | use crate::core::build_steps::tool::{RustcPrivateCompilers, SourceType, copy_lld_artifacts}; |
| 24 | 24 | use crate::core::build_steps::{dist, llvm}; |
| 25 | 25 | use crate::core::builder; |
| ... | ... | @@ -1569,21 +1569,29 @@ impl Step for RustcLink { |
| 1569 | 1569 | } |
| 1570 | 1570 | |
| 1571 | 1571 | /// Set of `libgccjit` dylibs that can be used by `cg_gcc` to compile code for a set of targets. |
| 1572 | /// `libgccjit` requires a separate build for each `(host, target)` pair. |
| 1573 | /// So if you are on linux-x64 and build for linux-aarch64, you will need at least: |
| 1574 | /// - linux-x64 -> linux-x64 libgccjit (for building host code like proc macros) |
| 1575 | /// - linux-x64 -> linux-aarch64 libgccjit (for the aarch64 target code) |
| 1572 | 1576 | #[derive(Clone)] |
| 1573 | 1577 | pub struct GccDylibSet { |
| 1574 | 1578 | dylibs: BTreeMap<GccTargetPair, GccOutput>, |
| 1575 | | host_pair: GccTargetPair, |
| 1576 | 1579 | } |
| 1577 | 1580 | |
| 1578 | 1581 | impl GccDylibSet { |
| 1579 | | /// Returns the libgccjit.so dylib that corresponds to a host target on which `cg_gcc` will be |
| 1580 | | /// executed, and which will target the host. So e.g. if `cg_gcc` will be executed on |
| 1581 | | /// x86_64-unknown-linux-gnu, the host dylib will be for compilation pair |
| 1582 | | /// `(x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu)`. |
| 1583 | | fn host_dylib(&self) -> &GccOutput { |
| 1584 | | self.dylibs.get(&self.host_pair).unwrap_or_else(|| { |
| 1585 | | panic!("libgccjit.so was not built for host target {}", self.host_pair) |
| 1586 | | }) |
| 1582 | /// Build a set of libgccjit dylibs that will be executed on `host` and will generate code for |
| 1583 | /// each specified target. |
| 1584 | pub fn build( |
| 1585 | builder: &Builder<'_>, |
| 1586 | host: TargetSelection, |
| 1587 | targets: Vec<TargetSelection>, |
| 1588 | ) -> Self { |
| 1589 | let dylibs = targets |
| 1590 | .iter() |
| 1591 | .map(|t| GccTargetPair::for_target_pair(host, *t)) |
| 1592 | .map(|target_pair| (target_pair, builder.ensure(Gcc { target_pair }))) |
| 1593 | .collect(); |
| 1594 | Self { dylibs } |
| 1587 | 1595 | } |
| 1588 | 1596 | |
| 1589 | 1597 | /// Install the libgccjit dylibs to the corresponding target directories of the given compiler. |
| ... | ... | @@ -1626,39 +1634,34 @@ impl GccDylibSet { |
| 1626 | 1634 | |
| 1627 | 1635 | /// Output of the `compile::GccCodegenBackend` step. |
| 1628 | 1636 | /// |
| 1629 | | /// It contains paths to all built libgccjit libraries on which this backend depends here. |
| 1637 | /// It contains a build stamp with the path to the built cg_gcc dylib. |
| 1630 | 1638 | #[derive(Clone)] |
| 1631 | 1639 | pub struct GccCodegenBackendOutput { |
| 1632 | 1640 | stamp: BuildStamp, |
| 1633 | | dylib_set: GccDylibSet, |
| 1641 | } |
| 1642 | |
| 1643 | impl GccCodegenBackendOutput { |
| 1644 | pub fn stamp(&self) -> &BuildStamp { |
| 1645 | &self.stamp |
| 1646 | } |
| 1634 | 1647 | } |
| 1635 | 1648 | |
| 1636 | 1649 | /// Builds the GCC codegen backend (`cg_gcc`). |
| 1637 | | /// The `cg_gcc` backend uses `libgccjit`, which requires a separate build for each |
| 1638 | | /// `host -> target` pair. So if you are on linux-x64 and build for linux-aarch64, |
| 1639 | | /// you will need at least: |
| 1640 | | /// - linux-x64 -> linux-x64 libgccjit (for building host code like proc macros) |
| 1641 | | /// - linux-x64 -> linux-aarch64 libgccjit (for the aarch64 target code) |
| 1642 | | /// |
| 1643 | | /// We model this by having a single cg_gcc for a given host target, which contains one |
| 1644 | | /// libgccjit per (host, target) pair. |
| 1645 | | /// Note that the host target is taken from `self.compilers.target_compiler.host`. |
| 1650 | /// Note that this **does not** build libgccjit, which is a dependency of cg_gcc. |
| 1651 | /// That has to be built separately, because a separate copy of libgccjit is required |
| 1652 | /// for each (host, target) compilation pair. |
| 1653 | /// cg_gcc goes to great lengths to ensure that it does not *directly* link to libgccjit, |
| 1654 | /// so we respect that here and allow building cg_gcc without building libgccjit itself. |
| 1646 | 1655 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
| 1647 | 1656 | pub struct GccCodegenBackend { |
| 1648 | 1657 | compilers: RustcPrivateCompilers, |
| 1649 | | targets: Vec<TargetSelection>, |
| 1658 | target: TargetSelection, |
| 1650 | 1659 | } |
| 1651 | 1660 | |
| 1652 | 1661 | impl GccCodegenBackend { |
| 1653 | | /// Build `cg_gcc` that will run on host `H` (`compilers.target_compiler.host`) and will be |
| 1654 | | /// able to produce code target pairs (`H`, `T`) for all `T` from `targets`. |
| 1655 | | pub fn for_targets( |
| 1656 | | compilers: RustcPrivateCompilers, |
| 1657 | | mut targets: Vec<TargetSelection>, |
| 1658 | | ) -> Self { |
| 1659 | | // Sort targets to improve step cache hits |
| 1660 | | targets.sort(); |
| 1661 | | Self { compilers, targets } |
| 1662 | /// Build `cg_gcc` that will run on the given host target. |
| 1663 | pub fn for_target(compilers: RustcPrivateCompilers, target: TargetSelection) -> Self { |
| 1664 | Self { compilers, target } |
| 1662 | 1665 | } |
| 1663 | 1666 | } |
| 1664 | 1667 | |
| ... | ... | @@ -1672,10 +1675,8 @@ impl Step for GccCodegenBackend { |
| 1672 | 1675 | } |
| 1673 | 1676 | |
| 1674 | 1677 | fn make_run(run: RunConfig<'_>) { |
| 1675 | | // By default, build cg_gcc that will only be able to compile native code for the given |
| 1676 | | // host target. |
| 1677 | 1678 | let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target); |
| 1678 | | run.builder.ensure(GccCodegenBackend { compilers, targets: vec![run.target] }); |
| 1679 | run.builder.ensure(GccCodegenBackend::for_target(compilers, run.target)); |
| 1679 | 1680 | } |
| 1680 | 1681 | |
| 1681 | 1682 | fn run(self, builder: &Builder<'_>) -> Self::Output { |
| ... | ... | @@ -1689,19 +1690,7 @@ impl Step for GccCodegenBackend { |
| 1689 | 1690 | &CodegenBackendKind::Gcc, |
| 1690 | 1691 | ); |
| 1691 | 1692 | |
| 1692 | | let dylib_set = GccDylibSet { |
| 1693 | | dylibs: self |
| 1694 | | .targets |
| 1695 | | .iter() |
| 1696 | | .map(|&target| { |
| 1697 | | let target_pair = GccTargetPair::for_target_pair(host, target); |
| 1698 | | (target_pair, builder.ensure(Gcc { target_pair })) |
| 1699 | | }) |
| 1700 | | .collect(), |
| 1701 | | host_pair: GccTargetPair::for_native_build(host), |
| 1702 | | }; |
| 1703 | | |
| 1704 | | if builder.config.keep_stage.contains(&build_compiler.stage) { |
| 1693 | if builder.config.keep_stage.contains(&build_compiler.stage) && stamp.path().exists() { |
| 1705 | 1694 | trace!("`keep-stage` requested"); |
| 1706 | 1695 | builder.info( |
| 1707 | 1696 | "WARNING: Using a potentially old codegen backend. \ |
| ... | ... | @@ -1709,7 +1698,7 @@ impl Step for GccCodegenBackend { |
| 1709 | 1698 | ); |
| 1710 | 1699 | // Codegen backends are linked separately from this step today, so we don't do |
| 1711 | 1700 | // anything here. |
| 1712 | | return GccCodegenBackendOutput { stamp, dylib_set }; |
| 1701 | return GccCodegenBackendOutput { stamp }; |
| 1713 | 1702 | } |
| 1714 | 1703 | |
| 1715 | 1704 | let mut cargo = builder::Cargo::new( |
| ... | ... | @@ -1723,15 +1712,12 @@ impl Step for GccCodegenBackend { |
| 1723 | 1712 | cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml")); |
| 1724 | 1713 | rustc_cargo_env(builder, &mut cargo, host); |
| 1725 | 1714 | |
| 1726 | | add_cg_gcc_cargo_flags(&mut cargo, dylib_set.host_dylib()); |
| 1727 | | |
| 1728 | 1715 | let _guard = |
| 1729 | 1716 | builder.msg(Kind::Build, "codegen backend gcc", Mode::Codegen, build_compiler, host); |
| 1730 | 1717 | let files = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false); |
| 1731 | 1718 | |
| 1732 | 1719 | GccCodegenBackendOutput { |
| 1733 | 1720 | stamp: write_codegen_backend_stamp(stamp, files, builder.config.dry_run()), |
| 1734 | | dylib_set, |
| 1735 | 1721 | } |
| 1736 | 1722 | } |
| 1737 | 1723 | |
| ... | ... | @@ -2457,12 +2443,18 @@ impl Step for Assemble { |
| 2457 | 2443 | // GCC dylibs built below by taking a look at the current stage and whether |
| 2458 | 2444 | // cg_gcc is used as the default codegen backend. |
| 2459 | 2445 | |
| 2446 | // First, the easy part: build cg_gcc |
| 2460 | 2447 | let compilers = prepare_compilers(); |
| 2448 | let cg_gcc = builder |
| 2449 | .ensure(GccCodegenBackend::for_target(compilers, target_compiler.host)); |
| 2450 | copy_codegen_backends_to_sysroot(builder, cg_gcc.stamp, target_compiler); |
| 2451 | |
| 2452 | // Then, the hard part: prepare all required libgccjit dylibs. |
| 2461 | 2453 | |
| 2462 | 2454 | // The left side of the target pairs below is implied. It has to match the |
| 2463 | | // host target on which cg_gcc will run, which is the host target of |
| 2455 | // host target on which libgccjit will be used, which is the host target of |
| 2464 | 2456 | // `target_compiler`. We only pass the right side of the target pairs to |
| 2465 | | // the `GccCodegenBackend` constructor. |
| 2457 | // the `GccDylibSet` constructor. |
| 2466 | 2458 | let mut targets = HashSet::new(); |
| 2467 | 2459 | // Add all host targets, so that we are able to build host code in this |
| 2468 | 2460 | // bootstrap invocation using cg_gcc. |
| ... | ... | @@ -2477,14 +2469,16 @@ impl Step for Assemble { |
| 2477 | 2469 | // host code (e.g. proc macros) using cg_gcc. |
| 2478 | 2470 | targets.insert(compilers.target_compiler().host); |
| 2479 | 2471 | |
| 2480 | | let output = builder.ensure(GccCodegenBackend::for_targets( |
| 2481 | | compilers, |
| 2472 | // Now build all the required libgccjit dylibs |
| 2473 | let dylib_set = GccDylibSet::build( |
| 2474 | builder, |
| 2475 | compilers.target_compiler().host, |
| 2482 | 2476 | targets.into_iter().collect(), |
| 2483 | | )); |
| 2484 | | copy_codegen_backends_to_sysroot(builder, output.stamp, target_compiler); |
| 2485 | | // Also copy all requires libgccjit dylibs to the corresponding |
| 2486 | | // library sysroots, so that they are available for the codegen backend. |
| 2487 | | output.dylib_set.install_to(builder, target_compiler); |
| 2477 | ); |
| 2478 | |
| 2479 | // And then copy all the dylibs to the corresponding |
| 2480 | // library sysroots, so that they are available for cg_gcc. |
| 2481 | dylib_set.install_to(builder, target_compiler); |
| 2488 | 2482 | } |
| 2489 | 2483 | CodegenBackendKind::Llvm | CodegenBackendKind::Custom(_) => continue, |
| 2490 | 2484 | } |