Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[lldb][RPC] Upstream Python scripts #138028

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

chelcassanova
Copy link
Contributor

As part of upstreaming LLDB RPC, this commit adds python scripts that are used by LLDB RPC to modify the public lldb header files for use with RPC.

https://discourse.llvm.org/t/rfc-upstreaming-lldb-rpc/85804

@llvmbot
Copy link
Member

llvmbot commented Apr 30, 2025

@llvm/pr-subscribers-lldb

Author: Chelsea Cassanova (chelcassanova)

Changes

As part of upstreaming LLDB RPC, this commit adds python scripts that are used by LLDB RPC to modify the public lldb header files for use with RPC.

https://discourse.llvm.org/t/rfc-upstreaming-lldb-rpc/85804


Full diff: https://github.com/llvm/llvm-project/pull/138028.diff

3 Files Affected:

  • (added) lldb/scripts/convert-lldb-header-to-rpc-header.py (+65)
  • (added) lldb/scripts/framework-header-include-fix.py (+44)
  • (added) lldb/scripts/framework-header-version-fix.py (+65)
diff --git a/lldb/scripts/convert-lldb-header-to-rpc-header.py b/lldb/scripts/convert-lldb-header-to-rpc-header.py
new file mode 100755
index 0000000000000..4550837d8e08d
--- /dev/null
+++ b/lldb/scripts/convert-lldb-header-to-rpc-header.py
@@ -0,0 +1,65 @@
+#!/usr/bin/env python3
+# Usage: convert-lldb-header-to-rpc-header.py <path/to/input-header.h> <path/to/output-header.h>
+# This scripts takes common LLDB headers (such as lldb-defines.h) and replaces references to LLDB
+# with those for RPC. This happens for:
+# - namespace definitions
+# - namespace usage
+# - version string macros
+# - ifdef/ifndef lines
+
+import argparse
+import os
+import re
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("input")
+    parser.add_argument("output")
+    args = parser.parse_args()
+    input_path = str(args.input)
+    output_path = str(args.output)
+    with open(input_path, "r") as input_file:
+        lines = input_file.readlines()
+
+    with open(output_path, "w") as output_file:
+        for line in lines:
+            # NOTE: We do not use lldb-forward.h or lldb-versioning.h in RPC, so remove
+            # all includes that are found for these files.
+            if re.match(
+                r'#include "lldb/lldb-forward|#include "lldb/lldb-versioning', line
+            ):
+                continue
+            # For lldb-rpc-defines.h, replace the ifndef LLDB_LLDB_ portion with LLDB_RPC_ as we're not
+            # using LLDB private definitions in RPC.
+            elif re.match(r".+LLDB_LLDB_", line):
+                output_file.write(re.sub(r"LLDB_LLDB_", r"LLDB_RPC_", line))
+            # Similarly to lldb-rpc-defines.h, replace the ifndef for LLDB_API in SBDefines.h to LLDB_RPC_API_ for the same reason.
+            elif re.match(r".+LLDB_API_", line):
+                output_file.write(re.sub(r"LLDB_API_", r"LLDB_RPC_API_", line))
+            # Replace the references for the macros that define the versioning strings in
+            # lldb-rpc-defines.h.
+            elif re.match(r".+LLDB_VERSION", line):
+                output_file.write(re.sub(r"LLDB_VERSION", r"LLDB_RPC_VERSION", line))
+            elif re.match(r".+LLDB_REVISION", line):
+                output_file.write(re.sub(r"LLDB_REVISION", r"LLDB_RPC_REVISION", line))
+            elif re.match(r".+LLDB_VERSION_STRING", line):
+                output_file.write(
+                    re.sub(r"LLDB_VERSION_STRING", r"LLDB_RPC_VERSION_STRING", line)
+                )
+            # For local #includes
+            elif re.match(r'#include "lldb/lldb-', line):
+                output_file.write(re.sub(r"lldb/lldb-", r"lldb-rpc-", line))
+            # Rename the lldb namespace definition to lldb-rpc.
+            elif re.match(r"namespace lldb", line):
+                output_file.write(re.sub(r"lldb", r"lldb_rpc", line))
+            # Rename namespace references
+            elif re.match(r".+lldb::", line):
+                output_file.write(re.sub(r"lldb::", r"lldb_rpc::", line))
+            else:
+                # Write any line that doesn't need to be converted
+                output_file.write(line)
+
+
+if __name__ == "__main__":
+    main()
diff --git a/lldb/scripts/framework-header-include-fix.py b/lldb/scripts/framework-header-include-fix.py
new file mode 100755
index 0000000000000..e214ce005923f
--- /dev/null
+++ b/lldb/scripts/framework-header-include-fix.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python3
+# Usage: framework-header-include-fix.py <path/to/input-header.h> <path/to/output-header.h>
+# This script modifies all #include lines in all lldb-rpc headers
+# from either filesystem or local includes to liblldbrpc includes.
+
+import argparse
+import os
+import re
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("input")
+    parser.add_argument("output")
+    args = parser.parse_args()
+    input_path = str(args.input)
+    output_path = str(args.output)
+    with open(input_path, "r+") as input_file:
+        lines = input_file.readlines()
+
+    with open(output_path, "w+") as output_file:
+        for line in lines:
+            # Replace includes from RPCCommon to liblldbrpc includes.
+            # e.g. #include <lldb-rpc/common/RPCArgument.h> -> #include <LLDBRPC/RPCArgument.h>
+            if re.match(r".+<lldb-rpc/common", line):
+                output_file.write(re.sub(r"<lldb-rpc/common", r"<LLDBRPC", line))
+                # Replace all local file includes to liblldbrpc includes.
+                # e.g. #include "SBFoo.h" -> #include <LLDBRPC/SBFoo.h>
+            elif re.match(r'#include "(.*)"', line):
+                include_filename = re.search(r'#include "(.*)"', line).groups()[0]
+                output_file.write(
+                    re.sub(
+                        r'#include "(.*)"',
+                        r"#include <LLDBRPC/" + include_filename + ">",
+                        line,
+                    )
+                )
+            else:
+                # Write any line that doesn't need to be converted
+                output_file.write(line)
+
+
+if __name__ == "__main__":
+    main()
diff --git a/lldb/scripts/framework-header-version-fix.py b/lldb/scripts/framework-header-version-fix.py
new file mode 100755
index 0000000000000..72185f8e820ce
--- /dev/null
+++ b/lldb/scripts/framework-header-version-fix.py
@@ -0,0 +1,65 @@
+#!/usr/bin/env python3
+# Usage: framework-header-version-fix.py <path/to/input-header.h> <path/to/output-header.h> MAJOR MINOR PATCH
+# This script modifies lldb-rpc-defines.h to uncomment the macro defines used for the LLDB
+# major, minor and patch values as well as populating their definitions.
+
+import argparse
+import os
+import re
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("input")
+    parser.add_argument("output")
+    parser.add_argument("lldb_version_major")
+    parser.add_argument("lldb_version_minor")
+    parser.add_argument("lldb_version_patch")
+    args = parser.parse_args()
+    input_path = str(args.input)
+    output_path = str(args.output)
+    lldb_version_major = args.lldb_version_major
+    lldb_version_minor = args.lldb_version_minor
+    lldb_version_patch = args.lldb_version_patch
+
+    with open(input_path, "r") as input_file:
+        lines = input_file.readlines()
+
+    with open(output_path, "w") as output_file:
+        for line in lines:
+            # Uncomment the line that defines the LLDB major version and populate its value.
+            if re.match(r"//#define LLDB_RPC_VERSION$", line):
+                output_file.write(
+                    re.sub(
+                        r"//#define LLDB_RPC_VERSION",
+                        r"#define LLDB_RPC_VERSION " + lldb_version_major,
+                        line,
+                    )
+                )
+            # Uncomment the line that defines the LLDB minor version and populate its value.
+            elif re.match(r"//#define LLDB_RPC_REVISION$", line):
+                output_file.write(
+                    re.sub(
+                        r"//#define LLDB_RPC_REVISION",
+                        r"#define LLDB_RPC_REVISION " + lldb_version_minor,
+                        line,
+                    )
+                )
+            # Uncomment the line that defines the complete LLDB version string and populate its value.
+            elif re.match(r"//#define LLDB_RPC_VERSION_STRING$", line):
+                output_file.write(
+                    re.sub(
+                        r"//#define LLDB_RPC_VERSION_STRING",
+                        r'#define LLDB_RPC_VERSION_STRING "{0}.{1}.{2}"'.format(
+                            lldb_version_major, lldb_version_minor, lldb_version_patch
+                        ),
+                        line,
+                    )
+                )
+            else:
+                # Write any line that doesn't need to be converted
+                output_file.write(line)
+
+
+if __name__ == "__main__":
+    main()

@JDevlieghere
Copy link
Member

We should add shell tests for these scripts.

@chelcassanova
Copy link
Contributor Author

I can add shell tests 👍🏾

As part of upstreaming LLDB RPC, this commit adds python scripts that
are used by LLDB RPC to modify the public lldb header files for use with
RPC.

https://discourse.llvm.org/t/rfc-upstreaming-lldb-rpc/85804
@chelcassanova chelcassanova force-pushed the upstream-lldb-rpc/add-python-scripts-for-headers branch from c915f7c to c51a312 Compare May 2, 2025 18:46
Copy link
Member

@bulbazord bulbazord left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding tests. Please let others take a look before merging.

@@ -0,0 +1,13 @@
// Generate a dummy SB API file using lldb-rpc-gen.
# RUN: mkdir -p %t/server
# RUN: mkdir -p %t/lib
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI failing with:

/var/lib/buildkite-agent/builds/linux-56-59b8f5d88-spx4x-1/llvm-project/github-pull-requests/build/tools/lldb/test/Shell/RPC/Scripts/TestFrameworkIncludeFixScript/Output/CheckSBClass.test.script: line 3: fg: no job control

Is it passing locally on Linux for you?

I don't see anything that would need job control, I'm wondering if a stray character is causing the shell to think that.

