Build failure for Linux: "No such module: SwiftGlibc"

I’m trying to cross-compile Swift for the Raspberry Pi. I’ve got the tools and most of the standard library compiling, but I’m getting stuck trying to build the platform components for Glibc. Swift is just complaining that the “SwiftGlibc” module doesn’t exist. I’d appreciate it if anybody could help trying to find out why.

I’ve been whittling down at the compile command, trying to figure out why it isn’t finding/building the module.

···

==============
<sourceroot>/build/Ninja-ReleaseAssert/swift-macosx-x86_64/bin/swiftc -c
-target armv7-unknown-linux-gnueabihf
-O -D INTERNAL_CHECKS_ENABLED
-no-link-objc-runtime -autolink-force-load -emit-module -module-link-name swiftGlibc -force-single-frontend-invocation -parse-as-library
-I <sourceroot>/build/Ninja-ReleaseAssert/swift-linux-armv7/./lib/swift/linux/armv7
-module-cache-path <sourceroot>/build/Ninja-ReleaseAssert/swift-linux-armv7/./module-cache
-emit-module-path <sourceroot>/build/Ninja-ReleaseAssert/swift-linux-armv7/./lib/swift/linux/armv7/Glibc.swiftmodule
-o <sourceroot>/build/Ninja-ReleaseAssert/swift-linux-armv7/stdlib/public/Platform/linux/armv7/Glibc.o
<sourceroot>/swift/stdlib/public/Platform/Glibc.swift

<sourceroot>/swift/stdlib/public/Platform/Glibc.swift:13:19: error: no such module 'SwiftGlibc'
@_exported import SwiftGlibc // Clang module

glibc.modulemap gets generated and copied in to the /lib/swift/linux/armv7 build dir, and Glibc.swift looks like it just exports that out, so I’m guessing that Swift can’t find my modulemap - or what else does it need to build the SwiftGlibc module?

Many thanks

In this message <http://article.gmane.org/gmane.comp.lang.swift.devel/1710&gt; there was a suggestion to make a symlink to work around this issue (but when building on Ubuntu x86_64, I think). Perhaps something similar would work?

What steps are you using to get as far as you have? I’m not having a lot of luck so far…

-tim

···

On Apr 19, 2016, at 1:57 AM, Karl Wagner via swift-dev <swift-dev@swift.org> wrote:

I’m trying to cross-compile Swift for the Raspberry Pi. I’ve got the tools and most of the standard library compiling, but I’m getting stuck trying to build the platform components for Glibc. Swift is just complaining that the “SwiftGlibc” module doesn’t exist. I’d appreciate it if anybody could help trying to find out why.

I’ve been whittling down at the compile command, trying to figure out why it isn’t finding/building the module.

Well that seems to be trying to resolve the runtime issue; I’m still trying to compile the standard library.

My changes are here: GitHub - karwa/swift: The Swift Programming Language

Then I’m building with:

../swift/utils/build-script -d \
  --install-prefix="/usr" \
  --install-symroot="${cc_files}/out/symroot" \
  -- \
  --cross-compile-tools-deployment-targets=linux-armv7 \
  --cross-compile-sysroot="${sysroot}" \
  --cross-compile-toolchain-bin="${toolchain}"
  --stdlib-deployment-targets="macosx-x86_64;linux-armv7=linux-armv7”

(I’m not sure about the install arguments; I’ve only been building for OSX, so I’ve never ‘installed’ a built swift besides Xcode toolchains.)

This builds for the host first, then uses the freshly baked clang and swift compilers to cross-compile to the target. I can compile the tools and what I believe is most of the standard library; it just flops at SwiftGlibc and I can’t understand it because glibc.modulemap exists where it should and looks good (headers pointing inside the cross-compiled sysroot). It’s not even complaining about the modulemap itself (like missing headers or whatever); it just appears unable to find it even though it’s in the swift compiler’s include path.

Is there some kind of extra flag to tell it to look inside that particular modulemap file, that perhaps isn’t being generated for me? I don’t know how that magic works, how Swift knows what to look for when it sees:

@_exported import SwiftGlibc

inside public/Platform/Glibc.swift

···

On 22 Apr 2016, at 06:46, Timothy Wood <tjw@omnigroup.com> wrote:

On Apr 19, 2016, at 1:57 AM, Karl Wagner via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:

I’m trying to cross-compile Swift for the Raspberry Pi. I’ve got the tools and most of the standard library compiling, but I’m getting stuck trying to build the platform components for Glibc. Swift is just complaining that the “SwiftGlibc” module doesn’t exist. I’d appreciate it if anybody could help trying to find out why.

I’ve been whittling down at the compile command, trying to figure out why it isn’t finding/building the module.

