Skip to content

stigmee/gdnative-cef

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Chromium Embedded Framework as Godot native module

⚠️ Note: this module is no longer maintained since the main project has been canceled. Better to use https://github.com/Lecrapouille/gdcef and/or search for "gdcef" in the Godot asset lib! ⚠️

This repository contains the Godot native module (GDNative) wrapping Chromium Embedded Framework (CEF), that we have named gdcef for our application Stigmee. The code source of this module is made in C++ and implements some classes wrapping a subset of the CEF API that can be directly usable in Godot scripts (gdscript) but feel free to help us implemented other features.

This module is compiled automatically by our application general script build.py, which works for Linux and for Windows 10 (but not yet for Mac OS) but for people who are less interested by our application, but only desired to use the CEF in Godot, they can jump directly to the section talking about our minimal example in this document.

The goal of this document is to make you understand the general ideas behind how this module gdcef is compiled (with examples for Window while similar for other operating systems). The detail design on how guts are working is described in an other document (currently in gestation). For the details of the implementation, you will have to dive directly inside the CEF code source, it has lot of comments (not always easy to apprehend at first lecture). Else, ask questions either in our Discord, or in the Discussions or Issues menu of the associated GitHub repository to help improving this document.

Environment

The tree structure of the Stigmee project is a little more complex than depicted in the next diagram: it contains folders the Godot editor code, folders for other Godot native modules (Stigmark, IPFS, ...), but only modules concerning CEF will be depicted in this document. The next sections in this document will describe these folders.

📦Stigmee
 ┣ 📂godot-cpp                 ⬅️ Godot C++ API and bindings (cloned)
 ┗ 📂godot-native              ⬅️ Base folder holding native modules (cloned)
   ┗ 📂browser                 ⬅️ Base folder holding native CEF module
     ┣ 📂gdcef                 ⬅️ Code for the CEF module (cloned)
     ┣ 📂subprocess            ⬅️ Code of the CEF sub-process executable (cloned)
     ┗ 📂cef_binary            ⬅️ CEF distribution used to build the dependencies (downloaded)

The Godot C++ binding API (godot-cpp)

The first component, godot-cpp folder, must be present before doing any compilation attempt on a Godot module (CEF, Stigmark, IPFS ...). This folder comes from this repo and contains binding on the Godot API and allows you to compile your module like if you we were compiling it directly inside the code source of the Godot editor (see here for more information).

IMPORTANT: You have to know that contrary than compiling your module directly inside the modules folder of the Godot engine, this method has the drawback, each time that one of your exported functions is called, to call extra intermediate functions imposed by the binding layer. In our case this is fine since CEF fewly triggers the Godot engine. The other point is that methods may have their name a little changed compared to the official API. Last good point for us for this project, is the presence of C++ namespace which fix for us a name conflict on the error enumerators: Godot and CEF using the same error names, the compiler does not know which one to use. Finally, to make use CEF natively inside Godot engine would mean to modify directly the Godot code source, which is more complex than using C++ binding. If you are curious and read French you can check this document detailing how we succeeded.

The godot-cpp repository is cloned when the Stigmee workspace is created thanks one of the following tool tsrc or git-repo and their associated manifest in this repository. The repo tool knows that it has to clone recursively using the appropriate branch (i.e. do not clone the master as you would end up with headers for the 4.0 version) : git clone --recursive -b 3.4 https://github.com/godotengine/godot-cpp. Recursive cloning will include the appropriate godot-headers used to generate the C++ bindings and will produce this kind of message (useless information have been removed for the clarity of this document):

