Auto merge of #149354 - antoyo:bootstrap-config/libgccjit-libs-dir, r… · rust-lang/rust@cec7008 (original) (raw)

`@@ -7,7 +7,7 @@

`

7

7

`//! goes along from the output of the previous stage.

`

8

8

``

9

9

`use std::borrow::Cow;

`

10

``

`-

use std::collections::{HashMap, HashSet};

`

``

10

`+

use std::collections::{BTreeMap, HashMap, HashSet};

`

11

11

`use std::ffi::OsStr;

`

12

12

`use std::io::BufReader;

`

13

13

`use std::io::prelude::*;

`

`@@ -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, add_cg_gcc_cargo_flags};

`

``

22

`+

use crate::core::build_steps::gcc::{Gcc, GccOutput, GccTargetPair, add_cg_gcc_cargo_flags};

`

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;

`

`@@ -1576,17 +1576,98 @@ impl Step for RustcLink {

`

1576

1576

`}

`

1577

1577

`}

`

1578

1578

``

``

1579

`` +

/// Set of libgccjit dylibs that can be used by cg_gcc to compile code for a set of targets.

``

``

1580

`+

#[derive(Clone)]

`

``

1581

`+

pub struct GccDylibSet {

`

``

1582

`+

dylibs: BTreeMap<GccTargetPair, GccOutput>,

`

``

1583

`+

host_pair: GccTargetPair,

`

``

1584

`+

}

`

``

1585

+

``

1586

`+

impl GccDylibSet {

`

``

1587

`` +

/// Returns the libgccjit.so dylib that corresponds to a host target on which cg_gcc will be

``

``

1588

`` +

/// executed, and which will target the host. So e.g. if cg_gcc will be executed on

``

``

1589

`+

/// x86_64-unknown-linux-gnu, the host dylib will be for compilation pair

`

``

1590

`` +

/// (x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu).

``

``

1591

`+

fn host_dylib(&self) -> &GccOutput {

`

``

1592

`+

self.dylibs.get(&self.host_pair).unwrap_or_else(|| {

`

``

1593

`+

panic!("libgccjit.so was not built for host target {}", self.host_pair)

`

``

1594

`+

})

`

``

1595

`+

}

`

``

1596

+

``

1597

`+

/// Install the libgccjit dylibs to the corresponding target directories of the given compiler.

`

``

1598

`+

/// cg_gcc know how to search for the libgccjit dylibs in these directories, according to the

`

``

1599

`+

/// (host, target) pair that is being compiled by rustc and cg_gcc.

`

``

1600

`+

pub fn install_to(&self, builder: &Builder<'_>, compiler: Compiler) {

`

``

1601

`+

if builder.config.dry_run() {

`

``

1602

`+

return;

`

``

1603

`+

}

`

``

1604

+

``

1605

`+

// /lib//codegen-backends

`

``

1606

`+

let cg_sysroot = builder.sysroot_codegen_backends(compiler);

`

``

1607

+

``

1608

`+

for (target_pair, libgccjit) in &self.dylibs {

`

``

1609

`+

assert_eq!(

`

``

1610

`+

target_pair.host(),

`

``

1611

`+

compiler.host,

`

``

1612

`+

"Trying to install libgccjit ({target_pair}) to a compiler with a different host ({})",

`

``

1613

`+

compiler.host

`

``

1614

`+

);

`

``

1615

`+

let libgccjit = libgccjit.libgccjit();

`

``

1616

`+

let target_filename = libgccjit.file_name().unwrap().to_str().unwrap();

`

``

1617

+

``

1618

`` +

// If we build libgccjit ourselves, then libgccjit can actually be a symlink.

``

``

1619

`+

// In that case, we have to resolve it first, otherwise we'd create a symlink to a

`

``

1620

`+

// symlink, which wouldn't work.

`

``

1621

`+

let actual_libgccjit_path = t!(

`

``

1622

`+

libgccjit.canonicalize(),

`

``

1623

`+

format!("Cannot find libgccjit at {}", libgccjit.display())

`

``

1624

`+

);

`

``

1625

+

``

1626

`+

// /lib//libgccjit.so

`

``

1627

`+

let dest_dir = cg_sysroot.join("lib").join(target_pair.target());

`

``

1628

`+

t!(fs::create_dir_all(&dest_dir));

`

``

1629

`+

let dst = dest_dir.join(target_filename);

`

``

1630

`+

builder.copy_link(&actual_libgccjit_path, &dst, FileType::NativeLibrary);

`

``

1631

`+

}

`

``

1632

`+

}

`

``

1633

`+

}

`

``

1634

+

1579

1635

`` /// Output of the compile::GccCodegenBackend step.

``

1580

``

`-

/// It includes the path to the libgccjit library on which this backend depends.

`

``

1636

`+

///

`

``

1637

`+

/// It contains paths to all built libgccjit libraries on which this backend depends here.

`

1581

1638

`#[derive(Clone)]

`

1582

1639

`pub struct GccCodegenBackendOutput {

`

1583

1640

`stamp: BuildStamp,

`

1584

``

`-

gcc: GccOutput,

`

``

1641

`+

dylib_set: GccDylibSet,

`

1585

1642

`}

`

1586

1643

``

``

1644

`` +

/// Builds the GCC codegen backend (cg_gcc).

``

``

1645

`` +

/// The cg_gcc backend uses libgccjit, which requires a separate build for each

``

``

1646

`` +

/// host -> target pair. So if you are on linux-x64 and build for linux-aarch64,

``

``

1647

`+

/// you will need at least:

`

``

1648

`+

/// - linux-x64 -> linux-x64 libgccjit (for building host code like proc macros)

`

``

1649

`+

/// - linux-x64 -> linux-aarch64 libgccjit (for the aarch64 target code)

`

``

1650

`+

///

`

``

1651

`+

/// We model this by having a single cg_gcc for a given host target, which contains one

`

``

1652

`+

/// libgccjit per (host, target) pair.

`

``

1653

`` +

/// Note that the host target is taken from self.compilers.target_compiler.host.

``

1587

1654

`#[derive(Debug, Clone, PartialEq, Eq, Hash)]

`

1588

1655

`pub struct GccCodegenBackend {

`

1589

1656

`compilers: RustcPrivateCompilers,

`

``

1657

`+

targets: Vec,

`

``

1658

`+

}

`

``

1659

+

``

1660

`+

impl GccCodegenBackend {

`

``

1661

`` +

/// Build cg_gcc that will run on host H (compilers.target_compiler.host) and will be

``

``

1662

`` +

/// able to produce code target pairs (H, T) for all T from targets.

``

``

1663

`+

pub fn for_targets(

`

``

1664

`+

compilers: RustcPrivateCompilers,

`

``

1665

`+

mut targets: Vec,

`

``

1666

`+

) -> Self {

`

``

1667

`+

// Sort targets to improve step cache hits

`

``

1668

`+

targets.sort();

`

``

1669

`+

Self { compilers, targets }

`

``

1670

`+

}

`

1590

1671

`}

`

1591

1672

``

1592

1673

`impl Step for GccCodegenBackend {

`

`@@ -1599,23 +1680,34 @@ impl Step for GccCodegenBackend {

`

1599

1680

`}

`

1600

1681

``

1601

1682

`fn make_run(run: RunConfig<'_>) {

`

1602

``

`-

run.builder.ensure(GccCodegenBackend {

`

1603

``

`-

compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),

`

1604

``

`-

});

`

``

1683

`+

// By default, build cg_gcc that will only be able to compile native code for the given

`

``

1684

`+

// host target.

`

``

1685

`+

let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target);

`

``

1686

`+

run.builder.ensure(GccCodegenBackend { compilers, targets: vec![run.target] });

`

1605

1687

`}

