当前位置: 首页 > article >正文

搭建gn环境踩坑存档

流程

1. 项目根目录下新增.gclient和.gclient_entries

//.gclient
solutions = [
  {
    "name": "src",
    "url": "",
    "managed": False,
    "custom_deps": {},
    "custom_vars": {},
  },
]

// .gclient_entries
entries = {
  'src': '',
}

gclient是一个多仓管理工具,可以把多个仓库的源码clone到本地的一个项目中,具体可以看2. chromium开发工具--gclient - Bigben - 博客园

2. 新建并进入src目录

3. 新建示例代码hello_world.cc

#include <iostream>
using namespace std;

int main()
{
    cout<< "hello world" << endl;
    while(1) {} // 为了让窗口不要自动关闭,好看到输出结果
    return 0;
}

4 新建.gn,该文件指出了gn的配置文件路径,以及使用哪个python解释器。

buildconfig = "//build/config/BUILDCONFIG.gn"

# The python interpreter to use by default. On Windows, this will look
# for python3.exe and python3.bat.
script_executable = "python3"

5. 新建BULD.gn,这个文件指出我们该如何形成可执行文件

executable("hello_world") {
    sources = [
        "hello-world.cc",
    ]
}

6. 新建build/config/BUILDCONFIG.gn,把chromuim源码下对应文件粘过来,因为我只想研究一下核心流程,不考虑兼容性,所以我把default_compiler_configs及以后的代码全删了,不然要复制太多文件了。

7. 运行gn gen out/default,out/后文件名可以任意,但是out/这个前缀不能修改。

8. 报错gn.py: Could not find checkout in any parent of the current path。原因是src目录下缺少buildtools,把chromium/src/buildtools复制到<your project>/src/buildtools即可。

9. 接下来会报一堆缺少文件的错误,这些文件分别在src/build、src/build_overrides、src/buildtools、src/tools四个目录下,你可以试着把这几个文件夹一次性从chromium项目下拷贝过来,我当时只拷了build文件夹所以报错了,而且没报具体错误原因所以没法排查,最后是缺哪个文件拷哪个文件一点点拷完了,rust相关代码我不想复制了,所以引用到的地方我就全删了。

10. gn gen out/default后,运行

autoninja -C out/default

这时候会报错depot_tools/ninja.py: Could not find Ninja in the third_party of the current project, nor in your PATH,原因就是ninja.exe既不在当前项目下,也不在环境变量里。

解决方案:在src目录下新建third_party,把chromium项目中的third_party/ninja复制过去。

11. 再次运行autoninja -C out/default,报错The system cannot find the file specified.

把chromium项目third_party目录下llvm-build\Release+Asserts\bin\clang-cl.exe复制过来,再次运行命令就可以成功了。

12. 双击out/default/hello_world.exe,显示

证明构建成功了。

问题汇总

问题一:gn.py: Could not find checkout in any parent of the current path.

核心原因:缺少buildtools。

解决方案:把chromium/src/buildtools复制到<your project>/src/buildtools,进入src目录后执行命令

gn gen out/default

.gclient和.gclient_entries文件最好也加上,虽然gclient_paths.py脚本中做了兼容,如果命令行所在目录下存在buildtools,就返回当前目录作为入口,但这毕竟不是一种规范的做法。

问题二:could not execute interpreter

根目录下的.gn文件需要设置script_executable,否则gn会直接执行py文件,windows环境下会在环境变量path中寻找python.exe和python.bat,没找到就会报错。

# The python interpreter to use by default. On Windows, this will look
# for python3.exe and python3.bat.
script_executable = "python3"

具体逻辑看gn源码src\gn\setup.cc

大致就是先查当前目录下是否存在python3.exe,存在就返回绝对路径。

否则查找环境变量path下是否存在python3.exe,和python3.bat;如果存在python3.exe,返回对应绝对路径,存在python3.bat,就通过该文件找到对应的python3.exe,返回exe的绝对路径。

否则返回空路径。