Cloning into 'godot-cpp'...
...
Submodule 'godot-headers' (https://github.com/godotengine/godot-headers) registered for path 'godot-headers'
Cloning into '<Project>\godot-native\godot-cpp/godot-headers'...
...
Submodule path 'godot-headers': checked out 'd1596b939d6c9f5df86655ea617713ef321ad938'

The godot-cpp folder is automatically compiled by the install script build.py which call a command similar to these lines:

cd godot-cpp
scons platform=windows target=release

Where scons is a build system like Makefile but using the Python interpreter and the build script knowing the operating system, if to compile in release or debug mode (and more parameters).

Prebuilt Chromium Embedded Framework (cef_binary)

The second component, cef_binary contains the CEF with prebuilt libraries with the C++ API and some code to compile. These libraries and artifacts are needed to make the Godot application (Stigmee) compilable and working. They are created when this component is compiled (in fact, compiling the CEF's cefsimple example given in the source is enough). Note that building CEF source code 'from scratch' is too complex: too long (around 4 hours with a good Ethernet connection, at worst 1 day with poor Ethernet connection), too huge (around 60 and 100 giga bytes on your disk) and your system shall install plenty of system packages (apt-get).

Since this folder cef_binary cannot be directly git cloned when the Stigmee workspace is created, we have to downloaded, unpacked and renamed from the CEF website https://cef-builds.spotifycdn.com/index.html in an automatic way. This is done by our install script build.py which knows your operating system and the desired CEF version: an inspection inside the CEF's README (if presents) allows to know if CEF has been previously downloaded or if the version is matching (if not, this means we wanted to install a different CEF version: the old cef_binary folder is removed and the new one is downloaded, unpacked and compiled automatically).

To compile CEF, our build script build.py will call something similar to the following lines (but depending on your operating system):

cd ./thirdparty/cef_binary
cmake -DCMAKE_BUILD_TYPE=Release .
cmake --build . --config Release

The following libraries and artifacts shall copied into the Godot project root res:// else Godot will not be able to locate them and will complain about not being able to load the module dependencies at project startup. The destination folder is https://github.com/stigmee/stigmee inside its build folder (to be created). Those files, for Windows, are mandatory to correctly startup CEF. Again, the build.py will do it for you, and for other operating system.

📦Stigmee
 ┗ 📂build
    ┣ 📂locales                      ⬅️ locale-specific resources and strings
    ┃ ┣ 📜en-US.pak                  ⬅️ English
    ┃ ┗ 📜*.pak                      ⬅️ Other countries
    ┣ 📜chrome_elf.dll               ⬅️
    ┣ 📜d3dcompiler_47.dll           ⬅️ Accelerated compositing support libraries
    ┣ 📜libEGL.dll                   ⬅️ Accelerated compositing support libraries
    ┣ 📜libGLESv2.dll                ⬅️ Accelerated compositing support libraries
    ┣ 📜libcef.dll                   ⬅️ main CEF library
    ┣ 📜snapshot_blob.bin            ⬅️ JavaScript V8 initial snapshot
    ┣ 📜v8_context_snapshot.bin      ⬅️ JavaScript V8 initial snapshot
    ┣ 📜icudtl.dat                   ⬅️ Unicode support data
    ┣ 📜chrome_100_percent.pak       ⬅️ Non-localized resources and strings
    ┣ 📜chrome_200_percent.pak       ⬅️ Non-localized resources and strings
    ┗ 📜resources.pak                ⬅️ Non-localized resources and strings

For Windows, actual builds are using dynamic library, and default VS solutions is configured for static compilation. Therefore need to use VS to compile in Release mode, and you (the build script) will change the compiler mode of the Release mode from /MT to /MD, and add the 2 following preprocessor flags:

  • _ITERATOR_DEBUG_LEVEL = 0; under C/C++ >> Preprocessor >> PreprocessorDefinitions.
  • _ALLOW_ITERATOR_DEBUG_LEVEL_MISMATCH under C/C++ >> Preprocessor >> PreprocessorDefinitions.

Our build script build.py will apply a patch before compiling. For Linux it seems not possible to compile in static, as consequence the libcef.so is quite fat: more than 1 gigabytes which is a factor more than the one for Windows (probably because this last knows better that Linux which symbol to export).

IMPORTANT: since CEF is using some thirdpart libraries under the LGPL licence. Compiling them as static libraries will contaminate the project under the GPL licence (which it is not the case when compiled as dynamic libraries). See this post. In our case this fine since our project is already under GPL licence.

CEF secondary process (subprocess)

This executable is needed in order for the CEF to spawn the various CEF sub-processes (GPU process, render handler...). In CEF, a secondary process is needed when the CEF initialization function cannot reach or modify the command line of the application (the int main(int argc, char* argv[])) which it is our case since we do not want to depend on a modified Godot (forked) holding internally a CEF. We gave a try: modifying Godot code source works but this becomes too complex to follow evolution of Godot and CEF (since we are not developing the Godot engine code source). For more information you can read this section.

The detail design on how the both processes talk together is described in this document.

The canonical path of the secondary process shall be known by the primary process (the primary process is explained in the next section). This is our case since this secondary process will live next to the Stigmee executable.

The code source of this secondary process is simply a simple version of the CEF's cefsimple example given in the source is enough. This executable can be directly used as it and you will have a minimal browser application.

📦subprocess
 ┣ 📂src
 ┃ ┣ 📜main.cpp
 ┃ ┗ 📜main.cpp
 ┗ 📜SConstruct

To compile this source :

cd subprocess
scons target=release platform=windows workspace=$WORKSPACE_STIGMEE godot_version=3.4.3-stable -j8

The executable will be created as gdcefSubProcess.exe. It should be placed into the appropriate our godot project https://github.com/stigmee/stigmee inside its build folder (to be created). Again the build.py will do it for you.

📦Stigmee
 ┗ 📂build
    ┣ 📜 ...                         ⬅️ CEF libs and artifacts (see previously)
    ┣ 📦Stigmee                      ⬅️ Stigmee executable
    ┗ 📦gdcefSubProcess              ⬅️ CEF secondary process

CEF native module (gdcef)

This directory contains the source of the gdcef library, allowing to generate the libgdcef.dll module. This dll file can then be loaded by the GDNative module (see Module configuration). The detail design is described in this document.

📦gdcef
 ┣ 📂src
 ┃ ┣ 📜gdcef.cpp
 ┃ ┣ 📜gdcef.hpp
 ┃ ┣ 📜gdbrowser.cpp
 ┃ ┣ 📜gdbrowser.hpp
 ┃ ┣ 📜gdlibrary.cpp
 ┃ ┗ 📜...
 ┗ 📜SConstruct

To compile this source :

cd gdcef
scons target=release platform=windows -j8 workspace=$WORKSPACE_STIGMEE godot_version=3.4.3-stable -j8

The library libgdcef.dll will be generated into the build directory. It should be placed into the appropriate our godot project https://github.com/stigmee/stigmee inside its build folder (to be created). Again the build.py will do it for you.

📦Stigmee
 ┗ 📂build
    ┣ 📜 ...                         ⬅️ CEF libs and artifacts (see previously)
    ┣ 📦Stigmee                      ⬅️ Stigmee executable
    ┣ 📦gdcefSubProcess              ⬅️ CEF secondary process
    ┗ 📜libgdcef.dll                 ⬅️ Our CEF native module library for Godot

Godot module configuration

In order for native modules to be used by Godot, you have to create the following 2 files under the the Godot project root res:// (for example in our case in the folder libs) else Godot will not be able to locate them and will complain about not being able to load the module dependencies at project startup.

📦Stigmee                            ⬅️ Godot res://
 ┣ 📜project.godot                   ⬅️ Your Godot project (here Stigmee)
 ┣ 📂libs
 ┃ ┣ 📜gdcef.gdns                    ⬅️ CEF native script for gdcef.gdnlib
 ┃ ┗ 📜gdcef.gdnlib                  ⬅️ CEF native script for ../build/libgdcef.dll
 ┗ 📂build
    ┣ 📜 ...                         ⬅️ CEF libs and artifacts (see previously)
    ┣ 📦Stigmee                      ⬅️ Stigmee executable
    ┣ 📦gdcefSubProcess              ⬅️ CEF secondary process
    ┗ 📜libgdcef.dll                 ⬅️ Our CEF native module library for Godot
  • gdcef.gdns:
[gd_resource type="NativeScript" load_steps=2 format=2]

[ext_resource path="res://libs/gdcef.gdnlib" type="GDNativeLibrary" id=1]

[resource]
resource_name = "gdcef"
class_name = "GDCef"
library = ExtResource( 1 )
script_class_name = "GDCef"

This file holds information of the C++ exported class name GDCef, its name on Godot and refers to the second file gdcef.gdnlib.

  • gdcef.gdnlib:
[general]

singleton=false
load_once=true
symbol_prefix="godot_"
reloadable=false

[entry]

OSX.64="res://build/libgdcef.dylib"
Windows.64="res://build/libgdcef.dll"
X11.64="res://build/libgdcef.so"

[dependencies]

OSX.64=[ "res://build/libcef.dylib" ]
Windows.64=[ "res://build/libcef.dll" ]
X11.64=[ "res://build/libcef.so" ]

This file holds information on how to find your gdnative library and the library it depends on.

To use the native module inside Godot, ensure libraries are correctly loaded into your project (open the lib in the Godot editor, make sure GDCef can be instantiated in GDScript). Then create a Spatial node in the scene graph and attach to it the gdcef.gdns file as NativeScript (in the language selector). If Godot is complaining is probably your node is incompatible. Select the correct node.

CEFnode

The Hello-CEF example

A minimal CEF example is given. We use it to prototype new API. It is automatically compiled by the install build.py script. But if you not want to get all Stigmee workspace to test it, you can call:

./example.py <path to Godot C++ API>

Where <path to Godot C++ API> refers to https://github.com/godotengine/godot-cpp which shall have be compiled before calling this script.