• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"""
2THIS IS THE EXTERNAL-ONLY VERSION OF THIS FILE. G3 HAS ITS OWN.
3
4This file contains macros which require no third-party dependencies.
5Using these where possible makes it easier for clients to use Skia
6without needing to download a bunch of unnecessary dependencies
7in their WORKSPACE.bazel file.
8"""
9
10load("@skia_user_config//:copts.bzl", "DEFAULT_COPTS", "DEFAULT_OBJC_COPTS")
11load("@skia_user_config//:linkopts.bzl", "DEFAULT_LINKOPTS")
12load("//bazel:cc_binary_with_flags.bzl", "cc_binary_with_flags")
13load(
14    "//bazel:generate_cpp_files_for_headers.bzl",
15    _generate_cpp_files_for_header_list = "generate_cpp_files_for_header_list",
16    _generate_cpp_files_for_headers = "generate_cpp_files_for_headers",
17)
18
19generate_cpp_files_for_headers = _generate_cpp_files_for_headers
20generate_cpp_files_for_header_list = _generate_cpp_files_for_header_list
21
22def select_multi(values_map):
23    """select() but allowing multiple matches of the keys.
24
25    select_multi works around a restriction in native select() that prevents multiple
26    keys from being matched unless one is a strict subset of another. For some features,
27    we allow multiple of that component to be active. For example, with codecs, we let
28    the clients mix and match anywhere from 0 built in codecs to all of them.
29
30    select_multi takes a given map and turns it into several distinct select statements
31    that have the effect of using any values associated with any active keys.
32    For example, if the following parameter is passed in:
33        values_map = {
34            ":alpha": ["apple", "apricot"],
35            ":beta": ["banana"],
36            ":gamma": ["grapefruit"],
37        }
38    it will be unrolled into the following select statements
39        [] + select({
40            ":apple": ["apple", "apricot"],
41            "//conditions:default": [],
42        }) + select({
43            ":beta": ["banana"],
44            "//conditions:default": [],
45        }) + select({
46            ":gamma": ["grapefruit"],
47            "//conditions:default": [],
48        })
49
50    Args:
51        values_map: dictionary of labels to a list of labels, just like select()
52
53    Returns:
54        A list of values that is filled in by the generated select statements.
55    """
56    if len(values_map) == 0:
57        return []
58    rv = []
59    for key, value in values_map.items():
60        rv += select({
61            key: value,
62            "//conditions:default": [],
63        })
64    return rv
65
66def skia_cc_binary(name, copts = DEFAULT_COPTS, linkopts = DEFAULT_LINKOPTS, **kwargs):
67    """A wrapper around cc_library for Skia C++ executables (e.g. tests).
68
69    This lets us provide compiler flags (copts) and global linker flags (linkopts) consistently
70    to Skia built executables. These executables are almost always things like unit tests and
71    dev tools.
72
73    Args:
74        name: the name of the underlying executable.
75        copts: Flags which should be passed to the C++ compiler. By default, we use DEFAULT_COPTS
76            from @skia_user_config//:copts.bzl.
77        linkopts: Global flags which should be passed to the C++ linker. By default, we use
78            DEFAULT_LINKOPTS from  @skia_user_config//:linkopts.bzl. Other linker flags will be
79            passed in via deps (see deps_and_linkopts below).
80        **kwargs: All the normal arguments that cc_binary takes.
81    """
82    native.cc_binary(name = name, copts = copts, linkopts = linkopts, **kwargs)
83
84def skia_cc_binary_with_flags(
85        name,
86        copts = DEFAULT_COPTS,
87        linkopts = DEFAULT_LINKOPTS,
88        set_flags = None,
89        **kwargs):
90    cc_binary_with_flags(
91        name = name,
92        copts = copts,
93        linkopts = linkopts,
94        set_flags = set_flags,
95        **kwargs
96    )
97
98def skia_cc_library(name, copts = DEFAULT_COPTS, **kwargs):
99    """A wrapper around cc_library for Skia C++ libraries.
100
101    This lets us provide compiler flags (copts) consistently to the Skia build (e.g. //:skia_public)
102    and builds which depend on those targets (e.g. things in //tools or //modules).
103
104    It also lets us easily tweak these settings when being built in G3.
105
106    Third party libraries should *not* use this directly, as there are likely some flags used
107    by Skia (e.g. warnings) that we do not want to have to fix for third party code.
108
109    Args:
110        name: the name of the underlying library.
111        copts: Flags which should be passed to the C++ compiler. By default, we use DEFAULT_COPTS
112            from @skia_user_config//:copts.bzl.
113        **kwargs: All the normal arguments that cc_library takes.
114    """
115    native.cc_library(name = name, copts = copts, **kwargs)
116
117def skia_cc_deps(name, visibility, deps = [], linkopts = [], textual_hdrs = [], testonly = False):
118    """A self-documenting wrapper around cc_library for things to pass to the top skia_cc_library.
119
120    It lets us have third_party deps, linkopts, etc be set close to where they impact,
121    and trickle up the file hierarchy to //:skia_public and //:skia_internal
122
123    Args:
124        name: the name of the underlying target. By convention, this is usually called "deps".
125        visibility: To prevent this rule from being used where it should not, we have the
126            convention of setting the visibility to just the parent package.
127        deps: A list of labels or select statements to collect third_party dependencies.
128        linkopts: A list of strings or select statements to collect linker flags.
129        textual_hdrs: A list of labels or select statements to collect files which are included, but
130            do not have a suffix of .h, like a typical C++ header does.
131        testonly: A boolean that, if true, will enforce all targets who depend on this are also
132            marked as testonly.
133    """
134    native.cc_library(
135        name = name,
136        visibility = visibility,
137        deps = deps,
138        linkopts = linkopts,
139        textual_hdrs = textual_hdrs,
140        testonly = testonly,
141    )
142
143def skia_defines(name, visibility, defines):
144    """A self-documenting wrapper around cc_library for defines"""
145    native.cc_library(name = name, visibility = visibility, defines = defines)
146
147def skia_filegroup(**kwargs):
148    """A wrapper around filegroup allowing us to customize visibility in G3."""
149    native.filegroup(**kwargs)
150
151def skia_objc_library(name, copts = DEFAULT_OBJC_COPTS, **kwargs):
152    """A wrapper around cc_library for Skia Objective C libraries.
153
154    This lets us provide compiler flags (copts) consistently to the Skia build (e.g. //:skia_public)
155    and builds which depend on those targets (e.g. things in //tools or //modules).
156
157    It also lets us easily tweak these settings when being built in G3.
158    Args:
159        name: the name of the underlying target.
160        copts: Flags which should be passed to the C++ compiler. By default, we use
161            DEFAULT_OBJC_COPTS from @skia_user_config//:copts.bzl.
162        **kwargs: Normal arguments to objc_library
163    """
164
165    # Internally, we need to combine sdk_frameworks and deps, but we can only
166    # do that if both are lists
167    # https://github.com/bazelbuild/bazel/issues/14157
168    sdks = kwargs.get("sdk_frameworks", None)
169    deps = kwargs.get("deps", [])
170    if type(sdks) != "NoneType":
171        if type(sdks) != "list" or type(deps) != "list":
172            fail("skd_frameworks and deps must both be normal lists, not selects")
173    native.objc_library(name = name, copts = copts, **kwargs)
174
175# buildifier: disable=unnamed-macro
176def exports_files_legacy(label_list = None, visibility = None):
177    """A self-annotating macro to export all files in this package for legacy G3 rules.
178
179    Args:
180        label_list: If provided, this will act like a normal exports_files rule. If not
181           provided, nothing happens.
182        visibility: Should be provided if label_list is set
183    """
184    if label_list:
185        native.exports_files(label_list, visibility = visibility)
186
187def split_srcs_and_hdrs(name, files):
188    """Take a list of files and creates filegroups for C++ sources and headers.
189
190    The reason we make filegroups is that they are more friendly towards a file being
191    listed twice than just returning a sorted list of files.
192
193    For example, in //src/codecs, "SkEncodedInfo.cpp" is needed for some, but not all
194    the codecs. It is easier for devs to list the file for the codecs that need it
195    rather than making a complicated select statement to make sure it is only in the
196    list of files once.
197
198    Bazel is smart enough to not compile the same file twice, even if it shows up in
199    multiple filegroups.
200
201    The "_srcs" and "_hdrs" filegroups will only be created if there are a non-zero amount
202    of files of both types. Otherwise, it will fail because we do not need the macro.
203
204    Args:
205        name: The prefix of the generated filegroups. One will have the suffix "_srcs" and
206            the other "_hdrs".
207        files: List of file names, e.g. ["SkAAClip.cpp", "SkAAClip.h"]
208    """
209    srcs = []
210    hdrs = []
211    for f in files:
212        if f.endswith(".cpp"):
213            srcs.append(f)
214        elif f.endswith(".mm"):
215            srcs.append(f)
216        elif f.endswith(".h"):
217            hdrs.append(f)
218        else:
219            fail("Neither .cpp, .mm, nor .h file " + f)
220
221    if len(srcs) == 0 or len(hdrs) == 0:
222        fail("The list consist of either only source or header files. No need to use this macro.")
223
224    skia_filegroup(
225        name = name + "_srcs",
226        srcs = srcs,
227    )
228    skia_filegroup(
229        name = name + "_hdrs",
230        srcs = hdrs,
231    )
232