blob: 27ef474957fd2146f7a530a317238ffad9ad341b [file] [log] [blame]
Justin DeMartino32c10882019-11-05 15:59:43 -08001# Copyright 2019 Google Inc. All rights reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://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,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15"""Generates gen_headers_<arch>.bp or generates/checks kernel headers."""
16
17from __future__ import absolute_import
18from __future__ import division
19from __future__ import print_function
20
21import argparse
22import filecmp
23import os
24import re
25import subprocess
26import sys
27
28
29def gen_version_h(verbose, gen_dir, version_makefile):
30 """Generate linux/version.h
31
32 Scan the version_makefile for the version info, and then generate
33 linux/version.h in the gen_dir as done in kernel Makefile function
34 filechk_version.h
35
36 Args:
37 verbose: Set True to print progress messages.
38 gen_dir: Where to place the generated files.
39 version_makefile: The makefile that contains version info.
40 Return:
41 If version info not found, False. Otherwise, True.
42 """
43
44 version_re = re.compile(r'VERSION\s*=\s*(\d+)')
45 patchlevel_re = re.compile(r'PATCHLEVEL\s*=\s*(\d+)')
46 sublevel_re = re.compile(r'SUBLEVEL\s*=\s*(\d+)')
47
48 version_str = None
49 patchlevel_str = None
50 sublevel_str = None
51
52 if verbose:
53 print('gen_version_h: processing [%s]' % version_makefile)
54
55 with open(version_makefile, 'r') as f:
56 while not version_str or not patchlevel_str or not sublevel_str:
57 line = f.readline()
58
59 if not line:
60 print(
61 'error: gen_version_h: failed to parse kernel version from %s' %
62 version_makefile)
63 return False
64
65 line = line.rstrip()
66
67 if verbose:
68 print('gen_version_h: line is %s' % line)
69
70 if not version_str:
71 match = version_re.match(line)
72 if match:
73 if verbose:
74 print('gen_version_h: matched version [%s]' % line)
75 version_str = match.group(1)
76 continue
77
78 if not patchlevel_str:
79 match = patchlevel_re.match(line)
80 if match:
81 if verbose:
82 print('gen_version_h: matched patchlevel [%s]' % line)
83 patchlevel_str = match.group(1)
84 continue
85
86 if not sublevel_str:
87 match = sublevel_re.match(line)
88 if match:
89 if verbose:
90 print('gen_version_h: matched sublevel [%s]' % line)
91 sublevel_str = match.group(1)
92 continue
93
94 version = int(version_str)
95 patchlevel = int(patchlevel_str)
96 sublevel = int(sublevel_str)
97
98 if verbose:
99 print(
100 'gen_version_h: found kernel version %d.%d.%d' %
101 (version, patchlevel, sublevel))
102
103 version_h = os.path.join(gen_dir, 'linux', 'version.h')
104
105 with open(version_h, 'w') as f:
106 # This code must match the code in Makefile in the make function
107 # filechk_version.h
108 version_code = (version << 16) + (patchlevel << 8) + sublevel
109 f.write('#define LINUX_VERSION_CODE %d\n' % version_code)
110 f.write(
111 '#define KERNEL_VERSION(a,b,c) ' +
112 '(((a) << 16) + ((b) << 8) + (c))\n')
113
114 return True
115
116
117def scan_arch_kbuild(verbose, arch_asm_kbuild, asm_generic_kbuild, arch_include_uapi):
118 """Scan arch_asm_kbuild for generated headers.
119
120 This function processes the Kbuild file to scan for three types of files that
121 need to be generated. The first type are syscall generated headers, which are
122 identified by adding to the generated-y make variable. The second type are
123 generic headers, which are arch-specific headers that simply wrap the
124 asm-generic counterpart, and are identified by adding to the generic-y make
125 variable. The third type are mandatory headers that should be present in the
126 /usr/include/asm folder.
127
128 Args:
129 verbose: Set True to print progress messages.
130 arch_asm_kbuild: The Kbuild file containing lists of headers to generate.
131 asm_generic_kbuild: The Kbuild file containing lists of mandatory headers.
132 arch_include_uapi: Headers in /arch/<arch>/include/uapi directory
133 Return:
134 Two lists of discovered headers, one for generated and one for generic.
135 """
136
137 generated_y_re = re.compile(r'generated-y\s*\+=\s*(\S+)')
138 generic_y_re = re.compile(r'generic-y\s*\+=\s*(\S+)')
139 mandatory_y_re = re.compile(r'mandatory-y\s*\+=\s*(\S+)')
140
141 # This loop parses arch_asm_kbuild for various kinds of headers to generate.
142
143 if verbose:
144 print('scan_arch_kbuild: processing [%s]' % arch_asm_kbuild)
145
146 generated_list = []
147 generic_list = []
148 arch_include_uapi_list = [os.path.basename(x) for x in arch_include_uapi]
149 mandatory_pre_list = []
150 mandatory_list = []
151
152
153 with open(arch_asm_kbuild, 'r') as f:
154 while True:
155 line = f.readline()
156
157 if not line:
158 break
159
160 line = line.rstrip()
161
162 if verbose:
163 print('scan_arch_kbuild: line is %s' % line)
164
165 match = generated_y_re.match(line)
166
167 if match:
168 if verbose:
169 print('scan_arch_kbuild: matched [%s]' % line)
170 generated_list.append(match.group(1))
171 continue
172
173 match = generic_y_re.match(line)
174
175 if match:
176 if verbose:
177 print('scan_arch_kbuild: matched [%s]' % line)
178 generic_list.append(match.group(1))
179 continue
180
181 # This loop parses asm_generic_kbuild for various kinds of headers to generate.
182
183 if verbose:
184 print('scan_arch_kbuild: processing [%s]' % asm_generic_kbuild)
185
186 with open(asm_generic_kbuild, 'r') as f:
187 while True:
188 line = f.readline()
189
190 if not line:
191 break
192
193 line = line.rstrip()
194
195 if verbose:
196 print('scan_arch_kbuild: line is %s' % line)
197
198 match = mandatory_y_re.match(line)
199
200 if match:
201 if verbose:
202 print('scan_arch_kbuild: matched [%s]' % line)
203 mandatory_pre_list.append(match.group(1))
204 continue
205
206 comb_list = generic_list + generated_list + arch_include_uapi_list
207 mandatory_list = [ x for x in mandatory_pre_list if x not in comb_list]
208 if verbose:
209 print("generic")
210 for x in generic_list:
211 print(x)
212 print("generated")
213 for x in generated_list:
214 print(x)
215 print("mandatory")
216 for x in mandatory_list:
217 print(x)
218 print("arch_include_uapi_list")
219 for x in arch_include_uapi_list:
220 print(x)
221
222 return (generated_list, generic_list, mandatory_list)
223
224
225def gen_arch_headers(
226 verbose, gen_dir, arch_asm_kbuild, asm_generic_kbuild, arch_syscall_tool, arch_syscall_tbl, arch_include_uapi):
227 """Process arch-specific and asm-generic uapi/asm/Kbuild to generate headers.
228
229 The function consists of a call to scan_arch_kbuild followed by three loops.
230 The first loop generates headers found and placed in the generated_list by
231 scan_arch_kbuild. The second loop generates headers found and placed in the
232 generic_list by the scan_arch_kbuild. The third loop generates headers found
233 in mandatory_list by scan_arch_kbuild.
234
235 The function does some parsing of file names and tool invocations. If that
236 parsing fails for some reason (e.g., we don't know how to generate the
237 header) or a tool invocation fails, then this function will count that as
238 an error but keep processing. In the end, the function returns the number of
239 errors encountered.
240
241 Args:
242 verbose: Set True to print progress messages.
243 gen_dir: Where to place the generated files.
244 arch_asm_kbuild: The Kbuild file containing lists of headers to generate.
245 asm_generic_kbuild: The Kbuild file containing lists of mandatory headers.
246 arch_syscall_tool: The arch script that generates syscall headers, or None.
247 arch_syscall_tbl: The arch script that defines syscall vectors, or None.
248 arch_include_uapi: Headers in arch/<arch>/include/uapi directory.
249 Return:
250 The number of parsing errors encountered.
251 """
252
253 error_count = 0
254
255 # First generate the lists
256
257 (generated_list, generic_list, mandatory_list) = scan_arch_kbuild(verbose, arch_asm_kbuild, asm_generic_kbuild ,arch_include_uapi)
258
259 # Now we're at the first loop, which is able to generate syscall headers
260 # found in the first loop, and placed in generated_list. It's okay for this
261 # list to be empty. In that case, of course, the loop does nothing.
262
263 abi_re = re.compile(r'unistd-(\S+)\.h')
264
265 for generated in generated_list:
266 gen_h = os.path.join(gen_dir, 'asm', generated)
267 match = abi_re.match(generated)
268
269 if match:
270 abi = match.group(1)
271
272 cmd = [
273 '/bin/bash',
274 arch_syscall_tool,
275 arch_syscall_tbl,
276 gen_h,
277 abi,
278 '',
279 '__NR_SYSCALL_BASE',
280 ]
281
282 if verbose:
283 print('gen_arch_headers: cmd is %s' % cmd)
284
285 result = subprocess.call(cmd)
286
287 if result != 0:
288 print('error: gen_arch_headers: cmd %s failed %d' % (cmd, result))
289 error_count += 1
290 else:
291 print('error: gen_arch_headers: syscall header has bad filename: %s' % generated)
292 error_count += 1
293
294 # Now we're at the second loop, which generates wrappers from arch-specific
295 # headers listed in generic_list to the corresponding asm-generic header.
296
297 for generic in generic_list:
298 wrap_h = os.path.join(gen_dir, 'asm', generic)
299 with open(wrap_h, 'w') as f:
300 f.write('#include <asm-generic/%s>\n' % generic)
301
302 # Now we're at the third loop, which generates wrappers from asm
303 # headers listed in mandatory_list to the corresponding asm-generic header.
304
305 for mandatory in mandatory_list:
306 wrap_h = os.path.join(gen_dir, 'asm', mandatory)
307 with open(wrap_h, 'w') as f:
308 f.write('#include <asm-generic/%s>\n' % mandatory)
309 return error_count
310
311
Bill Peckham8bca38b2021-01-26 13:06:41 -0800312def run_headers_install(verbose, gen_dir, headers_install, unifdef, prefix, h):
Justin DeMartino32c10882019-11-05 15:59:43 -0800313 """Process a header through the headers_install script.
314
315 The headers_install script does some processing of a header so that it is
316 appropriate for inclusion in a userland program. This function invokes that
317 script for one header file.
318
319 The input file is a header file found in the directory named by prefix. This
320 function stips the prefix from the header to generate the name of the
321 processed header.
322
323 Args:
324 verbose: Set True to print progress messages.
325 gen_dir: Where to place the generated files.
326 headers_install: The script that munges the header.
Bill Peckham8bca38b2021-01-26 13:06:41 -0800327 unifdef: The unifdef tool used by headers_install.
Justin DeMartino32c10882019-11-05 15:59:43 -0800328 prefix: The prefix to strip from h to generate the output filename.
329 h: The input header to process.
330 Return:
331 If parsing or the tool fails, False. Otherwise, True
332 """
333
334 if not h.startswith(prefix):
335 print('error: expected prefix [%s] on header [%s]' % (prefix, h))
336 return False
337
338 out_h = os.path.join(gen_dir, h[len(prefix):])
339 (out_h_dirname, out_h_basename) = os.path.split(out_h)
340 h_dirname = os.path.dirname(h)
341
342 cmd = [headers_install, h, out_h]
343
344 if verbose:
345 print('run_headers_install: cmd is %s' % cmd)
346
Bill Peckham8bca38b2021-01-26 13:06:41 -0800347 env = os.environ.copy()
348 env["LOC_UNIFDEF"] = unifdef
349 result = subprocess.call(['sh', headers_install, h, out_h], env=env)
Justin DeMartino32c10882019-11-05 15:59:43 -0800350
351 if result != 0:
352 print('error: run_headers_install: cmd %s failed %d' % (cmd, result))
353 return False
354
355 return True
356
357
358def glob_headers(prefix, rel_glob, excludes):
359 """Recursively scan the a directory for headers.
360
361 This function recursively scans the directory identified by prefix for
362 headers. We don't yet have a new enough version of python3 to use the
363 better glob function, so right now we assume the glob is '**/*.h'.
364
365 The function filters out any files that match the items in excludes.
366
367 Args:
368 prefix: The directory to recursively scan for headers.
369 rel_glob: The shell-style glob that identifies the header pattern.
370 excludes: A list of headers to exclude from the glob.
371 Return:
372 A list of headers discovered with excludes excluded.
373 """
374
375 # If we had python 3.5+, we could use the fancy new glob.glob.
376 # full_glob = os.path.join(prefix, rel_glob)
377 # full_srcs = glob.glob(full_glob, recursive=True)
378
379 full_dirs = [prefix]
380 full_srcs = []
381
382 while full_dirs:
383 full_dir = full_dirs.pop(0)
384 items = sorted(os.listdir(full_dir))
385
386 for item in items:
387 full_item = os.path.join(full_dir, item)
388
389 if os.path.isdir(full_item):
390 full_dirs.append(full_item)
391 continue
392
393 if full_item in excludes:
394 continue
395
396 if full_item.endswith('.h'):
397 full_srcs.append(full_item)
398
399 return full_srcs
400
401
402def find_out(verbose, module_dir, prefix, rel_glob, excludes, outs):
403 """Build a list of outputs for the genrule that creates kernel headers.
404
405 This function scans for headers in the source tree and produces a list of
406 output (generated) headers.
407
408 Args:
409 verbose: Set True to print progress messages.
410 module_dir: The root directory of the kernel source.
411 prefix: The prefix with in the kernel source tree to search for headers.
412 rel_glob: The pattern to use when matching headers under prefix.
413 excludes: A list of files to exclude from the glob.
414 outs: The list to populdate with the headers that will be generated.
415 Return:
416 The number of errors encountered.
417 """
418
419 # Turn prefix, which is relative to the soong module, to a full prefix that
420 # is relative to the Android source tree.
421
422 full_prefix = os.path.join(module_dir, prefix)
423
424 # Convert the list of excludes, which are relative to the soong module, to a
425 # set of excludes (for easy hashing), relative to the Android source tree.
426
427 full_excludes = set()
428
429 if excludes:
430 for exclude in excludes:
431 full_exclude = os.path.join(full_prefix, exclude)
432 full_excludes.add(full_exclude)
433
434 # Glob those headers.
435
436 full_srcs = glob_headers(full_prefix, rel_glob, full_excludes)
437
438 # Now convert the file names, which are relative to the Android source tree,
439 # to be relative to the gen dir. This means stripping off the module prefix
440 # and the directory within this module.
441
442 module_dir_sep = module_dir + os.sep
443 prefix_sep = prefix + os.sep
444
445 if verbose:
446 print('find_out: module_dir_sep [%s]' % module_dir_sep)
447 print('find_out: prefix_sep [%s]' % prefix_sep)
448
449 error_count = 0
450
451 for full_src in full_srcs:
452 if verbose:
453 print('find_out: full_src [%s]' % full_src)
454
455 if not full_src.startswith(module_dir_sep):
456 print('error: expected %s to start with %s' % (full_src, module_dir_sep))
457 error_count += 1
458 continue
459
460 local_src = full_src[len(module_dir_sep):]
461
462 if verbose:
463 print('find_out: local_src [%s]' % local_src)
464
465 if not local_src.startswith(prefix_sep):
466 print('error: expected %s to start with %s' % (local_src, prefix_sep))
467 error_count += 1
468 continue
469
470 # After stripping the module directory and the prefix, we're left with the
471 # name of a header that we'll generate, relative to the base of of a the
472 # the include path.
473
474 local_out = local_src[len(prefix_sep):]
475
476 if verbose:
477 print('find_out: local_out [%s]' % local_out)
478
479 outs.append(local_out)
480
481 return error_count
482
483
484def gen_blueprints(
485 verbose, header_arch, gen_dir, arch_asm_kbuild, asm_generic_kbuild, module_dir,
486 rel_arch_asm_kbuild, rel_asm_generic_kbuild, arch_include_uapi, techpack_include_uapi):
487 """Generate a blueprints file containing modules that invoke this script.
488
489 This function generates a blueprints file that contains modules that
490 invoke this script to generate kernel headers. We generate the blueprints
491 file as needed, but we don't actually use the generated file. The blueprints
492 file that we generate ends up in the out directory, and we can use it to
493 detect if the checked-in version of the file (in the source directory) is out
494 of date. This pattern occurs in the Android source tree in several places.
495
496 Args:
497 verbose: Set True to print progress messages.
498 header_arch: The arch for which to generate headers.
499 gen_dir: Where to place the generated files.
500 arch_asm_kbuild: The Kbuild file containing lists of headers to generate.
501 asm_generic_kbuild: The Kbuild file containing lists of mandatory headers.
502 module_dir: The root directory of the kernel source.
503 rel_arch_asm_kbuild: arch_asm_kbuild relative to module_dir.
504 Return:
505 The number of errors encountered.
506 """
507 error_count = 0
508
509 # The old and new blueprints files. We generate the new one, but we need to
510 # refer to the old one in the modules that we generate.
511 old_gen_headers_bp = 'gen_headers_%s.bp' % header_arch
512 new_gen_headers_bp = os.path.join(gen_dir, old_gen_headers_bp)
513
514 # Tools and tool files.
515 headers_install_sh = 'headers_install.sh'
Bill Peckham8bca38b2021-01-26 13:06:41 -0800516 unifdef = 'unifdef'
Justin DeMartino32c10882019-11-05 15:59:43 -0800517 kernel_headers_py = 'kernel_headers.py'
518 arm_syscall_tool = 'arch/arm/tools/syscallhdr.sh'
519
520 # Sources
521 makefile = 'Makefile'
522 arm_syscall_tbl = 'arch/arm/tools/syscall.tbl'
523 rel_glob = '**/*.h'
524 generic_prefix = 'include/uapi'
525 arch_prefix = os.path.join('arch', header_arch, generic_prefix)
526 generic_src = os.path.join(generic_prefix, rel_glob)
527 arch_src = os.path.join(arch_prefix, rel_glob)
Rishabh Bhatnagar8878f182020-02-12 13:50:44 -0800528 techpack_src = os.path.join('techpack/*',generic_prefix, '*',rel_glob)
Justin DeMartino32c10882019-11-05 15:59:43 -0800529
530 # Excluded sources, architecture specific.
531 exclude_srcs = []
532
533 if header_arch == "arm":
534 exclude_srcs = ['linux/a.out.h']
535
536 if header_arch == "arm64":
537 exclude_srcs = ['linux/a.out.h']
538
539 # Scan the arch_asm_kbuild file for files that need to be generated and those
540 # that are generic (i.e., need to be wrapped).
541
542 (generated_list, generic_list, mandatory_list) = scan_arch_kbuild(verbose,
543 arch_asm_kbuild, asm_generic_kbuild, arch_include_uapi)
544
545 generic_out = []
546 error_count += find_out(
547 verbose, module_dir, generic_prefix, rel_glob, exclude_srcs, generic_out)
548
549 arch_out = []
550 error_count += find_out(
551 verbose, module_dir, arch_prefix, rel_glob, None, arch_out)
552
553 techpack_out = [x.split('include/uapi/')[1] for x in techpack_include_uapi]
554
555 if error_count != 0:
556 return error_count
557
558 # Generate the blueprints file.
559
560 if verbose:
561 print('gen_blueprints: generating %s' % new_gen_headers_bp)
562
563 with open(new_gen_headers_bp, 'w') as f:
564 f.write('// ***** DO NOT EDIT *****\n')
565 f.write('// This file is generated by %s\n' % kernel_headers_py)
566 f.write('\n')
Rishabh Bhatnagar8878f182020-02-12 13:50:44 -0800567 f.write('gen_headers_srcs_%s = [\n' % header_arch)
568 f.write(' "%s",\n' % rel_arch_asm_kbuild)
569 f.write(' "%s",\n' % rel_asm_generic_kbuild)
570 f.write(' "%s",\n' % makefile)
571
572 if header_arch == "arm":
573 f.write(' "%s",\n' % arm_syscall_tbl)
574
575 f.write(' "%s",\n' % generic_src)
576 f.write(' "%s",\n' % arch_src)
577 f.write(' "%s",\n' % techpack_src)
578 f.write(']\n')
579 f.write('\n')
580
581 if exclude_srcs:
582 f.write('gen_headers_exclude_srcs_%s = [\n' % header_arch)
583 for h in exclude_srcs:
584 f.write(' "%s",\n' % os.path.join(generic_prefix, h))
585 f.write(']\n')
586 f.write('\n')
587
588 f.write('gen_headers_out_%s = [\n' % header_arch)
Justin DeMartino32c10882019-11-05 15:59:43 -0800589
590 if generated_list:
591 f.write('\n')
592 f.write(' // Matching generated-y:\n')
593 f.write('\n')
594 for h in generated_list:
595 f.write(' "asm/%s",\n' % h)
596
597 if generic_list:
598 f.write('\n')
599 f.write(' // Matching generic-y:\n')
600 f.write('\n')
601 for h in generic_list:
602 f.write(' "asm/%s",\n' % h)
603
604 if mandatory_list:
605 f.write('\n')
606 f.write(' // Matching mandatory-y:\n')
607 f.write('\n')
608 for h in mandatory_list:
609 f.write(' "asm/%s",\n' % h)
610
611 if generic_out:
612 f.write('\n')
613 f.write(' // From %s\n' % generic_src)
614 f.write('\n')
615 for h in generic_out:
616 f.write(' "%s",\n' % h)
617
618 if arch_out:
619 f.write('\n')
620 f.write(' // From %s\n' % arch_src)
621 f.write('\n')
622 for h in arch_out:
623 f.write(' "%s",\n' % h)
624
625 if techpack_out:
626 f.write('\n')
627 f.write(' // From %s\n' % techpack_src)
628 f.write('\n')
629 for h in techpack_out:
630 f.write(' "%s",\n' % h)
631
632 f.write(']\n')
633 f.write('\n')
634
635 gen_blueprints_module_name = 'qti_generate_gen_headers_%s' % header_arch
636
637 f.write('genrule {\n')
638 f.write(' // This module generates the gen_headers_<arch>.bp file\n')
639 f.write(' // (i.e., a new version of this file) so that it can be\n')
640 f.write(' // checked later to ensure that it matches the checked-\n')
641 f.write(' // in version (this file).\n')
642 f.write(' name: "%s",\n' % gen_blueprints_module_name)
Rishabh Bhatnagar8878f182020-02-12 13:50:44 -0800643 f.write(' srcs: gen_headers_srcs_%s,\n' % header_arch)
644 if exclude_srcs:
645 f.write(' exclude_srcs: gen_headers_exclude_srcs_%s,\n' % header_arch)
646
Justin DeMartino32c10882019-11-05 15:59:43 -0800647 f.write(' tool_files: ["kernel_headers.py"],\n')
648 f.write(' cmd: "python3 $(location kernel_headers.py) " +\n')
649 f.write(' kernel_headers_verbose +\n')
650 f.write(' "--header_arch %s " +\n' % header_arch)
651 f.write(' "--gen_dir $(genDir) " +\n')
652 f.write(' "--arch_asm_kbuild $(location %s) " +\n' % rel_arch_asm_kbuild)
653 f.write(' "--arch_include_uapi $(locations %s) " +\n' % arch_src)
Rishabh Bhatnagar8878f182020-02-12 13:50:44 -0800654 f.write(' "--techpack_include_uapi $(locations %s) " +\n' % techpack_src)
Justin DeMartino32c10882019-11-05 15:59:43 -0800655 f.write(' "--asm_generic_kbuild $(location %s) " +\n' % rel_asm_generic_kbuild)
Rishabh Bhatnagar8878f182020-02-12 13:50:44 -0800656 f.write(' "blueprints " +\n')
657 f.write(' "# $(in)",\n')
Justin DeMartino32c10882019-11-05 15:59:43 -0800658 f.write(' out: ["gen_headers_%s.bp"],\n' % header_arch)
659 f.write('}\n')
660 f.write('\n')
661
662 f.write('genrule {\n')
663 f.write(' name: "qti_generate_kernel_headers_%s",\n' % header_arch)
Bill Peckham8bca38b2021-01-26 13:06:41 -0800664 f.write(' tools: [\n')
665 f.write(' "%s",\n' % headers_install_sh)
666 f.write(' "%s",\n' % unifdef)
667 f.write(' ],\n')
Justin DeMartino32c10882019-11-05 15:59:43 -0800668 f.write(' tool_files: [\n')
669 f.write(' "%s",\n' % kernel_headers_py)
670
671 if header_arch == "arm":
672 f.write(' "%s",\n' % arm_syscall_tool)
673
674 f.write(' ],\n')
Rishabh Bhatnagar8878f182020-02-12 13:50:44 -0800675 f.write(' srcs: gen_headers_srcs_%s +[\n' % header_arch)
Justin DeMartino32c10882019-11-05 15:59:43 -0800676 f.write(' "%s",\n' % old_gen_headers_bp)
677 f.write(' ":%s",\n' % gen_blueprints_module_name)
Justin DeMartino32c10882019-11-05 15:59:43 -0800678 f.write(' ],\n')
679
680 if exclude_srcs:
Rishabh Bhatnagar8878f182020-02-12 13:50:44 -0800681 f.write(' exclude_srcs: gen_headers_exclude_srcs_%s,\n' % header_arch)
Justin DeMartino32c10882019-11-05 15:59:43 -0800682
683 f.write(' cmd: "python3 $(location %s) " +\n' % kernel_headers_py)
684 f.write(' kernel_headers_verbose +\n')
685 f.write(' "--header_arch %s " +\n' % header_arch)
686 f.write(' "--gen_dir $(genDir) " +\n')
687 f.write(' "--arch_asm_kbuild $(location %s) " +\n' % rel_arch_asm_kbuild)
688 f.write(' "--arch_include_uapi $(locations %s) " +\n' % arch_src)
Rishabh Bhatnagar8878f182020-02-12 13:50:44 -0800689 f.write(' "--techpack_include_uapi $(locations %s) " +\n' % techpack_src)
Justin DeMartino32c10882019-11-05 15:59:43 -0800690 f.write(' "--asm_generic_kbuild $(location %s) " +\n' % rel_asm_generic_kbuild)
691 f.write(' "headers " +\n')
692 f.write(' "--old_gen_headers_bp $(location %s) " +\n' % old_gen_headers_bp)
693 f.write(' "--new_gen_headers_bp $(location :%s) " +\n' % gen_blueprints_module_name)
694 f.write(' "--version_makefile $(location %s) " +\n' % makefile)
695
696 if header_arch == "arm":
697 f.write(' "--arch_syscall_tool $(location %s) " +\n' % arm_syscall_tool)
698 f.write(' "--arch_syscall_tbl $(location %s) " +\n' % arm_syscall_tbl)
699
700 f.write(' "--headers_install $(location %s) " +\n' % headers_install_sh)
Bill Peckham8bca38b2021-01-26 13:06:41 -0800701 f.write(' "--unifdef $(location %s) " +\n' % unifdef)
Justin DeMartino32c10882019-11-05 15:59:43 -0800702 f.write(' "--include_uapi $(locations %s)",\n' % generic_src)
Rishabh Bhatnagar8878f182020-02-12 13:50:44 -0800703 f.write(' out: ["linux/version.h"] + gen_headers_out_%s,\n' % header_arch)
Justin DeMartino32c10882019-11-05 15:59:43 -0800704 f.write('}\n')
705
706 return 0
707
Siddharth Guptafc242a92020-01-29 17:22:38 -0800708def parse_bp_for_headers(file_name, headers):
709 parsing_headers = False
Rishabh Bhatnagar8878f182020-02-12 13:50:44 -0800710 pattern = re.compile("gen_headers_out_[a-zA-Z0-9]+\s*=\s*\[\s*")
Siddharth Guptafc242a92020-01-29 17:22:38 -0800711 with open(file_name, 'r') as f:
712 for line in f:
713 line = line.strip()
714 if pattern.match(line):
715 parsing_headers = True
716 continue
717
718 if line.find("]") != -1 and parsing_headers:
719 break
720
721 if not parsing_headers:
722 continue
723
724 if line.find("//") == 0:
725 continue
726
727 headers.add(line[1:-2])
728
729def headers_diff(old_file, new_file):
730 old_headers = set()
731 new_headers = set()
732 diff_detected = False
733
734 parse_bp_for_headers(old_file, old_headers)
735 parse_bp_for_headers(new_file, new_headers)
736
737 diff = old_headers - new_headers
738 if len(diff):
739 diff_detected = True
740 print("Headers to remove:")
741 for x in diff:
742 print("\t{}".format(x))
743
744 diff = new_headers - old_headers
745 if len(diff):
746 diff_detected = True
747 print("Headers to add:")
748 for x in diff:
749 print("\t{}".format(x))
750
751 return diff_detected
Justin DeMartino32c10882019-11-05 15:59:43 -0800752
753def gen_headers(
754 verbose, header_arch, gen_dir, arch_asm_kbuild, asm_generic_kbuild, module_dir,
755 old_gen_headers_bp, new_gen_headers_bp, version_makefile,
Bill Peckham8bca38b2021-01-26 13:06:41 -0800756 arch_syscall_tool, arch_syscall_tbl, headers_install, unifdef, include_uapi,
Justin DeMartino32c10882019-11-05 15:59:43 -0800757 arch_include_uapi, techpack_include_uapi):
758 """Generate the kernel headers.
759
760 This script generates the version.h file, the arch-specific headers including
761 syscall-related generated files and wrappers around generic files, and uses
762 the headers_install tool to process other generic uapi and arch-specifc uapi
763 files.
764
765 Args:
766 verbose: Set True to print progress messages.
767 header_arch: The arch for which to generate headers.
768 gen_dir: Where to place the generated files.
769 arch_asm_kbuild: The Kbuild file containing lists of headers to generate.
770 asm_generic_kbuild: The Kbuild file containing mandatory headers.
771 module_dir: The root directory of the kernel source.
772 old_gen_headers_bp: The old gen_headers_<arch>.bp file to check.
773 new_gen_headers_bp: The new gen_headers_<arch>.bp file to check.
774 version_makefile: The kernel Makefile that contains version info.
775 arch_syscall_tool: The arch script that generates syscall headers.
776 arch_syscall_tbl: The arch script that defines syscall vectors.
777 headers_install: The headers_install tool to process input headers.
Bill Peckham8bca38b2021-01-26 13:06:41 -0800778 unifdef: The unifdef tool used by headers_install.
Justin DeMartino32c10882019-11-05 15:59:43 -0800779 include_uapi: The list of include/uapi header files.
780 arch_include_uapi: The list of arch/<arch>/include/uapi header files.
781 Return:
782 The number of errors encountered.
783 """
784
Siddharth Guptafc242a92020-01-29 17:22:38 -0800785 if headers_diff(old_gen_headers_bp, new_gen_headers_bp):
Justin DeMartino32c10882019-11-05 15:59:43 -0800786 print('error: gen_headers blueprints file is out of date, suggested fix:')
Siddharth Guptafc242a92020-01-29 17:22:38 -0800787 print('#######Please add or remove the above mentioned headers from %s' % (old_gen_headers_bp))
Justin DeMartino32c10882019-11-05 15:59:43 -0800788 print('then re-run the build')
Rishabh Bhatnagar20004262020-04-14 21:47:30 -0700789 #return 1
Justin DeMartino32c10882019-11-05 15:59:43 -0800790
791 error_count = 0
792
793 if not gen_version_h(verbose, gen_dir, version_makefile):
794 error_count += 1
795
796 error_count += gen_arch_headers(
797 verbose, gen_dir, arch_asm_kbuild, asm_generic_kbuild, arch_syscall_tool, arch_syscall_tbl ,arch_include_uapi)
798
799 uapi_include_prefix = os.path.join(module_dir, 'include', 'uapi') + os.sep
800
801 arch_uapi_include_prefix = os.path.join(
802 module_dir, 'arch', header_arch, 'include', 'uapi') + os.sep
803
804 for h in include_uapi:
805 if not run_headers_install(
Bill Peckham8bca38b2021-01-26 13:06:41 -0800806 verbose, gen_dir, headers_install, unifdef,
Justin DeMartino32c10882019-11-05 15:59:43 -0800807 uapi_include_prefix, h):
808 error_count += 1
809
810 for h in arch_include_uapi:
811 if not run_headers_install(
Bill Peckham8bca38b2021-01-26 13:06:41 -0800812 verbose, gen_dir, headers_install, unifdef,
Justin DeMartino32c10882019-11-05 15:59:43 -0800813 arch_uapi_include_prefix, h):
814 error_count += 1
815
816 for h in techpack_include_uapi:
817 techpack_uapi_include_prefix = os.path.join(h.split('/include/uapi')[0], 'include', 'uapi') + os.sep
818 if not run_headers_install(
Bill Peckham8bca38b2021-01-26 13:06:41 -0800819 verbose, gen_dir, headers_install, unifdef,
Justin DeMartino32c10882019-11-05 15:59:43 -0800820 techpack_uapi_include_prefix, h):
821 error_count += 1
822
823 return error_count
824
825def extract_techpack_uapi_headers(verbose, module_dir):
826
827 """EXtract list of uapi headers from techpack/* directories. We need to export
828 these headers to userspace.
829
830 Args:
831 verbose: Verbose option is provided to script
832 module_dir: Base directory
833 Returs:
834 List of uapi headers
835 """
836
837 techpack_subdir = []
838 techpack_dir = os.path.join(module_dir,'techpack')
839 techpack_uapi = []
840 techpack_uapi_sub = []
841
842 #get list of techpack directories under techpack/
843 if os.path.isdir(techpack_dir):
844 items = sorted(os.listdir(techpack_dir))
845 for x in items:
846 p = os.path.join(techpack_dir, x)
847 if os.path.isdir(p):
848 techpack_subdir.append(p)
849
850 #Print list of subdirs obtained
851 if (verbose):
852 for x in techpack_subdir:
853 print(x)
854
855 #For every subdirectory get list of .h files under include/uapi and append to techpack_uapi list
856 for x in techpack_subdir:
857 techpack_uapi_path = os.path.join(x, 'include/uapi')
858 if (os.path.isdir(techpack_uapi_path)):
859 techpack_uapi_sub = []
860 find_out(verbose, x, 'include/uapi', '**/*.h', None, techpack_uapi_sub)
861 tmp = [os.path.join(techpack_uapi_path, y) for y in techpack_uapi_sub]
862 techpack_uapi = techpack_uapi + tmp
863
864 if (verbose):
865 for x in techpack_uapi:
866 print(x)
867
868 return techpack_uapi
869
870def main():
871 """Parse command line arguments and perform top level control."""
872
873 parser = argparse.ArgumentParser(
874 description=__doc__,
875 formatter_class=argparse.RawDescriptionHelpFormatter)
876
877 # Arguments that apply to every invocation of this script.
878
879 parser.add_argument(
880 '--verbose',
881 action='store_true',
882 help='Print output that describes the workings of this script.')
883 parser.add_argument(
884 '--header_arch',
885 required=True,
886 help='The arch for which to generate headers.')
887 parser.add_argument(
888 '--gen_dir',
889 required=True,
890 help='Where to place the generated files.')
891 parser.add_argument(
892 '--arch_asm_kbuild',
893 required=True,
894 help='The Kbuild file containing lists of headers to generate.')
895 parser.add_argument(
896 '--asm_generic_kbuild',
897 required=True,
898 help='The Kbuild file containing lists of mandatory headers.')
899 parser.add_argument(
900 '--arch_include_uapi',
901 required=True,
902 nargs='*',
903 help='The list of arch/<arch>/include/uapi header files.')
Rishabh Bhatnagar8878f182020-02-12 13:50:44 -0800904 parser.add_argument(
905 '--techpack_include_uapi',
906 required=True,
907 nargs='*',
908 help='The list of techpack/*/include/uapi header files.')
Justin DeMartino32c10882019-11-05 15:59:43 -0800909
910 # The modes.
911
912 subparsers = parser.add_subparsers(
913 dest='mode',
914 help='Select mode')
915 parser_blueprints = subparsers.add_parser(
916 'blueprints',
917 help='Generate the gen_headers_<arch>.bp file.')
918 parser_headers = subparsers.add_parser(
919 'headers',
920 help='Check blueprints, then generate kernel headers.')
921
922 # Arguments that apply to headers mode.
923
924 parser_headers.add_argument(
925 '--old_gen_headers_bp',
926 required=True,
927 help='The old gen_headers_<arch>.bp file to check.')
928 parser_headers.add_argument(
929 '--new_gen_headers_bp',
930 required=True,
931 help='The new gen_headers_<arch>.bp file to check.')
932 parser_headers.add_argument(
933 '--version_makefile',
934 required=True,
935 help='The kernel Makefile that contains version info.')
936 parser_headers.add_argument(
937 '--arch_syscall_tool',
938 help='The arch script that generates syscall headers, if applicable.')
939 parser_headers.add_argument(
940 '--arch_syscall_tbl',
941 help='The arch script that defines syscall vectors, if applicable.')
942 parser_headers.add_argument(
943 '--headers_install',
944 required=True,
945 help='The headers_install tool to process input headers.')
946 parser_headers.add_argument(
Bill Peckham8bca38b2021-01-26 13:06:41 -0800947 '--unifdef',
948 required=True,
949 help='The unifdef tool used by headers_install.')
950 parser_headers.add_argument(
Justin DeMartino32c10882019-11-05 15:59:43 -0800951 '--include_uapi',
952 required=True,
953 nargs='*',
954 help='The list of include/uapi header files.')
955
956 args = parser.parse_args()
957
958 if args.verbose:
959 print('mode [%s]' % args.mode)
960 print('header_arch [%s]' % args.header_arch)
961 print('gen_dir [%s]' % args.gen_dir)
962 print('arch_asm_kbuild [%s]' % args.arch_asm_kbuild)
963 print('asm_generic_kbuild [%s]' % args.asm_generic_kbuild)
964
965 # Extract the module_dir from args.arch_asm_kbuild and rel_arch_asm_kbuild.
966
967 rel_arch_asm_kbuild = os.path.join(
968 'arch', args.header_arch, 'include/uapi/asm/Kbuild')
969
970 suffix = os.sep + rel_arch_asm_kbuild
971
972 if not args.arch_asm_kbuild.endswith(suffix):
973 print('error: expected %s to end with %s' % (args.arch_asm_kbuild, suffix))
974 return 1
975
976 module_dir = args.arch_asm_kbuild[:-len(suffix)]
977
978 rel_asm_generic_kbuild = os.path.join('include/uapi/asm-generic', os.path.basename(args.asm_generic_kbuild))
979
980
981 if args.verbose:
982 print('module_dir [%s]' % module_dir)
983
Justin DeMartino32c10882019-11-05 15:59:43 -0800984
985 if args.mode == 'blueprints':
986 return gen_blueprints(
987 args.verbose, args.header_arch, args.gen_dir, args.arch_asm_kbuild,
Rishabh Bhatnagar8878f182020-02-12 13:50:44 -0800988 args.asm_generic_kbuild, module_dir, rel_arch_asm_kbuild, rel_asm_generic_kbuild, args.arch_include_uapi, args.techpack_include_uapi)
Justin DeMartino32c10882019-11-05 15:59:43 -0800989
990 if args.mode == 'headers':
991 if args.verbose:
992 print('old_gen_headers_bp [%s]' % args.old_gen_headers_bp)
993 print('new_gen_headers_bp [%s]' % args.new_gen_headers_bp)
994 print('version_makefile [%s]' % args.version_makefile)
995 print('arch_syscall_tool [%s]' % args.arch_syscall_tool)
996 print('arch_syscall_tbl [%s]' % args.arch_syscall_tbl)
997 print('headers_install [%s]' % args.headers_install)
Bill Peckham8bca38b2021-01-26 13:06:41 -0800998 print('unifdef [%s]' % args.unifdef)
Justin DeMartino32c10882019-11-05 15:59:43 -0800999
1000 return gen_headers(
1001 args.verbose, args.header_arch, args.gen_dir, args.arch_asm_kbuild,
1002 args.asm_generic_kbuild, module_dir, args.old_gen_headers_bp, args.new_gen_headers_bp,
1003 args.version_makefile, args.arch_syscall_tool, args.arch_syscall_tbl,
Bill Peckham8bca38b2021-01-26 13:06:41 -08001004 args.headers_install, args.unifdef, args.include_uapi, args.arch_include_uapi,
1005 args.techpack_include_uapi)
Justin DeMartino32c10882019-11-05 15:59:43 -08001006
1007 print('error: unknown mode: %s' % args.mode)
1008 return 1
1009
1010
1011if __name__ == '__main__':
1012 sys.exit(main())