-
Notifications
You must be signed in to change notification settings - Fork 32
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
Cross-compile for Android from OSX #13
Comments
Awesome, @ephemer! I've been thinking about this same problem. I have some work up on a branch based off of apple/swift Here are my notes: Currently, the Swift build scripts and CMakeLists files support limited cross-compilation of the stdlib, from OS X x86_64 to:
(All other targets--Linux armv7, FreeBSD x86_64--can only be compiled on host machines of the same OS and architecture.) This cross-compilation is achieved using dynamically generated CMake custom targets. Each custom target is added as a dependency upon the main stdlib compilation target. Each custom target may target a different OS and architecture, so variables like People more familiar with CMake than I have indicated that this is an anti-pattern, and that scaling this out to support cross-compilation across OS X/Linux/iOS/Android would be "impossible". Instead, the suggestion is to invoke CMake multiple times. This is what projects like LLVM do. When cross-compiling from OS X to multiple other targets (such as all of the iOS/tvOS/etc targets), CMake should be invoked once for each. Doing so would allow us to reference variables like |
Hi @modocache, I like the look of the changes you made. Seems to make breaking apart host and target a lot more intuitive. Have you tested these for OS X/iOS targets? |
I too am elbow-deep in Swift CMake, but I'm working on adding support for the gold linker in linux. I hope that my changes don't conflict with either of these too much. Do you either of you have an estimate of when you expect these changes to be close to merging in? It sounds like there might be a somewhat delicate three-way merge of CMake changes on the horizon. |
@ephemer They currently only work for all host compilation, and for cross compilation from OS X to iOS/tvOS/watchOS targets. I tried applying the same patches to this SwiftAndroid fork but encountered some errors which I should have saved somewhere... 😞
|
@hpux735 Great to hear! No worries here. As I mention above, I think any patches I land to support cross-compilation will be very different from what I have on my https://github.com/modocache/swift/tree/build-script-cross-compile-sdks branch. I don't have a clear picture of what those will look like yet, and I'm happy to rebase onto your changes. |
I think going forward I'll end up basing any further patches on modocache's @modocache do you plan to continue work on this? Would be great if you get
|
Excellent, what do you think @modocache? Should I rebase off of you? |
I am actively working on cross-compiling Swift, but I don't think my work on https://github.com/modocache/swift/tree/build-script-cross-compile-sdks is a good approach, so I wouldn't advise rebasing off of that. I'll probably make a new branch that is based off of apple/swift |
@modocache the approach in your branch seems more manageable than what's currently in master. I missed what the catch is. Also I'm not sure how much further I'll get without some kind of structured approach like your current branch. Are you suggesting I wait a while before continuing with this? I have a pretty good idea what errors you would have come across with SwiftAndroid btw: I've just spent all afternoon working through them myself |
@ephemer The "catch" I'm imagining is that manually keeping track of which platform we're targeting will become increasingly unwieldy. When cross-compiling multiple targets, it is untenable. For example, let's say we're cross-compiling from OS X to iOS and Android. CMake provides a single, global Let me know if I'm misunderstanding something--I'm no CMake wizard. Still, if you can take my https://github.com/modocache/swift/tree/build-script-cross-compile-sdks branch and build something useful out of it, don't let me stop you! 😄 I'm just not convinced it's the right approach. |
Ok, I only looked at your code on GitHub and I guess I missed this It makes sense if we can just use the CMAKE_SYSTEM_NAME as the target name, I'm not sure how the LINK_FLAGS situation would be an issue if you're Generally the way you'd split the code up seemed good though. I'm going to Brian Gesiak notifications@github.com schrieb am Mo., 18. Jan. 2016 um
|
My change still builds all stdlib targets using a single CMake invocation, like apple/swift Basically, this is how Swift is built now: # build-script-impl
# Loop over each deployment target.
# This is cross-compilation for standalone Swift builds--that is,
# this builds LLVM and a Swift compiler executable for the target
# platform. (Note that this is different from the cross-compilation
# in SwiftAndroid, which builds a Swift compiler that runs on the
# host platform, and produces Swift programs that can be run on
# Android.)
for deployment_target in "${NATIVE_TOOLS_DEPLOYMENT_TARGETS[@]}" "${CROSS_TOOLS_DEPLOYMENT_TARGETS[@]}"; do
# Loop over cmark, llvm, swift (and potentially lldb, llbuild, swiftpm, xctest, foundation)
for product in "${PRODUCTS[@]}"; do
# ...
# Add all STDLIB_DEPLOYMENT_TARGETS to the targets built by
# the `cmake --build` invocation below.
build_targets=(all "${SWIFT_STDLIB_TARGETS[@]}")
# ...
# Build all stdlib targets at once.
${DISTCC_PUMP} "${CMAKE}" --build "${build_dir}" $(cmake_config_opt ${product}) -- ${BUILD_ARGS} ${build_targets[@]}
done
done This is how I'd like to change it: # build-script-impl
# Loop over each deployment target.
for deployment_target in "${NATIVE_TOOLS_DEPLOYMENT_TARGETS[@]}" "${CROSS_TOOLS_DEPLOYMENT_TARGETS[@]}"; do
# Loop over cmark, llvm, swift (and potentially lldb, llbuild, swiftpm, xctest, foundation)
for product in "${PRODUCTS[@]}"; do
# ...
# Loop over each stdlib target.
for stdlib_target in "${SWIFT_STDLIB_TARGETS[@]}"; do
# ...
# Build the stdlib target.
${DISTCC_PUMP} "${CMAKE}" --build "${build_dir}" $(cmake_config_opt ${product}) -- ${BUILD_ARGS} $stdlib_target}
done
done
done I may be missing something, though. Definitely let me know how your approach goes, or if you see something awkward about how I plan on doing it! 👍 |
Sounds great to me in theory. Before you get too far here though, I'd like to point you to the discussion on the swift mailing list about this topic, starting here (there are about 6 emails on the topic): Given that we're building a compiler which then builds other things itself (which is always going to be tricky with this kind of dependency graph), it's possible the multiple invocation approach isn't ideal, and is something we only do when really needed. Either way, I see the build-script AND the CMakeLists becoming unmanageable very quickly the more we work on this cross-compilation stuff. My knowledge of both python and bash are at the "just getting by" level, but I have a feeling the bash script is already way overblown in complexity. If you're going to make changes to build-script-impl, it may be worth trying to port them into the new modularised swift_build_support python modules.. |
@ephemer Absolutely. Have you seen https://bugs.swift.org/browse/SR-237? I'd love to move as much into Python as possible. Thanks a ton for the link to the mailing lists! I'll read through them now. |
From the mailing list discussion:
Cool, this mirrors my understanding as well. Glad to see I'm not completely out of my depth.
Interesting. I'm reading the linked article now, to get an idea as to whether we should pursue multiple invocations for OS X-to-Linux cross-compilation only, or whether we should a single CMake invocation no matter what kind of cross-compilation we're doing. |
@modocache I had seen that bug report but missed that you were driving force behind it! Haha, keep up the good work. From what I've found out the last couple of days, it seems that it really does make sense to run multiple CMake invocations when you want to use a different compiler/linker toolchain, as is most likely the case with e.g. OSX->Android cross compiling. That's because setting the CMAKE_C_COMPILER variable (which currently happens around build-script-impl:1060) causes all the other compiler settings (flags etc) to reset. This may be manageable but sounds like it could be more trouble than it's worth. My plan is to try to compiling the OSX swift driver etc with the standard Xcode toolchain and use the Android toolchain to build the stdlib. There is probably a missing piece in linking the two invocations here, which may also prove to bring more pain. We'll see. See here for more reading: |
I feel like I'm out of my depth and don't seem to be making any progress on this at the moment. It seems like the inbuilt clang would be fine to build the android sources, we just need to tell it to use the android linker. I'm not experienced enough with compiling and linking generally to know how to go about that but it seems doable. On a side note, I did come across this https://github.com/taka-no-me/android-cmake, which may be of interest. (it uses the multiple invocation paradigm) |
@froody is continuing to work on this; see the mailing list thread here. |
Closing this in order to centralize the discussion here: https://bugs.swift.org/browse/SR-1362 |
I have just pushed a branch called osx-crosscompile that is at the stage of correctly compiling the objects (as verified using
nm
from the different toolchains). It fails at the linker stage. I don't understand my way around the OSX toolchain just yet, or how to change it to use the Android toolchain.Basically it's failing because the OSX linker doesn't understand --sysroot, up until that point, we need the --sysroot linker option because otherwise the Android components attempt to link against the OSX /usr/include, which throws all sorts of errors because of wrong architecture etc.
Another thought was that maybe we can use the iOS linker, since it is also aware of armeabi-v7a. Not sure how to do this, or whether it's a good idea.
I'm going to try figure out how to use the linker from a different toolchain tomorrow but given my (non-existent) experience in this field I'm not sure how far I'll get. Any hints or help are most welcome.
The text was updated successfully, but these errors were encountered: