Skip to content
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

Automatically include path to <swift/bridging> in SDK installs #80142

Open
ADKaster opened this issue Mar 19, 2025 · 5 comments
Open

Automatically include path to <swift/bridging> in SDK installs #80142

ADKaster opened this issue Mar 19, 2025 · 5 comments
Labels
feature A feature request or implementation triage needed This issue needs more specific labels

Comments

@ADKaster
Copy link
Contributor

ADKaster commented Mar 19, 2025

Motivation

On Linux, if you use a toolchain that is installed into a non-standard location, such as via swiftly, some headers and module.modulemap files from the SDK are installed in a location that is not part of the default search paths.

The files are as such:

/home/andrew/.local/share/swiftly/toolchains/6.0.3/usr/include
├── llvm-c
│   └── lto.h
├── module.modulemap
├── SourceKit
│   └── sourcekitd.h
└── swift
    ├── bridging
    └── bridging.modulemap

4 directories, 5 files

To be clear, these files are installed into $PREFIX/include. So if you use, for example, the swift.org docker containers, then these files end up at /usr/include/llvm-c, /usr/include/SourceKit and /usr/include/swift.

Looking at the predefined system paths for swift.org release tarball clang, we can see that /path/to/swift-6.0.3-RELEASE-ubuntu24.04/usr/include is not included in the default search path.

ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include"
ignoring nonexistent directory "/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13
 /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/x86_64-linux-gnu/c++/13
 /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/backward
 /home/andrew/swift-installs/swift-6.0.3-RELEASE-ubuntu24.04/usr/lib/clang/17/include
 /usr/local/include
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.

The end result of this is that if you want to use swiftly or tarball swift toolchains, and you want your project to #include <swift/bridging>, the path to this "forgotten PREFIX" must be added manually.

On the command line, this is 'straightforward', like so:

/home/andrew/swift-installs/swift-6.0.3-RELEASE-ubuntu24.04/usr/bin/swiftc \
    -I. \
    -cxx-interoperability-mode=default \
    -I$(swiftc -print-target-info | jq -r '.paths.runtimeResourcePath + "/../../include"') \
    main.swift

And in CMake, one needs to query -print-target-info already to get the library paths (ahem), so also adding this include path isn't the end of the world. However, it is poor UX.

Proposed solution

One solution would be to invent a "swift resource directory" concept, similar to the clang resource directory, and either 1) add it to the clang driver in swiftlang's llvm fork, and/or 2) add it as a predefined path in any swift frontend invocations of clang.

This solution feels the most forward-looking, though it does add another difference to swift's llvm fork that would be difficult to upstream.

Alternatives considered

  • The files could be installed into the clang resource directory of the bundled clang. This feels unsatisfactory, because the files do not belong to clang
  • Ship a clang config file https://clang.llvm.org/docs/UsersManual.html#configuration-files that adds the extra include path. This file would need to be edited every time a new directory or special handling for swift interop features is added, and would be a maintenance burden.

Additional information

cc @etcwilde @egorzhdan @compnerd

@ADKaster ADKaster added feature A feature request or implementation triage needed This issue needs more specific labels labels Mar 19, 2025
@finagolfin
Copy link
Member

The end result of this is that if you want to use swiftly or tarball swift toolchains, and you want your project to #include <swift/bridging>, the path to this "forgotten PREFIX" must be added manually.

Are you sure? There are some C++ Interop tests that appear to test using it. Maybe the module map is checked for in other directories than the header search paths you listed?

@ADKaster
Copy link
Contributor Author

The tests you linked all have explicit -I%swift_source_root/lib/ClangImporter/SwiftBridging in the lit RUN comment command lines. That directory has the required files: https://github.com/swiftlang/swift/tree/main/lib/ClangImporter/SwiftBridging.

So those tests only work because they are in fact explicitly adding the "missing prefix" I described. They also don't try to use an "installed" version of the bridging header, but instead use the version in the source tree.

@ADKaster
Copy link
Contributor Author

ADKaster commented Mar 21, 2025

Another way to frame the problem might be that if the CMake rules here copied the files to a directory the compiler searched by default, then those extra include paths in the lit tests could be removed. https://github.com/swiftlang/swift/blob/main/lib/ClangImporter/SwiftBridging/CMakeLists.txt

However neither SWIFT_INCLUDE_PATH at post-build time nor $PREFIX/include at post-install are searched (when $PREFIX is different from the system install prefix)

@finagolfin
Copy link
Member

So those tests only work because they are in fact explicitly adding the "missing prefix" I described. They also don't try to use an "installed" version of the bridging header, but instead use the version in the source tree.

Huh, you're right, I simply checked if the tests were manually adding an include for the installed version and ignored the source tree includes. That makes sense that this doesn't work in the final toolchain then.

@lhoward, is this not working for you either on linux?

@lhoward
Copy link
Contributor

lhoward commented Mar 22, 2025

So those tests only work because they are in fact explicitly adding the "missing prefix" I described. They also don't try to use an "installed" version of the bridging header, but instead use the version in the source tree.

Huh, you're right, I simply checked if the tests were manually adding an include for the installed version and ignored the source tree includes. That makes sense that this doesn't work in the final toolchain then.

@lhoward, is this not working for you either on linux?

From memory, yes this doesn't work, and indeed there's a related issue (not) finding the Dispatch and Block headers. I have filed an issue about this. My workaround has been some heuristics in Package.swift to guess the Swift root and add the include paths explicitly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature A feature request or implementation triage needed This issue needs more specific labels
Projects
None yet
Development

No branches or pull requests

3 participants