Change:
Building the mozjs crate for any Windows target stopped working after mozjs has a build script that compiles the C++ library SpiderMonkey into , which is then . Before , these builds worked successfully. Since that PR was merged, CI using nightly and beta toolsets targeting MSVC x8664 and UWP x86_64 now fail to build with the following error: This was first reported in and 2022-12-03 nightly Rust 1.66 beta 2022-12-04 nightly Rust 1.67 beta If you know when this regression occurred, please add a line like below, replacing with one of stable, beta, or nightly. modify labels: +regression-from-stable-to-beta -regression-untriaged
cc
As workaround adding windows to should revert back to the old archive writer. Luckily it was preserved for wasm. Could you post a hex dump of the first 16 or so bytes of the archive to see the magic bytes of this file.
Here is hexdump: Here is GitHub action of working one: and here is GitHub action of defect one: Artifact contains .lib file, that is produced in job.
Yeah, that is indeed very much not a valid archive. It does look like (which is a valid header for thin archives) except with every pair of bytes swapped. Rustc also shouldn't be producing thin archives.
Well hex-editor in vscode shows it right (but is showing reversed bits on same file): !
Do you know if this affects all Windows targets or just MSVC based? I couldn't get it to build at all with :
Ideally we would want to find another case for regression, because mozjs is complicated. Do you have MozillaBuild 3.4 installed as error is in and MozBuild comes packaged with python? I suggest looking at GitHub Workflows to correctly setup for compiling.
No, I had checked first step in the readme but the link is dead:
Well, those instruction would not be relevant anymore as we are still few SM versions behind if they would be available. Following GitHub Workflows is currently the best way.
WG-prioritization assigning priority (). label -I-prioritize +P-high
label: -P-high +P-critical (Upgrading priority because, until we better understand the scope of this bug, it strikes me as something that might motivate a fast-tracked point release for 1.67.)
I wonder if we have another case of this issue in
You linked this issue itself.
Could be
Oh, I completely misunderstood what the issue was. I thought this was about rustc producing a malformed archive, but it is actually about rustc not being able to read thin archives produced by an external build system. Object indeed doesn't support parsing thin archives and even if it did, it would likely need to be wired up in rustc separately. I think the best course of action is to change to always take the branch. This will restore the old behavior for cg_llvm. will probably also need to be reverted partially or as a whole because it removed macOS fat archive reading for the LLVM archive writer. (This would have been so much more painful to revert if I hadn't needed to keep the old LLVM archive writer for wasm.)
And yes is very likely a duplicate of this.
I believe I may be encountering a similar, or related, regression between 1.67 and 1.66 when attempting to build and link against shaderc on MSVC:
I know it's a little late for clarification now, but still. (GitHub Actions) build has the same header as non-working build; and that .lib file is built by SM build scripts not Rust ( dir is SM out directory). The main misunderstanding comes from weird behavior:
Opened to revert back to LlvmArchiveWriter, which would fix this issue for now I think.
label: E-needs-test
(and any such test should probably be beta-backported; see discussion from )
Downgrading to as we've shipped a point release with this fix. Leaving open as we would love a regression test to be .
Untagging as a regression, since this has been fixed on beta + stable + nightly at this point as far as I can tell.

Discussion:
use crate::llvm::archive_ro::{ArchiveRO, Child}; use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport}; use rustc_codegen_ssa::back::archive::{ <del> get_native_object_symbols, ArArchiveBuilder, ArchiveBuildFailure, ArchiveBuilder, ArchiveBuilderBuilder, UnknownArchiveKind, </del> <ins> get_native_object_symbols, try_extract_macho_fat_archive, ArArchiveBuilder, ArchiveBuildFailure, ArchiveBuilder, ArchiveBuilderBuilder, UnknownArchiveKind, </ins> }; use rustc_session::cstore::DllImport;

archive: &Path, skip: Box<dyn FnMut(&str) -> bool + 'static>, ) -> io::Result<()> { <del> let archive_ro = match ArchiveRO::open(archive) { </del> <ins> let mut archive = archive.to_path_buf(); if self.sess.target.llvm_target.contains("-apple-macosx") { if let Some(new_archive) = try_extract_macho_fat_archive(&self.sess, &archive)? { archive = new_archive } } let archive_ro = match ArchiveRO::open(&archive) { </ins> Ok(ar) => ar, Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)), };

return Ok(()); } self.additions.push(Addition::Archive { <del> path: archive.to_path_buf(), </del> <ins> path: archive, </ins> archive: archive_ro, skip: Box::new(skip), });

impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder { fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a> { <del> if sess.target.arch == "wasm32" || sess.target.arch == "wasm64" { </del> <ins> // FIXME use ArArchiveBuilder on most targets again once reading thin archives is // implemented if true || sess.target.arch == "wasm32" || sess.target.arch == "wasm64" { </ins> Box::new(LlvmArchiveBuilder { sess, additions: Vec::new() }) } else { Box::new(ArArchiveBuilder::new(sess, get_llvm_object_symbols))

use std::error::Error; use std::fs::File; <del> use std::io; </del> <ins> use std::io::{self, Write}; </ins> use std::path::{Path, PathBuf}; // Re-exporting for rustc_codegen_llvm::back::archive

} } <del> fn try_filter_fat_archs<'a>( </del> <ins> fn try_filter_fat_archs( </ins> archs: object::read::Result<&[impl FatArch]>, target_arch: object::Architecture, <del> archive_map_data: &'a [u8], ) -> io::Result<Option<(&'a [u8], u64)>> { </del> <ins> archive_path: &Path, archive_map_data: &[u8], ) -> io::Result<Option<PathBuf>> { </ins> let archs = archs.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; let desired = match archs.iter().find(|a| a.architecture() == target_arch) {

None => return Ok(None), }; <del> Ok(Some(( </del> <ins> let (mut new_f, extracted_path) = tempfile::Builder::new() .suffix(archive_path.file_name().unwrap()) .tempfile()? .keep() .unwrap(); new_f.write_all( </ins> desired.data(archive_map_data).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?, <del> desired.offset().into(), ))) </del> <ins> )?; Ok(Some(extracted_path)) </ins> } <del> pub fn try_extract_macho_fat_archive<'a>( </del> <ins> pub fn try_extract_macho_fat_archive( </ins> sess: &Session, <del> archive_bytes: &'a [u8], ) -> io::Result<Option<(&'a [u8], u64)>> { </del> <ins> archive_path: &Path, ) -> io::Result<Option<PathBuf>> { let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? }; </ins> let target_arch = match sess.target.arch.as_ref() { "aarch64" => object::Architecture::Aarch64, "x86_64" => object::Architecture::X86_64, _ => return Ok(None), }; <del> match object::macho::FatHeader::parse(archive_bytes) { </del> <ins> match object::macho::FatHeader::parse(&*archive_map) { </ins> Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC => { <del> let archs = object::macho::FatHeader::parse_arch32(archive_bytes); try_filter_fat_archs(archs, target_arch, archive_bytes) </del> <ins> let archs = object::macho::FatHeader::parse_arch32(&*archive_map); try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map) </ins> } Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC_64 => { <del> let archs = object::macho::FatHeader::parse_arch64(archive_bytes); try_filter_fat_archs(archs, target_arch, archive_bytes) </del> <ins> let archs = object::macho::FatHeader::parse_arch64(&*archive_map); try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map) </ins> } // Not a FatHeader at all, just return None. _ => Ok(None),

archive_path: &Path, mut skip: Box<dyn FnMut(&str) -> bool + 'static>, ) -> io::Result<()> { <del> let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? }; </del> <ins> let mut archive_path = archive_path.to_path_buf(); if self.sess.target.llvm_target.contains("-apple-macosx") { if let Some(new_archive_path) = try_extract_macho_fat_archive(&self.sess, &archive_path)? { archive_path = new_archive_path } } </ins> if self.src_archives.iter().any(|archive| archive.0 == archive_path) { return Ok(()); } <del> let (archive_bytes, offset) = if self.sess.target.llvm_target.contains("-apple-macosx") { if let Some((sub_archive, archive_offset)) = try_extract_macho_fat_archive(&self.sess, &*archive_map)? { (sub_archive, Some(archive_offset)) } else { (&*archive_map, None) } } else { (&*archive_map, None) }; let archive = ArchiveFile::parse(&*archive_bytes) </del> <ins> let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? }; let archive = ArchiveFile::parse(&*archive_map) </ins> .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?; let archive_index = self.src_archives.len();

let file_name = String::from_utf8(entry.name().to_vec()) .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?; if !skip(&file_name) { <del> let mut range = entry.file_range(); if let Some(offset) = offset { range.0 += offset; } </del> self.entries.push(( file_name.into_bytes(), <del> ArchiveEntry::FromArchive { archive_index, file_range: range }, </del> <ins> ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() }, </ins> )); } }