Ungoogled Chromium127编译指南 Windows篇 - Rust标准库查找问题修复(十一)

1. 引言

在修复Python路径问题后,我们遇到的下一个技术挑战是Rust标准库的查找问题。在编译过程中,find_std_rlibs.py脚本无法正确处理Windows环境下的Rust工具链路径,导致编译失败。本文将详细介绍如何解决这个问题。

2. 问题分析

2.1 错误表现

编译过程中会遇到如下错误:

复制代码
ninja: Entering directory `out\Default'
[19/62261] ACTION //build/rust/std:find_stdlib(//build/toolchain/win:win_clang_x64)
FAILED: obj/build/rust/std/libstd.rlib obj/build/rust/std/liballoc.rlib obj/build/rust/std/libcfg_if.rlib obj/build/rust/std/libcompiler_builtins.rlib obj/build/rust/std/libcore.rlib obj/build/rust/std/libgetopts.rlib obj/build/rust/std/libhashbrown.rlib obj/build/rust/std/liblibc.rlib obj/build/rust/std/libpanic_abort.rlib obj/build/rust/std/libpanic_unwind.rlib obj/build/rust/std/librustc_demangle.rlib obj/build/rust/std/libstd_detect.rlib obj/build/rust/std/libtest.rlib obj/build/rust/std/libunicode_width.rlib obj/build/rust/std/libunwind.rlib obj/build/rust/std/libprofiler_builtins.rlib obj/build/rust/std/librustc_std_workspace_alloc.rlib obj/build/rust/std/librustc_std_workspace_core.rlib obj/build/rust/std/librustc_std_workspace_std.rlib
C:/Users/ym/AppData/Local/Programs/Python/Python310/python.exe ../../build/rust/std/find_std_rlibs.py --rust-bin-dir ../../third_party/rust-toolchain/bin --output obj/build/rust/std --depfile obj/build/rust/std/stdlib.d --depfile-target std --rustc-revision "rustc 1.80.0-nightly (faefc618c 2024-05-07)" --target x86_64-pc-windows-msvc
Traceback (most recent call last):
  File "C:\ungoogled-chromium-windows\build\src\build\rust\std\find_std_rlibs.py", line 132, in <module>
    sys.exit(main())
  File "C:\ungoogled-chromium-windows\build\src\build\rust\std\find_std_rlibs.py", line 53, in main
    rustlib_dir = subprocess.check_output(rustc_args).rstrip().decode()
  File "C:\Users\ym\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 420, in check_output
    return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
  File "C:\Users\ym\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 501, in run
    with Popen(*popenargs, **kwargs) as process:
  File "C:\Users\ym\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 966, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "C:\Users\ym\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 1435, in _execute_child
    hp, ht, pid, tid = _winapi.CreateProcess(executable, args,
OSError: [WinError 193] %1 is not a valid Win32 application
[24/62261] CXX obj/base/third_party/double_conversion/double_conversion/bignum.obj
ninja: build stopped: subcommand failed.

C:\ungoogled-chromium-windows\build\src>exit
Traceback (most recent call last):
  File "C:\ungoogled-chromium-windows\build.py", line 325, in <module>
    main()
  File "C:\ungoogled-chromium-windows\build.py", line 321, in main
    _run_build_process('third_party\\ninja\\ninja.exe', '-C', 'out\\Default', 'chrome',
  File "C:\ungoogled-chromium-windows\build.py", line 67, in _run_build_process
    subprocess.run(('cmd.exe', '/k'),
  File "C:\Users\ym\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 524, in run
    raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '('cmd.exe', '/k')' returned non-zero exit status 1.

2.2 错误原因

  • find_std_rlibs.py脚本未正确处理Windows可执行文件后缀
  • rustc命令调用缺少.exe后缀
  • 工具链路径解析不适配Windows环境

3. 修复方案

3.1 修改find_std_rlibs.py

打开build/rust/std/find_std_rlibs.py文件,定位到rustc命令构造部分:

修改前:

复制代码
rustc = os.path.join(args.rust_bin_dir, "rustc")

修改后:

复制代码
rustc = os.path.join(args.rust_bin_dir, "rustc.exe")

3.2 完整脚本

复制代码
#!/usr/bin/env/python3

# Copyright 2021 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# See BUILD.gn in this directory for an explanation of what this script is for.

import argparse
import os
import stat
import sys
import shutil
import subprocess
import re

from collections import defaultdict

EXPECTED_STDLIB_INPUT_REGEX = re.compile(r"([0-9a-z_]+)(?:-([0-9]+))?$")
RLIB_NAME_REGEX = re.compile(r"lib([0-9a-z_]+)-([0-9a-f]+)\.rlib$")


def main():
  parser = argparse.ArgumentParser("find_std_rlibs.py")
  parser.add_argument("--rust-bin-dir",
                      help="Path to Rust binaries",
                      required=True),
  parser.add_argument("--target", help="Rust target triple", required=False),
  parser.add_argument("--output",
                      help="Path to rlibs without suffixes",
                      required=True)
  parser.add_argument("--depfile", help="Path to write depfile", required=True)
  parser.add_argument("--depfile-target",
                      help="Target to key depfile around",
                      required=True)
  parser.add_argument("--extra-libs",
                      help="List of extra non-libstd sysroot libraries")
  parser.add_argument("--rustc-revision",
                      help="Not used, just passed from GN to add a dependency"
                      " on the rustc version.")
  args = parser.parse_args()

  extra_libs = set()
  if args.extra_libs:
    for lib in args.extra_libs.split(','):
      extra_libs.add(lib)

  # Ask rustc where to find the stdlib for this target.
  rustc = os.path.join(args.rust_bin_dir, "rustc.exe")
  rustc_args = [rustc, "--print", "target-libdir"]
  if args.target:
    rustc_args.extend(["--target", args.target])
  rustlib_dir = subprocess.check_output(rustc_args).rstrip().decode()

  # Copy the rlibs to a predictable location. Whilst we're doing so,
  # also write a .d file so that ninja knows it doesn't need to do this
  # again unless the source rlibs change.
  # Format:
  # <output path to>/lib<lib name.rlib>: <path to each Rust stlib rlib>
  with open(args.depfile, 'w') as depfile:
    # Ninja isn't versatile at understanding depfiles. We have to say that a
    # single output depends on all the inputs. We choose any one of the
    # output rlibs for that purpose. If any of the input rlibs change, ninja
    # will run this script again and we'll copy them all afresh.
    depfile.write(
        "%s:" % (os.path.join(args.output, "lib%s.rlib" % args.depfile_target)))

    def copy_file(infile, outfile):
      depfile.write(f" {infile}")
      if (not os.path.exists(outfile)
          or os.stat(infile).st_mtime != os.stat(outfile).st_mtime):
        if os.path.exists(outfile):
          st = os.stat(outfile)
          os.chmod(outfile, st.st_mode | stat.S_IWUSR)
        shutil.copy(infile, outfile)

    # Each rlib is named "lib<crate_name>-<metadata>.rlib". The metadata
    # disambiguates multiple crates of the same name. We want to throw away the
    # metadata and use stable names. To do so, we replace the metadata bit with
    # a simple number 1, 2, etc. It doesn't matter how we assign these numbers
    # as long as it's consistent for a particular set of rlibs.

    # The rlib names present in the Rust distribution, including metadata. We
    # sort this list so crates of the same name are ordered by metadata. Also
    # filter out names that aren't rlibs.
    rlibs_present = [
        name for name in os.listdir(rustlib_dir) if name.endswith('.rlib')
    ]
    rlibs_present.sort()

    # Keep a count of the instances a crate name, so we can disambiguate the
    # rlibs with an incrementing number at the end.
    rlibs_seen = defaultdict(lambda: 0)

    for f in rlibs_present:
      # As standard Rust includes a hash on the end of each filename
      # representing certain metadata, to ensure that clients will link
      # against the correct version. As gn will be manually passing
      # the correct file path to our linker invocations, we don't need
      # that, and it would prevent us having the predictable filenames
      # which we need for statically computable gn dependency rules.
      (crate_name, metadata) = RLIB_NAME_REGEX.match(f).group(1, 2)

      # Use the number of times we've seen this name to disambiguate the output
      # filenames. Since we sort the input filenames including the metadata,
      # this will be the same every time.
      #
      # Only append the times seen if it is greater than 1. This allows the
      # BUILD.gn file to avoid adding '-1' to every name if there's only one
      # version of a particular one.
      rlibs_seen[crate_name] += 1
      if rlibs_seen[crate_name] == 1:
        concise_name = crate_name
      else:
        concise_name = "%s-%d" % (crate_name, rlibs_seen[crate_name])

      output_filename = f"lib{concise_name}.rlib"

      infile = os.path.join(rustlib_dir, f)
      outfile = os.path.join(args.output, output_filename)
      copy_file(infile, outfile)

    for f in extra_libs:
      infile = os.path.join(rustlib_dir, f)
      outfile = os.path.join(args.output, f)
      copy_file(infile, outfile)

    depfile.write("\n")


if __name__ == '__main__':
  sys.exit(main())

4. 验证修复

4.1 测试修改

修改完成后,运行下面的命令继续进行编译即可

复制代码
python build.py --tarball

4.2 检查输出

  • 确认脚本能正确找到Rust标准库
  • 验证生成的库文件路径
  • 检查权限和访问问题

5. 可能遇到的问题

5.1 路径权限

  • 确保对Rust工具链目录有读取权限
  • 验证输出目录的写入权限
  • 检查临时文件的访问权限

5.2 工具链完整性

  • 验证Rust工具链安装完整
  • 确认所有必要组件存在
  • 检查版本匹配性

6. 结语

通过本文的指导,我们成功解决了Ungoogled Chromium编译过程中的Rust标准库查找问题。这个修复是确保Rust组件正确编译的关键步骤之一。

在下一篇文章《Ungoogled Chromium127编译指南 Windows篇 - Rust编译器包装器修复(十二)》中,我们将继续处理rustc_wrapper.py的相关问题,以完成Rust工具链的完整配置。请确保按本文的步骤正确修复find_std_rlibs的问题,为后续的编译工作创造良好条件。

1. 引言

在修复Python路径问题后,我们遇到的下一个技术挑战是Rust标准库的查找问题。在编译过程中,find_std_rlibs.py脚本无法正确处理Windows环境下的Rust工具链路径,导致编译失败。本文将详细介绍如何解决这个问题。

2. 问题分析

2.1 错误表现

编译过程中会遇到如下错误:

复制代码
ninja: Entering directory `out\Default'
[19/62261] ACTION //build/rust/std:find_stdlib(//build/toolchain/win:win_clang_x64)
FAILED: obj/build/rust/std/libstd.rlib obj/build/rust/std/liballoc.rlib obj/build/rust/std/libcfg_if.rlib obj/build/rust/std/libcompiler_builtins.rlib obj/build/rust/std/libcore.rlib obj/build/rust/std/libgetopts.rlib obj/build/rust/std/libhashbrown.rlib obj/build/rust/std/liblibc.rlib obj/build/rust/std/libpanic_abort.rlib obj/build/rust/std/libpanic_unwind.rlib obj/build/rust/std/librustc_demangle.rlib obj/build/rust/std/libstd_detect.rlib obj/build/rust/std/libtest.rlib obj/build/rust/std/libunicode_width.rlib obj/build/rust/std/libunwind.rlib obj/build/rust/std/libprofiler_builtins.rlib obj/build/rust/std/librustc_std_workspace_alloc.rlib obj/build/rust/std/librustc_std_workspace_core.rlib obj/build/rust/std/librustc_std_workspace_std.rlib
C:/Users/ym/AppData/Local/Programs/Python/Python310/python.exe ../../build/rust/std/find_std_rlibs.py --rust-bin-dir ../../third_party/rust-toolchain/bin --output obj/build/rust/std --depfile obj/build/rust/std/stdlib.d --depfile-target std --rustc-revision "rustc 1.80.0-nightly (faefc618c 2024-05-07)" --target x86_64-pc-windows-msvc
Traceback (most recent call last):
  File "C:\ungoogled-chromium-windows\build\src\build\rust\std\find_std_rlibs.py", line 132, in <module>
    sys.exit(main())
  File "C:\ungoogled-chromium-windows\build\src\build\rust\std\find_std_rlibs.py", line 53, in main
    rustlib_dir = subprocess.check_output(rustc_args).rstrip().decode()
  File "C:\Users\ym\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 420, in check_output
    return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
  File "C:\Users\ym\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 501, in run
    with Popen(*popenargs, **kwargs) as process:
  File "C:\Users\ym\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 966, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "C:\Users\ym\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 1435, in _execute_child
    hp, ht, pid, tid = _winapi.CreateProcess(executable, args,
OSError: [WinError 193] %1 is not a valid Win32 application
[24/62261] CXX obj/base/third_party/double_conversion/double_conversion/bignum.obj
ninja: build stopped: subcommand failed.

C:\ungoogled-chromium-windows\build\src>exit
Traceback (most recent call last):
  File "C:\ungoogled-chromium-windows\build.py", line 325, in <module>
    main()
  File "C:\ungoogled-chromium-windows\build.py", line 321, in main
    _run_build_process('third_party\\ninja\\ninja.exe', '-C', 'out\\Default', 'chrome',
  File "C:\ungoogled-chromium-windows\build.py", line 67, in _run_build_process
    subprocess.run(('cmd.exe', '/k'),
  File "C:\Users\ym\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 524, in run
    raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '('cmd.exe', '/k')' returned non-zero exit status 1.

2.2 错误原因

  • find_std_rlibs.py脚本未正确处理Windows可执行文件后缀
  • rustc命令调用缺少.exe后缀
  • 工具链路径解析不适配Windows环境

3. 修复方案

3.1 修改find_std_rlibs.py

打开build/rust/std/find_std_rlibs.py文件,定位到rustc命令构造部分:

修改前:

复制代码
rustc = os.path.join(args.rust_bin_dir, "rustc")

修改后:

复制代码
rustc = os.path.join(args.rust_bin_dir, "rustc.exe")

3.2 完整脚本

复制代码
#!/usr/bin/env/python3

# Copyright 2021 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# See BUILD.gn in this directory for an explanation of what this script is for.

import argparse
import os
import stat
import sys
import shutil
import subprocess
import re

from collections import defaultdict

EXPECTED_STDLIB_INPUT_REGEX = re.compile(r"([0-9a-z_]+)(?:-([0-9]+))?$")
RLIB_NAME_REGEX = re.compile(r"lib([0-9a-z_]+)-([0-9a-f]+)\.rlib$")


def main():
  parser = argparse.ArgumentParser("find_std_rlibs.py")
  parser.add_argument("--rust-bin-dir",
                      help="Path to Rust binaries",
                      required=True),
  parser.add_argument("--target", help="Rust target triple", required=False),
  parser.add_argument("--output",
                      help="Path to rlibs without suffixes",
                      required=True)
  parser.add_argument("--depfile", help="Path to write depfile", required=True)
  parser.add_argument("--depfile-target",
                      help="Target to key depfile around",
                      required=True)
  parser.add_argument("--extra-libs",
                      help="List of extra non-libstd sysroot libraries")
  parser.add_argument("--rustc-revision",
                      help="Not used, just passed from GN to add a dependency"
                      " on the rustc version.")
  args = parser.parse_args()

  extra_libs = set()
  if args.extra_libs:
    for lib in args.extra_libs.split(','):
      extra_libs.add(lib)

  # Ask rustc where to find the stdlib for this target.
  rustc = os.path.join(args.rust_bin_dir, "rustc.exe")
  rustc_args = [rustc, "--print", "target-libdir"]
  if args.target:
    rustc_args.extend(["--target", args.target])
  rustlib_dir = subprocess.check_output(rustc_args).rstrip().decode()

  # Copy the rlibs to a predictable location. Whilst we're doing so,
  # also write a .d file so that ninja knows it doesn't need to do this
  # again unless the source rlibs change.
  # Format:
  # <output path to>/lib<lib name.rlib>: <path to each Rust stlib rlib>
  with open(args.depfile, 'w') as depfile:
    # Ninja isn't versatile at understanding depfiles. We have to say that a
    # single output depends on all the inputs. We choose any one of the
    # output rlibs for that purpose. If any of the input rlibs change, ninja
    # will run this script again and we'll copy them all afresh.
    depfile.write(
        "%s:" % (os.path.join(args.output, "lib%s.rlib" % args.depfile_target)))

    def copy_file(infile, outfile):
      depfile.write(f" {infile}")
      if (not os.path.exists(outfile)
          or os.stat(infile).st_mtime != os.stat(outfile).st_mtime):
        if os.path.exists(outfile):
          st = os.stat(outfile)
          os.chmod(outfile, st.st_mode | stat.S_IWUSR)
        shutil.copy(infile, outfile)

    # Each rlib is named "lib<crate_name>-<metadata>.rlib". The metadata
    # disambiguates multiple crates of the same name. We want to throw away the
    # metadata and use stable names. To do so, we replace the metadata bit with
    # a simple number 1, 2, etc. It doesn't matter how we assign these numbers
    # as long as it's consistent for a particular set of rlibs.

    # The rlib names present in the Rust distribution, including metadata. We
    # sort this list so crates of the same name are ordered by metadata. Also
    # filter out names that aren't rlibs.
    rlibs_present = [
        name for name in os.listdir(rustlib_dir) if name.endswith('.rlib')
    ]
    rlibs_present.sort()

    # Keep a count of the instances a crate name, so we can disambiguate the
    # rlibs with an incrementing number at the end.
    rlibs_seen = defaultdict(lambda: 0)

    for f in rlibs_present:
      # As standard Rust includes a hash on the end of each filename
      # representing certain metadata, to ensure that clients will link
      # against the correct version. As gn will be manually passing
      # the correct file path to our linker invocations, we don't need
      # that, and it would prevent us having the predictable filenames
      # which we need for statically computable gn dependency rules.
      (crate_name, metadata) = RLIB_NAME_REGEX.match(f).group(1, 2)

      # Use the number of times we've seen this name to disambiguate the output
      # filenames. Since we sort the input filenames including the metadata,
      # this will be the same every time.
      #
      # Only append the times seen if it is greater than 1. This allows the
      # BUILD.gn file to avoid adding '-1' to every name if there's only one
      # version of a particular one.
      rlibs_seen[crate_name] += 1
      if rlibs_seen[crate_name] == 1:
        concise_name = crate_name
      else:
        concise_name = "%s-%d" % (crate_name, rlibs_seen[crate_name])

      output_filename = f"lib{concise_name}.rlib"

      infile = os.path.join(rustlib_dir, f)
      outfile = os.path.join(args.output, output_filename)
      copy_file(infile, outfile)

    for f in extra_libs:
      infile = os.path.join(rustlib_dir, f)
      outfile = os.path.join(args.output, f)
      copy_file(infile, outfile)

    depfile.write("\n")


if __name__ == '__main__':
  sys.exit(main())

4. 验证修复

4.1 测试修改

修改完成后,运行下面的命令继续进行编译即可

复制代码
python build.py --tarball

4.2 检查输出

  • 确认脚本能正确找到Rust标准库
  • 验证生成的库文件路径
  • 检查权限和访问问题

5. 可能遇到的问题

5.1 路径权限

  • 确保对Rust工具链目录有读取权限
  • 验证输出目录的写入权限
  • 检查临时文件的访问权限

5.2 工具链完整性

  • 验证Rust工具链安装完整
  • 确认所有必要组件存在
  • 检查版本匹配性

6. 结语

通过本文的指导,我们成功解决了Ungoogled Chromium编译过程中的Rust标准库查找问题。这个修复是确保Rust组件正确编译的关键步骤之一。

在下一篇文章《Ungoogled Chromium127编译指南 Windows篇 - Rust编译器包装器修复(十二)》中,我们将继续处理rustc_wrapper.py的相关问题,以完成Rust工具链的完整配置。请确保按本文的步骤正确修复find_std_rlibs的问题,为后续的编译工作创造良好条件。

相关推荐
IT小白杨2 天前
2026Shopee多站点运营的浏览器隔离与移动端云手机方案
经验分享·社交电子·webgl·安全架构·指纹浏览器
IT小白杨4 天前
2026年短视频平台风控技术解析:设备指纹体系、行为建模与环境隔离的边界在哪里
chrome·经验分享·架构·音视频·安全架构·指纹浏览器
Ai拆代码的曹操5 天前
Nginx upstream keepalive 连接池中毒排查实录
chrome·nginx·php
IT小白杨5 天前
防关联用指纹浏览器还是虚拟机好?2026年技术架构深度对比与选型决策
chrome·经验分享·microsoft·架构·安全架构·指纹浏览器
不可能掉发7 天前
Env Guard:让浏览器一眼分清生产、测试和开发环境
前端·javascript·chrome·测试工具·html·开源软件·个人开发
小龙飞刀7 天前
Chrome插件自动化测试:单元测试、集成测试
chrome·单元测试·集成测试
IT小白杨8 天前
2026亚马逊多店铺运营的环境隔离架构与合规实践
经验分享·架构·业界资讯·指纹浏览器
东方护航数据恢复(深圳)9 天前
服务器硬盘黄灯/红灯故障排查与处理命令全指南_东方护航数据恢复深圳店
运维·服务器·chrome
赵广陆9 天前
FastAPI零基础完整实战
前端·chrome·fastapi
Nuanyt10 天前
Linux系统的 Shell 常见指令和常见知识点(以bash为主)
linux·运维·chrome·bash