This is the actual guts of linking: the rest of the link-related functions are just digging through rustc's shenanigans to collect all the object files we need to link.
(
sess: &Session,
cg_args: &CodegenArgs,
objects: &[PathBuf],
rlibs: &[PathBuf],
outputs: &OutputFilenames,
disambiguated_crate_name_for_dumps: &OsStr,
)
| 516 | /// This is the actual guts of linking: the rest of the link-related functions are just digging through rustc's |
| 517 | /// shenanigans to collect all the object files we need to link. |
| 518 | fn do_link( |
| 519 | sess: &Session, |
| 520 | cg_args: &CodegenArgs, |
| 521 | objects: &[PathBuf], |
| 522 | rlibs: &[PathBuf], |
| 523 | outputs: &OutputFilenames, |
| 524 | disambiguated_crate_name_for_dumps: &OsStr, |
| 525 | ) -> linker::LinkResult { |
| 526 | let load_modules_timer = sess.timer("link_load_modules"); |
| 527 | |
| 528 | let mut modules = Vec::new(); |
| 529 | let mut add_module = |file_name: &OsStr, bytes: &[u8]| { |
| 530 | let module = { |
| 531 | let mut loader = rspirv::dr::Loader::new(); |
| 532 | rspirv::binary::parse_bytes(bytes, &mut loader).unwrap(); |
| 533 | loader.module() |
| 534 | }; |
| 535 | if let Some(dir) = &cg_args.dump_pre_link { |
| 536 | // FIXME(eddyb) is it a good idea to re-`assemble` the `rspirv::dr` |
| 537 | // module, or should this just save the original bytes? |
| 538 | std::fs::write( |
| 539 | dir.join(file_name).with_extension("spv"), |
| 540 | spirv_tools::binary::from_binary(&module.assemble()), |
| 541 | ) |
| 542 | .unwrap(); |
| 543 | } |
| 544 | modules.push(module); |
| 545 | }; |
| 546 | |
| 547 | // `objects` are the plain obj files we need to link - usually produced by the final crate. |
| 548 | for obj in objects { |
| 549 | add_module(obj.file_name().unwrap(), &std::fs::read(obj).unwrap()); |
| 550 | } |
| 551 | |
| 552 | // `rlibs` are archive files we've created in `create_archive`, usually produced by crates that are being |
| 553 | // referenced. We need to unpack them and add the modules inside. |
| 554 | for rlib in rlibs { |
| 555 | let mut archive = Archive::new(File::open(rlib).unwrap()); |
| 556 | while let Some(entry) = archive.next_entry() { |
| 557 | let mut entry = entry.unwrap(); |
| 558 | if entry.header().identifier() != METADATA_FILENAME.as_bytes() { |
| 559 | // std::fs::read adds 1 to the size, so do the same here - see comment: |
| 560 | // https://github.com/rust-lang/rust/blob/72868e017bdade60603a25889e253f556305f996/library/std/src/fs.rs#L200-L202 |
| 561 | let mut bytes = Vec::with_capacity(entry.header().size() as usize + 1); |
| 562 | entry.read_to_end(&mut bytes).unwrap(); |
| 563 | |
| 564 | let file_name = std::str::from_utf8(entry.header().identifier()).unwrap(); |
| 565 | add_module(OsStr::new(file_name), &bytes); |
| 566 | } |
| 567 | } |
| 568 | } |
| 569 | |
| 570 | drop(load_modules_timer); |
| 571 | |
| 572 | // Do the link... |
| 573 | let link_result = linker::link( |
| 574 | sess, |
| 575 | modules, |