In this message <http://article.gmane.org/gmane.comp.lang.swift.devel/1710&gt; there was a suggestion to make a symlink to work around this issue (but when building on Ubuntu x86_64, I think). Perhaps something similar would work?

What steps are you using to get as far as you have? I’m not having a lot of luck so far…

-tim

The logic to go look for that file is hardcoded in the compiler; it’s not picked up via include paths. It has to specifically be inside the lib/swift/ directory. (I think it’s at lib/swift/linux/, but I’m not 100% sure.)

Jordan

···

On Apr 29, 2016, at 23:46, Karl Wagner via swift-dev <swift-dev@swift.org> wrote:

On 22 Apr 2016, at 06:46, Timothy Wood <tjw@omnigroup.com <mailto:tjw@omnigroup.com>> wrote:

On Apr 19, 2016, at 1:57 AM, Karl Wagner via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:

I’m trying to cross-compile Swift for the Raspberry Pi. I’ve got the tools and most of the standard library compiling, but I’m getting stuck trying to build the platform components for Glibc. Swift is just complaining that the “SwiftGlibc” module doesn’t exist. I’d appreciate it if anybody could help trying to find out why.

I’ve been whittling down at the compile command, trying to figure out why it isn’t finding/building the module.

In this message <http://article.gmane.org/gmane.comp.lang.swift.devel/1710&gt; there was a suggestion to make a symlink to work around this issue (but when building on Ubuntu x86_64, I think). Perhaps something similar would work?

What steps are you using to get as far as you have? I’m not having a lot of luck so far…

-tim

Well that seems to be trying to resolve the runtime issue; I’m still trying to compile the standard library.

My changes are here: GitHub - karwa/swift: The Swift Programming Language

Then I’m building with:

../swift/utils/build-script -d \
  --install-prefix="/usr" \
  --install-symroot="${cc_files}/out/symroot" \
  -- \
  --cross-compile-tools-deployment-targets=linux-armv7 \
  --cross-compile-sysroot="${sysroot}" \
  --cross-compile-toolchain-bin="${toolchain}"
  --stdlib-deployment-targets="macosx-x86_64;linux-armv7=linux-armv7”

(I’m not sure about the install arguments; I’ve only been building for OSX, so I’ve never ‘installed’ a built swift besides Xcode toolchains.)

This builds for the host first, then uses the freshly baked clang and swift compilers to cross-compile to the target. I can compile the tools and what I believe is most of the standard library; it just flops at SwiftGlibc and I can’t understand it because glibc.modulemap exists where it should and looks good (headers pointing inside the cross-compiled sysroot). It’s not even complaining about the modulemap itself (like missing headers or whatever); it just appears unable to find it even though it’s in the swift compiler’s include path.

Is there some kind of extra flag to tell it to look inside that particular modulemap file, that perhaps isn’t being generated for me? I don’t know how that magic works, how Swift knows what to look for when it sees:

@_exported import SwiftGlibc

inside public/Platform/Glibc.swift

../swift/utils/build-script -d \
--install-prefix="/usr" \
--install-symroot="${cc_files}/out/symroot" \
-- \
--cross-compile-tools-deployment-targets=linux-armv7 \
--cross-compile-sysroot="${sysroot}" \
--cross-compile-toolchain-bin="${toolchain}"
--stdlib-deployment-targets="macosx-x86_64;linux-armv7=linux-armv7”

Karl I'm interested in helping you getting this working. Could you
explain to me your variables (i.e., `cc_files`, `sysroot` and
`toolchain`) and possibly provide examples of what you populate
them with?

Karl,

A number of us are on Slack working with ARM support - would you like an invite?

Joe

Hi,

yes that would nice.

The modulemap issue can be fixed by adding a -resource-dir flag. Going with a comment in AddSwift.cmake, I switched the include fag to the library output directory to "-resource-dir”, but then SwiftShims wouldn’t build. So I changed the flag back to a standard include and make it *also* specify “-resource-dir” on cross-compile (so the cross command has both -I and -resource-dir). Now the native host builds, but the cross-compiled stdlib won’t because of the same SwiftShims issue.

So I need to look at how the compiler uses -resource-dir what’s going on with SwiftShims.

My changes are here: GitHub - karwa/swift: The Swift Programming Language

Then I’m building with:

../swift/utils/build-script -d \
  --install-prefix="/usr" \
  --install-symroot="${cc_files}/out/symroot" \
  -- \
  --cross-compile-tools-deployment-targets=linux-armv7 \
  --cross-compile-sysroot="${sysroot}" \
  --cross-compile-toolchain-bin="${toolchain}"
  --stdlib-deployment-targets="macosx-x86_64;linux-armv7=linux-armv7”

Explanation on the flags, process:

${cc_files} = the place where I stick the cross-compile resources. Somewhere the stick the output package later.

${toolchain}:

