Reland "[lldb][headers] Create Python script to fix up framework head… (#143945)
…ers" (#143941) Reland the script that converts lldb headers to RPC headers. The RPC test was failing due to the incorrect input filepath being used. Original commit message: This commit replaces the shell script that fixes up includes for the LLDB framework with a Python script. This script will also be used when fixing up includes for the LLDBRPC.framework.
This commit is contained in:
parent
741ea80446
commit
8a8ea8fec0
@ -68,24 +68,17 @@ if(NOT APPLE_EMBEDDED)
|
||||
)
|
||||
endif()
|
||||
|
||||
# At configuration time, collect headers for the framework bundle and copy them
|
||||
# into a staging directory. Later we can copy over the entire folder.
|
||||
file(GLOB public_headers ${LLDB_SOURCE_DIR}/include/lldb/API/*.h)
|
||||
set(generated_public_headers ${LLDB_OBJ_DIR}/include/lldb/API/SBLanguages.h)
|
||||
file(GLOB root_public_headers ${LLDB_SOURCE_DIR}/include/lldb/lldb-*.h)
|
||||
file(GLOB root_private_headers ${LLDB_SOURCE_DIR}/include/lldb/lldb-private*.h)
|
||||
list(REMOVE_ITEM root_public_headers ${root_private_headers})
|
||||
|
||||
find_program(unifdef_EXECUTABLE unifdef)
|
||||
|
||||
set(lldb_header_staging ${CMAKE_CURRENT_BINARY_DIR}/FrameworkHeaders)
|
||||
foreach(header
|
||||
${public_headers}
|
||||
${generated_public_headers}
|
||||
${root_public_headers})
|
||||
# All necessary header files will be staged in the include directory in the build directory,
|
||||
# so just copy the files from there into the framework's staging directory.
|
||||
set(lldb_build_dir_header_staging "${CMAKE_BINARY_DIR}/include/lldb")
|
||||
set(lldb_framework_header_staging "${CMAKE_CURRENT_BINARY_DIR}/FrameworkHeaders")
|
||||
file(GLOB lldb_build_dir_header_staging_list ${lldb_build_dir_header_staging}/*)
|
||||
foreach(header ${lldb_build_dir_header_staging_list})
|
||||
|
||||
get_filename_component(basename ${header} NAME)
|
||||
set(staged_header ${lldb_header_staging}/${basename})
|
||||
set(staged_header ${lldb_framework_header_staging}/${basename})
|
||||
|
||||
if(unifdef_EXECUTABLE)
|
||||
# unifdef returns 0 when the file is unchanged and 1 if something was changed.
|
||||
@ -112,13 +105,20 @@ set_target_properties(liblldb-resource-headers PROPERTIES FOLDER "LLDB/Resources
|
||||
add_dependencies(liblldb-resource-headers liblldb-header-staging)
|
||||
add_dependencies(liblldb liblldb-resource-headers)
|
||||
|
||||
# At build time, copy the staged headers into the framework bundle (and do
|
||||
# some post-processing in-place).
|
||||
add_custom_command(TARGET liblldb POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${lldb_header_staging} $<TARGET_FILE_DIR:liblldb>/Headers
|
||||
COMMAND ${LLDB_SOURCE_DIR}/scripts/framework-header-fix.sh $<TARGET_FILE_DIR:liblldb>/Headers ${LLDB_VERSION}
|
||||
COMMENT "LLDB.framework: copy framework headers"
|
||||
)
|
||||
# Take the headers from the staging directory and fix up their includes for the framework.
|
||||
# Then write them to the output directory.
|
||||
# Also, run unifdef to remove any specified guards from the header files.
|
||||
file(GLOB lldb_framework_header_staging_list ${lldb_framework_header_staging}/*)
|
||||
foreach(header ${lldb_framework_header_staging_list})
|
||||
|
||||
set(input_header ${header})
|
||||
set(output_header $<TARGET_FILE_DIR:liblldb>/Headers/${input_header})
|
||||
|
||||
add_custom_command(TARGET liblldb POST_BUILD
|
||||
COMMAND ${LLDB_SOURCE_DIR}/scripts/framework-header-fix.py -f lldb_main -i ${input_header} -o ${output_header} -p ${unifdef_EXECUTABLE} USWIG
|
||||
COMMENT "LLDB.framework: Fix up and copy framework headers"
|
||||
)
|
||||
endforeach()
|
||||
|
||||
# Copy vendor-specific headers from clang (without staging).
|
||||
if(NOT APPLE_EMBEDDED)
|
||||
|
126
lldb/scripts/framework-header-fix.py
Executable file
126
lldb/scripts/framework-header-fix.py
Executable file
@ -0,0 +1,126 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
Usage: <path/to/input-directory> <path/to/output-directory>
|
||||
|
||||
This script is used when building LLDB.framework or LLDBRPC.framework. For each framework, local includes are converted to their respective framework includes.
|
||||
|
||||
This script is used in 2 ways:
|
||||
1. It is used on header files that are copied into LLDB.framework. For these files, local LLDB includes are converted into framework includes, e.g. #include "lldb/API/SBDefines.h" -> #include <LLDB/SBDefines.h>.
|
||||
|
||||
2. It is used on header files for LLDBRPC.framework. For these files, includes of RPC common files will be converted to framework includes, e.g. #include <lldb-rpc/common/RPCCommon.h> -> #include <LLDBRPC/RPCCommon.h>. It will also change local includes to framework includes, e.g. #include "SBAddress.h" -> #include <LLDBRPC/SBAddress.h>
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
# Main header regexes
|
||||
INCLUDE_FILENAME_REGEX = re.compile(
|
||||
r'#include "lldb/API/(?P<include_filename>.*){0,1}"'
|
||||
)
|
||||
|
||||
# RPC header regexes
|
||||
RPC_COMMON_REGEX = re.compile(r"#include <lldb-rpc/common/(?P<include_filename>.*)>")
|
||||
RPC_INCLUDE_FILENAME_REGEX = re.compile(r'#include "(?P<include_filename>.*)"')
|
||||
|
||||
|
||||
def modify_rpc_includes(input_file_path, output_file_path):
|
||||
with open(input_file_path, "r") as input_file:
|
||||
lines = input_file.readlines()
|
||||
file_buffer = "".join(lines)
|
||||
with open(output_file_path, "w") as output_file:
|
||||
# Local includes must be changed to RPC framework level includes.
|
||||
# e.g. #include "SBDefines.h" -> #include <LLDBRPC/SBDefines.h>
|
||||
# Also, RPC common code includes must change to RPC framework level includes.
|
||||
# e.g. #include "lldb-rpc/common/RPCPublic.h" -> #include <LLDBRPC/RPCPublic.h>
|
||||
rpc_common_matches = RPC_COMMON_REGEX.finditer(file_buffer)
|
||||
rpc_include_filename_matches = RPC_INCLUDE_FILENAME_REGEX.finditer(
|
||||
file_buffer
|
||||
)
|
||||
for match in rpc_common_matches:
|
||||
file_buffer = re.sub(
|
||||
match.group(),
|
||||
r"#include <LLDBRPC/" + match.group("include_filename") + ">",
|
||||
file_buffer,
|
||||
)
|
||||
for match in rpc_include_filename_matches:
|
||||
file_buffer = re.sub(
|
||||
match.group(),
|
||||
r"#include <LLDBRPC/" + match.group("include_filename") + ">",
|
||||
file_buffer,
|
||||
)
|
||||
output_file.write(file_buffer)
|
||||
|
||||
|
||||
def modify_main_includes(input_file_path, output_file_path):
|
||||
with open(input_file_path, "r") as input_file:
|
||||
lines = input_file.readlines()
|
||||
file_buffer = "".join(lines)
|
||||
with open(output_file_path, "w") as output_file:
|
||||
# Local includes must be changed to framework level includes.
|
||||
# e.g. #include "lldb/API/SBDefines.h" -> #include <LLDB/SBDefines.h>
|
||||
regex_matches = INCLUDE_FILENAME_REGEX.finditer(file_buffer)
|
||||
for match in regex_matches:
|
||||
file_buffer = re.sub(
|
||||
match.group(),
|
||||
r"#include <LLDB/" + match.group("include_filename") + ">",
|
||||
file_buffer,
|
||||
)
|
||||
output_file.write(file_buffer)
|
||||
|
||||
|
||||
def remove_guards(output_file_path, unifdef_path, unifdef_guards):
|
||||
# The unifdef path should be passed in from CMake. If it wasn't there in CMake or is incorrect,
|
||||
# find it using shutil. If shutil can't find it, then exit.
|
||||
if not shutil.which(unifdef_path):
|
||||
unifdef_path = shutil.which("unifdef")
|
||||
if not unifdef_path:
|
||||
print(
|
||||
"Unable to find unifdef executable. Guards will not be removed from input files. Exiting..."
|
||||
)
|
||||
sys.exit()
|
||||
|
||||
subprocess_command = (
|
||||
[unifdef_path, "-o", output_file_path] + unifdef_guards + [output_file_path]
|
||||
)
|
||||
subprocess.run(subprocess_command)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("-f", "--framework", choices=["lldb_main", "lldb_rpc"])
|
||||
parser.add_argument("-i", "--input_file")
|
||||
parser.add_argument("-o", "--output_file")
|
||||
parser.add_argument("-p", "--unifdef_path")
|
||||
parser.add_argument(
|
||||
"unifdef_guards",
|
||||
nargs="+",
|
||||
type=str,
|
||||
help="Guards to be removed with unifdef. These must be specified in the same way as they would be when passed directly into unifdef.",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
input_file_path = str(args.input_file)
|
||||
output_file_path = str(args.output_file)
|
||||
framework_version = args.framework
|
||||
unifdef_path = str(args.unifdef_path)
|
||||
# Prepend dashes to the list of guards passed in from the command line.
|
||||
# unifdef takes the guards to remove as arguments in their own right (e.g. -USWIG)
|
||||
# but passing them in with dashes for this script causes argparse to think that they're
|
||||
# arguments in and of themself, so they need to passed in without dashes.
|
||||
unifdef_guards = ["-" + guard for guard in args.unifdef_guards]
|
||||
|
||||
if framework_version == "lldb_main":
|
||||
modify_main_includes(input_file_path, output_file_path)
|
||||
if framework_version == "lldb_rpc":
|
||||
modify_rpc_includes(input_file_path, output_file_path)
|
||||
# After the incldues have been modified, run unifdef on the headers to remove any guards
|
||||
# specified at the command line.
|
||||
remove_guards(output_file_path, unifdef_path, unifdef_guards)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
13
lldb/test/Shell/Scripts/Inputs/Main/SBAddress.h
Normal file
13
lldb/test/Shell/Scripts/Inputs/Main/SBAddress.h
Normal file
@ -0,0 +1,13 @@
|
||||
// This is a truncated version of an SB API file
|
||||
// used to test framework-header-fix.py to make sure the includes are correctly fixed
|
||||
// up for the LLDB.framework.
|
||||
|
||||
// Local includes must be changed to framework level includes.
|
||||
// e.g. #include "lldb/API/SBDefines.h" -> #include <LLDB/SBDefines.h>
|
||||
#include "lldb/API/SBDefines.h"
|
||||
#include "lldb/API/SBModule.h"
|
||||
|
||||
// Any include guards specified at the command line must be removed.
|
||||
#ifndef SWIG
|
||||
int a = 10
|
||||
#endif
|
9
lldb/test/Shell/Scripts/Inputs/RPC/RPCSBAddress.h
Normal file
9
lldb/test/Shell/Scripts/Inputs/RPC/RPCSBAddress.h
Normal file
@ -0,0 +1,9 @@
|
||||
// This is a truncated version of an SB API file generated by lldb-rpc-gen
|
||||
// used to test framework-header-fix.py to make sure the includes are correctly fixed
|
||||
// up for the LLDBRPC.framework.
|
||||
|
||||
// Local includes must be changed to framework level includes.
|
||||
// e.g. #include "lldb/API/SBDefines.h" -> #include <LLDB/SBDefines.h>
|
||||
#include "LLDBRPC.h"
|
||||
#include "SBDefines.h"
|
||||
#include <lldb-rpc/common/RPCPublic.h>
|
11
lldb/test/Shell/Scripts/TestFrameworkFixScript.test
Normal file
11
lldb/test/Shell/Scripts/TestFrameworkFixScript.test
Normal file
@ -0,0 +1,11 @@
|
||||
# Create a temp dir for output and run the framework fix script on the truncated version of SBAddress.h in the inputs dir.
|
||||
RUN: mkdir -p %t/Outputs
|
||||
RUN: %python %p/../../../scripts/framework-header-fix.py -f lldb_main -i %p/Inputs/Main/SBAddress.h -o %t/Outputs/SBAddress.h -p /usr/bin/unifdef USWIG
|
||||
|
||||
# Check the output
|
||||
RUN: cat %t/Outputs/SBAddress.h | FileCheck %s
|
||||
|
||||
# Local includes must be changed to framework level includes.
|
||||
# e.g. #include "lldb/API/SBDefines.h" -> #include <LLDB/SBDefines.h>
|
||||
CHECK: #include <LLDB/SBDefines.h>
|
||||
CHECK: #include <LLDB/SBModule.h>
|
12
lldb/test/Shell/Scripts/TestFrameworkFixUnifdef.test
Normal file
12
lldb/test/Shell/Scripts/TestFrameworkFixUnifdef.test
Normal file
@ -0,0 +1,12 @@
|
||||
# REQUIRES: system-darwin
|
||||
# Create a temp dir for output and run the framework fix script on the truncated version of SBAddress.h in the inputs dir.
|
||||
RUN: mkdir -p %t/Outputs
|
||||
RUN: %python %p/../../../scripts/framework-header-fix.py -f lldb_main -i %p/Inputs/Main/SBAddress.h -o %t/Outputs/SBAddress.h -p /usr/bin/unifdef USWIG
|
||||
|
||||
# Check the output
|
||||
RUN: cat %t/Outputs/SBAddress.h | FileCheck %s
|
||||
|
||||
# Any include guards specified at the command line must be removed.
|
||||
CHECK-NOT: #ifndef SWIG
|
||||
CHECK: int a = 10
|
||||
CHECK-NOT: #endif
|
14
lldb/test/Shell/Scripts/TestRPCFrameworkFixScript.test
Normal file
14
lldb/test/Shell/Scripts/TestRPCFrameworkFixScript.test
Normal file
@ -0,0 +1,14 @@
|
||||
# Create a temp dir for output and run the framework fix script on the truncated version of SBAddress.h in the inputs dir.
|
||||
RUN: mkdir -p %t/Outputs
|
||||
RUN: %python %p/../../../scripts/framework-header-fix.py -f lldb_rpc -i %p/Inputs/RPC/RPCSBAddress.h -o %t/Outputs/RPCSBAddress.h -p /usr/bin/unifdef USWIG
|
||||
|
||||
# Check the output
|
||||
RUN: cat %t/Outputs/RPCSBAddress.h | FileCheck %s
|
||||
|
||||
# Local includes must be changed to RPC framework level includes.
|
||||
# e.g. #include "SBDefines.h" -> #include <LLDBRPC/SBDefines.h>
|
||||
# Also, RPC common code includes must change to RPC framework level includes.
|
||||
# e.g. #include "lldb-rpc/common/RPCPublic.h" -> #include <LLDBRPC/RPCPublic.h>
|
||||
CHECK: #include <LLDBRPC/LLDBRPC.h>
|
||||
CHECK: #include <LLDBRPC/SBDefines.h>
|
||||
CHECK: #include <LLDBRPC/RPCPublic.h>
|
Loading…
x
Reference in New Issue
Block a user