1import os 2import re 3import meson_impl as impl 4 5 6class Compiler(impl.Compiler): 7 8 def is_symbol_supported(self, header: str, symbol: str): 9 return super().is_symbol_supported(header, symbol) 10 11 def is_function_supported(self, function): 12 return super().is_function_supported(function) 13 14 def is_link_supported(self, name): 15 return super().is_link_supported(name) 16 17 def has_header_symbol( 18 self, 19 header: str, 20 symbol: str, 21 args=[], 22 dependencies=[], 23 include_directories=[], 24 no_builtin_args=False, 25 prefix=[], 26 required=False, 27 ): 28 # Exclude what is currently not working. 29 result = self.is_symbol_supported(header, symbol) 30 print("has_header_symbol '%s', '%s': %s" % (header, symbol, str(result))) 31 return result 32 33 def check_header(self, header, prefix=''): 34 result = self.is_header_supported(header) 35 print("check_header '%s': %s" % (header, str(result))) 36 return result 37 38 def has_function(self, function, args=[], prefix='', dependencies=''): 39 # Exclude what is currently not working. 40 result = self.is_function_supported(function) 41 print("has_function '%s': %s" % (function, str(result))) 42 return result 43 44 def links(self, snippet, name, args=[], dependencies=[]): 45 # Exclude what is currently not working. 46 result = self.is_link_supported(name) 47 print("links '%s': %s" % (name, str(result))) 48 return result 49 50 51class PkgconfigModule: 52 53 def generate(self, lib, name='', description='', extra_cflags=[]): 54 return 55 56 57# These globals exposed by the meson API 58meson = impl.Meson(Compiler()) 59host_machine = impl.Machine('android') 60build_machine = impl.Machine('linux') 61 62 63def open_output_file(): 64 impl.open_output_file(r'Android.bp') 65 66 67def close_output_file(): 68 impl.close_output_file() 69 70 71def load_config_file(): 72 impl.load_config_file('python-build/generate_android_build.config') 73 74 75def include_directories(*paths, is_system=False): 76 return impl.IncludeDirectories('', impl.get_include_dirs(paths)) 77 78 79def module_import(name: str): 80 if name == 'python': 81 return impl.PythonModule() 82 if name == 'pkgconfig': 83 return PkgconfigModule() 84 exit('Unhandled module: ' + name) 85 86 87def dependency( 88 *names, 89 required=True, 90 version='', 91 allow_fallback=False, 92 method='', 93 modules=[], 94 optional_modules=[], 95 static=True, 96 fallback=[], 97 include_type='', 98 native=False 99): 100 for name in names: 101 if name == 'zlib': 102 return impl.Dependency( 103 name, 104 targets=[ 105 impl.DependencyTarget( 106 'libz', impl.DependencyTargetType.STATIC_LIBRARY 107 ) 108 ], 109 version=version, 110 found=True, 111 ) 112 113 if name == 'hardware': 114 return impl.Dependency( 115 name, 116 targets=[ 117 impl.DependencyTarget( 118 'libhardware', impl.DependencyTargetType.SHARED_LIBRARY 119 ), 120 impl.DependencyTarget( 121 'hwvulkan_headers', impl.DependencyTargetType.HEADER_LIBRARY 122 ), 123 ], 124 version=version, 125 found=True, 126 ) 127 128 if name == 'cutils' or name == 'log' or name == 'nativewindow': 129 return impl.Dependency( 130 name, 131 targets=[ 132 impl.DependencyTarget( 133 'lib' + name, impl.DependencyTargetType.SHARED_LIBRARY 134 ) 135 ], 136 version=version, 137 found=True, 138 ) 139 140 if name == 'sync': 141 return impl.Dependency( 142 name, 143 targets=[ 144 impl.DependencyTarget( 145 'lib' + name, impl.DependencyTargetType.STATIC_LIBRARY 146 ) 147 ], 148 version=version, 149 found=True, 150 ) 151 152 if name == 'android.hardware.graphics.mapper': 153 assert version == '>= 4.0' 154 return impl.Dependency( 155 name, 156 targets=[ 157 impl.DependencyTarget( 158 'libgralloctypes', impl.DependencyTargetType.STATIC_LIBRARY 159 ), 160 impl.DependencyTarget( 161 'android.hardware.graphics.mapper@4.0', 162 impl.DependencyTargetType.STATIC_LIBRARY, 163 ), 164 impl.DependencyTarget( 165 'libhidlbase', impl.DependencyTargetType.SHARED_LIBRARY 166 ), 167 impl.DependencyTarget( 168 'libutils', impl.DependencyTargetType.SHARED_LIBRARY 169 ), 170 ], 171 version=version, 172 found=True, 173 ) 174 175 return impl.dependency(*names, required=required, version=version) 176 177 178def static_library( 179 target_name, 180 *source_files, 181 c_args=[], 182 cpp_args=[], 183 c_pch='', 184 build_by_default=False, 185 build_rpath='', 186 d_debug=[], 187 d_import_dirs=[], 188 d_module_versions=[], 189 d_unittest=False, 190 dependencies=[], 191 extra_files='', 192 gnu_symbol_visibility='', 193 gui_app=False, 194 implicit_include_directories=False, 195 include_directories=[], 196 install=False, 197 install_dir='', 198 install_mode=[], 199 install_rpath='', 200 install_tag='', 201 link_args=[], 202 link_depends='', 203 link_language='', 204 link_whole=[], 205 link_with=[], 206 name_prefix='', 207 name_suffix='', 208 native=False, 209 objects=[], 210 override_options=[], 211 pic=False, 212 prelink=False, 213 rust_abi='', 214 rust_crate_type='', 215 rust_dependency_map={}, 216 sources='', 217 vala_args=[], 218 win_subsystem='' 219): 220 print('static_library: ' + target_name) 221 222 link_with = impl.get_linear_list(link_with) 223 link_whole = impl.get_linear_list(link_whole) 224 225 # Emitting link_with/link_whole into a static library isn't useful for building, 226 # shared libraries must specify the whole chain of dependencies. 227 # Leaving them here for traceability though maybe it's less confusing to remove them? 228 _emit_builtin_target( 229 'cc_library_static', 230 target_name, 231 *source_files, 232 c_args=c_args, 233 cpp_args=cpp_args, 234 dependencies=dependencies, 235 include_directories=include_directories, 236 link_with=link_with, 237 link_whole=link_whole 238 ) 239 240 return impl.StaticLibrary( 241 target_name, link_with=link_with, link_whole=link_whole 242 ) 243 244 245def _get_sources(input_sources, sources, generated_sources, generated_headers): 246 for source in input_sources: 247 if type(source) is list: 248 _get_sources(source, sources, generated_sources, generated_headers) 249 elif type(source) is impl.CustomTarget: 250 if source.generates_h(): 251 generated_headers.add(source.target_name_h()) 252 if source.generates_c(): 253 generated_sources.add(source.target_name_c()) 254 elif type(source) is impl.CustomTargetItem: 255 source = source.target 256 if source.generates_h(): 257 generated_headers.add(source.target_name_h()) 258 if source.generates_c(): 259 generated_sources.add(source.target_name_c()) 260 elif type(source) is impl.File: 261 sources.add(source.name) 262 elif type(source) is str: 263 sources.add(impl.get_relative_dir(source)) 264 else: 265 exit('source type not handled: ' + str(type(source))) 266 267 268def _emit_builtin_target( 269 builtin_type_name, 270 target_name, 271 *source, 272 c_args=[], 273 cpp_args=[], 274 dependencies=[], 275 include_directories=[], 276 link_with=[], 277 link_whole=[] 278): 279 impl.fprint('%s {' % builtin_type_name) 280 impl.fprint(' name: "%s",' % target_name) 281 282 srcs = set() 283 generated_sources = set() 284 generated_headers = set() 285 for source_arg in source: 286 assert type(source_arg) is list 287 _get_sources(source_arg, srcs, generated_sources, generated_headers) 288 289 deps = impl.get_set_of_deps(dependencies) 290 include_directories = [impl.get_relative_dir()] + impl.get_include_dirs( 291 include_directories 292 ) 293 static_libs = [] 294 whole_static_libs = [] 295 shared_libs = [] 296 header_libs = [] 297 for dep in deps: 298 print(' dep: ' + dep.name) 299 for src in impl.get_linear_list([dep.sources]): 300 if type(src) == impl.CustomTargetItem: 301 generated_headers.add(src.target.target_name_h()) 302 elif type(src) == impl.CustomTarget: 303 generated_headers.add(src.target_name_h()) 304 else: 305 exit('Unhandled source dependency: ' + str(type(src))) 306 include_directories.extend(impl.get_include_dirs(dep.include_directories)) 307 for target in impl.get_static_libs([dep.link_with]): 308 assert type(target) == impl.StaticLibrary 309 static_libs.append(target.target_name) 310 for target in impl.get_linear_list([dep.link_whole]): 311 assert type(target) == impl.StaticLibrary 312 whole_static_libs.append(target.target_name) 313 for target in dep.targets: 314 if target.target_type == impl.DependencyTargetType.SHARED_LIBRARY: 315 shared_libs.append(target.target_name) 316 elif target.target_type == impl.DependencyTargetType.STATIC_LIBRARY: 317 static_libs.append(target.target_name) 318 elif target.target_type == impl.DependencyTargetType.HEADER_LIBRARY: 319 header_libs.append(target.target_name) 320 321 for target in impl.get_static_libs(link_with): 322 if type(target) == impl.StaticLibrary: 323 static_libs.append(target.target_name) 324 else: 325 exit('Unhandled link_with type: ' + str(type(target))) 326 327 for target in impl.get_whole_static_libs(link_whole): 328 if type(target) == impl.StaticLibrary: 329 whole_static_libs.append(target.target_name()) 330 else: 331 exit('Unhandled link_whole type: ' + str(type(target))) 332 333 # Android turns all warnings into errors but thirdparty projects typically can't handle that 334 cflags = ['-Wno-error'] + impl.get_linear_list( 335 impl.get_project_cflags() + c_args 336 ) 337 cppflags = ['-Wno-error'] + impl.get_linear_list( 338 impl.get_project_cppflags() + cpp_args 339 ) 340 341 impl.fprint(' srcs: [') 342 for src in srcs: 343 # Filter out header files 344 if not src.endswith('.h'): 345 impl.fprint(' "%s",' % src) 346 impl.fprint(' ],') 347 348 impl.fprint(' generated_headers: [') 349 for generated in generated_headers: 350 impl.fprint(' "%s",' % generated) 351 impl.fprint(' ],') 352 353 impl.fprint(' generated_sources: [') 354 for generated in generated_sources: 355 impl.fprint(' "%s",' % generated) 356 impl.fprint(' ],') 357 358 for arg in impl.get_project_options(): 359 if arg.name == 'c_std': 360 impl.fprint(' c_std: "%s",' % arg.value) 361 elif arg.name == 'cpp_std': 362 impl.fprint(' cpp_std: "%s",' % arg.value) 363 364 impl.fprint(' conlyflags: [') 365 for arg in cflags: 366 # Escape double quotations 367 arg = re.sub(r'"', '\\"', arg) 368 impl.fprint(' "%s",' % arg) 369 impl.fprint(' ],') 370 impl.fprint(' cppflags: [') 371 for arg in cppflags: 372 # Escape double quotations 373 arg = re.sub(r'"', '\\"', arg) 374 impl.fprint(' "%s",' % arg) 375 impl.fprint(' ],') 376 377 impl.fprint(' local_include_dirs: [') 378 for inc in include_directories: 379 impl.fprint(' "%s",' % inc) 380 impl.fprint(' ],') 381 382 impl.fprint(' static_libs: [') 383 for lib in static_libs: 384 impl.fprint(' "%s",' % lib) 385 impl.fprint(' ],') 386 387 impl.fprint(' whole_static_libs: [') 388 for lib in whole_static_libs: 389 impl.fprint(' "%s",' % lib) 390 impl.fprint(' ],') 391 392 impl.fprint(' shared_libs: [') 393 for lib in shared_libs: 394 impl.fprint(' "%s",' % lib) 395 impl.fprint(' ],') 396 397 impl.fprint(' header_libs: [') 398 for lib in header_libs: 399 impl.fprint(' "%s",' % lib) 400 impl.fprint(' ],') 401 402 impl.fprint('}') 403 404 405def shared_library( 406 target_name, 407 *source, 408 c_args=[], 409 cpp_args=[], 410 c_pch='', 411 build_by_default=False, 412 build_rpath='', 413 d_debug=[], 414 d_import_dirs=[], 415 d_module_versions=[], 416 d_unittest=False, 417 darwin_versions='', 418 dependencies=[], 419 extra_files='', 420 gnu_symbol_visibility='', 421 gui_app=False, 422 implicit_include_directories=False, 423 include_directories=[], 424 install=False, 425 install_dir='', 426 install_mode=[], 427 install_rpath='', 428 install_tag='', 429 link_args=[], 430 link_depends=[], 431 link_language='', 432 link_whole=[], 433 link_with=[], 434 name_prefix='', 435 name_suffix='', 436 native=False, 437 objects=[], 438 override_options=[], 439 rust_abi='', 440 rust_crate_type='', 441 rust_dependency_map={}, 442 sources=[], 443 soversion='', 444 vala_args=[], 445 version='', 446 vs_module_defs='', 447 win_subsystem='' 448): 449 print('shared_library: ' + target_name) 450 451 link_with = impl.get_linear_list([link_with]) 452 link_whole = impl.get_linear_list([link_whole]) 453 454 _emit_builtin_target( 455 'cc_library_shared', 456 target_name, 457 *source, 458 c_args=c_args, 459 cpp_args=cpp_args, 460 dependencies=dependencies, 461 include_directories=include_directories, 462 link_with=link_with, 463 link_whole=link_whole 464 ) 465 return impl.SharedLibrary(target_name) 466 467 468def _process_target_name(name): 469 name = re.sub(r'[\[\]]', '', name) 470 return name 471 472 473# Returns string or list of string 474def _location_wrapper(name_or_list): 475 if isinstance(name_or_list, list): 476 ret = [] 477 for i in name_or_list: 478 ret.append('$(location %s)' % i) 479 return ret 480 481 assert isinstance(name_or_list, str) 482 return '$(location %s)' % name_or_list 483 484 485def _is_header(name): 486 return re.search(r'\.h[xx|pp]?$', name) != None 487 488 489def _is_source(name): 490 return re.search(r'\.c[c|xx|pp]?$', name) != None 491 492 493def _get_command_args( 494 command, 495 input, 496 output, 497 deps, 498 location_wrap=False, 499 obfuscate_output_c=False, 500 obfuscate_output_h=False, 501 obfuscate_suffix='', 502): 503 args = [] 504 for command_item in command[1:]: 505 if isinstance(command_item, list): 506 for item in command_item: 507 assert type(item) == impl.File 508 args.append( 509 _location_wrapper(item.name) if location_wrap else item.name 510 ) 511 continue 512 513 assert type(command_item) is str 514 match = re.match(r'@INPUT([0-9])?@', command_item) 515 if match != None: 516 if match.group(1) != None: 517 input_index = int(match.group(1)) 518 input_list = impl.get_list_of_relative_inputs(input[input_index]) 519 else: 520 input_list = impl.get_list_of_relative_inputs(input) 521 args.extend( 522 _location_wrapper(input_list) if location_wrap else input_list 523 ) 524 continue 525 526 match = re.match(r'(.*?)@OUTPUT([0-9])?@', command_item) 527 if match != None: 528 output_list = [] 529 if match.group(2) != None: 530 output_index = int(match.group(2)) 531 selected_output = ( 532 output[output_index] if isinstance(output, list) else output 533 ) 534 output_list.append(impl.get_relative_gen_dir(selected_output)) 535 elif isinstance(output, list): 536 for out in output: 537 output_list.append(impl.get_relative_gen_dir(out)) 538 else: 539 output_list.append(impl.get_relative_gen_dir(output)) 540 for out in output_list: 541 if _is_header(out) and obfuscate_output_h: 542 args.append( 543 match.group(1) + '$(genDir)/%s' % out if location_wrap else out 544 ) 545 else: 546 if _is_source(out) and obfuscate_output_c: 547 out += obfuscate_suffix 548 args.append( 549 match.group(1) + _location_wrapper(out) if location_wrap else out 550 ) 551 continue 552 553 # Assume used to locate generated outputs 554 match = re.match(r'(.*?)@CURRENT_BUILD_DIR@', command_item) 555 if match != None: 556 args.append('$(genDir)' + '/' + impl.get_relative_dir()) 557 continue 558 559 # A plain arg 560 if ' ' in command_item: 561 args.append("'%s'" % command_item) 562 else: 563 args.append(command_item) 564 565 return args 566 567 568# Assume dependencies of custom targets are custom targets that are generating 569# python scripts; build a python path of their locations. 570def _get_python_path(deps): 571 python_path = '' 572 for index, dep in enumerate(deps): 573 assert type(dep) == impl.CustomTarget 574 if index > 0: 575 python_path += ':' 576 python_path += '`dirname %s`' % _location_wrapper(':%s' % dep.target_name()) 577 return python_path 578 579 580def _get_export_include_dirs(): 581 dirs = [impl.get_relative_dir()] 582 # HACK for source files that expect that include generated files like: 583 # include "vulkan/runtime/...h" 584 if impl.get_relative_dir().startswith('src'): 585 dirs.append('src') 586 return dirs 587 588 589def _process_wrapped_args_for_python( 590 wrapped_args, python_script, python_script_target_name, deps 591): 592 # The python script arg should be replaced with the python binary target name 593 args = impl.replace_wrapped_input_with_target( 594 wrapped_args, python_script, python_script_target_name 595 ) 596 python_path = 'PYTHONPATH=' 597 # Python scripts expect to be able to import other scripts from the same directory, but this 598 # doesn't work in the soong execution environment, so we have to explicitly add the script dir. 599 # We can't use $(location python_binary) because that is missing the relative path; 600 # instead we can use $(location python_script), which happens to work, and we're careful to ensure 601 # the script is in the list of sources even when it's used as the command directly. 602 python_path += '`dirname $(location %s)`' % python_script 603 # Also ensure that scripts generated by dependent custom targets can be imported. 604 if len(deps) > 0: 605 python_path += ':' + _get_python_path(deps) 606 args.insert(0, python_path) 607 return args 608 609 610# Create a custom top level build target 611# Issues: 612# - python scripts that call python modules from other directories: 613# may pass an absolute path to the module directory which violates the sandbox. 614def custom_target( 615 target_name: str, 616 build_always=False, 617 build_always_stale=False, 618 build_by_default=False, 619 capture=False, 620 command=[], 621 console=False, 622 depend_files=[], 623 depends=[], 624 depfile='', 625 env=[], 626 feed=False, 627 input=[], 628 install=False, 629 install_dir='', 630 install_mode=[], 631 install_tag=[], 632 output=[], 633): 634 target_name = _process_target_name(target_name) 635 print('Custom target: ' + target_name) 636 assert type(command) is list 637 program = command[0] 638 program_args = [] 639 640 # The program can be an array that includes arguments 641 if isinstance(program, list): 642 for arg in program[1:]: 643 assert type(arg) is str 644 program_args.append(arg) 645 program = program[0] 646 647 assert isinstance(program, impl.Program) 648 assert program.found() 649 650 args = program_args + _get_command_args(command, input, output, depends) 651 652 # Python scripts need special handling to find mako library 653 python_script = '' 654 python_script_target_name = '' 655 if program.command.endswith('.py'): 656 python_script = program.command 657 else: 658 for index, arg in enumerate(args): 659 if arg.endswith('.py'): 660 python_script = arg 661 break 662 663 if python_script != '': 664 python_script_target_name = ( 665 target_name + '_' + os.path.basename(python_script) 666 ) 667 srcs = [python_script] + impl.get_list_of_relative_inputs(depend_files) 668 impl.fprint('python_binary_host {') 669 impl.fprint(' name: "%s",' % python_script_target_name) 670 impl.fprint(' main: "%s",' % python_script) 671 impl.fprint(' srcs: [') 672 for src in srcs: 673 if src.endswith('.py'): 674 impl.fprint(' "%s",' % src) 675 impl.fprint(' ],') 676 impl.fprint(' libs: ["mako"],') 677 # For the PYTHONPATH to work in our genrules command, we need the python interpreter, 678 # not a compiled binary, so disable embedded_launcher. 679 impl.fprint(' version: {') 680 impl.fprint(' py3: {') 681 impl.fprint(' embedded_launcher: false,') 682 impl.fprint(' },') 683 impl.fprint(' },') 684 impl.fprint('}') 685 686 relative_inputs = impl.get_list_of_relative_inputs(input) 687 # We use python_host_binary instead of calling python scripts directly; 688 # however there's an issue with python locating modules in the same directory 689 # as the script; to workaround that (see _process_wrapped_args_for_python) we 690 # ensure the script is listed in the genrule targets. 691 if python_script != '' and not python_script in relative_inputs: 692 relative_inputs.append(python_script) 693 relative_inputs.extend(impl.get_list_of_relative_inputs(depend_files)) 694 695 relative_outputs = [] 696 if isinstance(output, list): 697 for file in output: 698 relative_outputs.append(impl.get_relative_gen_dir(file)) 699 else: 700 assert type(output) == str 701 relative_outputs.append(impl.get_relative_gen_dir(output)) 702 703 # Soong requires genrule to generate only headers OR non-headers 704 generates_h = False 705 generates_c = False 706 for out in relative_outputs: 707 if _is_header(out): 708 generates_h = True 709 if _is_source(out): 710 generates_c = True 711 712 custom_target = impl.CustomTarget( 713 target_name, relative_outputs, generates_h, generates_c 714 ) 715 716 program_command = program.command 717 if program_command == 'bison': 718 program_command_arg = 'M4=$(location m4) $(location bison)' 719 elif program_command == 'flex': 720 program_command_arg = 'M4=$(location m4) $(location flex)' 721 elif program_command.endswith('.py'): 722 program_command_arg = _location_wrapper(program_command) 723 else: 724 program_command_arg = program_command 725 726 program_args = [program_command_arg] + program_args 727 728 if custom_target.generates_h() and custom_target.generates_c(): 729 # Make a rule for only the headers 730 obfuscate_suffix = '.dummy.h' 731 wrapped_args = program_args + _get_command_args( 732 command, 733 input, 734 output, 735 depends, 736 location_wrap=True, 737 obfuscate_output_c=True, 738 obfuscate_suffix=obfuscate_suffix, 739 ) 740 if python_script: 741 wrapped_args = _process_wrapped_args_for_python( 742 wrapped_args, python_script, python_script_target_name, depends 743 ) 744 745 command_line = impl.get_command_line_from_args(wrapped_args) 746 if capture: 747 command_line += ' > %s' % _location_wrapper( 748 impl.get_relative_gen_dir(output) 749 ) 750 751 impl.fprint('genrule {') 752 impl.fprint(' name: "%s",' % custom_target.target_name_h()) 753 impl.fprint(' srcs: [') 754 for src in relative_inputs: 755 impl.fprint(' "%s",' % src) 756 for dep in depends: 757 assert type(dep) is CustomTarget 758 impl.fprint(' ":%s",' % dep.target_name()) 759 impl.fprint(' ],') 760 impl.fprint(' out: [') 761 for out in relative_outputs: 762 if _is_source(out): 763 out += obfuscate_suffix 764 impl.fprint(' "%s",' % out) 765 # The scripts may still write to the assumed .c file, ensure the obfuscated file exists 766 command_line += "; echo '//nothing to see here' > " + _location_wrapper( 767 out 768 ) 769 else: 770 impl.fprint(' "%s",' % out) 771 impl.fprint(' ],') 772 impl.fprint(' tools: [') 773 if python_script_target_name != '': 774 impl.fprint(' "%s",' % python_script_target_name) 775 if program_command == 'bison' or program_command == 'flex': 776 impl.fprint(' "%s",' % 'm4') 777 impl.fprint(' "%s",' % program_command) 778 impl.fprint(' ],') 779 impl.fprint(' export_include_dirs: [') 780 for dir in _get_export_include_dirs(): 781 impl.fprint(' "%s",' % dir) 782 impl.fprint(' ],') 783 impl.fprint(' cmd: "%s"' % command_line) 784 impl.fprint('}') 785 786 # Make a rule for only the sources 787 obfuscate_suffix = '.dummy.c' 788 wrapped_args = program_args + _get_command_args( 789 command, 790 input, 791 output, 792 depends, 793 location_wrap=True, 794 obfuscate_output_h=True, 795 obfuscate_suffix=obfuscate_suffix, 796 ) 797 if python_script: 798 wrapped_args = _process_wrapped_args_for_python( 799 wrapped_args, python_script, python_script_target_name, depends 800 ) 801 802 command_line = impl.get_command_line_from_args(wrapped_args) 803 if capture: 804 command_line += ' > %s' % _location_wrapper(get_relative_gen_dir(output)) 805 806 # We keep the header as an output with an obfuscated name because some scripts insist on having 807 # --out-h (like vk_entrypoints_gen.py). 808 # When Soong depends on this genrule it'll insist on compiling all the outputs, so we replace the 809 # content of all header outputs. 810 impl.fprint('genrule {') 811 impl.fprint(' name: "%s",' % custom_target.target_name_c()) 812 impl.fprint(' srcs: [') 813 for src in relative_inputs: 814 impl.fprint(' "%s",' % src) 815 for dep in depends: 816 assert type(dep) is CustomTarget 817 impl.fprint(' ":%s",' % dep.target_name()) 818 impl.fprint(' ],') 819 impl.fprint(' out: [') 820 for out in relative_outputs: 821 if _is_header(out): 822 out += obfuscate_suffix 823 impl.fprint(' "%s",' % out) 824 # Remove the content because Soong will compile this dummy source file 825 command_line += "; echo '//nothing to see here' > " + _location_wrapper( 826 out 827 ) 828 else: 829 impl.fprint(' "%s",' % out) 830 impl.fprint(' ],') 831 impl.fprint(' tools: [') 832 if python_script_target_name != '': 833 impl.fprint(' "%s",' % python_script_target_name) 834 if program_command == 'bison' or program_command == 'flex': 835 impl.fprint(' "%s",' % 'm4') 836 impl.fprint(' "%s",' % program_command) 837 impl.fprint(' ],') 838 impl.fprint(' cmd: "%s"' % command_line) 839 impl.fprint('}') 840 841 return custom_target 842 else: 843 wrapped_args = program_args + _get_command_args( 844 command, input, output, depends, location_wrap=True 845 ) 846 if python_script: 847 wrapped_args = _process_wrapped_args_for_python( 848 wrapped_args, python_script, python_script_target_name, depends 849 ) 850 851 command_line = impl.get_command_line_from_args(wrapped_args) 852 if capture: 853 command_line += ' > %s' % _location_wrapper( 854 impl.get_relative_gen_dir(output) 855 ) 856 857 impl.fprint('genrule {') 858 impl.fprint(' name: "%s",' % custom_target.target_name()) 859 impl.fprint(' srcs: [') 860 for src in relative_inputs: 861 impl.fprint(' "%s",' % src) 862 for dep in depends: 863 assert type(dep) is impl.CustomTarget 864 impl.fprint(' ":%s",' % dep.target_name()) 865 impl.fprint(' ],') 866 impl.fprint(' out: [') 867 for out in relative_outputs: 868 impl.fprint(' "%s",' % out) 869 impl.fprint(' ],') 870 impl.fprint(' tools: [') 871 if python_script_target_name != '': 872 impl.fprint(' "%s",' % python_script_target_name) 873 if program_command == 'bison' or program_command == 'flex': 874 impl.fprint(' "%s",' % 'm4') 875 impl.fprint(' "%s",' % program_command) 876 impl.fprint(' ],') 877 impl.fprint(' export_include_dirs: [') 878 for dir in _get_export_include_dirs(): 879 impl.fprint(' "%s",' % dir) 880 impl.fprint(' ],') 881 impl.fprint(' cmd: "%s"' % command_line) 882 impl.fprint('}') 883 884 return custom_target 885