CEF(Chromium Embedded Framework)をソースコードからビルドしてみた

# はじめに

Spotifyでホストされている公式のCEFビルドはmp4に含まれるプロプライエタリな音声コーデックおよび動画コーデックをサポートしておらず、mp4を再生するためにはproprietary codecsオプションつきでソースコードからビルドする必要がある。

https://support.google.com/webdesigner/answer/10043691

Jetson NanoのOBS Studioのブラウザソースでmp4を再生するためにCEFをビルドしてみた。

# 手順

CEFをソースコードからビルドするためにはある程度パワフルなコンピュータ環境が必要。
また、linuxarm64用にビルドする場合、ビルドスクリプトがx86のみに対応しているため、クロスコンパイル環境が必要になる。

## 環境

- CEFビルド環境  
 - SAKURA internet VPC(8 core CPU, 16GB memory, 800GB SSD, x86_64 Ubuntu linux)
- OBS Studioビルド環境  
 - Jetson Nano 2GB

### 1. ビルド用のディレクトリを作成する

```bash
$ mkdir code
$ mkdir code/automate
$ mkdir code/chromium_git
```

### 2. ビルドに必要なアプリケーションパッケージをインストールする

```bash
$ sudo apt install gperf
$ sudo apt install flex
$ sudo apt install bison
$ sudo pip install jinja2
$ sudo apt install g++-aarch64-linux-gnu gcc-aarch64-linux-gnu
$ sudo apt install build-essential gtk2.0 libgtk2.0-dev libgtkglext1-dev
$ sudo apt install curl
```

### 3. ソースコードをダウンロードする

```bash
$ cd code/
$ curl 'https://chromium.googlesource.com/chromium/src/+/master/build/install-build-deps.sh?format=TEXT' | base64 -d > install-build-deps.sh
$ chmod 755 install-build-deps.sh
$ sudo ./install-build-deps.sh --no-chromeos-fonts --arm
```

### 4. depot_toolsをダウンロードして、絶対パスを設定する

```bash
$ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
$ export PATH=/home/ubuntu/code/depot_tools:$PATH
```

### 5. automate-git.pyをダウンロードする

```bash
$ cd automate/
$ wget https://bitbucket.org/chromiumembedded/cef/raw/master/tools/automate/automate-git.py
```

### 6. 環境変数を設定する

```bash
$ export GYP_DEFINES=target_arch=arm64
$ export GN_DEFINES="use_jumbo_build=true is_official_build=true use_sysroot=true use_allocator=none symbol_level=1 enable_nacl=false use_cups=false proprietary_codecs=true ffmpeg_branding=Chrome"
$ export CEF_USE_GN=1
```

### 7. automate-git.pyを実行する

```bash
$ cd ../chromium_git/
$ python ../automate/automate-git.py --download-dir=/home/ubuntu/code/chromium_git --depot-tools-dir=/home/ubuntu/code/depot_tools --arm64-build --no-distrib --no-build --build-target=cefsimple
```

### 8. install-sysroot.pyを実行する

```bash
$ cd chromium/src/
$ ./build/linux/sysroot_scripts/install-sysroot.py --arch=arm64
```

### 9. cef_create_projects.shを実行する

```bash
$ cd cef/
$ ./cef_create_projects.sh
```

### 10. DebugビルドとReleaseビルドを実行する

8時間くらい時間が掛かる。

```bash
$ cd ..
$ ninja -C out/Debug_GN_arm64 cefsimple chrome_sandbox
$ ninja -C out/Release_GN_arm64 cefsimple chrome_sandbox
```

### 11. CEFパッケージを作成する

```bash
$ cd cef/tools/
$ ./make_distrib.sh --ninja-build --arm64-build
```

### 12. パッケージが作成されていることを確認する

```bash
$ cd ../binary_distrib/
$ ls
cef_binary_90.0.0-master.2318+gf7a4c77+chromium-90.0.4430.0_linuxarm64.zip
```

cef_binary_90.0.0-master.2318+gf7a4c77+chromium-90.0.4430.0_linuxarm64.zip
が作成されたCEFビルドパッケージです。

# CEFビルドの変更点

以降はJetson Nanoでの手順です。

https://qiita.com/kitazaki/items/f42a71c25d96fa830551

### 1. CMakeLists.txtのCEFバージョンをソースコードのバージョンに変更する。

```bash:
$ diff CMakeLists.txt CMakeLists.txt_org
24c24
> set(CEF_VERSION "90.0.0-master.2318+gf7a4c77+chromium-90.0.4430.0")
---
< set(CEF_VERSION "87.1.12+g03f9336+chromium-87.0.4280.88")
```

<B>※2021/3/31追記</B>

cefclientのビルドで<gtk/gtk.h>関連のエラーが出る場合

```bash
In file included from /home/jetson/20210330/cef-project/third_party/cef/cef_binary_90.0.0-master.2318+gf7a4c77+chromium-90.0.4430.0_linuxarm64/tests/cefclient/browser/client_handler.h:16:0,
                 from /home/jetson/20210330/cef-project/third_party/cef/cef_binary_90.0.0-master.2318+gf7a4c77+chromium-90.0.4430.0_linuxarm64/tests/cefclient/browser/browser_window.h:11,
                 from /home/jetson/20210330/cef-project/third_party/cef/cef_binary_90.0.0-master.2318+gf7a4c77+chromium-90.0.4430.0_linuxarm64/tests/cefclient/browser/browser_window.cc:5:
/home/jetson/20210330/cef-project/third_party/cef/cef_binary_90.0.0-master.2318+gf7a4c77+chromium-90.0.4430.0_linuxarm64/tests/cefclient/browser/client_types.h:12:10: fatal error: gtk/gtk.h: No such file or directory
 #include <gtk/gtk.h>
          ^~~~~~~~~~~
compilation terminated.
```

