Building `swift-inspect` on Linux

Hello,

I have tried to build swift-inspect but I have failed to build it.

I have used the provided helper script by invoking

$ ./build_script_helper.py --package-path . --build-path .build --toolchain /usr/local/bin/swift --configuration debug

but it always files on inability to import SwiftRemoteMirror.

/home/mikolas/Developer/swift/tools/swift-inspect/Sources/swift-inspect/Backtrace.swift:13:8: error: no such module 'SwiftRemoteMirror'
import SwiftRemoteMirror
       ^

I have tried (and failed) to play with SwiftRemoteMirror before.

In the script, I have noticed some things that bother me. For example the -I ${toolchain}/usr/include/swift directory does not exist in the toolchain (the swift directory is missing). And the -L ${toolchain}/usr/lib/swift/macosx directory is also missing - there is linux directory instead of macosx.

The linux directory, however, contains libswiftRemoteMirror.so, which made me think, that I have invoked the build incorrectly. On second thought, there should be some kind of header file or .swiftmodule "file" which is not the case.

Can I build and use swift-inspect using Linux (Ubuntu 20.04) RELEASE or Development SNAPSHOT toolchain? Or do I need to build by own toolchain from source?

Thanks :)

Note: The swift-inspect package I have tried to build is from apple/swift main branch.
Edit: I dare to tag @Mike_Ash :)

1 Like

swift-inspect is not usable on Linux - you will need to do a port of it. I haven't had time yet to do the port for Linux but should be relatively straightforward. All the infrastructure to support different platforms is now in place due to the Windows support being added. You should only need to implement the process inspection support (via ptrace).

Thanks for reply!

I have tried it on my macOS machine

swift-driver version: 1.45.2 Apple Swift version 5.6 (swiftlang-5.6.0.323.62 clang-1316.0.20.8)
Target: x86_64-apple-macosx12.0

using following configuration

$ python3 build_script_helper.py --package-path . --build-path .build --toolchain /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain --configuration release

however, it failed too. It looks like there is no issue with SwiftRemoteMirror but a bunch of types are missing.