Copy link
Contributor Author

@chelcassanova chelcassanova May 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't tried this on Linux yet, only macOS for now. I actually thought that error was a BuildKite failure 😅 so I can look to see what the issue is there.

args = parser.parse_args()
input_path = str(args.input)
output_path = str(args.output)
with open(input_path, "r+") as input_file:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be r only and same with the w mode below.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was a mistake from an earlier implementation, I shoud've had all of these replaced with just r or w from your original set of comments on the larger PR.

Comment on lines +27 to +28
# Replace all local file includes to liblldbrpc includes.
# e.g. #include "SBFoo.h" -> #include <LLDBRPC/SBFoo.h>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These 2 comment lines should be dedented, I think.

output_file.write(re.sub(r"<lldb-rpc/common", r"<LLDBRPC", line))
# Replace all local file includes to liblldbrpc includes.
# e.g. #include "SBFoo.h" -> #include <LLDBRPC/SBFoo.h>
elif re.match(r'#include "(.*)"', line):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe you can use https://docs.python.org/3/whatsnew/3.8.html#assignment-expressions and reuse the match below?

with open(output_path, "w") as output_file:
for line in lines:
# Uncomment the line that defines the LLDB major version and populate its value.
if re.match(r"//#define LLDB_RPC_VERSION$", line):
Copy link
Collaborator

@DavidSpickett DavidSpickett May 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, you could probably just skip right to the sub, but abundance of caution I suppose. If you did, you'd have to check for LLDB_RPC_VERSION_STRING first as LLDB_RPC_VERSION is a substring of it.

On balance, it doesn't really matter especially here where there is also an obvious pitfall.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used $ to make sure that the match here for LLDB_RPC_VERSION can't have something past the VERSION so I think it's possible to try using //#define LLDB_RPC_VERSION$ as the sub match here. Either that or my regex knowledge is out of whack.

// The LLDB version defines must be uncommented and filled in with the values passed into the script.
# CHECK: #define LLDB_RPC_VERSION 17
# CHECK: #define LLDB_RPC_REVISION 0
# CHECK: #define LLDB_RPC_VERSION_STRING "17.0.0"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect this would pass even if the line was commented, please try that and see if that's true.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll try this 👍🏾

@chelcassanova
Copy link
Contributor Author

For what it's worth, while these scripts do work for intended purpose for now, an approach I'd love is to have all this header modification be a subtool of the lldb-rpc-gen tool itself. Subtooling a ClangTool is something I'm not too sure on how to do so maybe a better Clang expert can help guide the way on this? :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants