Skip to content

Commit d0f5396

Browse files
linesightclaude
andcommitted
build: CMake/build-system fixes, de-duplication and cleanups
- Read the CEF version per-platform from src/version/cef_version_*.h. - Select the CEF directory matching the exact CEF_VERSION (top-level CMakeLists, subprocess CMakeLists, and build.py) so a leftover dir for a different CEF version in build/ is never picked up by accident. - De-duplicate compile flags into a cefpython_common_flags INTERFACE library; share a single filter_sources() function for platform source filtering (was duplicated in client_handler and subprocess). - Target Windows 10 (WINVER/_WIN32_WINNT=0x0A00, NTDDI_WIN10_FE) to match upstream CEF; define the triple once in CEFPYTHON_WIN_TARGET_DEFS. - Remove tools/cmake_fix_header.py: include the raw Cython header directly via CEFPYTHON_API_H_FILE="<module>.h"; the C4190 warning is already suppressed by /wd4190 and the renderer subprocess doesn't include it. - Harden except_all_missing() in cmake_prepare_pyx.py to also catch bare nogil/gil signatures (still ignores except*/noexcept). - Restore the license/copyright header in build.py. Addresses review feedback on PR cztomczak#691 (cztomczak/cefpython). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent fec9686 commit d0f5396

8 files changed

Lines changed: 190 additions & 205 deletions

File tree

CMakeLists.txt

Lines changed: 112 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,26 @@
11
cmake_minimum_required(VERSION 3.21)
22

3-
# Read CEF major version from the Windows header (used on all platforms at
4-
# configure time; the per-platform header values are identical for this field).
5-
file(STRINGS "src/version/cef_version_win.h" _ver_line
3+
# Read the CEF major version from the version header for the platform being
4+
# built, so each platform uses its own CEF version (the values may differ
5+
# across platforms). This runs before project() sets WIN32/APPLE/UNIX, and
6+
# builds are always native (no cross-compiling), so select by host platform.
7+
if(CMAKE_HOST_WIN32)
8+
set(_cef_version_header "src/version/cef_version_win.h")
9+
elseif(CMAKE_HOST_APPLE)
10+
set(_cef_version_header "src/version/cef_version_macarm64.h")
11+
else()
12+
set(_cef_version_header "src/version/cef_version_linux.h")
13+
endif()
14+
file(STRINGS "${_cef_version_header}" _ver_line
615
REGEX "^#define CHROME_VERSION_MAJOR ")
716
string(REGEX REPLACE "^#define CHROME_VERSION_MAJOR ([0-9]+).*" "\\1" _chrome_major "${_ver_line}")
17+
# Full CEF version string, e.g. "147.0.10+gd58e84d+chromium-147.0.7727.118".
18+
# Used to select the matching prebuilt CEF directory under build/ so a leftover
19+
# directory from a different CEF version is never picked up by accident.
20+
file(STRINGS "${_cef_version_header}" _cef_version_line
21+
REGEX "^#define CEF_VERSION ")
22+
string(REGEX REPLACE "^#define CEF_VERSION \"([^\"]+)\".*" "\\1" _cef_version "${_cef_version_line}")
23+
message(STATUS "CEF version header: ${_cef_version_header} -> ${_cef_version} (major ${_chrome_major})")
824

925
project(cefpython3 VERSION "${_chrome_major}.0" LANGUAGES CXX)
1026

@@ -46,16 +62,23 @@ if(NOT CEF_ROOT)
4662
set(_cef_glob_pat "${CMAKE_SOURCE_DIR}/build/cef*_linux64")
4763
endif()
4864
file(GLOB _cef_candidates LIST_DIRECTORIES true "${_cef_glob_pat}")
49-
# Prefer the versioned directory over cef_<os> fallback
65+
# Select the directory matching the exact CEF version from the header, so a
66+
# leftover prebuilt dir for a different CEF version in build/ is never picked
67+
# up by accident. string(FIND) is a literal substring search (the version
68+
# contains regex-special chars like '+' and '.', so MATCHES is unsafe here).
5069
foreach(_d IN LISTS _cef_candidates)
5170
if(IS_DIRECTORY "${_d}")
52-
set(CEF_ROOT "${_d}")
53-
break()
71+
string(FIND "${_d}" "${_cef_version}" _ver_match)
72+
if(NOT _ver_match EQUAL -1)
73+
set(CEF_ROOT "${_d}")
74+
break()
75+
endif()
5476
endif()
5577
endforeach()
5678
if(NOT CEF_ROOT)
5779
message(FATAL_ERROR
58-
"CEF_ROOT not set and cannot be auto-detected. "
80+
"CEF_ROOT not set and no prebuilt CEF ${_cef_version} found under "
81+
"build/ (matching ${_cef_glob_pat}). "
5982
"Download and prepare CEF first (python tools/download_cef.py && "
6083
"python tools/automate.py --prebuilt-cef), or pass -DCEF_ROOT=<path>.")
6184
endif()
@@ -122,34 +145,90 @@ add_custom_command(
122145
VERBATIM
123146
)
124147

125-
# ---- Fix Cython API header --------------------------------------------------
126-
# Generates:
127-
# cefpython_pyXX_fixed.h – original .h with #pragma warning(disable:4190)
128-
# cefpython_api_fixed.h – stable single-name wrapper for cefpython_public_api.h
129-
set(CEFPYTHON_H_FIXED "${PYX_STAGE_DIR}/${MODULE_NAME}_fixed.h")
130-
set(CEF_API_FIXED_H "${PYX_STAGE_DIR}/cefpython_api_fixed.h")
131-
132-
add_custom_command(
133-
OUTPUT "${CEFPYTHON_H_FIXED}" "${CEF_API_FIXED_H}"
134-
COMMAND "${Python_EXECUTABLE}"
135-
"${CMAKE_SOURCE_DIR}/tools/cmake_fix_header.py"
136-
"${CEFPYTHON_H}"
137-
"${CEFPYTHON_H_FIXED}"
138-
"${CEF_API_FIXED_H}"
139-
"${MODULE_NAME}"
140-
DEPENDS "${CEFPYTHON_H}" "${CMAKE_SOURCE_DIR}/tools/cmake_fix_header.py"
141-
COMMENT "Generating ${MODULE_NAME}_fixed.h + cefpython_api_fixed.h"
142-
VERBATIM
143-
)
144-
add_custom_target(cefpython_headers
145-
DEPENDS "${CEFPYTHON_H_FIXED}" "${CEF_API_FIXED_H}")
148+
# ---- Cython API header ------------------------------------------------------
149+
# C++ sources include the Cython-generated public API header directly via the
150+
# CEFPYTHON_API_H_FILE define (= "${MODULE_NAME}.h"); it sits in PYX_STAGE_DIR
151+
# which is on each target's include path. No post-processing is needed: the
152+
# C4190 warning is suppressed by the /wd4190 compile flag (and the renderer
153+
# subprocess, which lacks that flag, doesn't include the header at all).
154+
# cefpython_headers gates C++ compilation on the header being generated.
155+
add_custom_target(cefpython_headers DEPENDS "${CEFPYTHON_H}")
146156

147157
# ---- Static C++ libraries ---------------------------------------------------
148158
# All three libs share these settings so pass them via cache variables that
149159
# the subdirectory CMakeLists files can read.
150160
set(CEFPYTHON_PYX_STAGE_DIR "${PYX_STAGE_DIR}" CACHE INTERNAL "")
151161
set(CEFPYTHON_CEF_ROOT "${CEF_ROOT}" CACHE INTERNAL "")
152162
set(CEFPYTHON_SRC_DIR "${SRC_DIR}" CACHE INTERNAL "")
163+
set(CEFPYTHON_CEF_VERSION "${_cef_version}" CACHE INTERNAL "")
164+
165+
# Windows API target level. Match upstream CEF, which builds for Windows 10
166+
# (see cef_variables.cmake: WINVER/_WIN32_WINNT=0x0A00, NTDDI_WIN10_FE).
167+
# Chromium 147 only runs on Windows 10+, so targeting an older Windows here
168+
# would just hide newer Win32 APIs without buying real backward compatibility.
169+
# Defined once and consumed by both cefpython_common_flags (browser-process
170+
# targets) and the subprocess executable so the value can't drift between files.
171+
set(CEFPYTHON_WIN_TARGET_DEFS
172+
WINVER=0x0A00 _WIN32_WINNT=0x0A00 NTDDI_VERSION=NTDDI_WIN10_FE
173+
CACHE INTERNAL "Windows API target level (matches upstream CEF: Windows 10)")
174+
175+
# Shared compile settings for the browser-process C++ targets (the Python
176+
# extension module, client_handler, cpp_utils, cefpython_app). These flags
177+
# were previously duplicated verbatim in every CMake file - in particular the
178+
# Windows definition block with the NTDDI_VERSION/WINVER/_WIN32_WINNT triple.
179+
# Define them once here as an INTERFACE library that those targets link.
180+
#
181+
# NOTE: the subprocess executable is a *renderer*-process target with different
182+
# settings (RENDERER_PROCESS, static /MT CRT, _HAS_EXCEPTIONS=0, no /EHsc) and
183+
# deliberately does NOT use this. BROWSER_PROCESS only affects
184+
# src/subprocess/cefpython_app.cpp; it is a no-op for the other sources.
185+
add_library(cefpython_common_flags INTERFACE)
186+
target_compile_definitions(cefpython_common_flags INTERFACE
187+
BROWSER_PROCESS
188+
CEFPYTHON_API_H_FILE="${MODULE_NAME}.h"
189+
)
190+
if(WIN32)
191+
target_compile_options(cefpython_common_flags INTERFACE /EHsc /wd4190)
192+
target_compile_definitions(cefpython_common_flags INTERFACE
193+
WIN32 _WIN32 _WINDOWS
194+
${CEFPYTHON_WIN_TARGET_DEFS}
195+
NDEBUG _NDEBUG _CRT_SECURE_NO_WARNINGS NOMINMAX
196+
)
197+
else()
198+
target_compile_options(cefpython_common_flags INTERFACE -DNDEBUG -O3)
199+
endif()
200+
201+
# Filter a list of source files for the current platform: drop *_win.cpp,
202+
# *_linux.cpp, *_mac.cpp/.mm, x11.cpp and gtk* files that don't belong on the
203+
# OS being built. Shared by the client_handler and subprocess CMakeLists so the
204+
# rules live in one place. IN_LIST is the *name* of the input list variable;
205+
# the result is written to the variable named by OUT_VAR in the caller's scope.
206+
function(filter_sources IN_LIST OUT_VAR)
207+
set(_result "")
208+
foreach(_f IN LISTS ${IN_LIST})
209+
get_filename_component(_name "${_f}" NAME)
210+
set(_skip FALSE)
211+
if(_name MATCHES "_win\\.cpp$" AND NOT WIN32)
212+
set(_skip TRUE)
213+
endif()
214+
if(_name MATCHES "_linux\\.cpp$" AND NOT (CMAKE_SYSTEM_NAME STREQUAL "Linux"))
215+
set(_skip TRUE)
216+
endif()
217+
if(_name MATCHES "_mac\\.(cpp|mm)$" AND NOT APPLE)
218+
set(_skip TRUE)
219+
endif()
220+
if(_name MATCHES "^x11\\.cpp$" AND NOT (CMAKE_SYSTEM_NAME STREQUAL "Linux"))
221+
set(_skip TRUE)
222+
endif()
223+
if(_name MATCHES "gtk" AND NOT (CMAKE_SYSTEM_NAME STREQUAL "Linux"))
224+
set(_skip TRUE)
225+
endif()
226+
if(NOT _skip)
227+
list(APPEND _result "${_f}")
228+
endif()
229+
endforeach()
230+
set(${OUT_VAR} "${_result}" PARENT_SCOPE)
231+
endfunction()
153232

154233
add_subdirectory("${SRC_DIR}/client_handler"
155234
"${CMAKE_CURRENT_BINARY_DIR}/client_handler")
@@ -179,16 +258,13 @@ if(ENABLE_LINE_TRACING)
179258
target_compile_definitions(${MODULE_NAME} PRIVATE CYTHON_TRACE=1)
180259
endif()
181260

261+
# Common browser-process flags come from cefpython_common_flags; only the
262+
# module-specific extras are listed per platform below.
263+
target_link_libraries(${MODULE_NAME} PRIVATE cefpython_common_flags)
264+
182265
if(WIN32)
183266
target_include_directories(${MODULE_NAME} PRIVATE "${SRC_DIR}/windows")
184-
target_compile_options(${MODULE_NAME} PRIVATE /EHsc /wd4305 /wd4190)
185-
target_compile_definitions(${MODULE_NAME} PRIVATE
186-
WIN32 _WIN32 _WINDOWS
187-
NTDDI_VERSION=0x06010000 WINVER=0x0601 _WIN32_WINNT=0x0601
188-
NDEBUG _NDEBUG _CRT_SECURE_NO_WARNINGS NOMINMAX
189-
BROWSER_PROCESS
190-
CEFPYTHON_API_H_FILE="cefpython_api_fixed.h"
191-
)
267+
target_compile_options(${MODULE_NAME} PRIVATE /wd4305)
192268
target_link_libraries(${MODULE_NAME} PRIVATE
193269
cefpython_app
194270
client_handler
@@ -200,16 +276,11 @@ if(WIN32)
200276
target_link_options(${MODULE_NAME} PRIVATE /ignore:4217)
201277
elseif(APPLE)
202278
target_compile_options(${MODULE_NAME} PRIVATE
203-
-DNDEBUG -O3
204279
-Wno-return-type-c-linkage -Wno-constant-logical-operand
205280
-stdlib=libc++ -fno-strict-aliasing -fno-rtti
206281
-fno-threadsafe-statics -fobjc-call-cxx-cdtors
207282
-fvisibility=hidden -fvisibility-inlines-hidden
208283
)
209-
target_compile_definitions(${MODULE_NAME} PRIVATE
210-
BROWSER_PROCESS
211-
CEFPYTHON_API_H_FILE="cefpython_api_fixed.h"
212-
)
213284
target_link_options(${MODULE_NAME} PRIVATE
214285
-mmacosx-version-min=11.0
215286
-Wl,-search_paths_first -Wl,-dead_strip
@@ -223,14 +294,9 @@ elseif(APPLE)
223294
)
224295
else()
225296
target_compile_options(${MODULE_NAME} PRIVATE
226-
-DNDEBUG -O3
227297
-flto -fdata-sections -ffunction-sections
228298
-Wno-stringop-overflow
229299
)
230-
target_compile_definitions(${MODULE_NAME} PRIVATE
231-
BROWSER_PROCESS
232-
CEFPYTHON_API_H_FILE="cefpython_api_fixed.h"
233-
)
234300
target_include_directories(${MODULE_NAME} PRIVATE
235301
${GTK3_INCLUDE_DIRS}
236302
)

src/client_handler/CMakeLists.txt

Lines changed: 9 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,9 @@ if(APPLE)
44
list(APPEND _all_cpp ${_mm_files})
55
endif()
66

7-
set(_sources "")
8-
foreach(_f IN LISTS _all_cpp)
9-
get_filename_component(_name "${_f}" NAME)
10-
set(_skip FALSE)
11-
if(_name MATCHES "_win\\.cpp$" AND NOT WIN32)
12-
set(_skip TRUE)
13-
elseif(_name MATCHES "_linux\\.cpp$" AND NOT CMAKE_SYSTEM_NAME STREQUAL "Linux")
14-
set(_skip TRUE)
15-
elseif(_name MATCHES "_mac\\.(cpp|mm)$" AND NOT APPLE)
16-
set(_skip TRUE)
17-
elseif(_name MATCHES "^x11\\.cpp$" AND NOT CMAKE_SYSTEM_NAME STREQUAL "Linux")
18-
set(_skip TRUE)
19-
elseif(_name MATCHES "gtk" AND NOT CMAKE_SYSTEM_NAME STREQUAL "Linux")
20-
set(_skip TRUE)
21-
endif()
22-
if(NOT _skip)
23-
list(APPEND _sources "${_f}")
24-
endif()
25-
endforeach()
7+
# filter_sources() is defined in the top-level CMakeLists and shared with the
8+
# subprocess CMakeLists so the platform skip rules live in one place.
9+
filter_sources(_all_cpp _sources)
2610

2711
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
2812
find_package(PkgConfig REQUIRED)
@@ -43,21 +27,10 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
4327
target_include_directories(client_handler PRIVATE ${GTK3_INCLUDE_DIRS})
4428
endif()
4529

46-
if(WIN32)
47-
target_compile_options(client_handler PRIVATE /EHsc /wd4190)
48-
target_compile_definitions(client_handler PRIVATE
49-
WIN32 _WIN32 _WINDOWS
50-
NTDDI_VERSION=0x06010000 WINVER=0x0601 _WIN32_WINNT=0x0601
51-
NDEBUG _NDEBUG _CRT_SECURE_NO_WARNINGS NOMINMAX
52-
BROWSER_PROCESS
53-
CEFPYTHON_API_H_FILE="cefpython_api_fixed.h"
54-
)
55-
elseif(APPLE)
56-
target_compile_options(client_handler PRIVATE -DNDEBUG -O3)
57-
target_compile_definitions(client_handler PRIVATE
58-
CEFPYTHON_API_H_FILE="cefpython_api_fixed.h")
59-
else()
60-
target_compile_options(client_handler PRIVATE -DNDEBUG -O3 -Wno-stringop-overflow)
61-
target_compile_definitions(client_handler PRIVATE
62-
CEFPYTHON_API_H_FILE="cefpython_api_fixed.h")
30+
# Common browser-process flags (Windows def block, -DNDEBUG -O3, API header
31+
# define, etc.) come from cefpython_common_flags defined in the top-level
32+
# CMakeLists. Only the Linux-specific extra is listed here.
33+
target_link_libraries(client_handler PRIVATE cefpython_common_flags)
34+
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
35+
target_compile_options(client_handler PRIVATE -Wno-stringop-overflow)
6336
endif()

src/common/cefpython_public_api.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,22 @@
1515
// Python.h must be included first (avoids _POSIX_C_SOURCE redefinition on Linux)
1616
#include "Python.h"
1717

18-
// Includes required by the generated cefpython_*_fixed.h
18+
// Includes required by the Cython-generated public API header
1919
#include "include/cef_client.h"
2020
#include "include/cef_urlrequest.h"
2121
#include "include/cef_command_line.h"
2222
#include "util.h"
2323

24-
// cefpython_fixed.h uses DL_IMPORT/DL_EXPORT which were removed in Python 3.
24+
// The generated header uses DL_IMPORT/DL_EXPORT which were removed in Python 3.
2525
#ifndef DL_IMPORT
2626
#define DL_IMPORT(RTYPE) RTYPE
2727
#endif
2828
#ifndef DL_EXPORT
2929
#define DL_EXPORT(RTYPE) RTYPE
3030
#endif
3131

32-
// CMake sets CEFPYTHON_API_H_FILE to "cefpython_api_fixed.h", a generated
33-
// stable-name wrapper in the pyx_stage/ build directory resolved via the
32+
// CMake sets CEFPYTHON_API_H_FILE to the Cython-generated header name
33+
// ("cefpython_pyXX.h"), found in the pyx_stage/ build directory via the
3434
// target's include path.
3535
#include CEFPYTHON_API_H_FILE
3636

src/cpp_utils/CMakeLists.txt

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,9 @@ target_include_directories(cpp_utils PRIVATE
1010
${Python_INCLUDE_DIRS}
1111
)
1212

13-
if(WIN32)
14-
target_compile_options(cpp_utils PRIVATE /EHsc /wd4190)
15-
target_compile_definitions(cpp_utils PRIVATE
16-
WIN32 _WIN32 _WINDOWS
17-
NTDDI_VERSION=0x06010000 WINVER=0x0601 _WIN32_WINNT=0x0601
18-
NDEBUG _NDEBUG _CRT_SECURE_NO_WARNINGS NOMINMAX
19-
BROWSER_PROCESS
20-
CEFPYTHON_API_H_FILE="cefpython_api_fixed.h"
21-
)
22-
elseif(APPLE)
23-
target_compile_options(cpp_utils PRIVATE -DNDEBUG -O3)
24-
target_compile_definitions(cpp_utils PRIVATE
25-
CEFPYTHON_API_H_FILE="cefpython_api_fixed.h")
26-
else()
27-
target_compile_options(cpp_utils PRIVATE -DNDEBUG -O3 -Wno-stringop-overflow)
28-
target_compile_definitions(cpp_utils PRIVATE
29-
CEFPYTHON_API_H_FILE="cefpython_api_fixed.h")
13+
# Common browser-process flags come from cefpython_common_flags defined in the
14+
# top-level CMakeLists. Only the Linux-specific extra is listed here.
15+
target_link_libraries(cpp_utils PRIVATE cefpython_common_flags)
16+
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
17+
target_compile_options(cpp_utils PRIVATE -Wno-stringop-overflow)
3018
endif()

0 commit comments

Comments
 (0)