Skip to content

Commit

Permalink
bazel: Add initial config for binary distribution (see #3757)
Browse files Browse the repository at this point in the history
Add support for building the CEF binary distribution using Bazel
and the default platform toolchain. Tested to work for Windows
x64, MacOS ARM64 and x64 (cross-compile from ARM64), and
Linux x64. Windows x86 (cross-compile from x64) is known to
be broken, see bazelbuild/bazel#22164.

Includes minor changes to tests directory structure to meet
Bazel build requirements.
  • Loading branch information
magreenblatt committed Jul 28, 2024
1 parent 69b884d commit a6c00b2
Show file tree
Hide file tree
Showing 82 changed files with 3,405 additions and 196 deletions.
36 changes: 20 additions & 16 deletions BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -1834,7 +1834,7 @@ if (is_mac) {
bundle_data("cefclient_resources_bundle_data") {
sources = gypi_paths2.shared_sources_resources +
gypi_paths2.cefclient_sources_resources + [
"tests/cefclient/resources/mac/cefclient.icns",
"tests/cefclient/mac/cefclient.icns",
]

outputs = [
Expand All @@ -1844,7 +1844,7 @@ if (is_mac) {

bundle_data("cefclient_resources_bundle_data_english") {
sources = [
"tests/cefclient/resources/mac/English.lproj/InfoPlist.strings",
"tests/cefclient/mac/English.lproj/InfoPlist.strings",
]

outputs = [
Expand All @@ -1854,7 +1854,7 @@ if (is_mac) {

mac_xib_bundle_data("cefclient_xibs") {
sources = [
"tests/cefclient/resources/mac/English.lproj/MainMenu.xib",
"tests/cefclient/mac/English.lproj/MainMenu.xib",
]

output_path = "{{bundle_resources_dir}}/English.lproj"
Expand All @@ -1864,7 +1864,7 @@ if (is_mac) {
# Necessary because the cef_framework target is testonly.
testonly = true

helper_info_plist = "tests/cefclient/resources/mac/helper-Info.plist"
helper_info_plist = "tests/cefclient/mac/helper-Info.plist.in"
helper_sources = includes_common +
includes_mac +
gypi_paths2.includes_wrapper +
Expand All @@ -1878,7 +1878,7 @@ if (is_mac) {
"CEF_USE_SANDBOX",
]

info_plist = "tests/cefclient/resources/mac/Info.plist"
info_plist = "tests/cefclient/mac/Info.plist.in"
sources = includes_common +
includes_mac +
gypi_paths2.includes_wrapper +
Expand Down Expand Up @@ -1940,7 +1940,7 @@ if (is_mac) {
# Necessary because the cef_framework target is testonly.
testonly = true

helper_info_plist = "tests/cefsimple/mac/helper-Info.plist"
helper_info_plist = "tests/cefsimple/mac/helper-Info.plist.in"
helper_sources = includes_common +
includes_mac +
gypi_paths2.includes_wrapper +
Expand All @@ -1950,7 +1950,7 @@ if (is_mac) {
"CEF_USE_SANDBOX",
]

info_plist = "tests/cefsimple/mac/Info.plist"
info_plist = "tests/cefsimple/mac/Info.plist.in"
sources = includes_common +
includes_mac +
gypi_paths2.includes_wrapper +
Expand All @@ -1977,7 +1977,7 @@ if (is_mac) {

bundle_data("ceftests_resources_bundle_data") {
sources = gypi_paths2.shared_sources_resources + [
"tests/ceftests/resources/mac/ceftests.icns",
"tests/ceftests/mac/ceftests.icns",
]

outputs = [
Expand All @@ -1987,7 +1987,7 @@ if (is_mac) {

bundle_data("ceftests_resources_bundle_data_english") {
sources = [
"tests/ceftests/resources/mac/English.lproj/InfoPlist.strings",
"tests/ceftests/mac/English.lproj/InfoPlist.strings",
]

outputs = [
Expand All @@ -1997,19 +1997,20 @@ if (is_mac) {

mac_xib_bundle_data("ceftests_xibs") {
sources = [
"tests/ceftests/resources/mac/English.lproj/MainMenu.xib",
"tests/ceftests/mac/English.lproj/MainMenu.xib",
]
output_path = "{{bundle_resources_dir}}/English.lproj"
}

cef_app("ceftests") {
testonly = true

helper_info_plist = "tests/ceftests/resources/mac/helper-Info.plist"
helper_info_plist = "tests/ceftests/mac/helper-Info.plist.in"
helper_sources = gypi_paths2.shared_sources_common +
gypi_paths2.shared_sources_renderer +
gypi_paths2.shared_sources_mac_helper +
gypi_paths2.ceftests_sources_mac_helper
gypi_paths2.ceftests_sources_mac_helper +
gypi_paths2.ceftests_sources_mac_helper_shared
helper_deps = [
":gtest_teamcity",
"//testing/gtest",
Expand All @@ -2022,7 +2023,7 @@ if (is_mac) {
"CEF_TESTS_IN_SRC_DIRECTORY",
]

info_plist = "tests/ceftests/resources/mac/Info.plist"
info_plist = "tests/ceftests/mac/Info.plist.in"
sources = includes_common +
includes_mac +
gypi_paths2.includes_wrapper +
Expand Down Expand Up @@ -2107,7 +2108,8 @@ if (is_mac) {
if (is_win) {
sources += includes_win +
gypi_paths2.shared_sources_win +
gypi_paths2.cefclient_sources_win
gypi_paths2.cefclient_sources_win +
gypi_paths2.cefclient_sources_resources_win_rc

# Set /SUBSYSTEM:WINDOWS.
configs -= [ "//build/config/win:console" ]
Expand Down Expand Up @@ -2203,7 +2205,8 @@ if (is_mac) {

if (is_win) {
sources += includes_win +
gypi_paths2.cefsimple_sources_win
gypi_paths2.cefsimple_sources_win +
gypi_paths2.cefsimple_sources_resources_win_rc

# Set /SUBSYSTEM:WINDOWS.
configs -= [ "//build/config/win:console" ]
Expand Down Expand Up @@ -2278,7 +2281,8 @@ if (is_mac) {

if (is_win) {
sources += gypi_paths2.shared_sources_win +
gypi_paths2.ceftests_sources_win
gypi_paths2.ceftests_sources_win +
gypi_paths2.ceftests_sources_resources_win_rc

# Delay-load as many DLLs as possible for sandbox and startup perf
# improvements.
Expand Down
8 changes: 8 additions & 0 deletions bazel/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -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",
])
61 changes: 61 additions & 0 deletions bazel/copy_filegroups.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# 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 _copy_filegroups_impl(ctx):
inputs = ctx.files.filegroups
remove_prefixes = ctx.attr.remove_prefixes
add_prefix = ctx.attr.add_prefix

outputs = []
for f in inputs:
relative_path = f.path
for prefix in remove_prefixes:
# Add trailing forward slash if necessary.
if prefix[-1] != "/":
prefix += "/"
if len(prefix) > 0 and f.path.startswith(prefix):
relative_path = f.path[len(prefix):]
break

if len(add_prefix) > 0:
# Add trailing forward slash if necessary.
if add_prefix[-1] != "/":
add_prefix += "/"
relative_path = add_prefix + relative_path

out = ctx.actions.declare_file(relative_path)
outputs.append(out)

if relative_path.find("/") > 0:
command="mkdir -p $(dirname {}) && cp {} {}".format(out.path, f.path, out.path)
else:
command="cp {} {}".format(f.path, out.path)

ctx.actions.run_shell(
outputs=[out],
inputs=depset([f]),
command=command
)

# Small sanity check
if len(inputs) != len(outputs):
fail("Output count should be 1-to-1 with input count.")

return DefaultInfo(
files=depset(outputs),
runfiles=ctx.runfiles(files=outputs)
)

# Allows the file contents of |filegroups| to be copied next to a cc_binary
# target via the |data| attribute.
# Implementation based on https://stackoverflow.com/a/57983629
copy_filegroups = rule(
implementation=_copy_filegroups_impl,
attrs={
"filegroups": attr.label_list(),
"remove_prefixes": attr.string_list(default = []),
"add_prefix": attr.string(default = ""),
},
)

8 changes: 8 additions & 0 deletions bazel/linux/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -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",
])
58 changes: 58 additions & 0 deletions bazel/linux/exe_helpers.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# 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:copy_filegroups.bzl", "copy_filegroups")
load("//bazel/linux:fix_rpath.bzl", "fix_rpath")
load("//bazel/linux:variables.bzl",
"COMMON_LINKOPTS",
"COMMON_COPTS", "COMMON_COPTS_RELEASE", "COMMON_COPTS_DEBUG")
load("@rules_cc//cc:defs.bzl", "cc_binary")

def declare_exe(name, srcs=[], deps=[], linkopts=[], copts=[], defines=[], data=[]):
# Copy SOs and resources into the current project.
copy_target = "{}_sos_and_resources".format(name)
copy_filegroups(
name = copy_target,
filegroups = [
"//:sos",
"//:resources",
],
remove_prefixes = [
"Debug",
"Release",
"Resources",
],
)

# Executable target.
binary_target = "{}_incorrect_rpath".format(name)
cc_binary(
name = binary_target,
srcs = srcs,
deps = [
"//:cef_wrapper",
"//:cef",
"//:cef_sandbox",
] + deps,
linkopts = COMMON_LINKOPTS + linkopts,
copts = select({
"//:linux_dbg": COMMON_COPTS_DEBUG,
"//conditions:default": COMMON_COPTS_RELEASE,
}) + COMMON_COPTS + copts,
defines = defines,
data = [
":{}".format(copy_target),
] + data,
target_compatible_with = ["@platforms//os:linux"],
)

# Set rpath to $ORIGIN so that libraries can be loaded from next to the
# executable.
fix_rpath(
name = "{}_fixed_rpath".format(name),
src = ":{}".format(binary_target),
out = name,
target_compatible_with = ["@platforms//os:linux"],
)

41 changes: 41 additions & 0 deletions bazel/linux/fix_rpath.bzl
Original file line number Diff line number Diff line change
@@ -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.

def _fix_rpath_impl(ctx):
inputs = ctx.runfiles(files = [ctx.file.src])
# Bring over 'data' dependencies from the input.
inputs = inputs.merge_all([ctx.attr.src[DefaultInfo].default_runfiles])

src = ctx.file.src.path
out = ctx.outputs.out.path

ctx.actions.run_shell(
outputs = [ctx.outputs.out],
inputs = inputs.files,
arguments = [src, out],
command = "cp $1 $2 && " +
"chmod +w $2 && " +
"patchelf --remove-rpath $2 && " +
"patchelf --set-rpath '$ORIGIN' $2"
)

return [DefaultInfo(files = depset([ctx.outputs.out]))]

# Set rpath to $ORIGIN so that libraries can be loaded from next to the
# executable. The result can be confirmed with:
# $ objdump -x ./bazel-bin/path/to/binary | grep 'R.*PATH'
#
# Alternatively, define a custom CC toolchain that overrides
# 'runtime_library_search_directories'.
#
# This rule requires preinstallation of the patchelf package:
# $ sudo apt install patchelf
fix_rpath = rule(
implementation = _fix_rpath_impl,
attrs = {
"src": attr.label(allow_single_file = True),
"out": attr.output(mandatory = True),
},
)

7 changes: 7 additions & 0 deletions bazel/linux/pkg_config/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package(default_visibility = ["//visibility:public"])

exports_files([
"pkg_config.bzl",
"BUILD.tmpl",
])

32 changes: 32 additions & 0 deletions bazel/linux/pkg_config/BUILD.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# vi: ft=bzl
package(default_visibility = ["//visibility:private"])

_imports = [p[:len(p)-2] for p in glob(["{}/**/*.a".format(d) for d in [%{deps}]])]
[cc_import(
name = i.replace("/", "_"),
hdrs = glob([%{hdrs}]),
# TODO: library extension for platform.
static_library = "{}.a".format(i),
shared_library = "{}.dylib".format(i),
) for i in _imports]

cc_library(
name = "internal_lib",
hdrs = glob([%{hdrs}]),
copts = [%{copts}],
includes = [%{includes}],
linkopts = [%{linkopts}],
deps = [(":" + i.replace("/", "_")) for i in _imports],
)

cc_library(
name = "lib",
hdrs = glob(["%{strip_include}/**/*.h"]),
copts = [%{extra_copts}],
linkopts = [%{extra_linkopts}],
deps = [":internal_lib"] + [%{extra_deps}],
visibility = ["//visibility:public"],
strip_include_prefix = "%{strip_include}",
include_prefix = "%{include_prefix}",
)

11 changes: 11 additions & 0 deletions bazel/linux/pkg_config/README.cef
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Name: pkg_config
URL: https://github.com/cherrry/bazel_pkg_config
Version: 284219a

Description:
Bazel rules for pkg-config tools.

CEF-specific changes:
- Fix failure with duplicate symlinks.
- Remove `--static` flag from pkg-config invocation.

2 changes: 2 additions & 0 deletions bazel/linux/pkg_config/WORKSPACE
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
workspace(name = "pkg_config")

Loading

0 comments on commit a6c00b2

Please sign in to comment.