blob: cbd4ef756087b3b33231da4a244e6d0df64c4eca [file] [log] [blame]
Yuval Peress7e9e1df2025-02-27 13:47:34 -08001# Copyright 2025 The Pigweed Authors
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may not
4# use this file except in compliance with the License. You may obtain a copy of
5# the License at
6#
7# https://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations under
13# the License.
14
Yuval Peress4b724812024-07-16 15:35:51 +000015def _local_patched_repository_impl(rctx):
16 path = rctx.attr.path
17
18 # This path is a bit ugly to get the actual path if it is relative.
19 if path[0] != "/":
20 path = rctx.workspace_root.get_child(path)
21
22 # Copy the repository
23 rctx.execute(["mkdir", str(rctx.path(""))])
24 for child in path.readdir():
25 copy_args = ["cp", "-fr", str(child), str(rctx.path(""))]
26 if rctx.attr.debug:
27 print(copy_args)
28 result = rctx.execute(copy_args)
29 if result.return_code != 0:
30 fail("Failed to copy %s (%s):\n%s" % (rctx.attr.path, result.return_code, result.stderr))
31
32 # Now patch the repository
33 for patch_file in rctx.attr.patches:
34 patch_file_path_string = str(rctx.path(patch_file).realpath)
35 if rctx.attr.debug:
36 print("Applying patch file: %s / %s" % (patch_file, patch_file_path_string))
37 result = rctx.execute([
38 "bash",
39 "-c",
40 "patch -p0 < " + patch_file_path_string,
41 ])
42 if result.return_code != 0:
43 fail("Failed to apply patch: %s\n%s" % (patch_file, result.stderr))
44
45local_patched_repository = repository_rule(
46 implementation = _local_patched_repository_impl,
47 attrs = {
48 "debug": attr.bool(default = False),
49 "patches": attr.label_list(allow_files = True),
50 "path": attr.string(mandatory = True),
51 },
52 local = True,
53)
54
55def _create_zephyr_patch_file_impl(rctx):
56 script_path = Label("//:generate_diff.py")
57 output_file = rctx.attr.filename
58 output_file_path = rctx.path(output_file)
59
60 rctx.file(output_file)
61 rctx.file("BUILD")
62
63 args = [
64 rctx.which("python3"),
65 script_path,
66 "--root-dir",
67 rctx.path(script_path).dirname,
68 "-o",
69 output_file_path,
70 ]
71 if rctx.attr.debug:
72 print(args)
73 result = rctx.execute(args)
74 if result.return_code != 0:
75 fail("Failed to generate zephyr-bazel diff file (%s):\n%s" % (result.return_code, result.stderr))
76
77 if rctx.attr.debug:
78 print("Generated %s" % (output_file_path))
79 return [
80 DefaultInfo(
81 files = depset([output_file_path, rctx.path("BUILD")]),
82 ),
83 ]
84
85create_zephyr_patch_file = repository_rule(
86 implementation = _create_zephyr_patch_file_impl,
87 attrs = {
88 "debug": attr.bool(default = False),
89 "filename": attr.string(
90 default = "patch.diff",
91 mandatory = True,
92 ),
93 },
94 local = True,
95)
96
97###############################################################################
98
99def _print_file_impl(ctx):
100 # Get the input file
101 input_file = ctx.file.file
102
103 # Create a dummy output file
104 output_file = ctx.actions.declare_file(ctx.label.name + ".out")
105
106 # Create a shell action to print the file
107 ctx.actions.run_shell(
108 outputs = [output_file],
109 inputs = [input_file],
110 command = "cat {} > {}".format(input_file.path, output_file.path),
111 )
112
113 # Return DefaultInfo to signal dependencies on the input file
114 return DefaultInfo(files = depset([output_file]))
115
116# Define the rule
117print_file = rule(
118 implementation = _print_file_impl,
119 attrs = {
120 "file": attr.label(allow_single_file = True, mandatory = True),
121 },
122)
Yuval Peress7e9e1df2025-02-27 13:47:34 -0800123
124###############################################################################
125
126def _version_header_impl(ctx):
127 version_file = ctx.attr.version_file
128 version_template = ctx.attr.version_template
129
130 version_content = ctx.read(version_file)
131 template_content = ctx.read(version_template)
132
133 # Extract version components using string manipulation
134 version_major = 0
135 version_minor = 0
136 patchlevel = 0
137 version_tweak = 0
138 for line in version_content.splitlines():
139 if line.startswith("VERSION_MAJOR"):
140 version_major = int(line.split("=")[1].strip())
141 elif line.startswith("VERSION_MINOR"):
142 version_minor = int(line.split("=")[1].strip())
143 elif line.startswith("PATCHLEVEL"):
144 patchlevel = int(line.split("=")[1].strip())
145 elif line.startswith("VERSION_TWEAK"):
146 version_tweak = int(line.split("=")[1].strip())
147
148 version_type = ctx.attr.VERSION_TYPE
149 zephyr_version_code = (version_major << 16) | (version_minor << 8) | patchlevel
150 kernelversion = (zephyr_version_code << 8) | version_tweak
151 kernelversion_hex = "0x%x" % kernelversion
152 kernel_version_number_hex = "0x%x" % zephyr_version_code
153 kernel_version_major = version_major
154 kernel_version_minor = version_minor
155 kernel_patchlevel = patchlevel
156 kernel_version_tweak = version_tweak
157 kernel_version_string = "{}.{}.{}-{}".format(version_major, version_minor, patchlevel, version_tweak)
158 kernel_version_extended_string = kernel_version_string + "+0"
159 kernel_version_tweak_string = "{}.{}.{}-0".format(version_major, version_minor, patchlevel)
160 build_version_name = "BUILD_VERSION"
161
162 template_dict = {
163 "VERSION_TYPE": version_type,
164 "ZEPHYR_VERSION_CODE": str(zephyr_version_code),
165 "KERNELVERSION": kernelversion_hex,
166 "KERNEL_VERSION_NUMBER": kernel_version_number_hex,
167 "KERNEL_VERSION_MAJOR": str(kernel_version_major),
168 "KERNEL_VERSION_MINOR": str(kernel_version_minor),
169 "KERNEL_PATCHLEVEL": str(kernel_patchlevel),
170 "KERNEL_VERSION_TWEAK": str(kernel_version_tweak),
171 "KERNEL_VERSION_STRING": kernel_version_string,
172 "KERNEL_VERSION_EXTENDED_STRING": kernel_version_extended_string,
173 "KERNEL_VERSION_TWEAK_STRING": kernel_version_tweak_string,
174 "KERNEL_VERSION_CUSTOMIZATION": "",
175 "BUILD_VERSION_NAME": build_version_name,
176 "BUILD_VERSION": "v" + kernel_version_string,
177 }
178
179 template_content = template_content.replace("#cmakedefine", "#define")
180
181 for variable, value in template_dict.items():
182 template_content = template_content.replace("@" + variable + "@", value)
183
184 for variable, value in template_dict.items():
185 template_content = template_content.replace("@" + variable + "@", value)
186
187
188 ctx.file("zephyr/version.h", content = template_content, executable = False)
189 ctx.file(
190 "BUILD.bazel",
191 content = """
192cc_library(
193 name = "version",
194 hdrs = ["zephyr/version.h"],
195 includes = ["."],
196 visibility = ["//visibility:public"],
197)
198""",
199 executable = False,
200 )
201
202version_header = repository_rule(
203 implementation = _version_header_impl,
204 attrs = {
205 "version_file": attr.label(
206 mandatory = True,
207 allow_single_file = True,
208 ),
209 "version_template": attr.label(
210 mandatory = True,
211 allow_single_file = True,
212 ),
213 "VERSION_TYPE": attr.string(default = "KERNEL"),
214 },
215)