1*3a22c0a3SAlix# Copyright 2022 Google LLC. All rights reserved. 2*3a22c0a3SAlix# 3*3a22c0a3SAlix# Licensed under the Apache License, Version 2.0 (the License); 4*3a22c0a3SAlix# you may not use this file except in compliance with the License. 5*3a22c0a3SAlix# You may obtain a copy of the License at 6*3a22c0a3SAlix# 7*3a22c0a3SAlix# http://www.apache.org/licenses/LICENSE-2.0 8*3a22c0a3SAlix# 9*3a22c0a3SAlix# Unless required by applicable law or agreed to in writing, software 10*3a22c0a3SAlix# distributed under the License is distributed on an "AS IS" BASIS, 11*3a22c0a3SAlix# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*3a22c0a3SAlix# See the License for the specific language governing permissions and 13*3a22c0a3SAlix# limitations under the License. 14*3a22c0a3SAlix 15*3a22c0a3SAlix"""A rule for declaring and passing kotlinc opts in a restricted way. 16*3a22c0a3SAlix 17*3a22c0a3SAlixIt is a goal for rules_kotlin that Kotlin libraries use consistent default compiler 18*3a22c0a3SAlixoptions across as much of the repo as possible. Doing so makes Kotlin easier to 19*3a22c0a3SAlixmaintain at scale. 20*3a22c0a3SAlix 21*3a22c0a3SAlixIf an exception needs to be made for some library, `kt_compiler_opt` can be used to 22*3a22c0a3SAlixdeclare a set of additional options with restricted visibility. That target can then 23*3a22c0a3SAlixbe passed to the `custom_kotlincopts` attribute. The set of directories that allow 24*3a22c0a3SAlix`kt_compiler_opt` targets is also limited, to prevent misuse. 25*3a22c0a3SAlix""" 26*3a22c0a3SAlix 27*3a22c0a3SAlixload("//bazel:stubs.bzl", "check_compiler_opt_allowlist") 28*3a22c0a3SAlixload("//:visibility.bzl", "RULES_DEFS_THAT_COMPILE_KOTLIN") 29*3a22c0a3SAlix 30*3a22c0a3SAlix# Intentionally private to prevent misuse. 31*3a22c0a3SAlix_KtCompilerOptInfo = provider( 32*3a22c0a3SAlix doc = "A restricted set of kotlinc opts", 33*3a22c0a3SAlix fields = {"opts": "list[string]"}, 34*3a22c0a3SAlix) 35*3a22c0a3SAlix 36*3a22c0a3SAlix_ALLOWED_VISIBILITY_NAMES = [ 37*3a22c0a3SAlix "__pkg__", 38*3a22c0a3SAlix "__subpackages__", 39*3a22c0a3SAlix] 40*3a22c0a3SAlix 41*3a22c0a3SAlixdef _kt_compiler_opt_impl(ctx): 42*3a22c0a3SAlix check_compiler_opt_allowlist(ctx.label) 43*3a22c0a3SAlix 44*3a22c0a3SAlix visibility_groups = [v for v in ctx.attr.visibility if not v.name in _ALLOWED_VISIBILITY_NAMES] 45*3a22c0a3SAlix if len(visibility_groups) > 0: 46*3a22c0a3SAlix fail("Using package groups for visibility may expose custom options too broadly: " + str(visibility_groups)) 47*3a22c0a3SAlix 48*3a22c0a3SAlix return [_KtCompilerOptInfo(opts = ctx.attr.opts)] 49*3a22c0a3SAlix 50*3a22c0a3SAlixkt_compiler_opt = rule( 51*3a22c0a3SAlix implementation = _kt_compiler_opt_impl, 52*3a22c0a3SAlix attrs = { 53*3a22c0a3SAlix "opts": attr.string_list( 54*3a22c0a3SAlix doc = "The opt(s) this target represents.", 55*3a22c0a3SAlix mandatory = True, 56*3a22c0a3SAlix ), 57*3a22c0a3SAlix }, 58*3a22c0a3SAlix) 59*3a22c0a3SAlix 60*3a22c0a3SAlixdef kotlincopts_attrs(): 61*3a22c0a3SAlix return dict( 62*3a22c0a3SAlix custom_kotlincopts = attr.label_list( 63*3a22c0a3SAlix doc = "kt_compiler_opt targets to pass to Kotlin compiler. Most users should not need this attr.", 64*3a22c0a3SAlix providers = [[_KtCompilerOptInfo]], 65*3a22c0a3SAlix cfg = "exec", 66*3a22c0a3SAlix ), 67*3a22c0a3SAlix ) 68*3a22c0a3SAlix 69*3a22c0a3SAlixdef merge_kotlincopts(ctx): 70*3a22c0a3SAlix """Returns the complete list of opts behind custom_kotlincopts 71*3a22c0a3SAlix 72*3a22c0a3SAlix Args: 73*3a22c0a3SAlix ctx: A ctx matching kotlincopts_attrs 74*3a22c0a3SAlix 75*3a22c0a3SAlix Returns: 76*3a22c0a3SAlix The list of opts 77*3a22c0a3SAlix """ 78*3a22c0a3SAlix custom_opts = [] 79*3a22c0a3SAlix for target in ctx.attr.custom_kotlincopts: 80*3a22c0a3SAlix custom_opts.extend(target[_KtCompilerOptInfo].opts) 81*3a22c0a3SAlix 82*3a22c0a3SAlix return custom_opts 83