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.

JD Tech Talk
JD Tech Talk
JD Tech Talk
Cross‑Platform CEF Integration: Windows & macOS Setup Guide

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.

图片
图片
Cross‑platformEmbeddingwindowsmacOSCEFQtbrowser engine
JD Tech Talk
Written by

JD Tech Talk

Official JD Tech public account delivering best practices and technology innovation.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.