Skip to content

ClangImporter looks in the wrong path for the libc and new C++ module maps when -sdk is specified #74696

Closed
@finagolfin

Description

@finagolfin

Description

I was just building the latest June 13 trunk source snapshot natively on Android in the Termux app, when I ran into a compilation error while trying to build CxxStdlib for the first time, which was only recently enabled for Android too, 273edcf.

For some background, the Termux app has an Android C/C++ sysroot installed at /data/data/com.termux/files/, ie C/C++ header files are found in /data/data/com.termux/files/usr/include/, and I have a Swift 5.10.1 toolchain installed there too, so the Swift modules can also be found in /data/data/com.termux/files/usr/lib/swift/android/. This constitutes a full Swift 5.10.1 SDK, as the C/C++ headers/libraries and Swift modules/libraries are all together in a single sysroot.

Well, this caused problems, as the build of the trunk 6.1 Swift toolchain was picking up the wrong libcxxshim.modulemap, ie the one from the full Swift 5.10.1 SDK not the newly generated one in build/Ninja-Release/swift-android-aarch64/, which caused a compilation error as one of those shim headers was recently updated. I worked around this bug by removing that C++ interop module map from the 5.10.1 SDK.

Since there was nothing specific to Android here, I just tried to reproduce this issue in Fedora 40 x86_64. However, it turns out Fedora 40 is still installing Swift 5.8.1 in the system, so I could not reproduce, as libcxxshim.modulemap was installed in usr/lib/swift/linux/x86_64/ back then while a more recent 5.10 toolchain looks in usr/lib/swift/linux/ for that C++ module map:

> dnf repoquery -l swift-lang | ag "lib/swift/.*cxx.*modulemap"
/usr/libexec/swift/5.8.1/lib/swift/linux/x86_64/libcxxshim.modulemap
/usr/libexec/swift/5.8.1/lib/swift/linux/x86_64/libstdcxx.modulemap
> ls -l /usr/lib/swift
lrwxrwxrwx. 1 root root 34 Feb 16 00:00 /usr/lib/swift -> /usr/libexec/swift/5.8.1/lib/swift

So I simply moved those shims over to test for this bug, mv /usr/lib/swift/linux/x86_64/lib* /usr/lib/swift/linux/, and found that I could reproduce on linux also:

/home/finagolfin/swift-5.10.1-RELEASE-fedora39/usr/bin/swift-frontend -frontend -c -primary-file swift/test/Interpreter/hello_toplevel.swift -target x86_64-unknown-linux-gnu -disable-objc-interop -cxx-interoperability-mode=default -sdk / -color-diagnostics -new-driver-path /home/finagolfin/swift-5.10.1-RELEASE-fedora39/usr/bin/swift-driver -dump-clang-diagnostics -empty-abi-descriptor -resource-dir /home/finagolfin/swift-5.10.1-RELEASE-fedora39/usr/lib/swift -module-name hello_toplevel -plugin-path /home/finagolfin/swift-5.10.1-RELEASE-fedora39/usr/lib/swift/host/plugins -plugin-path /home/finagolfin/swift-5.10.1-RELEASE-fedora39/usr/local/lib/swift/host/plugins -o /tmp/TemporaryDirectory.hfI2hS/hello_toplevel-1.o
'/home/finagolfin/swift-5.10.1-RELEASE-fedora39/usr/bin/clang' '-fsyntax-only' '-fblocks' '-D__swift__=51001' '-fretain-comments-from-system-headers' '-isystem' '/home/finagolfin/swift-5.10.1-RELEASE-fedora39/usr/lib/swift' '-fPIC' '-fmodules' '-Xclang' '-fmodule-feature' '-Xclang' 'swift' '-x' 'c++' '-std=gnu++14' '-fmodule-map-file=/usr/lib/swift/linux/libcxxshim.modulemap' '--sysroot' '/' '-fmodules-validate-system-headers' '-Xclang' '-fmodule-format=obj' '-fapinotes-modules' '-fapinotes-swift-version=5' '-iapinotes-modules' '/home/finagolfin/swift-5.10.1-RELEASE-fedora39/usr/lib/swift/apinotes' '-target' 'x86_64-unknown-linux-gnu' '<swift-imported-modules>' '-mcx16' '-resource-dir' '/home/finagolfin/swift-5.10.1-RELEASE-fedora39/usr/lib/swift/clang' '-fansi-escape-codes' '-Xclang' '-opaque-pointers' '-working-directory' '/home/finagolfin'

Note the wrong 5.8.1 C++ module map used in the above output from the 5.10.1 repro command below, -fmodule-map-file=/usr/lib/swift/linux/libcxxshim.modulemap, despite the frontend explicitly specifying the right resource directory, -resource-dir /home/finagolfin/swift-5.10.1-RELEASE-fedora39/usr/lib/swift.

I just checked and the Fedora system package was finally updated to 5.10.1 last week, with the Fedora 40 build currently undergoing testing before deployment, so this bug will start hitting Fedora installs soon. It only happens when the -sdk / flag is explicitly passed in, which SwiftPM doesn't appear to for normal package builds, but the new SDK bundles and building a new stdlib as part of a fresh toolchain build do pass in. @tachoknight, perhaps you can run the repro command below on Fedora 41 with your new 5.10.1 package installed and confirm.

The issue is the getActualModuleMap() function in ClangImporter, which first looks in -sdk for these module maps, then in -resource-dir. That is not the precedence used everywhere else in the compiler, ie -resource-dir is always given precedence normally.

With more distros starting to package Swift in the system and SDK bundles starting to be used, this bug will start hitting more people.

Reproduction

./swift-5.10.1-RELEASE-fedora39/usr/bin/swiftc swift/test/Interpreter/hello_toplevel.swift -v -Xfrontend -dump-clang-diagnostics -cxx-interoperability-mode=default -sdk /

Only the -cxx-interoperability-mode=default -sdk / flags and an installed system toolchain are required, the other flags simply dump verbose output to show what's going on.

Expected behavior

-resource-dir is always given precedence in the compiler for other files, but not for these module maps. The compiler might also be using the wrong glibc.modulemap and libstdcxx.modulemap, but it simply does not dump those paths in the verbose output. Whatever happens with this bug, the compiler should be modified to dump those paths in verbose mode, so we can easily check them.

Environment

I tested with Swift 5.10, but the code goes back to 5.8.

Additional information

I should also note that a new cross-compilation model is planned. In that new scenario, it depends if these module maps are considered compiler resources or "Platform Swift Modules." If the former, they should then only be looked for in -resource-dir at that point, and if the latter, only in -sdk, ie not looked for in both as getActualModuleMap() currently does.

Pinging @zoecarver, who originally wrote this code in #59754 years ago, and @egorzhdan, who subsequently moved some of it around. @compnerd may want to chime in on whether these C++ module maps are compiler resources and how they should be handled under his new cross-compilation model.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugA deviation from expected or documented behavior. Also: expected but undesirable behavior.c++ interopFeature: Interoperability with C++clang importerArea → compiler: The clang importer

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions