blob: f25ca1446b8189cbc39a469d7c34ec8c47f08514 [file] [log] [blame]
Serge Bazanski9e861a82020-09-16 13:46:41 +02001# Copyright 2020 The Monogon Project Authors.
2#
3# SPDX-License-Identifier: Apache-2.0
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17# Copyright Google Inc.
18# This file's contents are licensed under the Apache License, Version 2.0.
19# See third_party/licenses/LICENSE.APACHE20 file in this repository for a copy
20# of the License.
21
22# This file contains code adapted from github.com/bazelbuiled/rules_foreign_cc:
23# Files:
24# - tools/build_defs/detect_root.bzl
25
Tim Windelschmidtb0f019c2025-04-15 21:12:22 +020026def detect_roots(sources):
27 """Does the same as detect_root but filters for source and generated files first."""
28
29 src, gen = [], []
30 for f in sources:
31 if f.is_source:
32 src.append(f)
33 else:
34 gen.append(f)
35
36 return (
37 detect_root(src),
38 detect_root(gen),
39 )
40
41def detect_root(sources):
42 """Detects the path to the topmost directory of the sources file list.
43 To be used with external build systems to point to the sources code/tools directories.
Serge Bazanski9e861a82020-09-16 13:46:41 +020044"""
45
46 root = ""
Serge Bazanski9e861a82020-09-16 13:46:41 +020047 if (root and len(root) > 0) or len(sources) == 0:
48 return root
49
50 root = ""
51 level = -1
52 num_at_level = 0
Tim Windelschmidtb0f019c2025-04-15 21:12:22 +020053 source_type = None
54 warning_printed = False
Serge Bazanski9e861a82020-09-16 13:46:41 +020055
56 # find topmost directory
57 for file in sources:
Tim Windelschmidtb0f019c2025-04-15 21:12:22 +020058 if source_type == None:
59 source_type = file.is_source
60
61 if source_type != file.is_source and not warning_printed:
62 # buildifier: disable=print
63 print("WARNING: Source and non-source (generated) files in same list. This will result in undefined behavior.")
64 warning_printed = True
65
Serge Bazanski9e861a82020-09-16 13:46:41 +020066 file_level = _get_level(file.path)
67 if level == -1 or level > file_level:
68 root = file.path
69 level = file_level
70 num_at_level = 1
71 elif level == file_level:
72 num_at_level += 1
73
74 if num_at_level == 1:
75 return root
76
77 (before, sep, after) = root.rpartition("/")
78 if before and sep and after:
79 return before
80 return root
81
82def _get_level(path):
83 normalized = path
Tim Windelschmidt156248b2025-01-10 00:27:45 +010084 for _ in range(len(path)):
Serge Bazanski9e861a82020-09-16 13:46:41 +020085 new_normalized = normalized.replace("//", "/")
86 if len(new_normalized) == len(normalized):
87 break
88 normalized = new_normalized
89
90 return normalized.count("/")