From a7a1ce3d6b2350242b4535342f2c45f5f9d7f5a7 Mon Sep 17 00:00:00 2001 From: Marshall Greenblatt Date: Fri, 2 Aug 2024 12:19:30 -0400 Subject: [PATCH] Add initial Bazel configuration Bazel can be used to build CEF-based applications. CEF support for Bazel is considered experimental. For current development status see https://github.com/chromiumembedded/cef/issues/3757 . For updated build and usage instructions see the README.md. --- .bazelrc | 54 +++++ .bazelversion | 1 + .gitignore | 5 + BUILD.bazel | 90 ++++++++ CMakeLists.txt | 2 +- MODULE.bazel | 17 ++ README.md | 98 ++++++-- WORKSPACE | 72 ++++++ bazel/BUILD.bazel | 8 + bazel/cef/BUILD.bazel | 8 + bazel/cef/loader.bzl | 37 +++ bazel/cef/platform.bzl.in | 7 + bazel/cef/version.bzl | 34 +++ bazel/cef/version.bzl.in | 21 ++ bazel/external_local_repository.bzl | 17 ++ examples/message_router/BUILD.bazel | 134 +++++++++++ examples/message_router/linux/BUILD.bazel | 43 ++++ examples/message_router/mac/BUILD.bazel | 39 ++++ examples/message_router/win/BUILD.bazel | 41 ++++ examples/minimal/BUILD.bazel | 163 ++++++++++++++ examples/minimal/linux/BUILD.bazel | 43 ++++ examples/minimal/mac/BUILD.bazel | 39 ++++ examples/minimal/resource_util_win_impl.cc | 14 ++ examples/minimal/win/BUILD.bazel | 41 ++++ examples/resource_manager/BUILD.bazel | 135 +++++++++++ examples/resource_manager/linux/BUILD.bazel | 43 ++++ examples/resource_manager/mac/BUILD.bazel | 39 ++++ examples/resource_manager/win/BUILD.bazel | 41 ++++ examples/scheme_handler/BUILD.bazel | 138 ++++++++++++ examples/scheme_handler/linux/BUILD.bazel | 43 ++++ examples/scheme_handler/mac/BUILD.bazel | 39 ++++ examples/scheme_handler/win/BUILD.bazel | 41 ++++ examples/shared/BUILD.bazel | 170 ++++++++++++++ examples/shared/client_util_mac.mm | 3 +- examples/shared/mac/Info.plist.in | 4 +- examples/shared/mac/helper-Info.plist.in | 4 +- examples/shared/main_mac.mm | 97 ++++---- tools/bazel/bazel_util.py | 121 ++++++++++ tools/bazel/platform_updater.py | 235 ++++++++++++++++++++ tools/bazel/version_updater.py | 147 ++++++++++++ tools/file_util.py | 14 ++ 41 files changed, 2271 insertions(+), 71 deletions(-) create mode 100755 .bazelrc create mode 100644 .bazelversion create mode 100755 BUILD.bazel create mode 100644 MODULE.bazel create mode 100755 WORKSPACE create mode 100644 bazel/BUILD.bazel create mode 100644 bazel/cef/BUILD.bazel create mode 100644 bazel/cef/loader.bzl create mode 100644 bazel/cef/platform.bzl.in create mode 100644 bazel/cef/version.bzl create mode 100644 bazel/cef/version.bzl.in create mode 100644 bazel/external_local_repository.bzl create mode 100644 examples/message_router/BUILD.bazel create mode 100644 examples/message_router/linux/BUILD.bazel create mode 100644 examples/message_router/mac/BUILD.bazel create mode 100644 examples/message_router/win/BUILD.bazel create mode 100644 examples/minimal/BUILD.bazel create mode 100644 examples/minimal/linux/BUILD.bazel create mode 100644 examples/minimal/mac/BUILD.bazel create mode 100644 examples/minimal/resource_util_win_impl.cc create mode 100644 examples/minimal/win/BUILD.bazel create mode 100644 examples/resource_manager/BUILD.bazel create mode 100644 examples/resource_manager/linux/BUILD.bazel create mode 100644 examples/resource_manager/mac/BUILD.bazel create mode 100644 examples/resource_manager/win/BUILD.bazel create mode 100644 examples/scheme_handler/BUILD.bazel create mode 100644 examples/scheme_handler/linux/BUILD.bazel create mode 100644 examples/scheme_handler/mac/BUILD.bazel create mode 100644 examples/scheme_handler/win/BUILD.bazel create mode 100644 examples/shared/BUILD.bazel create mode 100644 tools/bazel/bazel_util.py create mode 100755 tools/bazel/platform_updater.py create mode 100755 tools/bazel/version_updater.py diff --git a/.bazelrc b/.bazelrc new file mode 100755 index 0000000..494c773 --- /dev/null +++ b/.bazelrc @@ -0,0 +1,54 @@ +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +# Enable Bzlmod for every Bazel command. +common --enable_bzlmod + +# Enable build:{macos,linux,windows}. +build --enable_platform_specific_config + +# +# Common configuration. +# + +# Build with C++17. +build:linux --cxxopt='-std=c++17' +build:macos --cxxopt='-std=c++17' +build:macos --copt='-std=c++17' +build:windows --cxxopt='/std:c++17' + +# +# MacOS configuration. +# + +build:macos --copt='-ObjC++' + +# +# Windows configuration. +# + +# Enable creation of symlinks for runfiles. +build:windows --enable_runfiles + +# Use /MT[d]. +build:windows --features=static_link_msvcrt + +# +# Linux configuration. +# + +# The cfi-icall attribute is not supported by the GNU C++ compiler. +# TODO: Move to toolchain or add `--config=[gcc|llvm]` command-line option. +build:linux --cxxopt=-Wno-attributes + +# Use hardlinks instead of symlinks in sandboxes on Linux. +# This is required for CEF binaries to run, and for copy_filegroups() to work +# as expected on Linux. +build:linux --experimental_use_hermetic_linux_sandbox +build:linux --sandbox_add_mount_pair=/etc +build:linux --sandbox_add_mount_pair=/usr + ## symlinks into /usr +build:linux --sandbox_add_mount_pair=/usr/bin:/bin +build:linux --sandbox_add_mount_pair=/usr/lib:/lib +build:linux --sandbox_add_mount_pair=/usr/lib64:/lib64 diff --git a/.bazelversion b/.bazelversion new file mode 100644 index 0000000..21c8c7b --- /dev/null +++ b/.bazelversion @@ -0,0 +1 @@ +7.1.1 diff --git a/.gitignore b/.gitignore index d285d64..2b842d0 100644 --- a/.gitignore +++ b/.gitignore @@ -51,3 +51,8 @@ Thumbs.db /tools/buildtools/linux64/clang-format /tools/buildtools/mac/clang-format /tools/buildtools/win/clang-format.exe +# Bazel generated files +bazel/cef/platform.bzl +# Bazel output files/directories +bazel-* +MODULE.bazel.lock diff --git a/BUILD.bazel b/BUILD.bazel new file mode 100755 index 0000000..d6082e9 --- /dev/null +++ b/BUILD.bazel @@ -0,0 +1,90 @@ +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +# Allow access from targets in other packages. +package(default_visibility = [ + "//visibility:public", +]) + +load("@bazel_skylib//lib:selects.bzl", "selects") + +# +# Define supported configurations. +# See https://bazel.build/docs/configurable-attributes +# +# Normal build (ARM64 host): +# % bazel build //examples/minimal [-c dbg] +# +# Cross-compile build (ARM64 host): +# % bazel build //examples/minimal --cpu=darwin_x86_64 [-c dbg] +# + +config_setting( + name = "dbg", + values = {"compilation_mode": "dbg"}, +) + +config_setting( + name = "fastbuild", + values = {"compilation_mode": "fastbuild"}, +) + +config_setting( + name = "opt", + values = {"compilation_mode": "opt"}, +) + +selects.config_setting_group( + name = "windows_32", + match_all = ["@platforms//os:windows", "@platforms//cpu:x86_32"], +) + +selects.config_setting_group( + name = "windows_64", + match_all = ["@platforms//os:windows", "@platforms//cpu:x86_64"], +) + +selects.config_setting_group( + name = "windows_arm64", + match_all = ["@platforms//os:windows", "@platforms//cpu:arm64"], +) + +selects.config_setting_group( + name = "linux_64", + match_all = ["@platforms//os:windows", "@platforms//cpu:x86_64"], +) + +selects.config_setting_group( + name = "linux_arm64", + match_all = ["@platforms//os:windows", "@platforms//cpu:arm64"], +) + +selects.config_setting_group( + name = "linux_arm", + match_all = ["@platforms//os:windows", "@platforms//cpu:armv7"], +) + +config_setting( + name = "darwin_x86_64", + values = { + "cpu": "darwin_x86_64" + } +) + +config_setting( + name = "darwin_arm64", + values = { + "cpu": "darwin_arm64" + } +) + +selects.config_setting_group( + name = "macos_64", + match_all = ["@platforms//os:macos", ":darwin_x86_64"], +) + +selects.config_setting_group( + name = "macos_arm64", + match_all = ["@platforms//os:macos", ":darwin_arm64"], +) diff --git a/CMakeLists.txt b/CMakeLists.txt index bef87a9..671e239 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,7 @@ set_property(GLOBAL PROPERTY OS_FOLDERS ON) # # Specify the CEF distribution version. -set(CEF_VERSION "127.1.0+ga1ec504+chromium-127.0.6533.57") +set(CEF_VERSION "127.1.5+g35f74cc+chromium-127.0.6533.89") # Determine the platform. if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin") diff --git a/MODULE.bazel b/MODULE.bazel new file mode 100644 index 0000000..3c03c61 --- /dev/null +++ b/MODULE.bazel @@ -0,0 +1,17 @@ +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +module(name = "cef-project") + +# Configure local MacOS toolchain. +# See https://github.com/bazelbuild/apple_support/releases +bazel_dep(name = "apple_support", version = "1.16.0", repo_name = "build_bazel_apple_support") +# See https://github.com/bazelbuild/rules_apple/releases +bazel_dep(name = "rules_apple", version = "3.6.0", repo_name = "build_bazel_rules_apple") + +# Configure local C++ toolchain. +# See https://github.com/bazelbuild/rules_cc/releases +bazel_dep(name = "rules_cc", version = "0.0.9") + +# Add other dependencies here. diff --git a/README.md b/README.md index 38ba88e..88f2f1d 100644 --- a/README.md +++ b/README.md @@ -10,17 +10,15 @@ The [Chromium Embedded Framework](https://bitbucket.org/chromiumembedded/cef/) ( First install some necessary tools and download the cef-project source code. -1\. Install [CMake](https://cmake.org/), a cross-platform open-source build system. Version 3.21 or newer is required. +1\. Install [Python](https://www.python.org/downloads/). Version 3.9 to 3.11 is required. -2\. Install [Python](https://www.python.org/downloads/). Version 2.7.x or 3.9.x is required. If Python is not installed to the default location you can set the `PYTHON_EXECUTABLE` environment variable before running CMake (watch for errors during the CMake generation step below). +2\. Install platform-specific build tools. -3\. Install platform-specific build tools. - -* Linux: Currently supported distributions include Debian 10 (Buster), Ubuntu 18 (Bionic Beaver), and related. Ubuntu 18.04 64-bit with GCC 7.5.0+ is recommended. Newer versions will likely also work but may not have been tested. Required packages include: build-essential, libgtk-3-dev. +* Linux: Currently supported distributions include Debian 10 (Buster), Ubuntu 18 (Bionic Beaver), and related, with minimum GCC version 7.5.0. Ubuntu 22.04 64-bit with GCC 11+ is recommended. Newer versions will likely also work but may not have been tested. Required packages include: build-essential, libgtk-3-dev. * MacOS: Xcode 12.2 to 15.0 building on MacOS 10.15.4 (Catalina) or newer. The Xcode command-line tools must also be installed. * Windows: Visual Studio 2022 building on Windows 10 or newer. Windows 10/11 64-bit is recommended. -4\. Download the cef-project source code from the [Downloads page](https://bitbucket.org/chromiumembedded/cef-project/downloads) or by using [Git](https://git-scm.com/) command-line tools: +3\. Download the cef-project source code from the [Downloads page](https://bitbucket.org/chromiumembedded/cef-project/downloads) or by using [Git](https://git-scm.com/) command-line tools: ``` git clone https://bitbucket.org/chromiumembedded/cef-project.git @@ -28,7 +26,22 @@ git clone https://bitbucket.org/chromiumembedded/cef-project.git # Build -Now run CMake which will download the CEF binary distribution from the [Spotify automated builder](https://cef-builds.spotifycdn.com/index.html) and generate build files for your platform. Then build using platform build tools. For example, using the most recent tool versions on each platform: +The CEF examples included in this project can be built using either [CMake](https://cmake.org/) or [Bazel](https://bazel.build/). +These are both highly regarded cross-platform open-source build systems. + +## Using CMake + +[CMake](https://cmake.org/) can be used to generate project files in many different formats. + +To build the cef-project example applications using CMake: + +1\. Install [CMake](https://cmake.org/download/). Version 3.21 or newer is required. + +2\. Set the `PYTHON_EXECUTABLE` environment variable if required (watch for errors during the CMake generation step below). + +3\. Run CMake to download the CEF binary distribution from the [Spotify automated builder](https://cef-builds.spotifycdn.com/index.html) and generate build files for your platform. + +4\. Build using platform build tools. For example, using the most recent tool versions on each platform: ``` cd /path/to/cef-project @@ -71,6 +84,56 @@ CMake supports different generators on each platform. Run `cmake --help` to list Ninja is a cross-platform open-source tool for running fast builds using pre-installed platform toolchains (GNU, clang, Xcode or MSVC). See comments in the "third_party/cef/cef_binary_*/CMakeLists.txt" file for Ninja usage instructions. +## Using Bazel + +CEF support for [Bazel](https://bazel.build/) is considered experimental. For current development status see +https://github.com/chromiumembedded/cef/issues/3757. + +To build the cef-project example applications using Bazel: + +1\. Install [Bazelisk](https://github.com/bazelbuild/bazelisk/blob/master/README.md). + +2\. (Linux only) Install the patchelf package: +``` +sudo apt install patchelf +``` + +3\. Configure the CEF platform (see command output for details): +``` +cd /path/to/cef-project +python3 ./tools/bazel/platform_updater.py +``` +4\. Build using Bazel: +``` +bazel build //examples/minimal +``` +This will perform the following actions: + +* Download/install Bazel at the required [version](.bazelversion) (if necessary). +* Download the CEF binary distribution at the required [version](bazel/cef/version.bzl) from the +[Spotify automated builder](https://cef-builds.spotifycdn.com/index.html) (if necessary). +* Build using the default platform toolchain. + +5\. Run using Bazel: +``` +# On Linux/MacOS: +bazel run //examples/minimal + +# On Windows: +bazel run //examples/minimal/win:minimal.exe +``` + +To build other cef-project example applications replace `minimal` with the name of +the other application. To build CEF sample applications from the binary distribution +(cefsimple, cefclient, ceftests) use the `@cef//tests/cefsimple` target syntax. + +Additional notes: + +* To generate a Debug build add `-c dbg` (both `build` and `run` + command-line). +* To pass arguments using the `run` command add `-- [...]` at the end. +* See `platform_updater.py` output for additional instructions when cross-compiling. + # Examples CEF provides a number of examples that you can use as a starting point or reference for your own CEF-based development. @@ -81,7 +144,7 @@ CEF provides a number of examples that you can use as a starting point or refere * The cefclient application demonstrates a wide range of CEF functionality most of which is documented on the [GeneralUsage](https://bitbucket.org/chromiumembedded/cef/wiki/GeneralUsage.md) Wiki page. * The [examples directory](examples) contains example targets that demonstrate specific aspects of CEF functionality. * See the [examples README.md file](examples/README.md) for information about the examples targets. - * Add `-DWITH_EXAMPLES=Off` to the cmake command-line if you do not wish to build the examples targets. + * Using CMake: Add `-DWITH_EXAMPLES=Off` to the CMake command-line if you do not wish to build the examples targets. # Next Steps @@ -90,17 +153,24 @@ Here are some activities you might want to try next to gain a better understandi 1\. Update the CEF version used to build your local copy of cef-project: * Visit the [Spotify automated builder](https://cef-builds.spotifycdn.com/index.html) page to see what CEF versions are available. -* Change the "CEF_VERSION" value near the top of the [top-level CMakeLists.txt file](https://bitbucket.org/chromiumembedded/cef-project/src/master/CMakeLists.txt?fileviewer=file-view-default). -* Re-run the cmake and build commands. Add `-DWITH_EXAMPLES=Off` to the cmake command-line to disable targets from the [examples directory](examples) because they may not build successfully with the new CEF version. +* Using CMake: + * Change the "CEF_VERSION" value near the top of the [top-level CMakeLists.txt file](https://bitbucket.org/chromiumembedded/cef-project/src/master/CMakeLists.txt?fileviewer=file-view-default). + * Re-run the CMake and build commands. Add `-DWITH_EXAMPLES=Off` to the CMake command-line to disable targets from the [examples directory](examples) because they may not build successfully with the new CEF version. +* Using Bazel: + * Run the `./tools/bazel/version_updater.py` script to update the CEF version (see command output for details). + * Build and run the `@cef//tests/cefsimple` target. See instructions above. 2\. Add your own project source code: * Create a new "myproject" directory in the root cef-project directory (e.g. "/path/to/cef-project/myproject"). * Copy the contents of the "third_party/cef/cef_binary_*/tests/cefsimple" directory to "myproject" as a starting point. -* Add a new `add_subdirectory(myproject)` command near the end of [top-level CMakeLists.txt file](https://bitbucket.org/chromiumembedded/cef-project/src/master/CMakeLists.txt?fileviewer=file-view-default) after the existing add_subdirectory commands. -* Change the "CEF_TARGET", "CEF_HELPER_TARGET" and "CEF_HELPER_OUTPUT_NAME" values in "myproject/CMakeLists.txt" replacing "cefsimple" with "myproject". -* (Windows only) Rename the "cefclient.exe.manifest" file to "myproject.exe.manifest" in both "myproject/CMakeLists.txt" and the "myproject" directory. -* Re-run the cmake and build commands. +* Replace all instances of "cefsimple" with "myproject" and "tests" with "examples" in file names and file contents. +* Using CMake: + * Add a new `add_subdirectory(myproject)` command near the end of [top-level CMakeLists.txt file](https://bitbucket.org/chromiumembedded/cef-project/src/master/CMakeLists.txt?fileviewer=file-view-default) after the existing add_subdirectory commands. + * Re-run the cmake and build commands. +* Using Bazel: + * In all copied `BUILD.bazel` files change `load("//bazel...` to `load("@cef//bazel...` + * Build and run the `//examples/myproject` target. See instructions above. 3\. Gain a better understanding of the cefsimple application by reading the [Tutorial](https://bitbucket.org/chromiumembedded/cef/wiki/Tutorial.md) Wiki page. diff --git a/WORKSPACE b/WORKSPACE new file mode 100755 index 0000000..efb39b5 --- /dev/null +++ b/WORKSPACE @@ -0,0 +1,72 @@ +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +workspace(name = "cef-project") + +# +# Load the CEF binary distribution. +# + +# Download, extract and load the distribution. +load("//bazel/cef:loader.bzl", "load_cef_repo") +load_cef_repo() + +# To load a locally downloaded/extracted distribution use the following +# lines instead: +# load("//bazel/cef:loader.bzl", "load_local_cef_repo") +# load_local_cef_repo(path = "third_party/cef") + +# +# Windows configuration. +# + +# Configure windows SDK. +load("@cef//bazel/win:setup_sdk.bzl", "setup_sdk") +setup_sdk(name = "winsdk") + +# +# Linux configuration. +# + +# Configure Linux using pkg-config. +load("//bazel:external_local_repository.bzl", "external_local_repository") +external_local_repository( + name="pkg_config", + path="@cef//bazel/linux/pkg_config" +) +load("@pkg_config//:pkg_config.bzl", "pkg_config") + +# Define packages used by @cef//tests/cefclient. + +pkg_config( + name = "gmodule2", + pkg_name = "gmodule-2.0", +) + +pkg_config( + name = "gtk3", + pkg_name = "gtk+-3.0", +) + +pkg_config( + name = "gthread2", + pkg_name = "gthread-2.0", +) + +pkg_config( + name = "gtkprint3", + pkg_name = "gtk+-unix-print-3.0", +) + +pkg_config( + name = "xi", +) + +# Define packages used by @cef//tests/ceftests. + +pkg_config( + name = "glib2", + pkg_name = "glib-2.0", +) + diff --git a/bazel/BUILD.bazel b/bazel/BUILD.bazel new file mode 100644 index 0000000..013cc21 --- /dev/null +++ b/bazel/BUILD.bazel @@ -0,0 +1,8 @@ +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +# Allow access from targets in other packages. +package(default_visibility = [ + "//visibility:public", +]) diff --git a/bazel/cef/BUILD.bazel b/bazel/cef/BUILD.bazel new file mode 100644 index 0000000..013cc21 --- /dev/null +++ b/bazel/cef/BUILD.bazel @@ -0,0 +1,8 @@ +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +# Allow access from targets in other packages. +package(default_visibility = [ + "//visibility:public", +]) diff --git a/bazel/cef/loader.bzl b/bazel/cef/loader.bzl new file mode 100644 index 0000000..ae519c3 --- /dev/null +++ b/bazel/cef/loader.bzl @@ -0,0 +1,37 @@ +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") +load(":platform.bzl", "CEF_PLATFORM") +load(":version.bzl", "CEF_DOWNLOAD_URL", "CEF_VERSION", "CEF_FILE_SHA256") + +def load_cef_repo(name = "cef", + version = CEF_VERSION, + platform = CEF_PLATFORM, + url = CEF_DOWNLOAD_URL): + """ + Download, extract and load a CEF binary distribution. + """ + file_name = "cef_binary_{}_{}".format(version, platform) + + http_archive( + name = name, + sha256 = CEF_FILE_SHA256[platform], + strip_prefix = file_name, + url = "{}{}.tar.bz2".format(url, file_name), + repo_mapping = {"@cef": "@{}".format(name)} + ) + +def load_local_cef_repo(path, + name = "cef", + version = CEF_VERSION, + platform = CEF_PLATFORM): + """ + Load an already downloaded/extracted CEF binary distribution. + """ + native.local_repository( + name = "cef", + path = "{}/cef_binary_{}_{}".format(path, version, platform), + repo_mapping = {"@cef": "@{}".format(name)} + ) diff --git a/bazel/cef/platform.bzl.in b/bazel/cef/platform.bzl.in new file mode 100644 index 0000000..772de88 --- /dev/null +++ b/bazel/cef/platform.bzl.in @@ -0,0 +1,7 @@ +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +${description} + +CEF_PLATFORM = "${platform}" diff --git a/bazel/cef/version.bzl b/bazel/cef/version.bzl new file mode 100644 index 0000000..ef0b6e1 --- /dev/null +++ b/bazel/cef/version.bzl @@ -0,0 +1,34 @@ +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +# +# THIS FILE IS AUTO-GENERATED. DO NOT EDIT BY HAND. +# +# Use the following command to update version information: +# % python3 ./tools/bazel/version_updater.py --version= [--url=] +# +# Specify a fully-qualified CEF version. Optionally override the default +# download URL. +# +# CEF binary distribution file names are expected to take the form +# "cef_binary__.tar.bz2". These files must exist for each +# supported platform at the download URL location. Sha256 hashes must also +# exist for each file at ".sha256". +# + +CEF_DOWNLOAD_URL = "https://cef-builds.spotifycdn.com/" + +CEF_VERSION = "127.1.5+g35f74cc+chromium-127.0.6533.89" + +# Map of supported platform to sha256 for binary distribution download. +CEF_FILE_SHA256 = { + "windows32": "8f7fc81aad0341ac176964f105d28ea67d5fc70f3281b90e8985901f37f0ce2b", + "windows64": "83884e6378cabeb761a1a8f0e89e8493dd2f2fe43595f3991d5bcd903fa626a7", + "windowsarm64": "9dcf3fed173add7eb235a894e0775a107afc21274dc44d2b298788ed9cc69b5f", + "macosx64": "db730776cb266508e36a7d3e156ef4d80b298673d29e280525cd6151f2097811", + "macosarm64": "1ef2073b72f9080fe291a1b0ec39ba636fa752703ec67a0be39148e0bb860a07", + "linux64": "b8d4399b05430d53cd1e3946164bb17c013c19f2ee2ef5d7036f8e3f9573dad5", + "linuxarm64": "c7a480ea476709f8eb9ffdb6d68fafb9bbbd3e685cb734edf2d3c3038e113d67", + "linuxarm": "95c7d9bff29d22eb49bedd76041462d41ddcb65efd83133b2c7f7f6b0efe4380", +} diff --git a/bazel/cef/version.bzl.in b/bazel/cef/version.bzl.in new file mode 100644 index 0000000..41783db --- /dev/null +++ b/bazel/cef/version.bzl.in @@ -0,0 +1,21 @@ +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +${description} + +CEF_DOWNLOAD_URL = "${url}" + +CEF_VERSION = "${version}" + +# Map of supported platform to sha256 for binary distribution download. +CEF_FILE_SHA256 = { + "windows32": "${windows32_sha256}", + "windows64": "${windows64_sha256}", + "windowsarm64": "${windowsarm64_sha256}", + "macosx64": "${macosx64_sha256}", + "macosarm64": "${macosarm64_sha256}", + "linux64": "${linux64_sha256}", + "linuxarm64": "${linuxarm64_sha256}", + "linuxarm": "${linuxarm_sha256}", +} diff --git a/bazel/external_local_repository.bzl b/bazel/external_local_repository.bzl new file mode 100644 index 0000000..000dffe --- /dev/null +++ b/bazel/external_local_repository.bzl @@ -0,0 +1,17 @@ +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +def _external_local_repository_impl(repository_ctx): + # Create a symlink to the external directory in the current workspace. + absolute_path = repository_ctx.path(Label(repository_ctx.attr.path)).dirname + repository_ctx.symlink(absolute_path, "") + +# Like `local_repository` but referencing a directory in an external repository. +# Based on https://groups.google.com/g/bazel-discuss/c/xpsg3mWQPZg/m/cUY-w7AMBgAJ +external_local_repository = repository_rule( + implementation = _external_local_repository_impl, + attrs = { + "path": attr.string(mandatory = True), + }, +) diff --git a/examples/message_router/BUILD.bazel b/examples/message_router/BUILD.bazel new file mode 100644 index 0000000..47b42bb --- /dev/null +++ b/examples/message_router/BUILD.bazel @@ -0,0 +1,134 @@ +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +PRODUCT_NAME = "message_router" +PKG_NAME = "//examples/{}".format(PRODUCT_NAME) + +# Allow access from subpackages only. +package(default_visibility = [ + ":__subpackages__", +]) + +load("@rules_cc//cc:defs.bzl", "cc_library", "objc_library") + +# +# Source file lists. +# + +srcs_common = [ +] + +srcs_renderer = [ + "//examples/minimal:file-app_other_minimal.cc", + "app_renderer_impl.cc", +] + +srcs_renderer_mac = [ + "//examples/minimal:file-process_helper_mac_minimal.cc", +] + +srcs_browser = [ + "app_browser_impl.cc", + "client_impl.cc", + "client_impl.h", + "//examples/minimal:file-main_minimal.cc", +] + +srcs_browser_linux = [ +] + +srcs_browser_mac = [ +] + +srcs_browser_win = [ + "resource.h", + "resource_util_win_impl.cc", +] + +srcs_resources = [ + "resources/message_router.html", +] + +filegroup( + name = "Resources", + srcs = srcs_resources, +) + +# +# MacOS targets. +# + +objc_library( + name = "BrowserLibMac", + srcs = srcs_common + srcs_browser + srcs_browser_mac, + target_compatible_with = [ + "@platforms//os:macos", + ], + deps = [ + "@cef//:cef_wrapper", + "//examples/shared:BrowserLibMac", + ], +) + +objc_library( + name = "RendererLibMac", + srcs = srcs_common + srcs_renderer + srcs_renderer_mac, + target_compatible_with = [ + "@platforms//os:macos", + ], + deps = [ + "@cef//:cef_wrapper", + "//examples/shared:RendererLibMac", + ], +) + +# +# Windows targets. +# + +# Headers used by win/resource.rc to be included by the declare_exe target. +cc_library( + name = "ResourceH", + hdrs = [ + "resource.h" + ] +) + +# Include files directly in the declare_exe target. This simplifies the build +# configuration and avoids issues with Windows discarding symbols (like WinMain) +# when linking libraries. +filegroup( + name = "SrcsWin", + srcs = srcs_common + srcs_browser + srcs_browser_win + srcs_renderer, + target_compatible_with = [ + "@platforms//os:windows", + ], +) + +# +# Linux targets. +# + +# Include files directly in the declare_exe target. This simplifies the build +# configuration. +filegroup( + name = "SrcsLinux", + srcs = srcs_common + srcs_browser + srcs_browser_linux + srcs_renderer, + target_compatible_with = [ + "@platforms//os:linux", + ], +) + +# +# Alias to platform-specific build targets. +# + +alias( + name = PRODUCT_NAME, + actual = select({ + "@platforms//os:linux": "{}/linux:{}".format(PKG_NAME, PRODUCT_NAME), + "@platforms//os:macos": "{}/mac:{}".format(PKG_NAME, PRODUCT_NAME), + "@platforms//os:windows": "{}/win:{}".format(PKG_NAME, PRODUCT_NAME), + }), +) diff --git a/examples/message_router/linux/BUILD.bazel b/examples/message_router/linux/BUILD.bazel new file mode 100644 index 0000000..517fba1 --- /dev/null +++ b/examples/message_router/linux/BUILD.bazel @@ -0,0 +1,43 @@ +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +PRODUCT_NAME = "message_router" +PKG_NAME = "//examples/{}".format(PRODUCT_NAME) + +# Allow access from the parent package only. +package(default_visibility = [ + "{}:__pkg__".format(PKG_NAME), +]) + +load("@cef//bazel:copy_filegroups.bzl", "copy_filegroups") +load("@cef//bazel/linux:exe_helpers.bzl", "declare_exe") + +# +# Linux executable target. +# + +# Copy resources into the current project. +copy_target = "{}_resources".format(PRODUCT_NAME) +copy_filegroups( + name = copy_target, + filegroups = [ + "{}:Resources".format(PKG_NAME), + ], + remove_prefixes = [ + "examples/{}/resources".format(PRODUCT_NAME), + ], + add_prefix = "{}_files".format(PRODUCT_NAME), +) + +declare_exe( + name = PRODUCT_NAME, + srcs = [ + "{}:SrcsLinux".format(PKG_NAME), + "//examples/shared:SrcsLinux", + ], + data = [ + ":{}".format(copy_target), + ], +) + diff --git a/examples/message_router/mac/BUILD.bazel b/examples/message_router/mac/BUILD.bazel new file mode 100644 index 0000000..b035d3b --- /dev/null +++ b/examples/message_router/mac/BUILD.bazel @@ -0,0 +1,39 @@ +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +PRODUCT_NAME = "message_router" +PKG_NAME = "//examples/{}".format(PRODUCT_NAME) + +# Allow access from the parent package only. +package(default_visibility = [ + "{}:__pkg__".format(PKG_NAME), +]) + +load("@cef//bazel/mac:app_helpers.bzl", "declare_all_helper_apps", "declare_main_app") + +# +# MacOS app bundle target. +# + +# Helper app bundles. +declare_all_helper_apps( + name = PRODUCT_NAME, + info_plist = "//examples/shared:helper-Info.plist.in", + deps = [ + "{}:RendererLibMac".format(PKG_NAME), + ], +) + +# Main app bundle. +declare_main_app( + name = PRODUCT_NAME, + info_plist = "//examples/shared:Info.plist.in", + deps = [ + "{}:BrowserLibMac".format(PKG_NAME), + ], + resources = [ + "{}:Resources".format(PKG_NAME), + "//examples/shared:ResourcesMac", + ] +) diff --git a/examples/message_router/win/BUILD.bazel b/examples/message_router/win/BUILD.bazel new file mode 100644 index 0000000..9f86b4e --- /dev/null +++ b/examples/message_router/win/BUILD.bazel @@ -0,0 +1,41 @@ +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +PRODUCT_NAME = "message_router" +PKG_NAME = "//examples/{}".format(PRODUCT_NAME) + +# Allow access from the parent package only. +package(default_visibility = [ + "{}:__pkg__".format(PKG_NAME), +]) + +load("@cef//bazel/win:exe_helpers.bzl", "declare_exe") + +# +# Windows executable target. +# + +declare_exe( + name = PRODUCT_NAME, + srcs = [ + "{}:SrcsWin".format(PKG_NAME), + "//examples/shared:SrcsWin", + ], + rc_file = "resource.rc", + manifest_srcs = [ + "//examples/shared:compatibility.manifest", + "//examples/shared:shared.exe.manifest", + ], + resources_srcs = [ + "{}:Resources".format(PKG_NAME), + "//examples/shared:ResourcesWin", + ], + resources_deps = [ + "{}:ResourceH".format(PKG_NAME), + "//examples/shared:ResourceH", + ], + linkopts = [ + "/SUBSYSTEM:WINDOWS", + ], +) diff --git a/examples/minimal/BUILD.bazel b/examples/minimal/BUILD.bazel new file mode 100644 index 0000000..09847d4 --- /dev/null +++ b/examples/minimal/BUILD.bazel @@ -0,0 +1,163 @@ +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +PRODUCT_NAME = "minimal" +PKG_NAME = "//examples/{}".format(PRODUCT_NAME) + +# Allow access from all //examples packages. +package(default_visibility = [ + "//examples:__subpackages__", +]) + +load("@rules_cc//cc:defs.bzl", "cc_library", "objc_library") + +# +# Source file lists. +# + +srcs_common = [ +] + +srcs_renderer = [ + "app_other_minimal.cc", + "app_renderer_minimal.cc", +] + +srcs_renderer_mac = [ + "process_helper_mac_minimal.cc", +] + +srcs_browser = [ + "app_browser_minimal.cc", + "client_minimal.cc", + "client_minimal.h", + "main_minimal.cc", +] + +srcs_browser_linux = [ +] + +srcs_browser_mac = [ +] + +srcs_browser_win = [ + "resource_util_win_impl.cc", +] + +srcs_resources = [ +] + +filegroup( + name = "Resources", + srcs = srcs_resources, +) + +# Use alias() to allow file access from outside this package. +alias( + name = "file-app_other_minimal.cc", + actual = "app_other_minimal.cc" +) + +alias( + name = "file-app_renderer_minimal.cc", + actual = "app_renderer_minimal.cc" +) + +alias( + name = "file-client_minimal.cc", + actual = "client_minimal.cc" +) + +alias( + name = "file-client_minimal.h", + actual = "client_minimal.h" +) + +alias( + name = "file-main_minimal.cc", + actual = "main_minimal.cc" +) + +alias( + name = "file-process_helper_mac_minimal.cc", + actual = "process_helper_mac_minimal.cc" +) + +# +# MacOS targets. +# + +objc_library( + name = "BrowserLibMac", + srcs = srcs_common + srcs_browser + srcs_browser_mac, + target_compatible_with = [ + "@platforms//os:macos", + ], + deps = [ + "@cef//:cef_wrapper", + "//examples/shared:BrowserLibMac", + ], +) + +objc_library( + name = "RendererLibMac", + srcs = srcs_common + srcs_renderer + srcs_renderer_mac, + target_compatible_with = [ + "@platforms//os:macos", + ], + deps = [ + "@cef//:cef_wrapper", + "//examples/shared:RendererLibMac", + ], +) + +# +# Windows targets. +# + +# Headers used by win/resource.rc to be included by the declare_exe target. +cc_library( + name = "ResourceH", + hdrs = [ + "resource.h" + ] +) + +# Include files directly in the declare_exe target. This simplifies the build +# configuration and avoids issues with Windows discarding symbols (like WinMain) +# when linking libraries. +filegroup( + name = "SrcsWin", + srcs = srcs_common + srcs_browser + srcs_browser_win + srcs_renderer, + target_compatible_with = [ + "@platforms//os:windows", + ], +) + +# +# Linux targets. +# + +# Include files directly in the declare_exe target. This simplifies the build +# configuration. +filegroup( + name = "SrcsLinux", + srcs = srcs_common + srcs_browser + srcs_browser_linux + srcs_renderer, + target_compatible_with = [ + "@platforms//os:linux", + ], +) + +# +# Alias to platform-specific build targets. +# + +alias( + name = PRODUCT_NAME, + actual = select({ + "@platforms//os:linux": "{}/linux:{}".format(PKG_NAME, PRODUCT_NAME), + "@platforms//os:macos": "{}/mac:{}".format(PKG_NAME, PRODUCT_NAME), + "@platforms//os:windows": "{}/win:{}".format(PKG_NAME, PRODUCT_NAME), + }), +) diff --git a/examples/minimal/linux/BUILD.bazel b/examples/minimal/linux/BUILD.bazel new file mode 100644 index 0000000..d2b401c --- /dev/null +++ b/examples/minimal/linux/BUILD.bazel @@ -0,0 +1,43 @@ +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +PRODUCT_NAME = "minimal" +PKG_NAME = "//examples/{}".format(PRODUCT_NAME) + +# Allow access from the parent package only. +package(default_visibility = [ + "{}:__pkg__".format(PKG_NAME), +]) + +load("@cef//bazel:copy_filegroups.bzl", "copy_filegroups") +load("@cef//bazel/linux:exe_helpers.bzl", "declare_exe") + +# +# Linux executable target. +# + +# Copy resources into the current project. +copy_target = "{}_resources".format(PRODUCT_NAME) +copy_filegroups( + name = copy_target, + filegroups = [ + "{}:Resources".format(PKG_NAME), + ], + remove_prefixes = [ + "examples/{}/resources".format(PRODUCT_NAME), + ], + add_prefix = "{}_files".format(PRODUCT_NAME), +) + +declare_exe( + name = PRODUCT_NAME, + srcs = [ + "{}:SrcsLinux".format(PKG_NAME), + "//examples/shared:SrcsLinux", + ], + data = [ + ":{}".format(copy_target), + ], +) + diff --git a/examples/minimal/mac/BUILD.bazel b/examples/minimal/mac/BUILD.bazel new file mode 100644 index 0000000..6b45f6c --- /dev/null +++ b/examples/minimal/mac/BUILD.bazel @@ -0,0 +1,39 @@ +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +PRODUCT_NAME = "minimal" +PKG_NAME = "//examples/{}".format(PRODUCT_NAME) + +# Allow access from the parent package only. +package(default_visibility = [ + "{}:__pkg__".format(PKG_NAME), +]) + +load("@cef//bazel/mac:app_helpers.bzl", "declare_all_helper_apps", "declare_main_app") + +# +# MacOS app bundle target. +# + +# Helper app bundles. +declare_all_helper_apps( + name = PRODUCT_NAME, + info_plist = "//examples/shared:helper-Info.plist.in", + deps = [ + "{}:RendererLibMac".format(PKG_NAME), + ], +) + +# Main app bundle. +declare_main_app( + name = PRODUCT_NAME, + info_plist = "//examples/shared:Info.plist.in", + deps = [ + "{}:BrowserLibMac".format(PKG_NAME), + ], + resources = [ + "{}:Resources".format(PKG_NAME), + "//examples/shared:ResourcesMac", + ] +) diff --git a/examples/minimal/resource_util_win_impl.cc b/examples/minimal/resource_util_win_impl.cc new file mode 100644 index 0000000..d0d4423 --- /dev/null +++ b/examples/minimal/resource_util_win_impl.cc @@ -0,0 +1,14 @@ +// Copyright (c) 2017 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#include "examples/shared/resource_util.h" + +namespace shared { + +int GetResourceId(const std::string& resource_path) { + // Nothing to do here. + return 0; +} + +} // namespace shared diff --git a/examples/minimal/win/BUILD.bazel b/examples/minimal/win/BUILD.bazel new file mode 100644 index 0000000..a5d789b --- /dev/null +++ b/examples/minimal/win/BUILD.bazel @@ -0,0 +1,41 @@ +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +PRODUCT_NAME = "minimal" +PKG_NAME = "//examples/{}".format(PRODUCT_NAME) + +# Allow access from the parent package only. +package(default_visibility = [ + "{}:__pkg__".format(PKG_NAME), +]) + +load("@cef//bazel/win:exe_helpers.bzl", "declare_exe") + +# +# Windows executable target. +# + +declare_exe( + name = PRODUCT_NAME, + srcs = [ + "{}:SrcsWin".format(PKG_NAME), + "//examples/shared:SrcsWin", + ], + rc_file = "resource.rc", + manifest_srcs = [ + "//examples/shared:compatibility.manifest", + "//examples/shared:shared.exe.manifest", + ], + resources_srcs = [ + "{}:Resources".format(PKG_NAME), + "//examples/shared:ResourcesWin", + ], + resources_deps = [ + "{}:ResourceH".format(PKG_NAME), + "//examples/shared:ResourceH", + ], + linkopts = [ + "/SUBSYSTEM:WINDOWS", + ], +) diff --git a/examples/resource_manager/BUILD.bazel b/examples/resource_manager/BUILD.bazel new file mode 100644 index 0000000..362a770 --- /dev/null +++ b/examples/resource_manager/BUILD.bazel @@ -0,0 +1,135 @@ +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +PRODUCT_NAME = "resource_manager" +PKG_NAME = "//examples/{}".format(PRODUCT_NAME) + +# Allow access from subpackages only. +package(default_visibility = [ + ":__subpackages__", +]) + +load("@rules_cc//cc:defs.bzl", "cc_library", "objc_library") + +# +# Source file lists. +# + +srcs_common = [ +] + +srcs_renderer = [ + "//examples/minimal:file-app_other_minimal.cc", + "//examples/minimal:file-app_renderer_minimal.cc", +] + +srcs_renderer_mac = [ + "//examples/minimal:file-process_helper_mac_minimal.cc", +] + +srcs_browser = [ + "app_browser_impl.cc", + "client_impl.cc", + "client_impl.h", + "//examples/minimal:file-main_minimal.cc", +] + +srcs_browser_linux = [ +] + +srcs_browser_mac = [ +] + +srcs_browser_win = [ + "resource.h", + "resource_util_win_impl.cc", +] + +srcs_resources = [ + "resources/logo.png", + "resources/resource_manager.html", +] + +filegroup( + name = "Resources", + srcs = srcs_resources, +) + +# +# MacOS targets. +# + +objc_library( + name = "BrowserLibMac", + srcs = srcs_common + srcs_browser + srcs_browser_mac, + target_compatible_with = [ + "@platforms//os:macos", + ], + deps = [ + "@cef//:cef_wrapper", + "//examples/shared:BrowserLibMac", + ], +) + +objc_library( + name = "RendererLibMac", + srcs = srcs_common + srcs_renderer + srcs_renderer_mac, + target_compatible_with = [ + "@platforms//os:macos", + ], + deps = [ + "@cef//:cef_wrapper", + "//examples/shared:RendererLibMac", + ], +) + +# +# Windows targets. +# + +# Headers used by win/resource.rc to be included by the declare_exe target. +cc_library( + name = "ResourceH", + hdrs = [ + "resource.h" + ] +) + +# Include files directly in the declare_exe target. This simplifies the build +# configuration and avoids issues with Windows discarding symbols (like WinMain) +# when linking libraries. +filegroup( + name = "SrcsWin", + srcs = srcs_common + srcs_browser + srcs_browser_win + srcs_renderer, + target_compatible_with = [ + "@platforms//os:windows", + ], +) + +# +# Linux targets. +# + +# Include files directly in the declare_exe target. This simplifies the build +# configuration. +filegroup( + name = "SrcsLinux", + srcs = srcs_common + srcs_browser + srcs_browser_linux + srcs_renderer, + target_compatible_with = [ + "@platforms//os:linux", + ], +) + +# +# Alias to platform-specific build targets. +# + +alias( + name = PRODUCT_NAME, + actual = select({ + "@platforms//os:linux": "{}/linux:{}".format(PKG_NAME, PRODUCT_NAME), + "@platforms//os:macos": "{}/mac:{}".format(PKG_NAME, PRODUCT_NAME), + "@platforms//os:windows": "{}/win:{}".format(PKG_NAME, PRODUCT_NAME), + }), +) diff --git a/examples/resource_manager/linux/BUILD.bazel b/examples/resource_manager/linux/BUILD.bazel new file mode 100644 index 0000000..4b1ebe5 --- /dev/null +++ b/examples/resource_manager/linux/BUILD.bazel @@ -0,0 +1,43 @@ +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +PRODUCT_NAME = "resource_manager" +PKG_NAME = "//examples/{}".format(PRODUCT_NAME) + +# Allow access from the parent package only. +package(default_visibility = [ + "{}:__pkg__".format(PKG_NAME), +]) + +load("@cef//bazel:copy_filegroups.bzl", "copy_filegroups") +load("@cef//bazel/linux:exe_helpers.bzl", "declare_exe") + +# +# Linux executable target. +# + +# Copy resources into the current project. +copy_target = "{}_resources".format(PRODUCT_NAME) +copy_filegroups( + name = copy_target, + filegroups = [ + "{}:Resources".format(PKG_NAME), + ], + remove_prefixes = [ + "examples/{}/resources".format(PRODUCT_NAME), + ], + add_prefix = "{}_files".format(PRODUCT_NAME), +) + +declare_exe( + name = PRODUCT_NAME, + srcs = [ + "{}:SrcsLinux".format(PKG_NAME), + "//examples/shared:SrcsLinux", + ], + data = [ + ":{}".format(copy_target), + ], +) + diff --git a/examples/resource_manager/mac/BUILD.bazel b/examples/resource_manager/mac/BUILD.bazel new file mode 100644 index 0000000..6a13e9d --- /dev/null +++ b/examples/resource_manager/mac/BUILD.bazel @@ -0,0 +1,39 @@ +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +PRODUCT_NAME = "resource_manager" +PKG_NAME = "//examples/{}".format(PRODUCT_NAME) + +# Allow access from the parent package only. +package(default_visibility = [ + "{}:__pkg__".format(PKG_NAME), +]) + +load("@cef//bazel/mac:app_helpers.bzl", "declare_all_helper_apps", "declare_main_app") + +# +# MacOS app bundle target. +# + +# Helper app bundles. +declare_all_helper_apps( + name = PRODUCT_NAME, + info_plist = "//examples/shared:helper-Info.plist.in", + deps = [ + "{}:RendererLibMac".format(PKG_NAME), + ], +) + +# Main app bundle. +declare_main_app( + name = PRODUCT_NAME, + info_plist = "//examples/shared:Info.plist.in", + deps = [ + "{}:BrowserLibMac".format(PKG_NAME), + ], + resources = [ + "{}:Resources".format(PKG_NAME), + "//examples/shared:ResourcesMac", + ] +) diff --git a/examples/resource_manager/win/BUILD.bazel b/examples/resource_manager/win/BUILD.bazel new file mode 100644 index 0000000..9371398 --- /dev/null +++ b/examples/resource_manager/win/BUILD.bazel @@ -0,0 +1,41 @@ +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +PRODUCT_NAME = "resource_manager" +PKG_NAME = "//examples/{}".format(PRODUCT_NAME) + +# Allow access from the parent package only. +package(default_visibility = [ + "{}:__pkg__".format(PKG_NAME), +]) + +load("@cef//bazel/win:exe_helpers.bzl", "declare_exe") + +# +# Windows executable target. +# + +declare_exe( + name = PRODUCT_NAME, + srcs = [ + "{}:SrcsWin".format(PKG_NAME), + "//examples/shared:SrcsWin", + ], + rc_file = "resource.rc", + manifest_srcs = [ + "//examples/shared:compatibility.manifest", + "//examples/shared:shared.exe.manifest", + ], + resources_srcs = [ + "{}:Resources".format(PKG_NAME), + "//examples/shared:ResourcesWin", + ], + resources_deps = [ + "{}:ResourceH".format(PKG_NAME), + "//examples/shared:ResourceH", + ], + linkopts = [ + "/SUBSYSTEM:WINDOWS", + ], +) diff --git a/examples/scheme_handler/BUILD.bazel b/examples/scheme_handler/BUILD.bazel new file mode 100644 index 0000000..53889f1 --- /dev/null +++ b/examples/scheme_handler/BUILD.bazel @@ -0,0 +1,138 @@ +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +PRODUCT_NAME = "scheme_handler" +PKG_NAME = "//examples/{}".format(PRODUCT_NAME) + +# Allow access from subpackages only. +package(default_visibility = [ + ":__subpackages__", +]) + +load("@rules_cc//cc:defs.bzl", "cc_library", "objc_library") + +# +# Source file lists. +# + +srcs_common = [ + "scheme_strings.cc", + "scheme_strings.h", +] + +srcs_renderer = [ + "app_subprocess_impl.cc", +] + +srcs_renderer_mac = [ + "//examples/minimal:file-process_helper_mac_minimal.cc", +] + +srcs_browser = [ + "app_browser_impl.cc", + "scheme_handler_impl.cc", + "scheme_handler_impl.h", + "//examples/minimal:file-client_minimal.cc", + "//examples/minimal:file-client_minimal.h", + "//examples/minimal:file-main_minimal.cc", +] + +srcs_browser_linux = [ +] + +srcs_browser_mac = [ +] + +srcs_browser_win = [ + "resource.h", + "resource_util_win_impl.cc", +] + +srcs_resources = [ + "resources/logo.png", + "resources/scheme_handler.html", +] + +filegroup( + name = "Resources", + srcs = srcs_resources, +) + +# +# MacOS targets. +# + +objc_library( + name = "BrowserLibMac", + srcs = srcs_common + srcs_browser + srcs_browser_mac, + target_compatible_with = [ + "@platforms//os:macos", + ], + deps = [ + "@cef//:cef_wrapper", + "//examples/shared:BrowserLibMac", + ], +) + +objc_library( + name = "RendererLibMac", + srcs = srcs_common + srcs_renderer + srcs_renderer_mac, + target_compatible_with = [ + "@platforms//os:macos", + ], + deps = [ + "@cef//:cef_wrapper", + "//examples/shared:RendererLibMac", + ], +) + +# +# Windows targets. +# + +# Headers used by win/resource.rc to be included by the declare_exe target. +cc_library( + name = "ResourceH", + hdrs = [ + "resource.h" + ] +) + +# Include files directly in the declare_exe target. This simplifies the build +# configuration and avoids issues with Windows discarding symbols (like WinMain) +# when linking libraries. +filegroup( + name = "SrcsWin", + srcs = srcs_common + srcs_browser + srcs_browser_win + srcs_renderer, + target_compatible_with = [ + "@platforms//os:windows", + ], +) + +# +# Linux targets. +# + +# Include files directly in the declare_exe target. This simplifies the build +# configuration. +filegroup( + name = "SrcsLinux", + srcs = srcs_common + srcs_browser + srcs_browser_linux + srcs_renderer, + target_compatible_with = [ + "@platforms//os:linux", + ], +) + +# +# Alias to platform-specific build targets. +# + +alias( + name = PRODUCT_NAME, + actual = select({ + "@platforms//os:linux": "{}/linux:{}".format(PKG_NAME, PRODUCT_NAME), + "@platforms//os:macos": "{}/mac:{}".format(PKG_NAME, PRODUCT_NAME), + "@platforms//os:windows": "{}/win:{}".format(PKG_NAME, PRODUCT_NAME), + }), +) diff --git a/examples/scheme_handler/linux/BUILD.bazel b/examples/scheme_handler/linux/BUILD.bazel new file mode 100644 index 0000000..60343ed --- /dev/null +++ b/examples/scheme_handler/linux/BUILD.bazel @@ -0,0 +1,43 @@ +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +PRODUCT_NAME = "scheme_handler" +PKG_NAME = "//examples/{}".format(PRODUCT_NAME) + +# Allow access from the parent package only. +package(default_visibility = [ + "{}:__pkg__".format(PKG_NAME), +]) + +load("@cef//bazel:copy_filegroups.bzl", "copy_filegroups") +load("@cef//bazel/linux:exe_helpers.bzl", "declare_exe") + +# +# Linux executable target. +# + +# Copy resources into the current project. +copy_target = "{}_resources".format(PRODUCT_NAME) +copy_filegroups( + name = copy_target, + filegroups = [ + "{}:Resources".format(PKG_NAME), + ], + remove_prefixes = [ + "examples/{}/resources".format(PRODUCT_NAME), + ], + add_prefix = "{}_files".format(PRODUCT_NAME), +) + +declare_exe( + name = PRODUCT_NAME, + srcs = [ + "{}:SrcsLinux".format(PKG_NAME), + "//examples/shared:SrcsLinux", + ], + data = [ + ":{}".format(copy_target), + ], +) + diff --git a/examples/scheme_handler/mac/BUILD.bazel b/examples/scheme_handler/mac/BUILD.bazel new file mode 100644 index 0000000..f706000 --- /dev/null +++ b/examples/scheme_handler/mac/BUILD.bazel @@ -0,0 +1,39 @@ +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +PRODUCT_NAME = "scheme_handler" +PKG_NAME = "//examples/{}".format(PRODUCT_NAME) + +# Allow access from the parent package only. +package(default_visibility = [ + "{}:__pkg__".format(PKG_NAME), +]) + +load("@cef//bazel/mac:app_helpers.bzl", "declare_all_helper_apps", "declare_main_app") + +# +# MacOS app bundle target. +# + +# Helper app bundles. +declare_all_helper_apps( + name = PRODUCT_NAME, + info_plist = "//examples/shared:helper-Info.plist.in", + deps = [ + "{}:RendererLibMac".format(PKG_NAME), + ], +) + +# Main app bundle. +declare_main_app( + name = PRODUCT_NAME, + info_plist = "//examples/shared:Info.plist.in", + deps = [ + "{}:BrowserLibMac".format(PKG_NAME), + ], + resources = [ + "{}:Resources".format(PKG_NAME), + "//examples/shared:ResourcesMac", + ] +) diff --git a/examples/scheme_handler/win/BUILD.bazel b/examples/scheme_handler/win/BUILD.bazel new file mode 100644 index 0000000..2048444 --- /dev/null +++ b/examples/scheme_handler/win/BUILD.bazel @@ -0,0 +1,41 @@ +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +PRODUCT_NAME = "scheme_handler" +PKG_NAME = "//examples/{}".format(PRODUCT_NAME) + +# Allow access from the parent package only. +package(default_visibility = [ + "{}:__pkg__".format(PKG_NAME), +]) + +load("@cef//bazel/win:exe_helpers.bzl", "declare_exe") + +# +# Windows executable target. +# + +declare_exe( + name = PRODUCT_NAME, + srcs = [ + "{}:SrcsWin".format(PKG_NAME), + "//examples/shared:SrcsWin", + ], + rc_file = "resource.rc", + manifest_srcs = [ + "//examples/shared:compatibility.manifest", + "//examples/shared:shared.exe.manifest", + ], + resources_srcs = [ + "{}:Resources".format(PKG_NAME), + "//examples/shared:ResourcesWin", + ], + resources_deps = [ + "{}:ResourceH".format(PKG_NAME), + "//examples/shared:ResourceH", + ], + linkopts = [ + "/SUBSYSTEM:WINDOWS", + ], +) diff --git a/examples/shared/BUILD.bazel b/examples/shared/BUILD.bazel new file mode 100644 index 0000000..3010ee9 --- /dev/null +++ b/examples/shared/BUILD.bazel @@ -0,0 +1,170 @@ +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +load("@rules_cc//cc:defs.bzl", "cc_library", "objc_library") + +PRODUCT_NAME = "shared" +PKG_NAME = "//examples/{}".format(PRODUCT_NAME) + +# Allow access from all //examples packages. +package(default_visibility = [ + "//examples:__subpackages__", +]) + +# +# Source file lists. +# + +srcs_common = [ + "app_factory.h", + "main_util.cc", + "main_util.h", +] + +srcs_browser = [ + "client_manager.cc", + "client_manager.h", + "client_util.cc", + "client_util.h", + "browser_util.cc", + "browser_util.h", + "main.h", + "resource_util.cc", + "resource_util.h", +] + +srcs_browser_linux = [ + "client_util_linux.cc", + "main_linux.cc", + "resource_util_linux.cc", + "resource_util_posix.cc", +] + +srcs_browser_mac = [ + "client_util_mac.mm", + "main_mac.mm", + "resource_util_mac.mm", + "resource_util_posix.cc", +] + +srcs_browser_win = [ + "client_util_win.cc", + "main_win.cc", + "resource_util_win.cc", +] + +srcs_renderer = [ +] + +srcs_renderer_mac = [ + "process_helper_mac.cc", + "process_helper_mac.h", +] + +# +# MacOS targets. +# + +filegroup( + name = "ResourcesMac", + srcs = [ + "mac/English.lproj/InfoPlist.strings", + "mac/English.lproj/MainMenu.xib", + "mac/{}.icns".format(PRODUCT_NAME), + ], +) + +# Use alias() to allow file access from outside this package. +alias( + name = "Info.plist.in", + actual = "mac/Info.plist.in" +) + +alias( + name = "helper-Info.plist.in", + actual = "mac/helper-Info.plist.in" +) + +objc_library( + name = "BrowserLibMac", + srcs = srcs_common + srcs_browser + srcs_browser_mac, + target_compatible_with = [ + "@platforms//os:macos", + ], + deps = [ + "@cef//:cef_wrapper", + ], +) + +cc_library( + name = "RendererLibMac", + srcs = srcs_common + srcs_renderer + srcs_renderer_mac, + target_compatible_with = [ + "@platforms//os:macos", + ], + deps = [ + "@cef//:cef_wrapper", + ], +) + +# +# Windows targets. +# + +filegroup( + name = "ResourcesWin", + srcs = [ + "win/big.ico", + "win/shared.rc", + "win/small.ico", + ], +) + +# Headers used by win/shared.rc to be included by the declare_exe target. +cc_library( + name = "ResourceH", + hdrs = [ + "win/resource.h", + ], + deps = [ + # For inclusion of the "include/cef_version.h" header. + "@cef//:cef_wrapper", + ], +) + +# Use alias() to allow file access from outside this package. +alias( + name = "compatibility.manifest", + actual = "win/compatibility.manifest" +) + +alias( + name = "shared.exe.manifest", + actual = "win/shared.exe.manifest" +) + +# Include files directly in the declare_exe target. This simplifies the build +# configuration and avoids issues with Windows discarding symbols (like WinMain) +# when linking libraries. +filegroup( + name = "SrcsWin", + srcs = srcs_common + srcs_browser + srcs_browser_win + srcs_renderer, + target_compatible_with = [ + "@platforms//os:windows", + ], +) + +# +# Linux targets. +# + +# Include files directly in the declare_exe target. This simplifies the build +# configuration. +filegroup( + name = "SrcsLinux", + srcs = srcs_common + srcs_browser + srcs_browser_linux + srcs_renderer, + target_compatible_with = [ + "@platforms//os:linux", + ], +) diff --git a/examples/shared/client_util_mac.mm b/examples/shared/client_util_mac.mm index 10b4f8e..6faeb50 100644 --- a/examples/shared/client_util_mac.mm +++ b/examples/shared/client_util_mac.mm @@ -12,7 +12,8 @@ void PlatformTitleChange(CefRefPtr browser, const CefString& title) { - NSView* view = (NSView*)browser->GetHost()->GetWindowHandle(); + NSView* view = + CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(browser->GetHost()->GetWindowHandle()); NSWindow* window = [view window]; std::string titleStr(title); NSString* str = [NSString stringWithUTF8String:titleStr.c_str()]; diff --git a/examples/shared/mac/Info.plist.in b/examples/shared/mac/Info.plist.in index 1ce9055..f2929c7 100644 --- a/examples/shared/mac/Info.plist.in +++ b/examples/shared/mac/Info.plist.in @@ -9,11 +9,11 @@ CFBundleIconFile shared.icns CFBundleIdentifier - org.cef.shared + org.cef.${PRODUCT_NAME} CFBundleInfoDictionaryVersion 6.0 CFBundleName - ${PRODUCT_NAME} + ${EXECUTABLE_NAME} CFBundlePackageType APPL CFBundleVersion diff --git a/examples/shared/mac/helper-Info.plist.in b/examples/shared/mac/helper-Info.plist.in index 6ec2c04..1141135 100644 --- a/examples/shared/mac/helper-Info.plist.in +++ b/examples/shared/mac/helper-Info.plist.in @@ -9,11 +9,11 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier - org.cef.shared.helper${BUNDLE_ID_SUFFIX} + org.cef.${PRODUCT_NAME}.helper${BUNDLE_ID_SUFFIX} CFBundleInfoDictionaryVersion 6.0 CFBundleName - ${PRODUCT_NAME} + ${EXECUTABLE_NAME} CFBundlePackageType APPL CFBundleVersion diff --git a/examples/shared/main_mac.mm b/examples/shared/main_mac.mm index 7e07f9d..edbe2bc 100644 --- a/examples/shared/main_mac.mm +++ b/examples/shared/main_mac.mm @@ -122,59 +122,54 @@ int main(int argc, char* argv[]) { if (!library_loader.LoadInMain()) return 1; - // Initialize the AutoRelease pool. - NSAutoreleasePool* autopool = [[NSAutoreleasePool alloc] init]; - - // Provide CEF with command-line arguments. - CefMainArgs main_args(argc, argv); - - // Create a temporary CommandLine object. - CefRefPtr command_line = CreateCommandLine(main_args); - - // Create a CefApp for the browser process. Other processes are handled by - // process_helper_mac.cc. - CefRefPtr app = CreateBrowserProcessApp(); - - // Initialize the SharedApplication instance. - [SharedApplication sharedApplication]; - - // Create the singleton manager instance. - ClientManager manager; - - // Specify CEF global settings here. - CefSettings settings; - - // Use the CEF Chrome bootstrap. The Alloy bootstrap is deprecated and removed - // in M128. See https://github.com/chromiumembedded/cef/issues/3685. - settings.chrome_runtime = true; - - // Initialize the CEF browser process. The first browser instance will be - // created in CefBrowserProcessHandler::OnContextInitialized() after CEF has - // been initialized. May return false if initialization fails or if early exit - // is desired (for example, due to process singleton relaunch behavior). - if (!CefInitialize(main_args, settings, app, nullptr)) { - return 1; + // Scoped AutoRelease pool. + @autoreleasepool { + // Provide CEF with command-line arguments. + CefMainArgs main_args(argc, argv); + + // Create a temporary CommandLine object. + CefRefPtr command_line = CreateCommandLine(main_args); + + // Create a CefApp for the browser process. Other processes are handled by + // process_helper_mac.cc. + CefRefPtr app = CreateBrowserProcessApp(); + + // Initialize the SharedApplication instance. + [SharedApplication sharedApplication]; + + // Create the singleton manager instance. + ClientManager manager; + + // Specify CEF global settings here. + CefSettings settings; + + // Use the CEF Chrome bootstrap. The Alloy bootstrap is deprecated and + // removed in M128. See https://github.com/chromiumembedded/cef/issues/3685. + settings.chrome_runtime = true; + + // Initialize the CEF browser process. The first browser instance will be + // created in CefBrowserProcessHandler::OnContextInitialized() after CEF has + // been initialized. May return false if initialization fails or if early + // exit is desired (for example, due to process singleton relaunch + // behavior). + if (!CefInitialize(main_args, settings, app, nullptr)) { + return 1; + } + + // Create the application delegate. + NSObject* delegate = [[SharedAppDelegate alloc] init]; + [delegate performSelectorOnMainThread:@selector(createApplication:) + withObject:nil + waitUntilDone:NO]; + + // Run the CEF message loop. This will block until CefQuitMessageLoop() is + // called. + CefRunMessageLoop(); + + // Shut down CEF. + CefShutdown(); } - // Create the application delegate. - NSObject* delegate = [[SharedAppDelegate alloc] init]; - [delegate performSelectorOnMainThread:@selector(createApplication:) - withObject:nil - waitUntilDone:NO]; - - // Run the CEF message loop. This will block until CefQuitMessageLoop() is - // called. - CefRunMessageLoop(); - - // Shut down CEF. - CefShutdown(); - - // Release the delegate. - [delegate release]; - - // Release the AutoRelease pool. - [autopool release]; - return 0; } diff --git a/tools/bazel/bazel_util.py b/tools/bazel/bazel_util.py new file mode 100644 index 0000000..608e4c1 --- /dev/null +++ b/tools/bazel/bazel_util.py @@ -0,0 +1,121 @@ +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +QUIET = False + + +def bazel_set_quiet(quiet): + global QUIET + QUIET = quiet + + +LAST_ERROR = None + + +def bazel_last_error(): + return LAST_ERROR + + +def _set_last_error(error): + global LAST_ERROR + LAST_ERROR = error + + +def _print(label, data, pos, msg): + data_to_pos = data[0:pos] + line = data_to_pos.count('\n') + pos_in_line = (pos - data_to_pos.rfind('\n') - 1) if line > 0 else pos + + _set_last_error('ERROR: %s: %s at line %d:%d' % (label, msg, line + 1, + pos_in_line + 1)) + if not QUIET: + print(LAST_ERROR) + + +def bazel_substitute(data, + variables, + var_delim_start='${', + var_delim_end='}', + label='data'): + _set_last_error(None) + + result = '' + + epos = 0 + spos = data.find(var_delim_start, epos) + while spos >= 0: + result += data[epos:spos] + epos = data.find(var_delim_end, spos + len(var_delim_start)) + if epos > spos: + sub = '' + var = data[spos + len(var_delim_start):epos] + if var in variables: + # Direct replacement. + sub = str(variables[var]) + else: + _print(label, data, spos, + 'No value for "%s%s%s"' % (var_delim_start, var, var_delim_end)) + if len(sub) > 0: + result += sub + epos += len(var_delim_end) + else: + _print(label, data, spos, + 'Missing close bracket for "%s..."' % (data[spos:spos + 5])) + # Can't parse any further. + break + spos = data.find(var_delim_start, epos) + + if epos >= 0: + result += data[epos:] + + return result + + +# Test the module. +if __name__ == "__main__": + # Don't print error messages. + bazel_set_quiet(True) + + # No substitution + assert (bazel_substitute('foobar', {}) == 'foobar') + assert (bazel_last_error() == None) + + # No matching variable + assert (bazel_substitute('${a}foobar', {}) == 'foobar') + assert (bazel_last_error() == 'ERROR: data: No value for "${a}" at line 1:1') + assert (bazel_substitute('\nfoo${a}bar', {}) == '\nfoobar') + assert (bazel_last_error() == 'ERROR: data: No value for "${a}" at line 2:4') + assert (bazel_substitute('\n\nfoobar${a}', {}) == '\n\nfoobar') + assert (bazel_last_error() == 'ERROR: data: No value for "${a}" at line 3:7') + + # Missing end bracket. + assert (bazel_substitute('${afoobar', {}) == '') + assert (bazel_last_error() == + 'ERROR: data: Missing close bracket for "${afo..." at line 1:1') + assert (bazel_substitute('\nfoo${abar', {}) == '\nfoo') + assert (bazel_last_error() == + 'ERROR: data: Missing close bracket for "${aba..." at line 2:4') + assert (bazel_substitute('\n\nfoobar${a', {}) == '\n\nfoobar') + assert (bazel_last_error() == + 'ERROR: data: Missing close bracket for "${a..." at line 3:7') + + # Variable substitution + assert (bazel_substitute('foo${choo}bar', {'choo': 'blah'}) == 'fooblahbar') + assert (bazel_last_error() == None) + assert (bazel_substitute('${ah}${choo}bar${ba}', + {'ah': 'foo', + 'choo': 5, + 'ba': ''}) == 'foo5bar') + assert (bazel_last_error() == None) + + # Custom variable delimiters. + assert (bazel_substitute( + '$$ah$$$$choo$$bar$$ba$$', {'ah': 'foo', + 'choo': 5, + 'ba': ''}, + var_delim_start='$$', + var_delim_end='$$') == 'foo5bar') + assert (bazel_last_error() == None) + + print('Tests passed!') diff --git a/tools/bazel/platform_updater.py b/tools/bazel/platform_updater.py new file mode 100755 index 0000000..3583225 --- /dev/null +++ b/tools/bazel/platform_updater.py @@ -0,0 +1,235 @@ +#!/usr/bin/env python3 +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +from bazel_util import bazel_substitute, bazel_last_error +from optparse import OptionParser +import os +import platform as python_platform +import sys + +# Script directory. +script_dir = os.path.dirname(__file__) +root_script_dir = os.path.realpath(os.path.join(script_dir, os.pardir)) +root_dir = os.path.realpath(os.path.join(root_script_dir, os.pardir)) + +sys.path.append(root_script_dir) + +from file_util import read_file, write_file_if_changed + +description = """ +Use the following command to update platform information: +% python3 ./tools/bazel/platform_updater.py [--arch=x86|x64|arm64|arm] + +This must be configured before running Bazel for the first time, or when a +new target architecture is desired. + +By default (with no `--arch` argument), the host platform and architecture +will be selected. Optionally specify a different architecture for cross- +compilation. See the list of available architecture values below. +""" + + +def get_description(): + lines = [ + "", + "THIS FILE IS AUTO-GENERATED. DO NOT EDIT BY HAND.", + ] + description.split("\n") + get_config_desc().split("\n") + return "\n".join([("# " + l).strip() for l in lines]) + + +def get_config_desc(selected=None): + str = "Host platform: %s\nHost architecture: %s\n\n" % (get_host_os(), + get_host_arch()) + str += "CEF architectures and platforms available to build on this host:\n" + default = get_host_platform() + for arch, platform in get_available_platforms().items(): + tags = [] + if platform == default: + tags.append('default') + if platform == selected: + tags.append('selected') + tag_str = '' if len(tags) == 0 else ("[%s]" % ', '.join(tags)) + str += " %7s = %-12s %s\n" % (arch, platform, tag_str) + return str + + +def get_cmds(selected): + cmds = [] + if selected != get_host_platform(): + # Commands related to cross-compilation. + cmd_map = { + "windows32": "--cpu=x64_x86_windows", + "windows64": "--cpu=x64_windows", + "windowsarm64": "--cpu=arm64_windows", + "macosx64": "--cpu=darwin_x86_64", + "macosarm64": "--cpu=darwin_arm64", + "linux64": "--cpu=x86_64", + "linuxarm64": "--cpu=aarch64", + "linuxarm": "--cpu=armv7", + } + if selected in cmd_map: + cmds.append(cmd_map[selected]) + return cmds + + +def get_warnings(selected): + warnings = [] + if selected != get_host_platform(): + # Warnings related to cross-compilation. + if selected.startswith('windows'): + warnings.append("Windows cross-compile builds using Bazel may be broken, see\n" \ + "https://github.com/bazelbuild/bazel/issues/22164") + elif selected.startswith('linux'): + warnings.append("Linux cross-compile builds using Bazel may be broken, see\n" \ + "https://github.com/bazelbuild/examples/issues/173") + return warnings + + +def exit_with_error(error): + sys.stderr.write("ERROR: %s\n" % error) + sys.stderr.write(description) + sys.stderr.write("\n" + get_config_desc() + "\n") + sys.exit(1) + + +# Overrides for testing. +TEST_HOST_OS = None +TEST_HOST_ARCH = None + + +def get_host_os(): + if not TEST_HOST_OS is None: + return TEST_HOST_OS + + if sys.platform == 'win32': + return 'windows' + if sys.platform == 'darwin': + return 'macos' + if sys.platform.startswith('linux'): + return 'linux' + return '' + + +def get_host_arch(): + if not TEST_HOST_ARCH is None: + return TEST_HOST_ARCH + + # Windows: i386, AMD64, ARM64 + # MacOS: x86_64, arm64 + # Linux: i386, x86_64, aarch64, armv7l + mach = python_platform.machine() + if mach in ('AMD64', 'x86_64'): + return 'x64' + if mach == 'i386': + return 'x86' + if mach in ('ARM64', 'arm64', 'aarch64'): + return 'arm64' + if mach == 'armv7l': + return 'arm' + return '' + + +def get_available_platforms(): + # Map of available host architecture to CEF platform. + os = get_host_os() + if os == 'windows': + return { + 'x86': 'windows32', + 'x64': 'windows64', + 'arm64': 'windowsarm64', + } + if os == 'macos': + return { + 'x64': 'macosx64', + 'arm64': 'macosarm64', + } + if os == 'linux': + return { + 'x64': 'linux64', + 'arm64': 'linuxarm64', + 'arm': 'linuxarm', + } + return {} + + +def get_host_platform(): + # Returns None for unknown platform. + return get_available_platforms().get(get_host_arch(), None) + + +def is_available_arch(arch): + return arch in get_available_platforms() + + +def get_platform(arch): + return get_available_platforms()[arch] + + +# Cannot be loaded as a module. +if __name__ != "__main__": + exit_with_error('This file cannot be loaded as a module!') + +# Parse command-line options. +parser = OptionParser() +parser.add_option( + '--arch', + dest='arch', + help='CEF target architecture.', + default=get_host_arch()) +parser.add_option( + '--test-host-os', + dest='testhostos', + help='Override the host OS for testing.') +parser.add_option( + '--test-host-arch', + dest='testhostarch', + help='Override the host architecture for testing.') +(options, args) = parser.parse_args() + +# Overrides for testing. +if not options.testhostos is None: + TEST_HOST_OS = options.testhostos +if not options.testhostarch is None: + TEST_HOST_ARCH = options.testhostarch + +arch = options.arch +if not is_available_arch(arch): + exit_with_error('Invalid arch value.') + +platform = get_platform(arch) +if platform is None: + exit_with_error('Platform could not be determined.') + +out_file = os.path.join(root_dir, 'bazel', 'cef', 'platform.bzl') +in_file = out_file + '.in' +if not os.path.isfile(in_file): + exit_with_error('Missing input file %s' % in_file) + +variables = { + 'description': get_description(), + 'platform': platform, +} + +changed = False +output = bazel_substitute(read_file(in_file), variables, label=in_file) +if bazel_last_error() is None and len(output) > 0: + changed = write_file_if_changed(out_file, output) +else: + exit_with_error('Failed to parse template file %s' % in_file) + +if changed: + print("Successfully updated: %s" % out_file) +else: + print("Already up to date: %s" % out_file) + +print("\n" + get_config_desc(selected=platform)) + +cmds = get_cmds(selected=platform) +print("NOW RUN:\n%% bazel build %s%s[target]\n" % (" ".join(cmds), ' ' + if len(cmds) > 0 else '')) + +warnings = get_warnings(selected=platform) +if len(warnings) > 0: + print("WARNING:\n" + "\n".join(warnings) + "\n") diff --git a/tools/bazel/version_updater.py b/tools/bazel/version_updater.py new file mode 100755 index 0000000..14f2716 --- /dev/null +++ b/tools/bazel/version_updater.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python3 +# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +from bazel_util import bazel_substitute, bazel_last_error +from optparse import OptionParser +import os +import re +import sys +from urllib.error import HTTPError, URLError +import urllib.request + +# Script directory. +script_dir = os.path.dirname(__file__) +root_script_dir = os.path.realpath(os.path.join(script_dir, os.pardir)) +root_dir = os.path.realpath(os.path.join(root_script_dir, os.pardir)) + +sys.path.append(root_script_dir) + +from file_util import read_file, write_file_if_changed + +CEF_DOWNLOAD_URL = "https://cef-builds.spotifycdn.com/" + +CEF_PLATFORMS = ("windows32", "windows64", "windowsarm64", "macosx64", + "macosarm64", "linux64", "linuxarm64", "linuxarm") + +description = """ +Use the following command to update version information: +% python3 ./tools/bazel/version_updater.py --version= [--url=] + +Specify a fully-qualified CEF version. Optionally override the default +download URL. + +CEF binary distribution file names are expected to take the form +"cef_binary__.tar.bz2". These files must exist for each +supported platform at the download URL location. Sha256 hashes must also +exist for each file at ".sha256". +""" + + +def get_description(): + lines = [ + "", + "THIS FILE IS AUTO-GENERATED. DO NOT EDIT BY HAND.", + ] + description.split("\n") + return "\n".join([("# " + l).strip() for l in lines]) + + +def exit_with_error(error): + sys.stderr.write("ERROR: %s\n" % error) + sys.stderr.write(description + "\n") + sys.exit(1) + + +# Check if the CEF version number format is valid. The format is documented at +# https://bitbucket.org/chromiumembedded/cef/wiki/BranchesAndBuilding.md#markdown-header-version-number-format +# Code from https://bitbucket.org/chromiumembedded/cef/src/master/tools/cefbuilds/cef_json_builder.py +def is_valid_version(version): + _chromium_version_regex = r'[1-9]{1}[0-9]{1,2}\.0\.[1-9]{1}[0-9]{2,4}\.(0|[1-9]{1}[0-9]{0,2})' + _cef_hash_regex = r'g[0-9a-f]{7}' + _cef_number_regex = r'[0-9]{1,5}\.[0-9]{1,5}\.[0-9]{1,5}' + + # Example: 3.2704.1414.g185cd6c + _cef_old_version_regex = _cef_number_regex + r'\.' + _cef_hash_regex + # Example: 74.0.1+g62d140e+chromium-74.0.3729.6 + _cef_version_release_regex = _cef_number_regex + r'\+' + _cef_hash_regex + \ + r'\+chromium\-' + _chromium_version_regex + # Example: 74.0.0-master.1920+g725ed88+chromium-74.0.3729.0 + _cef_version_dev_regex = _cef_number_regex + r'\-\w+\.[0-9]{1,7}\+' + _cef_hash_regex + \ + r'\+chromium\-' + _chromium_version_regex + + return bool(re.compile(r'^' + _cef_old_version_regex + r'$').match(version)) \ + or bool(re.compile(r'^' + _cef_version_release_regex + r'$').match(version)) \ + or bool(re.compile(r'^' + _cef_version_dev_regex + r'$').match(version)) + + +def is_valid_sha256(sha256): + if sha256 is None: + return False + return bool(re.compile(r'^[0-9a-f]{64}$').match(sha256)) + + +def download_url(url): + # Attempt to download a URL. + try: + with urllib.request.urlopen(url) as f: + return f.read().decode('utf-8') + except HTTPError as e: + exit_with_error("Download of %s failed with error code %d" % (url, e.code)) + except URLError as e: + exit_with_error("Download of %s failed with reason %s" % (url, e.reason)) + return None + + +# Cannot be loaded as a module. +if __name__ != "__main__": + exit_with_error('This file cannot be loaded as a module!') + +# Parse command-line options. +parser = OptionParser() +parser.add_option( + '--version', dest='version', help='CEF version to download [required].') +parser.add_option('--url', dest='url', + help='CEF download URL. If not specified the default URL '+\ + 'will be used.', + default=CEF_DOWNLOAD_URL) +(options, args) = parser.parse_args() + +version = options.version +if version is None: + exit_with_error('Version parameter is required.') +if not is_valid_version(version): + exit_with_error('Invalid version format.') + +out_file = os.path.join(root_dir, 'bazel', 'cef', 'version.bzl') +in_file = out_file + '.in' +if not os.path.isfile(in_file): + exit_with_error('Missing input file %s' % in_file) + +variables = { + 'description': get_description(), + 'version': version, + 'url': options.url, +} + +print("Downloading sha256 values...") +for platform in CEF_PLATFORMS: + url = "%scef_binary_%s_%s.tar.bz2.sha256" % (options.url, version, platform) + sha256 = download_url(url) + if not is_valid_sha256(sha256): + exit_with_error('Missing or invalid sha256 from %s' % url) + variables["%s_sha256" % platform] = sha256 + +changed = False +output = bazel_substitute(read_file(in_file), variables, label=in_file) +if bazel_last_error() is None and len(output) > 0: + changed = write_file_if_changed(out_file, output) +else: + exit_with_error('Failed to parse template file %s' % in_file) + +if changed: + print("Successfully updated: %s" % out_file) +else: + print("Already up to date: %s" % out_file) + +print("\nConfigured version: %s\n" % version) diff --git a/tools/file_util.py b/tools/file_util.py index 6a8cb0d..70ce0f7 100644 --- a/tools/file_util.py +++ b/tools/file_util.py @@ -5,6 +5,7 @@ from __future__ import absolute_import from glob import iglob from io import open +import os import sys @@ -39,6 +40,19 @@ def write_file(name, data): raise +def write_file_if_changed(name, data): + """ Write a file if the contents have changed. Returns True if the file was written. """ + if os.path.exists(name): + old_contents = read_file(name) + else: + old_contents = '' + + if (data != old_contents): + write_file(name, data) + return True + return False + + def get_files(search_glob): """ Returns all files matching the search glob. """ # Sort the result for consistency across platforms.