Electron Internals: Building Chromium as a Library
Electron is based on Google's open-source Chromium, a project that is not necessarily designed to be used by other projects. This post introduces how Chromium is built as a library for Electron's use, and how the build system has evolved over the years.
Using CEF
The Chromium Embedded Framework (CEF) is a project that turns Chromium into a library, and provides stable APIs based on Chromium's codebase. Very early versions of Atom editor and NW.js used CEF.
To maintain a stable API, CEF hides all the details of Chromium and wraps Chromium's APIs with its own interface. So when we needed to access underlying Chromium APIs, like integrating Node.js into web pages, the advantages of CEF became blockers.
So in the end both Electron and NW.js switched to using Chromium's APIs directly.
Building as part of Chromium
Even though Chromium does not officially support outside projects, the codebase is modular and it is easy to build a minimal browser based on Chromium. The core module providing the browser interface is called Content Module.
To develop a project with Content Module, the easiest way is to build the project as part of Chromium. This can be done by first checking out Chromium's source code, and then adding the project to Chromium's DEPS
file.
NW.js and very early versions of Electron are using this way for building.
The downside is, Chromium is a very large codebase and requires very powerful machines to build. For normal laptops, that can take more than 5 hours. So this greatly impacts the number of developers that can contribute to the project, and it also makes development slower.
Building Chromium as a single shared library
As a user of Content Module, Electron does not need to modify Chromium's code under most cases, so an obvious way to improve the building of Electron is to build Chromium as a shared library, and then link with it in Electron. In this way developers no longer need to build all off Chromium when contributing to Electron.
Проект libchromiumcontent был создан @aroben для этой цели. It builds the Content Module of Chromium as a shared library, and then provides Chromium's headers and prebuilt binaries for download. Он строит модуль содержимого Chromium в качестве общей библиотеки, а затем предоставляет заголовки Chromium и готовые бинарные файлы для скачивания.
Проект brightray также родил ся как часть libchromiumсодержания, который обеспечивает тонкий слой вокруг Content Module.
By using libchromiumcontent and brightray together, developers can quickly build a browser without getting into the details of building Chromium. And it removes the requirement of a fast network and powerful machine for building the project.
Apart from Electron, there were also other Chromium-based projects built in this way, like the Breach browser.
Filtering exported symbols
On Windows there is a limitation of how many symbols one shared library can export. As the codebase of Chromium grew, the number of symbols exported in libchromiumcontent soon exceeded the limitation.
The solution was to filter out unneeded symbols when generating the DLL file. It worked by providing a .def
file to the linker, and then using a script to judge whether symbols under a namespace should be exported.
By taking this approach, though Chromium kept adding new exported symbols, libchromiumcontent could still generate shared library files by stripping more symbols.