Built from: 5-2015-q4-major : Series 5.0 : GNU Arm Embedded Toolchain
Edit install_toolchain.sh and add “--enable-gold” to the binutils flags
Also in install_common.sh, charged TARGET to "arm-linux-eabi”, but not sure that’s necessary.

Give the path to the unprefixed versions of the tools, e.g: "${cc_files}/toolchain/gcc-arm-none-eabi-5_2-2015q4/install-native/arm-linux-eabi/bin"

${sysroot}:

Created using this script: Creates a linux sysroot with packages required for swift (requires dpkg-deb) · GitHub

./make_sysroot.py --distro debian --version jessie --arch armhf --install sysroot.armhf.debian.jessie

···

On 2 May 2016, at 18:42, Joseph Bell <joe@iachieved.it> wrote:

-resource-dir covers everything in lib/swift/. I'm not sure we're properly set up to handle more than one architecture on Linux, though: we still link against the .so's in lib/swift/linux/ rather than lib/swift/linux/$ARCH, despite "fat" libraries not being sensible here. Maybe that's the way to go: reorganize lib/swift/linux/ so that there's nothing that's not in an architecture-specific subdirectory.

Meanwhile, you can probably get things off the ground by copying or symlinking everything in lib/swift/ that's not in lib/swift/linux/ into your custom resource directory. (I think that's just the shims/ folder right now.)

Jordan

···

On May 3, 2016, at 10:40, Karl Wagner via swift-dev <swift-dev@swift.org> wrote:

On 2 May 2016, at 18:42, Joseph Bell <joe@iachieved.it <mailto:joe@iachieved.it>> wrote:

Karl,

A number of us are on Slack working with ARM support - would you like an invite?

Joe

Hi,

yes that would nice.

The modulemap issue can be fixed by adding a -resource-dir flag. Going with a comment in AddSwift.cmake, I switched the include fag to the library output directory to "-resource-dir”, but then SwiftShims wouldn’t build. So I changed the flag back to a standard include and make it *also* specify “-resource-dir” on cross-compile (so the cross command has both -I and -resource-dir). Now the native host builds, but the cross-compiled stdlib won’t because of the same SwiftShims issue.

So I need to look at how the compiler uses -resource-dir what’s going on with SwiftShims.

Thanks, that was helpful! Got it to finally complete. I had to set the resource-dir to lib/swift.

A few things get generated to the non-specific lib/swift/linux folder, but they’re also in linux/armv7 (which does seem like something we should fix). The shims and clang headers are the only things that aren’t also in the armv7 folder.

However, it did work after that; compiled both the tools and standard library for the RPi :). I am having some trouble installing, though. There is no “install” build target generated. I’ve been looking at the sources, and I can’t see it, either - I can see how the install components get passed in, how things get added to the components, but not where any copying takes place. What is the intended command to install the built components, “ninja install”?

The things it built do seem to work. I “manually installed” them, and besides needing some massaging to satisfy SwiftGlibc (modulemap obviously needed to be regenerated with correct system root, stddef.h and stdarg.h strangely unable to be found — they were in /usr/include/linux) it seems reasonable. There is a known LLVM bug preventing ‘swift’ (the interpreter) from working, which should definitely be merged in to our clone of LLVM (see https://github.com/hpux735/swift-llvm\), but ‘swiftc’ works.

Karl

···

On 3 May 2016, at 20:12, Jordan Rose <jordan_rose@apple.com> wrote:

On May 3, 2016, at 10:40, Karl Wagner via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:

On 2 May 2016, at 18:42, Joseph Bell <joe@iachieved.it <mailto:joe@iachieved.it>> wrote:

Karl,

A number of us are on Slack working with ARM support - would you like an invite?

Joe

Hi,

yes that would nice.

The modulemap issue can be fixed by adding a -resource-dir flag. Going with a comment in AddSwift.cmake, I switched the include fag to the library output directory to "-resource-dir”, but then SwiftShims wouldn’t build. So I changed the flag back to a standard include and make it *also* specify “-resource-dir” on cross-compile (so the cross command has both -I and -resource-dir). Now the native host builds, but the cross-compiled stdlib won’t because of the same SwiftShims issue.

So I need to look at how the compiler uses -resource-dir what’s going on with SwiftShims.

-resource-dir covers everything in lib/swift/. I'm not sure we're properly set up to handle more than one architecture on Linux, though: we still link against the .so's in lib/swift/linux/ rather than lib/swift/linux/$ARCH, despite "fat" libraries not being sensible here. Maybe that's the way to go: reorganize lib/swift/linux/ so that there's nothing that's not in an architecture-specific subdirectory.

Meanwhile, you can probably get things off the ground by copying or symlinking everything in lib/swift/ that's not in lib/swift/linux/ into your custom resource directory. (I think that's just the shims/ folder right now.)

Jordan