gtk-3.0関連パッケージをインストールする。

```bash
$ sudo apt install libgtk-3-0 libgtk-3-dev
```

CMakeLists.txtにインクルードファイルのパスを追加する。

```text:CMakeLists.txt
include_directories(/usr/include/gtk-3.0)
```

### 2. cmake/DownloadCEF.cmakeを変更して、ビルド済CEFパッケージをダウンロードしないように変更する。

ビルド済CEFパッケージをダウンロードして展開する部分を削除(コメントアウト)する。

```bash
$ diff DownloadCEF.cmake DownloadCEF.cmake_org
18a19,47
>   # Download and/or extract the binary distribution if necessary.
>   if(NOT IS_DIRECTORY "${CEF_ROOT}")
>     set(CEF_DOWNLOAD_FILENAME "${CEF_DISTRIBUTION}.tar.bz2")
>     set(CEF_DOWNLOAD_PATH "${CEF_DOWNLOAD_DIR}/${CEF_DOWNLOAD_FILENAME}")
>     if(NOT EXISTS "${CEF_DOWNLOAD_PATH}")
>       set(CEF_DOWNLOAD_URL "https://cef-builds.spotifycdn.com/${CEF_DOWNLOAD_FILENAME}")
>       string(REPLACE "+" "%2B" CEF_DOWNLOAD_URL_ESCAPED ${CEF_DOWNLOAD_URL})
> 
>       # Download the SHA1 hash for the binary distribution.
>       message(STATUS "Downloading ${CEF_DOWNLOAD_PATH}.sha1 from ${CEF_DOWNLOAD_URL_ESCAPED}...")
>       file(DOWNLOAD "${CEF_DOWNLOAD_URL_ESCAPED}.sha1" "${CEF_DOWNLOAD_PATH}.sha1")
>       file(READ "${CEF_DOWNLOAD_PATH}.sha1" CEF_SHA1)
> 
>       # Download the binary distribution and verify the hash.
>       message(STATUS "Downloading ${CEF_DOWNLOAD_PATH}...")
>       file(
>         DOWNLOAD "${CEF_DOWNLOAD_URL_ESCAPED}" "${CEF_DOWNLOAD_PATH}"
>         EXPECTED_HASH SHA1=${CEF_SHA1}
>         SHOW_PROGRESS
>         )
>     endif()
> 
>     # Extract the binary distribution.
>     message(STATUS "Extracting ${CEF_DOWNLOAD_PATH}...")
>     execute_process(
>       COMMAND ${CMAKE_COMMAND} -E tar xzf "${CEF_DOWNLOAD_DIR}/${CEF_DOWNLOAD_FILENAME}"
>       WORKING_DIRECTORY ${CEF_DOWNLOAD_DIR}
>       )
>   endif()
```

### 3. ソースコードからビルドしたCEFパッケージを手動で配置し展開する。

```bash
$ cp cef_binary_90.0.0-master.2318+gf7a4c77+chromium-90.0.4430.0_linuxarm64.zip cef-project/third_party/cef/
$ cd cef-project/third_party/cef/
$ unzip cef_binary_90.0.0-master.2318+gf7a4c77+chromium-90.0.4430.0_linuxarm64.zip
```

以降のビルド手順は同じ。

https://qiita.com/kitazaki/items/f42a71c25d96fa830551

# OBS Studioの変更点

以降はJetson Nanoでの手順です。

https://qiita.com/kitazaki/items/3950c48a68bab1766fb6

OBS Studioのビルド途中で、obs-browser-sourceのビルドでエラーが出ます。

```bash
/home/jetson/20210330/obs-studio/plugins/obs-browser/obs-browser-source.cpp: In lambda function:
/home/jetson/20210330/obs-studio/plugins/obs-browser/obs-browser-source.cpp:184:23: error: ‘CefBrowserSettings {aka class CefStructBase<CefBrowserSettingsTraits>}’ has no member named ‘web_security’
    cefBrowserSettings.web_security = STATE_DISABLED;
                       ^~~~~~~~~~~~
plugins/obs-browser/CMakeFiles/obs-browser.dir/build.make:62: recipe for target 'plugins/obs-browser/CMakeFiles/obs-browser.dir/obs-browser-source.cpp.o' failed
make[2]: *** [plugins/obs-browser/CMakeFiles/obs-browser.dir/obs-browser-source.cpp.o] Error 1
```

理由はCEFの新しいバージョンではcefBrowserSettings.web_securityオプションがサポートされなくなったことが原因とのこと。

https://bitbucket.org/chromiumembedded/cef/issues/3058/remove-cefbrowsersettingsweb_security

解決方法はcefBrowserSettings.web_securityオプションの設定をコメントアウトする。

```c++:obs-browser-source.
# 変更前
	cefBrowserSettings.web_security = STATE_DISABLED;

# 変更後
	// cefBrowserSettings.web_security = STATE_DISABLED;
```

以降のビルド手順は同じ。

https://qiita.com/kitazaki/items/3950c48a68bab1766fb6

### Jetson NanoのOBS Studioで、Browser Sourceからmp4を再生している様子

![Screenshot from 2021-03-30 19-40-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/8afe2b06-ed0a-2e14-2e0c-51dd68460867.png)


## 参考

https://bitbucket.org/chromiumembedded/cef/wiki/MasterBuildQuickStart.md

https://www.magpcss.org/ceforum/viewtopic.php?f=6&t=16963

https://bitbucket.org/chromiumembedded/cef/wiki/BranchesAndBuilding.md#markdown-header-current-release-branches-supported