Cross‑Platform CEF Integration: Windows & macOS Setup Guide
This article explains how to integrate the Chromium Embedded Framework (CEF) on both Windows and macOS, covering required libraries, resource paths, main‑process initialization, render‑process creation, message‑loop handling, window adaptation, and version management to ensure a seamless cross‑platform deployment.
Background
CEF is a cross‑platform framework based on the Chrome engine, used to display web‑related pages such as chat windows, history messages, and plugin pages. The guide describes adapting CEF from Windows‑only to a macOS version, summarizing practical usage methods to avoid future pitfalls.
1. Libraries and Resource Files
The essential library files include several folders and resource files that must be packaged with the installer.
Key directories (Windows / macOS):
include : Header files exposed by CEF.
libcef_dll : Wrapper library source files.
Resources : CEF’s .pak files.
libcef.dll / Chromium Embedded Framework.framework : Core CEF library.
Other DLLs/dylibs (e.g., libEGL.dll, libEGL.dylib) and binary files (e.g., natives_blob.bin) required by CEF.
These files can be combined into a static library (typically libcef_dll_wrapper.lib) for linking in other modules. Upgrading CEF only requires replacing the corresponding files in these folders.
2. File Path Lookup
Resource files must be located via absolute paths set in CefSettings. The relevant settings are:
resources_dir_path (Windows) / framework_dir_path/main_bundle_path (macOS) – path to the Resources folder.
locales_dir_path – path to the locales folder (same on both platforms).
browser_subprocess_path – path to the subprocess executable (identical on both platforms).
Absolute paths are mandatory; relative paths (e.g., ../../../) will cause initialization failures.
3. Main‑Process Initialization
The main process initialization involves several steps:
Load the CEF dynamic library – on Windows, place libcef.dll alongside the executable; on macOS, use CefScopedLibraryLoader with library_loader.LoadInMain() or cef_load_library for a specific path.
Obtain launch arguments using CefMainArgs and CefCommandLine.
// Windows example
HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);
CefMainArgs main_args(hInstance);
CefRefPtr<CefCommandLine> command_line = CefCommandLine::CreateCommandLine();
command_line->InitFromString(::GetCommandLineW()); // macOS example
CefMainArgs main_args(argc, argv);
CefRefPtr<CefCommandLine> command_line = CefCommandLine::CreateCommandLine();
command_line->InitFromArgv(argc, argv);Set additional parameters such as settings.log_severity, settings.log_file, settings.user_agent, and settings.remote_debugging_port.
Initialize CEF with CefInitialize(main_args, settings, app.get(), sandbox_info). A successful return allows subsequent steps; failure aborts the process.
4. Render‑Process Generation
The render process can be merged with the main process or run separately. For complex projects, a dedicated render process (or multiple sub‑processes) is recommended.
Key points:
Define a subprocess path (standard location or custom directory).
On Windows, the library can be loaded automatically if placed beside the executable; otherwise, load it explicitly.
On macOS, use
CefScopedLibraryLoader library_loader; library_loader.LoadInHelper();or cef_load_library with an absolute path.
Start the subprocess with CefExecuteProcess(main_args, app, nullptr). A return value > 0 indicates successful launch; < 0 means failure, though the main process can still run.
5. Message Loop
Different platforms require different message‑loop strategies:
Windows : Enable multi_threaded_message_loop = true to run a separate CEF message loop alongside the application’s UI loop.
macOS : Two options – (a) let CEF take over the main loop via CefRunMessageLoop(), or (b) embed CEF’s loop into an existing Qt loop using time‑slice processing with CefDoMessageLoopWork().
6. Window Adaptation
When displaying web pages, window size adjustments are required. Platform‑specific APIs are used:
Get window ID : (CefWindowHandle) this->winId() on both Windows and macOS.
Resize window : Windows –
::MoveWindow(hwnd, rect.x(), rect.y(), rect.width(), rect.height(), true); macOS –
[nsview setFrameSize:NSMakeSize(rect.width(), rect.height())].
Obtain window handle : browser->GetHost()->GetWindowHandle() (macOS also provides GetOpenerWindowHandle() for non‑pop windows).
7. Version Differentiation
Use macro definitions to distinguish operating systems ( Q_OS_WIN, Q_OS_MAC) and CEF versions ( CEF_VERSION_MAJOR, CEF_VERSION_MINOR, CEF_VERSION_PATCH, CEF_COMMIT_NUMBER). Major version differences may require conditional handling of API changes.
Conclusion
By sharing the same set of CEF files across Windows and macOS and using Qt macros for platform checks, the same source code can run on both systems and support multiple CEF versions, simplifying maintenance and upgrades. Future work can modularize additional features to further reduce development friction.
JD Tech Talk
Official JD Tech public account delivering best practices and technology innovation.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