/Users/mikolasstuchlik/Developer/swift/tools/swift-inspect/Sources/swift-inspect/Operations/DumpConcurrency.swift:280:33: error: cannot find type 'swift_actor_info_t' in scope
  func decodeActorFlags(_ info: swift_actor_info_t) -> (
                                ^~~~~~~~~~~~~~~~~~
/Users/mikolasstuchlik/Developer/swift/tools/swift-inspect/Sources/swift-inspect/Operations/DumpConcurrency.swift:154:18: error: cannot find 'swift_reflection_metadataIsActor' in scope
    let result = swift_reflection_metadataIsActor(context, metadata) != 0
                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/mikolasstuchlik/Developer/swift/tools/swift-inspect/Sources/swift-inspect/Operations/DumpConcurrency.swift:170:26: error: cannot find 'swift_reflection_asyncTaskInfo' in scope
    let reflectionInfo = swift_reflection_asyncTaskInfo(context, task)
                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(redacted)
/Users/mikolasstuchlik/Developer/swift/tools/swift-inspect/Sources/swift-inspect/Operations/DumpConcurrency.swift:395:18: error: cannot find 'swift_reflection_actorInfo' in scope
      let info = swift_reflection_actorInfo(context, actor)
                 ^~~~~~~~~~~~~~~~~~~~~~~~~~
(redacted)
/Users/mikolasstuchlik/Developer/swift/tools/swift-inspect/Sources/swift-inspect/Operations/DumpConcurrency.swift:425:17: error: cannot find 'swift_reflection_nextJob' in scope
          job = swift_reflection_nextJob(context, job);
                ^~~~~~~~~~~~~~~~~~~~~~~~
/Users/mikolasstuchlik/Developer/swift/tools/swift-inspect/Sources/swift-inspect/main.swift:47:36: error: protocol 'RemoteProcess' can only be used as a generic constraint because it has Self or associated type requirements
                      _ body: (any RemoteProcess) throws -> Void) throws {
                                   ^

I have removed error: type of expression is ambiguous without more context and error: generic parameter 'Element' could not be inferred from the output.

I have therefore removed the whole DumpConcurrency.swift file and modified the main.swift as follows

diff --git a/tools/swift-inspect/Sources/swift-inspect/main.swift b/tools/swift-inspect/Sources/swift-inspect/main.swift
index 649f31c7..5f0b6365 100644
--- a/tools/swift-inspect/Sources/swift-inspect/main.swift
+++ b/tools/swift-inspect/Sources/swift-inspect/main.swift
@@ -44,27 +44,16 @@ internal struct BacktraceOptions: ParsableArguments {
 
 
 internal func inspect(options: UniversalOptions,
-                      _ body: (any RemoteProcess) throws -> Void) throws {
+                      _ body: (DarwinRemoteProcess) throws -> Void) throws {
   guard let processId = process(matching: options.nameOrPid) else {
     print("No process found matching \(options.nameOrPid)")
     return
   }
-
-#if os(iOS) || os(macOS) || os(tvOS) || os(watchOS)
   guard let process = DarwinRemoteProcess(processId: processId,
                                           forkCorpse: options.forkCorpse) else {
     print("Failed to create inspector for process id \(processId)")
     return
   }
-#elseif os(Windows)
-  guard let process = WindowsRemoteProcess(processId: processId) else {
-    print("Failed to create inspector for process id \(processId)")
-    return
-  }
-#else
-#error("Unsupported platform")
-#endif
-
   try body(process)
 }
 
@@ -79,7 +68,6 @@ internal struct SwiftInspect: ParsableCommand {
     DumpGenericMetadata.self,
     DumpCacheNodes.self,
     DumpArrays.self,
-    DumpConcurrency.self,
   ]
 #else
   static let subcommands: [ParsableCommand.Type] = [

basically, I have removed the now deleted DumpConcurrency option from the list of options and removed the any RemoteProcess syntax since it's not part of the Swift 5.6

The compilation then succeeded using the same command as above. I will try to run the tool in following days.

However, there is one thing that still bothers me @compnerd . Even if I implement something like LinuxRemoteProcess and use it in some sort of #elseif os(Linux) macro, I still won't be able to compile it on Linux, since the SwiftRemoteMirror module is not part of the toolchain, only the .so file. Is there any workaround :thinking:

1 Like

If the DSO is there - you should be able to work around it pretty easily. IIRC, the module in question is a C module, not a Swift module. That means that you should only need the corresponding headers and should be able to use that to construct the module.

1 Like

Thank you for your reply.

On my Linux system, I have downloaded THUNK DEVELOPMENT release of the Toolchain and used the header files located in the apple/swift repo I have previously checked-out to get the swift-inspect.

I only modified build_script_helper.py in following manner:

mikolas@mikolas-desktop:~/Developer/swift/tools/swift-inspect$ git diff build_script_helper.py 
diff --git a/tools/swift-inspect/build_script_helper.py b/tools/swift-inspect/build_script_helper.py
index d11e254d53c..5a9e68716b1 100755
--- a/tools/swift-inspect/build_script_helper.py
+++ b/tools/swift-inspect/build_script_helper.py
@@ -17,11 +17,11 @@ def perform_build(args, swiftbuild_path):
         "-Xswiftc",
         "-I",
         "-Xswiftc",
-        os.path.join(args.toolchain, 'usr', 'include', 'swift'),
+        "/home/mikolas/Developer/swift/include/swift",
         "-Xswiftc",
         "-L",
         "-Xswiftc",
-        os.path.join(args.toolchain, 'usr', 'lib', 'swift', 'macosx'),
+        os.path.join(args.toolchain, 'usr', 'lib', 'swift', 'linux'),
         "-Xswiftc",
         "-lswiftRemoteMirror"
     ]

The compilation fails successfully on the expected error: Unsupported platform directives.

I am interested in commiting LinuxRemoteProcess in the future, but it will take me probably few monts before I post anything. This would be the first time I will play around with ptrace and there is a lot to learn for me.

I have already found some materials, but if you (or anyone reading this :slight_smile:) happen to know about some good articles, documentation or blog posts that would be related to this topic, I would appreciate it.