`

1606

1688

``

1607

1689

`fn run(self, builder: &Builder<'_>) -> Self::Output {

`

1608

``

`-

let target = self.compilers.target();

`

``

1690

`+

let host = self.compilers.target();

`

1609

1691

`let build_compiler = self.compilers.build_compiler();

`

1610

1692

``

1611

1693

`let stamp = build_stamp::codegen_backend_stamp(

`

1612

1694

` builder,

`

1613

1695

` build_compiler,

`

1614

``

`-

target,

`

``

1696

`+

host,

`

1615

1697

`&CodegenBackendKind::Gcc,

`

1616

1698

`);

`

1617

1699

``

1618

``

`-

let gcc = builder.ensure(Gcc { target });

`

``

1700

`+

let dylib_set = GccDylibSet {

`

``

1701

`+

dylibs: self

`

``

1702

`+

.targets

`

``

1703

`+

.iter()

`

``

1704

`+

.map(|&target| {

`

``

1705

`+

let target_pair = GccTargetPair::for_target_pair(host, target);

`

``

1706

`+

(target_pair, builder.ensure(Gcc { target_pair }))

`

``

1707

`+

})

`

``

1708

`+

.collect(),

`

``

1709

`+

host_pair: GccTargetPair::for_native_build(host),

`

``

1710

`+

};

`

1619

1711

``

1620

1712

`if builder.config.keep_stage.contains(&build_compiler.stage) {

`

1621

1713

`` trace!("keep-stage requested");

``

`@@ -1625,29 +1717,29 @@ impl Step for GccCodegenBackend {

`

1625

1717

`);

`

1626

1718

`// Codegen backends are linked separately from this step today, so we don't do

`

1627

1719

`// anything here.

`

1628

``

`-

return GccCodegenBackendOutput { stamp, gcc };

`

``

1720

`+

return GccCodegenBackendOutput { stamp, dylib_set };

`

1629

1721

`}

`

1630

1722

``

1631

1723

`let mut cargo = builder::Cargo::new(

`

1632

1724

` builder,

`

1633

1725

` build_compiler,

`

1634

1726

`Mode::Codegen,

`

1635

1727

`SourceType::InTree,

`

1636

``

`-

target,

`

``

1728

`+

host,

`

1637

1729

`Kind::Build,

`

1638

1730

`);

`

1639

1731

` cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml"));

`

1640

``

`-

rustc_cargo_env(builder, &mut cargo, target);

`

``

1732

`+

rustc_cargo_env(builder, &mut cargo, host);

`

1641

1733

``

1642

``

`-

add_cg_gcc_cargo_flags(&mut cargo, &gcc);

`

``

1734

`+

add_cg_gcc_cargo_flags(&mut cargo, dylib_set.host_dylib());

`

1643

1735

``

1644

1736

`let _guard =

`

1645

``

`-

builder.msg(Kind::Build, "codegen backend gcc", Mode::Codegen, build_compiler, target);

`

``

1737

`+

builder.msg(Kind::Build, "codegen backend gcc", Mode::Codegen, build_compiler, host);

`

1646

1738

`let files = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);

`

1647

1739

``

1648

1740

`GccCodegenBackendOutput {

`

1649

1741

`stamp: write_codegen_backend_stamp(stamp, files, builder.config.dry_run()),

`

1650

``

`-

gcc,

`

``

1742

`+

dylib_set,

`

1651

1743

`}

`

1652

1744

`}

`

1653

1745

``

`@@ -2324,12 +2416,65 @@ impl Step for Assemble {

`

2324

2416

`copy_codegen_backends_to_sysroot(builder, stamp, target_compiler);

`

2325

2417

`}