// python_exe_name and python_bat_name can be empty but cannot be absolute
// paths. They should be "python.exe" or "", etc., and "python.bat" or "", etc.
base::FilePath FindWindowsPython(const base::FilePath& python_exe_name,
                                 const base::FilePath& python_bat_name) {
  char16_t current_directory[MAX_PATH];
  ::GetCurrentDirectory(MAX_PATH, reinterpret_cast<LPWSTR>(current_directory));

  // First search for python.exe in the current directory.
  if (!python_exe_name.empty()) {
    CHECK(python_exe_name.FinalExtension() == u".exe");
    CHECK_EQ(python_exe_name.IsAbsolute(), false);
    base::FilePath cur_dir_candidate_exe =
        base::FilePath(current_directory).Append(python_exe_name);
    if (base::PathExists(cur_dir_candidate_exe))
      return cur_dir_candidate_exe;
  }

  // Get the path.
  const char16_t kPathEnvVarName[] = u"Path";
  DWORD path_length = ::GetEnvironmentVariable(
      reinterpret_cast<LPCWSTR>(kPathEnvVarName), nullptr, 0);
  if (path_length == 0)
    return base::FilePath();
  std::unique_ptr<char16_t[]> full_path(new char16_t[path_length]);
  DWORD actual_path_length = ::GetEnvironmentVariable(
      reinterpret_cast<LPCWSTR>(kPathEnvVarName),
      reinterpret_cast<LPWSTR>(full_path.get()), path_length);
  CHECK_EQ(path_length, actual_path_length + 1);

  // Search for python.exe in the path.
  for (const auto& component : base::SplitStringPiece(
           std::u16string_view(full_path.get(), path_length), u";",
           base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) {
    if (!python_exe_name.empty()) {
      base::FilePath candidate_exe =
          base::FilePath(component).Append(python_exe_name);
      if (base::PathExists(candidate_exe))
        return candidate_exe;
    }

    // Also allow python.bat, but convert into the .exe.
    if (!python_bat_name.empty()) {
      CHECK(python_bat_name.FinalExtension() == u".bat");
      CHECK_EQ(python_bat_name.IsAbsolute(), false);
      base::FilePath candidate_bat =
          base::FilePath(component).Append(python_bat_name);
      if (base::PathExists(candidate_bat)) {
        base::FilePath python_exe = PythonBatToExe(candidate_bat);
        if (!python_exe.empty())
          return python_exe;
      }
    }
  }
  return base::FilePath();
}

问题三:depot_tools/ninja.py: Could not find Ninja in the third_party of the current project, nor in your PATH

解决方案,要么添加指向ninja.exe的path,要么就在项目里添加third_party/ninja.exe

def main(args):
    # ...

    # Get gclient root + src.
    primary_solution_path = gclient_paths.GetPrimarySolutionPath()
    gclient_root_path = gclient_paths.FindGclientRoot(os.getcwd())
    gclient_src_root_path = None
    if gclient_root_path:
        gclient_src_root_path = os.path.join(gclient_root_path, "src")

    for base_path in set(
        # 这三个目录下只要有一个存在/third_party/ninja.exe就行
        [primary_solution_path, gclient_root_path, gclient_src_root_path]):
        if not base_path:
            continue
        ninja_path = os.path.join(
            base_path,
            "third_party",
            "ninja",
            "ninja" + gclient_paths.GetExeSuffix(),
        )
        if os.path.isfile(ninja_path):
            check_out_dir(args[1:])
            return subprocess.call([ninja_path] + args[1:])

    return fallback(args[1:]) #这个函数会在环境变量中找ninja.exe,还没找到就会打印报错信息了


http://www.kler.cn/a/566037.html

相关文章:

  • wzl-django学习
  • 大模型(DeepSeek),具身智能,VLA(pi0),机器人,全网资料总结。
  • 数据库MySQL,在终端输入后,提示不是内部命令等
  • 深入解析设备树(Device Tree)中的属性(Properties)
  • 【C++】Rusage(一)
  • HTTP~文件 MIME 类型
  • 深圳出版集团通过腾讯云接入DeepSeek,用于智能问答、客户服务、活动策划等场景
  • 使用 Selenium 和 Requests 自动化获取动态 Referer 和 Sign 的完整指南
  • 论文阅读《 FEDERATED RECOMMENDATION WITH ADDITIVE PERSONALIZATION》
  • paddlehub hub TypeError 错误
  • StableDiffusion本地部署 3 整合包猜想
  • TCP/IP 5层协议簇:网络层(ARP协议)
  • HIVE中的分组聚合语句
  • ds-国内主要显卡
  • 告别“node版本冲突”:用nvm实现开发环境无缝切换
  • c++11新特性 chrono库
  • Android 12 AOSP拦截Home键教程
  • 线程(Thread)
  • 学术ppt模板_院士增选_自然科学奖_技术发明奖_科技进步奖_杰青_长江学者特聘教授_校企联聘长江学者_重点研发_优青_青长_青拔ppt制作案例
  • 第P6周:VGG-16-Pytorch实现人脸识别