| #!/usr/bin/env python3 |
| |
| # Copyright (C) 2022 Apple Inc. All rights reserved. |
| # |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions |
| # are met: |
| # |
| # 1. Redistributions of source code must retain the above copyright |
| # notice, this list of conditions and the following disclaimer. |
| # 2. Redistributions in binary form must reproduce the above copyright |
| # notice, this list of conditions and the following disclaimer in the |
| # documentation and/or other materials provided with the distribution. |
| # 3. Neither the name of Apple Inc. ("Apple") nor the names of |
| # its contributors may be used to endorse or promote products derived |
| # from this software without specific prior written permission. |
| # |
| # THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
| # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| # DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
| # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| # Script to generate compile_commands.json file |
| |
| import re |
| import os |
| import sys |
| import glob |
| import json |
| import argparse |
| |
| # Get command line args |
| parser = argparse.ArgumentParser(description='Generate compile_commands.json', |
| usage=""" |
| make r EXPORT_COMPILE_COMMANDS=YES |
| generate-compile-commands WebKitBuild/Release |
| |
| https://trac.webkit.org/wiki/Clangd |
| """) |
| |
| parser.add_argument('built_products_dir', help='path to the build directory containing generated compile commands (ex: WebKitBuild/Release)') |
| opts = parser.parse_args() |
| |
| # Change to the root of WebKit Directory |
| file_dir = os.path.dirname(os.path.realpath(__file__)) |
| base_dir = file_dir + "/../../" |
| os.chdir(base_dir) |
| |
| # Check compile_commands folder exists |
| compile_commands_dir = opts.built_products_dir + "/compile_commands/" |
| |
| if not os.path.exists(compile_commands_dir): |
| print("Please specify the build directory with compile_commands.") |
| print("Example: generate-compile-commands WebKitBuild/Release") |
| exit(1) |
| |
| # Generate compile_commands.json |
| |
| # For things not to horribly break for users during normal use we need to validate the compiler is spitting out |
| # valid json files. Sometimes if a compile error happens or the user stops the build part way through |
| # there will be a very invalid json file sitting in the directory. When we go to bundle it up into the final |
| # compile_commands.json file, we now have an invalid compile_commands.json file and clangd will not work. |
| # To prevent this from happening we should check that every json file we add is valid, and also ensure there are no |
| # duplicate entries. We will build a map of all the valid files. |
| |
| # Key - JSON file contents |
| # Value - Timestamp contents |
| files = dict() |
| |
| # Do not index third party code. |
| # Most people probably do not need it. |
| third_party_regex = re.compile('Source/ThirdParty') |
| |
| for j_file_name in glob.glob(compile_commands_dir + "/*.json"): |
| j_file = open(j_file_name, "r") |
| json_contents = j_file.read() |
| |
| if third_party_regex.search(json_contents): |
| continue |
| |
| # -2 gets rid of the comma at the end of the file. |
| json_contents = json_contents[:-2] |
| |
| # Try to load JSON File |
| try: |
| json.loads(json_contents) |
| except Exception: |
| print("Invalid JSON File: " + j_file_name) |
| continue |
| |
| # Validate if the json file already exists in the map. |
| if json_contents in files: |
| pass |
| else: |
| files[json_contents] = os.path.getmtime(j_file_name) |
| |
| # Remove any previous compile_commands.json |
| try: |
| os.remove("compile_commands.json") |
| except Exception: |
| pass |
| |
| # Write the new compile_commands.json file |
| new_compile_commands_file = open("compile_commands.json", 'w') |
| new_compile_commands_file.write("[") |
| |
| for index, key in enumerate(files.keys()): |
| if index != 0: |
| new_compile_commands_file.write(",\n") |
| else: |
| new_compile_commands_file.write("\n") |
| new_compile_commands_file.write(key) |
| |
| new_compile_commands_file.write("\n]\n") |
| new_compile_commands_file.close() |
| |
| print("Generated Compile Commands!") |