`

2326

2418

`CodegenBackendKind::Gcc => {

`

2327

``

`-

let output =

`

2328

``

`-

builder.ensure(GccCodegenBackend { compilers: prepare_compilers() });

`

``

2419

`+

// We need to build cg_gcc for the host target of the compiler which we

`

``

2420

`` +

// build here, which is target_compiler.

``

``

2421

`+

// But we also need to build libgccjit for some additional targets, in

`

``

2422

`+

// the most general case.

`

``

2423

`+

// 1. We need to build (target_compiler.host, stdlib target) libgccjit

`

``

2424

`+

// for all stdlibs that we build, so that cg_gcc can be used to build code

`

``

2425

`+

// for all those targets.

`

``

2426

`+

// 2. We need to build (target_compiler.host, target_compiler.host)

`

``

2427

`+

// libgccjit, so that the target compiler can compile host code (e.g. proc

`

``

2428

`+

// macros).

`

``

2429

`+

// 3. We need to build (target_compiler.host, host target) libgccjit

`

``

2430

`+

// for all host targets that we build, so that cg_gcc can be used to

`

``

2431

`+

// build a (possibly cross-compiled) stage 2+ rustc.

`

``

2432

`+

//

`

``

2433

`+

// Assume that we are on host T1 and we do a stage2 build of rustc for T2.

`

``

2434

`+

// We want the T2 rustc compiler to be able to use cg_gcc and build code

`

``

2435

`+

// for T2 (host) and T3 (target). We also want to build the stage2 compiler

`

``

2436

`+

// itself using cg_gcc.

`

``

2437

`+

// This could correspond to the following bootstrap invocation:

`

``

2438

`` +

// x build rustc --build T1 --host T2 --target T3 --set codegen-backends=['gcc', 'llvm']

``

``

2439

`+

//

`

``

2440

`+

// For that, we will need the following GCC target pairs:

`

``

2441

`+

// 1. T1 -> T2 (to cross-compile a T2 rustc using cg_gcc running on T1)

`

``

2442

`+

// 2. T2 -> T2 (to build host code with the stage 2 rustc running on T2)

`

``

2443

`+

// 3. T2 -> T3 (to cross-compile code with the stage 2 rustc running on T2)

`

``

2444

`+

//

`

``

2445

`+

// FIXME: this set of targets is maximal, in reality we might need

`

``

2446

`+

// less libgccjits at this current build stage. Try to reduce the set of

`

``

2447

`+

// GCC dylibs built below by taking a look at the current stage and whether

`

``

2448

`+

// cg_gcc is used as the default codegen backend.

`

``

2449

+

``

2450

`+

let compilers = prepare_compilers();

`

``

2451

+

``

2452

`+

// The left side of the target pairs below is implied. It has to match the

`

``

2453

`+

// host target on which cg_gcc will run, which is the host target of

`

``

2454

`` +

// target_compiler. We only pass the right side of the target pairs to

``

``

2455

`` +

// the GccCodegenBackend constructor.

``

``

2456

`+

let mut targets = HashSet::new();

`

``

2457

`+

// Add all host targets, so that we are able to build host code in this

`

``

2458

`+

// bootstrap invocation using cg_gcc.

`

``

2459

`+

for target in &builder.hosts {

`

``

2460

`+

targets.insert(*target);

`

``

2461

`+

}

`

``

2462

`+

// Add all stdlib targets, so that the built rustc can produce code for them

`

``

2463

`+

for target in &builder.targets {

`

``

2464

`+

targets.insert(*target);

`

``

2465

`+

}

`

``

2466

`+

// Add the host target of the built rustc itself, so that it can build

`

``

2467

`+

// host code (e.g. proc macros) using cg_gcc.

`

``

2468

`+

targets.insert(compilers.target_compiler().host);

`

``

2469

+

``

2470

`+

let output = builder.ensure(GccCodegenBackend::for_targets(

`

``

2471

`+

compilers,

`

``

2472

`+

targets.into_iter().collect(),

`

``

2473

`+

));

`

2329

2474

`copy_codegen_backends_to_sysroot(builder, output.stamp, target_compiler);

`

2330

``

`-

// Also copy libgccjit to the library sysroot, so that it is available for

`

2331

``

`-

// the codegen backend.

`

2332

``

`-

output.gcc.install_to(builder, &rustc_libdir);

`

``

2475

`+

// Also copy all requires libgccjit dylibs to the corresponding

`

``

2476

`+

// library sysroots, so that they are available for the codegen backend.

`

``

2477

`+

output.dylib_set.install_to(builder, target_compiler);

`

2333

2478

`}

`

2334

2479

`CodegenBackendKind::Llvm | CodegenBackendKind::Custom(_) => continue,

`

2335

2480

`}

`