Skip to content

Commit 1c9a6ce

Browse files
linesightclaude
andcommitted
Add Linux CI workflow and make build.py cross-platform
- Add .github/workflows/ci-linux.yml targeting ubuntu-24.04 - Update src/version/cef_version_linux.h from CEF 66 to CEF 146 - Make tools/build.py cross-platform (cmake flags, artifact paths, CEF runtime detection) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 55a4e3a commit 1c9a6ce

3 files changed

Lines changed: 220 additions & 74 deletions

File tree

.github/workflows/ci-linux.yml

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
name: CI Linux
2+
3+
on:
4+
push:
5+
branches: ["github-actions-ci", "master", "146-linux"]
6+
pull_request:
7+
branches: ["master"]
8+
workflow_dispatch:
9+
inputs:
10+
bypass_cache:
11+
description: "Bypass all caches for a clean run"
12+
type: boolean
13+
default: false
14+
15+
jobs:
16+
compile:
17+
runs-on: ubuntu-24.04
18+
timeout-minutes: 60
19+
strategy:
20+
fail-fast: false
21+
matrix:
22+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
23+
24+
steps:
25+
- name: Checkout
26+
uses: actions/checkout@v4
27+
28+
- name: Set up Python
29+
uses: actions/setup-python@v5
30+
with:
31+
python-version: ${{ matrix.python-version }}
32+
33+
- name: Read CEF version
34+
id: cef-version
35+
run: |
36+
ver=$(grep -oP '(?<=#define CEF_VERSION ")[^"]+' src/version/cef_version_linux.h)
37+
echo "value=$ver" >> $GITHUB_OUTPUT
38+
39+
- name: Cache CEF binaries
40+
uses: actions/cache@v4
41+
if: ${{ inputs.bypass_cache != true }}
42+
with:
43+
path: build/cef_binary_*
44+
key: cef-linux64-${{ steps.cef-version.outputs.value }}
45+
46+
- name: Install system dependencies
47+
run: |
48+
sudo apt-get update -q
49+
sudo apt-get install -y --no-install-recommends \
50+
cmake ninja-build pkg-config \
51+
libgtk2.0-dev libgtk-3-dev \
52+
libglib2.0-dev libx11-dev \
53+
libnss3-dev libatk1.0-dev \
54+
libxcomposite-dev libxdamage-dev libxext-dev \
55+
libxfixes-dev libxrandr-dev libxrender-dev
56+
57+
- name: Install build tools
58+
run: python tools/requirements.py
59+
60+
- name: Download CEF binaries
61+
run: python tools/download_cef.py
62+
63+
- name: Prepare prebuilt CEF
64+
run: python tools/automate.py --prebuilt-cef
65+
66+
- name: Configure CMake
67+
run: cmake -S . -B build/_cmake_build -G Ninja -DCMAKE_BUILD_TYPE=Release
68+
69+
- name: Build
70+
run: cmake --build build/_cmake_build --parallel
71+
72+
- name: Stage build outputs
73+
run: |
74+
mkdir -p build/artifacts
75+
cp build/_cmake_build/cefpython_py*.so build/artifacts/
76+
cp build/_cmake_build/subprocess_build/subprocess build/artifacts/
77+
cef_dir=$(ls -d build/cef*_linux64 2>/dev/null | head -1)
78+
find "$cef_dir/bin" -maxdepth 1 -mindepth 1 \
79+
! -name 'cefclient*' ! -name 'cefsimple*' ! -name 'ceftests*' ! -name 'chrome-sandbox' \
80+
-exec cp -r {} build/artifacts/ \;
81+
82+
- name: Upload build artifacts
83+
uses: actions/upload-artifact@v4
84+
with:
85+
name: build-py${{ matrix.python-version }}-linux64
86+
path: build/artifacts/
87+
retention-days: 1
88+
89+
test:
90+
needs: compile
91+
runs-on: ubuntu-24.04
92+
timeout-minutes: 30
93+
strategy:
94+
fail-fast: false
95+
matrix:
96+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
97+
98+
steps:
99+
- name: Checkout
100+
uses: actions/checkout@v4
101+
102+
- name: Set up Python
103+
uses: actions/setup-python@v5
104+
with:
105+
python-version: ${{ matrix.python-version }}
106+
107+
- name: Install runtime dependencies
108+
run: |
109+
sudo apt-get update -q
110+
sudo apt-get install -y --no-install-recommends \
111+
libnss3 libatk1.0-0 libatk-bridge2.0-0 \
112+
libx11-6 libxcomposite1 libxdamage1 libxext6 \
113+
libxfixes3 libxrandr2 libxrender1 \
114+
libgtk2.0-0 libglib2.0-0 xvfb
115+
116+
- name: Download build artifacts
117+
uses: actions/download-artifact@v4
118+
with:
119+
name: build-py${{ matrix.python-version }}-linux64
120+
path: build/artifacts/
121+
122+
- name: Set up cefpython3 package for testing
123+
run: cp -r build/artifacts/. cefpython3/
124+
125+
- name: Run unit tests
126+
run: xvfb-run python unittests/_test_runner.py
127+
env:
128+
PYTHONPATH: ${{ github.workspace }}
129+
130+
wheel:
131+
needs: test
132+
runs-on: ubuntu-24.04
133+
timeout-minutes: 15
134+
strategy:
135+
fail-fast: false
136+
matrix:
137+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
138+
139+
steps:
140+
- name: Checkout
141+
uses: actions/checkout@v4
142+
143+
- name: Set up Python
144+
uses: actions/setup-python@v5
145+
with:
146+
python-version: ${{ matrix.python-version }}
147+
148+
- name: Download build artifacts
149+
uses: actions/download-artifact@v4
150+
with:
151+
name: build-py${{ matrix.python-version }}-linux64
152+
path: build/artifacts/
153+
154+
- name: Set up cefpython3 package
155+
run: cp -r build/artifacts/. cefpython3/
156+
157+
- name: Build wheel
158+
run: python tools/build_distrib.py
159+
160+
- name: Upload wheel artifact
161+
uses: actions/upload-artifact@v4
162+
with:
163+
name: cefpython3-py${{ matrix.python-version }}-linux64
164+
path: build/dist/*.whl

src/version/cef_version_linux.h

Lines changed: 18 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -35,68 +35,27 @@
3535
#ifndef CEF_INCLUDE_CEF_VERSION_H_
3636
#define CEF_INCLUDE_CEF_VERSION_H_
3737

38-
#define CEF_VERSION "3.3359.1774.gd49d25f"
39-
#define CEF_VERSION_MAJOR 3
40-
#define CEF_COMMIT_NUMBER 1774
41-
#define CEF_COMMIT_HASH "d49d25f881b68f418e243e12801cbbb7caebb563"
42-
#define COPYRIGHT_YEAR 2018
43-
44-
#define CHROME_VERSION_MAJOR 66
38+
#define CEF_VERSION "146.0.11+g3a0fcf1+chromium-146.0.7680.179"
39+
#define CEF_VERSION_MAJOR 146
40+
#define CEF_VERSION_MINOR 0
41+
#define CEF_VERSION_PATCH 11
42+
#define CEF_COMMIT_NUMBER 3505
43+
#define CEF_COMMIT_HASH "3a0fcf1e1b6249b50c96ac77c429bfefade09d96"
44+
#define COPYRIGHT_YEAR 2026
45+
46+
#define CHROME_VERSION_MAJOR 146
4547
#define CHROME_VERSION_MINOR 0
46-
#define CHROME_VERSION_BUILD 3359
47-
#define CHROME_VERSION_PATCH 181
48-
49-
#define DO_MAKE_STRING(p) #p
50-
#define MAKE_STRING(p) DO_MAKE_STRING(p)
51-
52-
#ifndef APSTUDIO_HIDDEN_SYMBOLS
53-
54-
#include "include/internal/cef_export.h"
48+
#define CHROME_VERSION_BUILD 7680
49+
#define CHROME_VERSION_PATCH 179
5550

56-
#ifdef __cplusplus
57-
extern "C" {
58-
#endif
51+
#define CEF_SANDBOX_COMPAT_HASH "06ced0d54abb1a72"
5952

60-
// The API hash is created by analyzing CEF header files for C API type
61-
// definitions. The hash value will change when header files are modified
62-
// in a way that may cause binary incompatibility with other builds. The
63-
// universal hash value will change if any platform is affected whereas the
64-
// platform hash values will change only if that particular platform is
65-
// affected.
66-
#define CEF_API_HASH_UNIVERSAL "84263345b0b1143139aba560e5e5ed16fb6a9628"
67-
#if defined(OS_WIN)
68-
#define CEF_API_HASH_PLATFORM "cf092ef692a2ff18b0fc732b58bde9b8b8655fcc"
69-
#elif defined(OS_MACOSX)
70-
#define CEF_API_HASH_PLATFORM "34f636bde2f02cb43c10061f384af4fc51c26e1f"
71-
#elif defined(OS_LINUX)
72-
#define CEF_API_HASH_PLATFORM "6b57a640612f8d459042917ad2568b1526a70af4"
73-
#endif
53+
// Experimental API hash for Linux (CEF_API_VERSION 999999).
54+
// Used by the cefpython build tools; sourced from cef_api_versions.h.
55+
#define CEF_API_HASH_PLATFORM "95e5118d3fc65ae6c2645b6f381947d38586e669"
56+
#define CEF_API_HASH_UNIVERSAL "95e5118d3fc65ae6c2645b6f381947d38586e669"
7457

75-
// Returns CEF version information for the libcef library. The |entry|
76-
// parameter describes which version component will be returned:
77-
// 0 - CEF_VERSION_MAJOR
78-
// 1 - CEF_COMMIT_NUMBER
79-
// 2 - CHROME_VERSION_MAJOR
80-
// 3 - CHROME_VERSION_MINOR
81-
// 4 - CHROME_VERSION_BUILD
82-
// 5 - CHROME_VERSION_PATCH
83-
///
84-
CEF_EXPORT int cef_version_info(int entry);
85-
86-
///
87-
// Returns CEF API hashes for the libcef library. The returned string is owned
88-
// by the library and should not be freed. The |entry| parameter describes which
89-
// hash value will be returned:
90-
// 0 - CEF_API_HASH_PLATFORM
91-
// 1 - CEF_API_HASH_UNIVERSAL
92-
// 2 - CEF_COMMIT_HASH
93-
///
94-
CEF_EXPORT const char* cef_api_hash(int entry);
95-
96-
#ifdef __cplusplus
97-
}
98-
#endif
99-
100-
#endif // APSTUDIO_HIDDEN_SYMBOLS
58+
#define DO_MAKE_STRING(p) #p
59+
#define MAKE_STRING(p) DO_MAKE_STRING(p)
10160

10261
#endif // CEF_INCLUDE_CEF_VERSION_H_

tools/build.py

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
BUILD_DIR = os.path.join("build", "_cmake_build")
3232
PKG_DIR = "cefpython3"
3333

34+
WINDOWS = sys.platform == "win32"
35+
3436

3537
def run(cmd, **kwargs):
3638
print("[build.py]", " ".join(str(a) for a in cmd))
@@ -45,34 +47,55 @@ def cmake_dev_build(clean=False, profiling=False, line_tracing=False):
4547
shutil.rmtree(BUILD_DIR)
4648
cache = os.path.join(BUILD_DIR, "CMakeCache.txt")
4749
if not os.path.exists(cache):
48-
cmake_args = ["cmake", "-S", ".", "-B", BUILD_DIR, "-A", "x64"]
50+
cmake_args = ["cmake", "-S", ".", "-B", BUILD_DIR]
51+
if WINDOWS:
52+
cmake_args += ["-A", "x64"]
53+
else:
54+
cmake_args += ["-G", "Ninja", "-DCMAKE_BUILD_TYPE=Release"]
4955
if profiling:
5056
cmake_args.append("-DENABLE_PROFILING=ON")
5157
if line_tracing:
5258
cmake_args.append("-DENABLE_LINE_TRACING=ON")
5359
run(cmake_args)
54-
run(["cmake", "--build", BUILD_DIR, "--config", "Release", "--parallel"])
5560

56-
# Copy .pyd to cefpython3/
57-
pyds = glob.glob(os.path.join(BUILD_DIR, "Release", "cefpython_py*.pyd"))
58-
if not pyds:
59-
print("[build.py] ERROR: no .pyd found after build")
61+
build_args = ["cmake", "--build", BUILD_DIR, "--parallel"]
62+
if WINDOWS:
63+
build_args += ["--config", "Release"]
64+
run(build_args)
65+
66+
# Copy extension module to cefpython3/
67+
if WINDOWS:
68+
pattern = os.path.join(BUILD_DIR, "Release", "cefpython_py*.pyd")
69+
else:
70+
pattern = os.path.join(BUILD_DIR, "cefpython_py*.so")
71+
modules = glob.glob(pattern)
72+
if not modules:
73+
print("[build.py] ERROR: no extension module found after build")
6074
sys.exit(1)
61-
for pyd in pyds:
62-
dst = os.path.join(PKG_DIR, os.path.basename(pyd))
63-
shutil.copy2(pyd, dst)
75+
for mod in modules:
76+
dst = os.path.join(PKG_DIR, os.path.basename(mod))
77+
shutil.copy2(mod, dst)
6478
print("[build.py] ->", dst)
6579

66-
# Copy subprocess.exe to cefpython3/
67-
exe = os.path.join(BUILD_DIR, "subprocess_build", "Release", "subprocess.exe")
80+
# Copy subprocess executable to cefpython3/
81+
if WINDOWS:
82+
exe = os.path.join(BUILD_DIR, "subprocess_build", "Release", "subprocess.exe")
83+
else:
84+
exe = os.path.join(BUILD_DIR, "subprocess_build", "subprocess")
6885
if os.path.exists(exe):
69-
dst = os.path.join(PKG_DIR, "subprocess.exe")
86+
dst = os.path.join(PKG_DIR, os.path.basename(exe))
7087
shutil.copy2(exe, dst)
7188
print("[build.py] ->", dst)
7289

73-
# One-time: copy CEF runtime files (DLLs, .pak, locales/) into cefpython3/
74-
if not glob.glob(os.path.join(PKG_DIR, "*.dll")):
75-
cef_dirs = sorted(glob.glob(os.path.join("build", "cef*_win64")))
90+
# One-time: copy CEF runtime files (DLLs/SOs, .pak, locales/) into cefpython3/
91+
if WINDOWS:
92+
already_copied = bool(glob.glob(os.path.join(PKG_DIR, "*.dll")))
93+
cef_glob = os.path.join("build", "cef*_win64")
94+
else:
95+
already_copied = os.path.exists(os.path.join(PKG_DIR, "libcef.so"))
96+
cef_glob = os.path.join("build", "cef*_linux64")
97+
if not already_copied:
98+
cef_dirs = sorted(glob.glob(cef_glob))
7699
if cef_dirs:
77100
cef_bin = os.path.join(cef_dirs[-1], "bin")
78101
print("[build.py] One-time: copying CEF runtime files to", PKG_DIR)

0 commit comments

Comments
 (0)