blob: 89d60ac780c16f60e30cecd12e08f250b3701de4 [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
312def run_headers_install(verbose, gen_dir, headers_install, prefix, h):
313 """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.
327 prefix: The prefix to strip from h to generate the output filename.
328 h: The input header to process.
329 Return:
330 If parsing or the tool fails, False. Otherwise, True
331 """
332
333 if not h.startswith(prefix):
334 print('error: expected prefix [%s] on header [%s]' % (prefix, h))
335 return False
336
337 out_h = os.path.join(gen_dir, h[len(prefix):])
338 (out_h_dirname, out_h_basename) = os.path.split(out_h)
339 h_dirname = os.path.dirname(h)
340
341 cmd = [headers_install, h, out_h]
342
343 if verbose:
344 print('run_headers_install: cmd is %s' % cmd)
345
346 result = subprocess.call(cmd)
347
348 if result != 0:
349 print('error: run_headers_install: cmd %s failed %d' % (cmd, result))
350 return False
351
352 return True
353
354
355def glob_headers(prefix, rel_glob, excludes):
356 """Recursively scan the a directory for headers.
357
358 This function recursively scans the directory identified by prefix for
359 headers. We don't yet have a new enough version of python3 to use the
360 better glob function, so right now we assume the glob is '**/*.h'.
361
362 The function filters out any files that match the items in excludes.
363
364 Args:
365 prefix: The directory to recursively scan for headers.
366 rel_glob: The shell-style glob that identifies the header pattern.
367 excludes: A list of headers to exclude from the glob.
368 Return:
369 A list of headers discovered with excludes excluded.
370 """
371
372 # If we had python 3.5+, we could use the fancy new glob.glob.
373 # full_glob = os.path.join(prefix, rel_glob)
374 # full_srcs = glob.glob(full_glob, recursive=True)
375
376 full_dirs = [prefix]
377 full_srcs = []
378
379 while full_dirs:
380 full_dir = full_dirs.pop(0)
381 items = sorted(os.listdir(full_dir))
382
383 for item in items:
384 full_item = os.path.join(full_dir, item)
385
386 if os.path.isdir(full_item):
387 full_dirs.append(full_item)
388 continue
389
390 if full_item in excludes:
391 continue
392
393 if full_item.endswith('.h'):
394 full_srcs.append(full_item)
395
396 return full_srcs
397
398
399def find_out(verbose, module_dir, prefix, rel_glob, excludes, outs):
400 """Build a list of outputs for the genrule that creates kernel headers.
401
402 This function scans for headers in the source tree and produces a list of
403 output (generated) headers.
404
405 Args:
406 verbose: Set True to print progress messages.
407 module_dir: The root directory of the kernel source.
408 prefix: The prefix with in the kernel source tree to search for headers.
409 rel_glob: The pattern to use when matching headers under prefix.
410 excludes: A list of files to exclude from the glob.
411 outs: The list to populdate with the headers that will be generated.
412 Return:
413 The number of errors encountered.
414 """
415
416 # Turn prefix, which is relative to the soong module, to a full prefix that
417 # is relative to the Android source tree.
418
419 full_prefix = os.path.join(module_dir, prefix)
420
421 # Convert the list of excludes, which are relative to the soong module, to a
422 # set of excludes (for easy hashing), relative to the Android source tree.
423
424 full_excludes = set()
425
426 if excludes:
427 for exclude in excludes:
428 full_exclude = os.path.join(full_prefix, exclude)
429 full_excludes.add(full_exclude)
430
431 # Glob those headers.
432
433 full_srcs = glob_headers(full_prefix, rel_glob, full_excludes)
434
435 # Now convert the file names, which are relative to the Android source tree,
436 # to be relative to the gen dir. This means stripping off the module prefix
437 # and the directory within this module.
438
439 module_dir_sep = module_dir + os.sep
440 prefix_sep = prefix + os.sep
441
442 if verbose:
443 print('find_out: module_dir_sep [%s]' % module_dir_sep)
444 print('find_out: prefix_sep [%s]' % prefix_sep)
445
446 error_count = 0
447
448 for full_src in full_srcs:
449 if verbose:
450 print('find_out: full_src [%s]' % full_src)
451
452 if not full_src.startswith(module_dir_sep):
453 print('error: expected %s to start with %s' % (full_src, module_dir_sep))
454 error_count += 1
455 continue
456
457 local_src = full_src[len(module_dir_sep):]
458
459 if verbose:
460 print('find_out: local_src [%s]' % local_src)
461
462 if not local_src.startswith(prefix_sep):
463 print('error: expected %s to start with %s' % (local_src, prefix_sep))
464 error_count += 1
465 continue
466
467 # After stripping the module directory and the prefix, we're left with the
468 # name of a header that we'll generate, relative to the base of of a the
469 # the include path.
470
471 local_out = local_src[len(prefix_sep):]
472
473 if verbose:
474 print('find_out: local_out [%s]' % local_out)
475
476 outs.append(local_out)
477
478 return error_count
479
480
481def gen_blueprints(
482 verbose, header_arch, gen_dir, arch_asm_kbuild, asm_generic_kbuild, module_dir,
483 rel_arch_asm_kbuild, rel_asm_generic_kbuild, arch_include_uapi, techpack_include_uapi):
484 """Generate a blueprints file containing modules that invoke this script.
485
486 This function generates a blueprints file that contains modules that
487 invoke this script to generate kernel headers. We generate the blueprints
488 file as needed, but we don't actually use the generated file. The blueprints
489 file that we generate ends up in the out directory, and we can use it to
490 detect if the checked-in version of the file (in the source directory) is out
491 of date. This pattern occurs in the Android source tree in several places.
492
493 Args:
494 verbose: Set True to print progress messages.
495 header_arch: The arch for which to generate headers.
496 gen_dir: Where to place the generated files.
497 arch_asm_kbuild: The Kbuild file containing lists of headers to generate.
498 asm_generic_kbuild: The Kbuild file containing lists of mandatory headers.
499 module_dir: The root directory of the kernel source.
500 rel_arch_asm_kbuild: arch_asm_kbuild relative to module_dir.
501 Return:
502 The number of errors encountered.
503 """
504 error_count = 0
505
506 # The old and new blueprints files. We generate the new one, but we need to
507 # refer to the old one in the modules that we generate.
508 old_gen_headers_bp = 'gen_headers_%s.bp' % header_arch
509 new_gen_headers_bp = os.path.join(gen_dir, old_gen_headers_bp)
510
511 # Tools and tool files.
512 headers_install_sh = 'headers_install.sh'
513 kernel_headers_py = 'kernel_headers.py'
514 arm_syscall_tool = 'arch/arm/tools/syscallhdr.sh'
515
516 # Sources
517 makefile = 'Makefile'
518 arm_syscall_tbl = 'arch/arm/tools/syscall.tbl'
519 rel_glob = '**/*.h'
520 generic_prefix = 'include/uapi'
521 arch_prefix = os.path.join('arch', header_arch, generic_prefix)
522 generic_src = os.path.join(generic_prefix, rel_glob)
523 arch_src = os.path.join(arch_prefix, rel_glob)
524 techpack_src = 'techpack/*'
525
526 # Excluded sources, architecture specific.
527 exclude_srcs = []
528
529 if header_arch == "arm":
530 exclude_srcs = ['linux/a.out.h']
531
532 if header_arch == "arm64":
533 exclude_srcs = ['linux/a.out.h']
534
535 # Scan the arch_asm_kbuild file for files that need to be generated and those
536 # that are generic (i.e., need to be wrapped).
537
538 (generated_list, generic_list, mandatory_list) = scan_arch_kbuild(verbose,
539 arch_asm_kbuild, asm_generic_kbuild, arch_include_uapi)
540
541 generic_out = []
542 error_count += find_out(
543 verbose, module_dir, generic_prefix, rel_glob, exclude_srcs, generic_out)
544
545 arch_out = []
546 error_count += find_out(
547 verbose, module_dir, arch_prefix, rel_glob, None, arch_out)
548
549 techpack_out = [x.split('include/uapi/')[1] for x in techpack_include_uapi]
550
551 if error_count != 0:
552 return error_count
553
554 # Generate the blueprints file.
555
556 if verbose:
557 print('gen_blueprints: generating %s' % new_gen_headers_bp)
558
559 with open(new_gen_headers_bp, 'w') as f:
560 f.write('// ***** DO NOT EDIT *****\n')
561 f.write('// This file is generated by %s\n' % kernel_headers_py)
562 f.write('\n')
563 f.write('gen_headers_%s = [\n' % header_arch)
564
565 if generated_list:
566 f.write('\n')
567 f.write(' // Matching generated-y:\n')
568 f.write('\n')
569 for h in generated_list:
570 f.write(' "asm/%s",\n' % h)
571
572 if generic_list:
573 f.write('\n')
574 f.write(' // Matching generic-y:\n')
575 f.write('\n')
576 for h in generic_list:
577 f.write(' "asm/%s",\n' % h)
578
579 if mandatory_list:
580 f.write('\n')
581 f.write(' // Matching mandatory-y:\n')
582 f.write('\n')
583 for h in mandatory_list:
584 f.write(' "asm/%s",\n' % h)
585
586 if generic_out:
587 f.write('\n')
588 f.write(' // From %s\n' % generic_src)
589 f.write('\n')
590 for h in generic_out:
591 f.write(' "%s",\n' % h)
592
593 if arch_out:
594 f.write('\n')
595 f.write(' // From %s\n' % arch_src)
596 f.write('\n')
597 for h in arch_out:
598 f.write(' "%s",\n' % h)
599
600 if techpack_out:
601 f.write('\n')
602 f.write(' // From %s\n' % techpack_src)
603 f.write('\n')
604 for h in techpack_out:
605 f.write(' "%s",\n' % h)
606
607 f.write(']\n')
608 f.write('\n')
609
610 gen_blueprints_module_name = 'qti_generate_gen_headers_%s' % header_arch
611
612 f.write('genrule {\n')
613 f.write(' // This module generates the gen_headers_<arch>.bp file\n')
614 f.write(' // (i.e., a new version of this file) so that it can be\n')
615 f.write(' // checked later to ensure that it matches the checked-\n')
616 f.write(' // in version (this file).\n')
617 f.write(' name: "%s",\n' % gen_blueprints_module_name)
618 f.write(' srcs: ["%s", "%s", "%s"],\n' % (rel_arch_asm_kbuild, rel_asm_generic_kbuild, arch_src))
619 f.write(' tool_files: ["kernel_headers.py"],\n')
620 f.write(' cmd: "python3 $(location kernel_headers.py) " +\n')
621 f.write(' kernel_headers_verbose +\n')
622 f.write(' "--header_arch %s " +\n' % header_arch)
623 f.write(' "--gen_dir $(genDir) " +\n')
624 f.write(' "--arch_asm_kbuild $(location %s) " +\n' % rel_arch_asm_kbuild)
625 f.write(' "--arch_include_uapi $(locations %s) " +\n' % arch_src)
626 f.write(' "--asm_generic_kbuild $(location %s) " +\n' % rel_asm_generic_kbuild)
627 f.write(' "blueprints",\n')
628 f.write(' out: ["gen_headers_%s.bp"],\n' % header_arch)
629 f.write('}\n')
630 f.write('\n')
631
632 f.write('genrule {\n')
633 f.write(' name: "qti_generate_kernel_headers_%s",\n' % header_arch)
634 f.write(' tools: ["%s"],\n' % headers_install_sh)
635 f.write(' tool_files: [\n')
636 f.write(' "%s",\n' % kernel_headers_py)
637
638 if header_arch == "arm":
639 f.write(' "%s",\n' % arm_syscall_tool)
640
641 f.write(' ],\n')
642 f.write(' srcs: [\n')
643 f.write(' "%s",\n' % rel_arch_asm_kbuild)
644 f.write(' "%s",\n' % rel_asm_generic_kbuild)
645 f.write(' "%s",\n' % old_gen_headers_bp)
646 f.write(' ":%s",\n' % gen_blueprints_module_name)
647 f.write(' "%s",\n' % makefile)
648
649 if header_arch == "arm":
650 f.write(' "%s",\n' % arm_syscall_tbl)
651
652 f.write(' "%s",\n' % generic_src)
653 f.write(' "%s",\n' % arch_src)
654 f.write(' ],\n')
655
656 if exclude_srcs:
657 f.write(' exclude_srcs: [\n')
658 for h in exclude_srcs:
659 f.write(' "%s",\n' % os.path.join(generic_prefix, h))
660 f.write(' ],\n')
661
662 f.write(' cmd: "python3 $(location %s) " +\n' % kernel_headers_py)
663 f.write(' kernel_headers_verbose +\n')
664 f.write(' "--header_arch %s " +\n' % header_arch)
665 f.write(' "--gen_dir $(genDir) " +\n')
666 f.write(' "--arch_asm_kbuild $(location %s) " +\n' % rel_arch_asm_kbuild)
667 f.write(' "--arch_include_uapi $(locations %s) " +\n' % arch_src)
668 f.write(' "--asm_generic_kbuild $(location %s) " +\n' % rel_asm_generic_kbuild)
669 f.write(' "headers " +\n')
670 f.write(' "--old_gen_headers_bp $(location %s) " +\n' % old_gen_headers_bp)
671 f.write(' "--new_gen_headers_bp $(location :%s) " +\n' % gen_blueprints_module_name)
672 f.write(' "--version_makefile $(location %s) " +\n' % makefile)
673
674 if header_arch == "arm":
675 f.write(' "--arch_syscall_tool $(location %s) " +\n' % arm_syscall_tool)
676 f.write(' "--arch_syscall_tbl $(location %s) " +\n' % arm_syscall_tbl)
677
678 f.write(' "--headers_install $(location %s) " +\n' % headers_install_sh)
679 f.write(' "--include_uapi $(locations %s)",\n' % generic_src)
680 f.write(' out: ["linux/version.h"] + gen_headers_%s,\n' % header_arch)
681 f.write('}\n')
682
683 return 0
684
685
686def gen_headers(
687 verbose, header_arch, gen_dir, arch_asm_kbuild, asm_generic_kbuild, module_dir,
688 old_gen_headers_bp, new_gen_headers_bp, version_makefile,
689 arch_syscall_tool, arch_syscall_tbl, headers_install, include_uapi,
690 arch_include_uapi, techpack_include_uapi):
691 """Generate the kernel headers.
692
693 This script generates the version.h file, the arch-specific headers including
694 syscall-related generated files and wrappers around generic files, and uses
695 the headers_install tool to process other generic uapi and arch-specifc uapi
696 files.
697
698 Args:
699 verbose: Set True to print progress messages.
700 header_arch: The arch for which to generate headers.
701 gen_dir: Where to place the generated files.
702 arch_asm_kbuild: The Kbuild file containing lists of headers to generate.
703 asm_generic_kbuild: The Kbuild file containing mandatory headers.
704 module_dir: The root directory of the kernel source.
705 old_gen_headers_bp: The old gen_headers_<arch>.bp file to check.
706 new_gen_headers_bp: The new gen_headers_<arch>.bp file to check.
707 version_makefile: The kernel Makefile that contains version info.
708 arch_syscall_tool: The arch script that generates syscall headers.
709 arch_syscall_tbl: The arch script that defines syscall vectors.
710 headers_install: The headers_install tool to process input headers.
711 include_uapi: The list of include/uapi header files.
712 arch_include_uapi: The list of arch/<arch>/include/uapi header files.
713 Return:
714 The number of errors encountered.
715 """
716
717 if not filecmp.cmp(old_gen_headers_bp, new_gen_headers_bp):
718 print('error: gen_headers blueprints file is out of date, suggested fix:')
719 print('cp %s %s' % (new_gen_headers_bp, old_gen_headers_bp))
720 print('then re-run the build')
721 return 1
722
723 error_count = 0
724
725 if not gen_version_h(verbose, gen_dir, version_makefile):
726 error_count += 1
727
728 error_count += gen_arch_headers(
729 verbose, gen_dir, arch_asm_kbuild, asm_generic_kbuild, arch_syscall_tool, arch_syscall_tbl ,arch_include_uapi)
730
731 uapi_include_prefix = os.path.join(module_dir, 'include', 'uapi') + os.sep
732
733 arch_uapi_include_prefix = os.path.join(
734 module_dir, 'arch', header_arch, 'include', 'uapi') + os.sep
735
736 for h in include_uapi:
737 if not run_headers_install(
738 verbose, gen_dir, headers_install,
739 uapi_include_prefix, h):
740 error_count += 1
741
742 for h in arch_include_uapi:
743 if not run_headers_install(
744 verbose, gen_dir, headers_install,
745 arch_uapi_include_prefix, h):
746 error_count += 1
747
748 for h in techpack_include_uapi:
749 techpack_uapi_include_prefix = os.path.join(h.split('/include/uapi')[0], 'include', 'uapi') + os.sep
750 if not run_headers_install(
751 verbose, gen_dir, headers_install,
752 techpack_uapi_include_prefix, h):
753 error_count += 1
754
755 return error_count
756
757def extract_techpack_uapi_headers(verbose, module_dir):
758
759 """EXtract list of uapi headers from techpack/* directories. We need to export
760 these headers to userspace.
761
762 Args:
763 verbose: Verbose option is provided to script
764 module_dir: Base directory
765 Returs:
766 List of uapi headers
767 """
768
769 techpack_subdir = []
770 techpack_dir = os.path.join(module_dir,'techpack')
771 techpack_uapi = []
772 techpack_uapi_sub = []
773
774 #get list of techpack directories under techpack/
775 if os.path.isdir(techpack_dir):
776 items = sorted(os.listdir(techpack_dir))
777 for x in items:
778 p = os.path.join(techpack_dir, x)
779 if os.path.isdir(p):
780 techpack_subdir.append(p)
781
782 #Print list of subdirs obtained
783 if (verbose):
784 for x in techpack_subdir:
785 print(x)
786
787 #For every subdirectory get list of .h files under include/uapi and append to techpack_uapi list
788 for x in techpack_subdir:
789 techpack_uapi_path = os.path.join(x, 'include/uapi')
790 if (os.path.isdir(techpack_uapi_path)):
791 techpack_uapi_sub = []
792 find_out(verbose, x, 'include/uapi', '**/*.h', None, techpack_uapi_sub)
793 tmp = [os.path.join(techpack_uapi_path, y) for y in techpack_uapi_sub]
794 techpack_uapi = techpack_uapi + tmp
795
796 if (verbose):
797 for x in techpack_uapi:
798 print(x)
799
800 return techpack_uapi
801
802def main():
803 """Parse command line arguments and perform top level control."""
804
805 parser = argparse.ArgumentParser(
806 description=__doc__,
807 formatter_class=argparse.RawDescriptionHelpFormatter)
808
809 # Arguments that apply to every invocation of this script.
810
811 parser.add_argument(
812 '--verbose',
813 action='store_true',
814 help='Print output that describes the workings of this script.')
815 parser.add_argument(
816 '--header_arch',
817 required=True,
818 help='The arch for which to generate headers.')
819 parser.add_argument(
820 '--gen_dir',
821 required=True,
822 help='Where to place the generated files.')
823 parser.add_argument(
824 '--arch_asm_kbuild',
825 required=True,
826 help='The Kbuild file containing lists of headers to generate.')
827 parser.add_argument(
828 '--asm_generic_kbuild',
829 required=True,
830 help='The Kbuild file containing lists of mandatory headers.')
831 parser.add_argument(
832 '--arch_include_uapi',
833 required=True,
834 nargs='*',
835 help='The list of arch/<arch>/include/uapi header files.')
836
837 # The modes.
838
839 subparsers = parser.add_subparsers(
840 dest='mode',
841 help='Select mode')
842 parser_blueprints = subparsers.add_parser(
843 'blueprints',
844 help='Generate the gen_headers_<arch>.bp file.')
845 parser_headers = subparsers.add_parser(
846 'headers',
847 help='Check blueprints, then generate kernel headers.')
848
849 # Arguments that apply to headers mode.
850
851 parser_headers.add_argument(
852 '--old_gen_headers_bp',
853 required=True,
854 help='The old gen_headers_<arch>.bp file to check.')
855 parser_headers.add_argument(
856 '--new_gen_headers_bp',
857 required=True,
858 help='The new gen_headers_<arch>.bp file to check.')
859 parser_headers.add_argument(
860 '--version_makefile',
861 required=True,
862 help='The kernel Makefile that contains version info.')
863 parser_headers.add_argument(
864 '--arch_syscall_tool',
865 help='The arch script that generates syscall headers, if applicable.')
866 parser_headers.add_argument(
867 '--arch_syscall_tbl',
868 help='The arch script that defines syscall vectors, if applicable.')
869 parser_headers.add_argument(
870 '--headers_install',
871 required=True,
872 help='The headers_install tool to process input headers.')
873 parser_headers.add_argument(
874 '--include_uapi',
875 required=True,
876 nargs='*',
877 help='The list of include/uapi header files.')
878
879 args = parser.parse_args()
880
881 if args.verbose:
882 print('mode [%s]' % args.mode)
883 print('header_arch [%s]' % args.header_arch)
884 print('gen_dir [%s]' % args.gen_dir)
885 print('arch_asm_kbuild [%s]' % args.arch_asm_kbuild)
886 print('asm_generic_kbuild [%s]' % args.asm_generic_kbuild)
887
888 # Extract the module_dir from args.arch_asm_kbuild and rel_arch_asm_kbuild.
889
890 rel_arch_asm_kbuild = os.path.join(
891 'arch', args.header_arch, 'include/uapi/asm/Kbuild')
892
893 suffix = os.sep + rel_arch_asm_kbuild
894
895 if not args.arch_asm_kbuild.endswith(suffix):
896 print('error: expected %s to end with %s' % (args.arch_asm_kbuild, suffix))
897 return 1
898
899 module_dir = args.arch_asm_kbuild[:-len(suffix)]
900
901 rel_asm_generic_kbuild = os.path.join('include/uapi/asm-generic', os.path.basename(args.asm_generic_kbuild))
902
903
904 if args.verbose:
905 print('module_dir [%s]' % module_dir)
906
907 # Get list of techpack uapi headers to be exported from techpack/* directories.
908 techpack_uapi = extract_techpack_uapi_headers(args.verbose, module_dir)
909
910
911 if args.mode == 'blueprints':
912 return gen_blueprints(
913 args.verbose, args.header_arch, args.gen_dir, args.arch_asm_kbuild,
914 args.asm_generic_kbuild, module_dir, rel_arch_asm_kbuild, rel_asm_generic_kbuild, args.arch_include_uapi, techpack_uapi)
915
916 if args.mode == 'headers':
917 if args.verbose:
918 print('old_gen_headers_bp [%s]' % args.old_gen_headers_bp)
919 print('new_gen_headers_bp [%s]' % args.new_gen_headers_bp)
920 print('version_makefile [%s]' % args.version_makefile)
921 print('arch_syscall_tool [%s]' % args.arch_syscall_tool)
922 print('arch_syscall_tbl [%s]' % args.arch_syscall_tbl)
923 print('headers_install [%s]' % args.headers_install)
924
925 return gen_headers(
926 args.verbose, args.header_arch, args.gen_dir, args.arch_asm_kbuild,
927 args.asm_generic_kbuild, module_dir, args.old_gen_headers_bp, args.new_gen_headers_bp,
928 args.version_makefile, args.arch_syscall_tool, args.arch_syscall_tbl,
929 args.headers_install, args.include_uapi, args.arch_include_uapi, techpack_uapi)
930
931 print('error: unknown mode: %s' % args.mode)
932 return 1
933
934
935if __name__ == '__main__':
936 sys.exit(main())