研究一个超级开源工程是一件极其有挑战的事情,把自己研究的过程文档化记录,也是一种能力的锻炼,希望同时也能帮到需要的人。此文档记录本人学习和研究firefox的过程,鉴于能力有限,其中必定存在错误和疏漏,欢迎指正。

编译

参考文档
https://developer.mozilla.org/en-US/docs/Mozilla/Building_Mozilla
https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Source_Code/Mercurial/Bundles
https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Build_Instructions/Configuring_Build_Options
1.安装VS,具体需求可参考文档,设置需要安装的版本,组件等。
2.安装mozbuild,根据文档下载并安装。
3.下载源码,可以直接hg clone代码库,网络不行的话参考文档可以下载bundle,然后unbundle即可。
4.执行mach bootstrap,该命令会下载编译依赖的工具到目录~/.mozbuild目录中。
5.根据文档写下编译的配置,这里主要是禁用优化,启用调试的设置,配置文件名为mozconfig,放在源码根目录里面。

mk_add_options MOZ_MAKE_FLAGS="-j4"
ac_add_options --disable-optimize --enable-debug
mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-firefox
ac_add_options --enable-application=browser

6.执行mach build编译,生成的可执行文件在编译根目录的dist\bin子目录中。

调试

参考文档
https://developer.mozilla.org/en-US/docs/Mozilla/Debugging/Debugging_on_Windows
如果可以直接用VS调试的话,跟着调试器去理解代码会更容易读懂。编译完成后会自动生成VS的解决方案和相关的工程,在编译目标的子目录msvc中的mozilla.sln,直接双击就可以打开。由于firefox采用了多进程,调试起来比较麻烦,所以进行如下设置,地址栏输入about:config,搜索browser.tabs.remote.autostart,双击置为false。重新打开浏览器,在任务管理器查看,可以发现只有两个firefox进程。下面小试牛刀,将firefox.exe工程设置为启动项目,打开xpcom_threads工程里面的nsThread.cpp文件,找到nsresult nsThread::Init(const nsACString& aName),在该函数里面加上一行打印线程名字的代码printf(“ThreadName:%s\n”, aName.Data());,然后点击生成解决方案,经过漫长的等待,终于链接成功,点击运行可以看到自己加的打印在控制台输出了。 依然有些问题,在VS里面点击全部中断后发现只有一个线程,但是在控制台窗口里面可以看见打印出的几十个线程的名字,这说明目前调试的进程并不是我期望调试的那个进程。根据堆栈可以找到程序的入口wmain函数,查看代码发现是按下面执行的:

#if defined(mozilla_LauncherProcessWin_h)
  mozilla::Maybe<int> launcherResult =
      mozilla::LauncherMain(argc, argv, sAppData);
  if (launcherResult) {
    return launcherResult.value();
  }
#endif  // defined(mozilla_LauncherProcessWin_h)

在前面增加一行#undef mozilla_LauncherProcessWin_h,再编译,启动调试,点击全部中断,这时候可以看见好多线程,至此开发环境算是最终整好了。

所学知识

1.入口函数wmain,即使写了很多年程序,我一直以为入口函数只有main和WinMain,原来还有一个wmain。
2.构造函数相关default和delete,可以设置编译器生不生成默认的函数,enum class用来定义枚举,这些都是属于C++11的知识。
3.线程和网络相关的底层调用函数在工程nspr4里面的w95thred.c和w95sock.c。

遗留问题

1.mozilla_LauncherProcessWin_h定义启动的进程到底是干什么的?
2.运行firefox.exe,打开任务管理器,查看进程Nightly-APPVERSION,显示有两个,一个是firefox.exe,另一个是C:\Windows\System32\conhost.exe,这是为什么?原以为应该是单进程程序呢。