在macOS上面编译与调试Chromium


编译chromium

系统要求

  1. A mac, intel or M1
  2. Xcode
  3. The macOS SDK. 运行下面的命令来检测是不是已经安装
    ls `xcode-select -p`/Platforms/MacOSX.platform/Developer/SDKs
  4. An APFS-formatted volume (macOS系统的默认文件系统格式)

安装 depot_tools

下载 depot_tools

git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git

将depot_tools添加到环境变量PATH中

export PATH="$PATH:/path/to/depot_tools"

获取chromium源码

新建chromium目录来放置源码, 需要大概100G的空间,如果没有,最后会因为空间不足而失败。

mkdir chromium && cd chromium

拉取源码, 这个取决于你的网络速度,一般要几个小时,所以可以放到晚上拉取, 还有如果失败要重试,使用gclient sync命令

caffeinate fetch chromium

配置build参数

通过GN工具生成.ninja配置文件,通过ninja工具编译

生成build目录

gn gen out/Default

编译Chromium

有5万多个文件需要编译,一般也需要2-3个小时,所以也可以放到晚上编译。

autoninja -C out/Default chrome

运行编译好的Chromium

out/Default/Chromium.app/Contents/MacOS/Chromium

调试Chromium

目前有几种方式来调试Chromium

  1. 添加日志代码,然后通过日志来调试
  2. 使用lldb调试
  3. 使用Xcode调试, 这个xcode占用内存太大,不推荐使用

这次重点介绍使用lldb单步调试Chromium

重新编译Chromium debug版本

  1. 生成Xcode项目

    gn gen out/Debug
  2. 添加debug参数到args.gn, vim out/Debug/args.gn

    is_debug = true
    is_component_build = true
    symbol_level = 2
  3. 重新编译chromium

    autoninja -C out/Debug chrome

调试Chromium

  1. 打开Chromium

    ./out/Debug/Chromium.app/Contents/MacOS/Chromium
  2. 在out/Debug目录打开lldb,如果不在这个目录下面打开会导致符号表找不到,也可以使用下面的命令设置符号表路径 platform settings -w /path/to/chromium/src/out/Debug/

    lldb 
    (lldb) attach ${chrome main process id}
  3. 在主进程的代码位置(chrome/browser/ui/views/tabs/new_tab_button.cc:void NewTabButton::NotifyClick)处打断开,然后就可以开始调试了

    (lldb) breakpoint set -f chrome/browser/ui/views/tabs/new_tab_button.cc --line 203 
    (lldb) c
  4. 打开断点后,回到chromium, 点击新建标签页,就会触发断点,然后就可以开始调试了

    Process 57308 stopped
    * thread #1, name = 'CrBrowserMain', queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
        frame #0: 0x0000000152d7efe8 libchrome_dll.dylib`NewTabButton::NotifyClick(this=0x00007faed48d6000, event=0x00007ff7b6fb35e0) at new_tab_button.cc:203:28
       200 	}
       201
       202 	void NewTabButton::NotifyClick(const ui::Event& event) {
    -> 203 	  ImageButton::NotifyClick(event);
       204 	  views::InkDrop::Get(this)->GetInkDrop()->AnimateToState(
       205 	      views::InkDropState::ACTION_TRIGGERED);
       206 	}
    Target 0: (Chromium) stopped.
    (lldb) n
    Process 57308 stopped
    * thread #1, name = 'CrBrowserMain', queue = 'com.apple.main-thread', stop reason = step over
        frame #0: 0x0000000152d7eff5 libchrome_dll.dylib`NewTabButton::NotifyClick(this=0x00007faed48d6000, event=0x00007ff7b6fb35e0) at new_tab_button.cc:204:3
       201
       202 	void NewTabButton::NotifyClick(const ui::Event& event) {
       203 	  ImageButton::NotifyClick(event);
    -> 204 	  views::InkDrop::Get(this)->GetInkDrop()->AnimateToState(
       205 	      views::InkDropState::ACTION_TRIGGERED);
       206 	}
       207
    Target 0: (Chromium) stopped.
    (lldb) v
    (NewTabButton *) this = 0x00007faed48d6000
    (const ui::Event &) event = 0x00007ff7b6fb35e0 {}
    (lldb) p event
    (const ui::Event) $1 = {
      type_ = ET_MOUSE_RELEASED
      time_stamp_ = {
        base::time_internal::TimeBase<base::TimeTicks> = {
          us_ = (value_ = 1573625617957)
        }
      }
      latency_ = {
        latency_components_ = {
          base::internal::flat_tree<ui::LatencyComponentType, base::internal::GetFirst, std::__Cr::less<void>, std::__Cr::vector<std::__Cr::pair<ui::LatencyComponentType, base::TimeTicks>, std::__Cr::allocator<std::__Cr::pair<ui::LatencyComponentType, base::TimeTicks> > > > = {
            comp_ = {}
            body_ = size=2 {
              [0] = {
                first = INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT
                second ={...}
              }
              [1] = {
                first = INPUT_EVENT_LATENCY_UI_COMPONENT
                second ={...}
              }
            }
          }
        }
        trace_id_ = -1
        ukm_source_id_ = 0
        coalesced_ = false
        began_ = false
        terminated_ = false
        source_event_type_ = MOUSE
        gesture_scroll_id_ = 0
        touch_trace_id_ = 0
      }
      flags_ = 2048
      native_event_ = {
        objc_storage_ = base::apple::OwnedNSEvent::ObjCStorage @ 0x000060000212c2d0 {
          __value_ = 0x000060000212c2d0
        }
      }
      cancelable_ = true
      target_ = {
        wrapped_ptr_ = 0x00007faed48d6000
      }
      phase_ = EP_TARGET
      result_ = ER_UNHANDLED
      source_device_id_ = -1
      properties_ = nullptr {
        __value_ = nullptr
      }
    }

在上面的设计过程,使用了next,print等命令,可以比较清楚看到event里面的所有内容,这样就可以很方便的调试了。

Reference

  1. Checking out and building Chromium for Mac
  2. Debugging Chromium on macOS
  3. debug chromium with lldb under Mac OSX
  4. Chromium源码学习(1)—— 构建,调试

文章作者: Payne Fu
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Payne Fu !
评论