Cross-compile for Android armv7 from OSX

android

(Geordie J) #1

I have just pushed a branch to the SwiftAndroid repo that is at the stage of correctly compiling the swift toolchain and stdlib objects for android-armv7 and macosx-x86_64 (as verified using nm from the different toolchains): https://github.com/SwiftAndroid/swift/tree/osx-crosscompile. The problem is it fails at the linker stage.

Basically the OSX linker doesn't understand the “—sysroot” option (See AddSwift.cmake:59). Up until that point though (throughout the compiling stage), we need that option because otherwise the Android components attempt to use OSX /usr/include, which throws all sorts of errors because of wrong architecture etc. Why it fails to compile when I remove the “—sysroot” option, but also fails _with_ it in the link stage will probably be key to fixing this. Again, it seems that what we really need to do is use the Android linker, not the Xcode one.

I'm going to try figure out how to do that tomorrow but not confident I’ll get far given my limited experience with this.. This work may also be of interest to the Raspberry Pi / BeagleBoard folks, would also love to hear some opinions about how to solve the CMAKE_SYSTEM_NAME problem, that will also affect cross-compilation for those uses. In any case, any hints or collaborators would be most welcome.

Geordie


(Tom Gall) #2

Cool!

I was just starting a similar exercise but using x86-64 linux as the
host since I've managed to get swift building and running on my
arm-linux box.

Cheers!

···

On Mon, Jan 18, 2016 at 1:03 PM, Geordie Jay via swift-dev <swift-dev@swift.org> wrote:

I have just pushed a branch to the SwiftAndroid repo that is at the stage of
correctly compiling the swift toolchain and stdlib objects for android-armv7
and macosx-x86_64 (as verified using nm from the different toolchains):
https://github.com/SwiftAndroid/swift/tree/osx-crosscompile. The problem is
it fails at the linker stage.

Basically the OSX linker doesn't understand the “—sysroot” option (See
AddSwift.cmake:59). Up until that point though (throughout the compiling
stage), we need that option because otherwise the Android components attempt
to use OSX /usr/include, which throws all sorts of errors because of wrong
architecture etc. Why it fails to compile when I remove the “—sysroot”
option, but also fails _with_ it in the link stage will probably be key to
fixing this. Again, it seems that what we really need to do is use the
Android linker, not the Xcode one.

I'm going to try figure out how to do that tomorrow but not confident I’ll
get far given my limited experience with this.. This work may also be of
interest to the Raspberry Pi / BeagleBoard folks, would also love to hear
some opinions about how to solve the CMAKE_SYSTEM_NAME problem, that will
also affect cross-compilation for those uses. In any case, any hints or
collaborators would be most welcome.

Geordie

_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev

--
Regards,
Tom

"Where's the kaboom!? There was supposed to be an earth-shattering
kaboom!" Marvin Martian
Director, Linaro Mobile Group
Tech Lead, GPGPU
Linaro.org │ Open source software for ARM SoCs
irc: tgall_foo | skype : tom_gall


(Geordie J) #3

I'm in discussions about this with some others over at
https://github.com/SwiftAndroid/swift/issues/13

Basically the Swift build process as is isn't made for arbitrary
cross-compiling. The iOS cross-compiling from OSX relies on some happy
accidents, e.g. that they're all Apple platforms, and isn't robust. So
we're discussing some alternatives that would eventually also benefit your
porting effort.

Out of interest, have you found a version of clang that compiles from your
host machine to an arm-Linux target? Or delved into the source in order to
make your own? I'd be interested in cross-compiling for Raspberry Pi too
but haven't looked into toolchains yet.

Geordie

···

Tom Gall <tom.gall@linaro.org> schrieb am Mo., 18. Jan. 2016 um 22:07:

Cool!

I was just starting a similar exercise but using x86-64 linux as the
host since I've managed to get swift building and running on my
arm-linux box.

Cheers!

On Mon, Jan 18, 2016 at 1:03 PM, Geordie Jay via swift-dev > <swift-dev@swift.org> wrote:
> I have just pushed a branch to the SwiftAndroid repo that is at the
stage of
> correctly compiling the swift toolchain and stdlib objects for
android-armv7
> and macosx-x86_64 (as verified using nm from the different toolchains):
> https://github.com/SwiftAndroid/swift/tree/osx-crosscompile. The
problem is
> it fails at the linker stage.
>
> Basically the OSX linker doesn't understand the “—sysroot” option (See
> AddSwift.cmake:59). Up until that point though (throughout the compiling
> stage), we need that option because otherwise the Android components
attempt
> to use OSX /usr/include, which throws all sorts of errors because of
wrong
> architecture etc. Why it fails to compile when I remove the “—sysroot”
> option, but also fails _with_ it in the link stage will probably be key
to
> fixing this. Again, it seems that what we really need to do is use the
> Android linker, not the Xcode one.
>
> I'm going to try figure out how to do that tomorrow but not confident
I’ll
> get far given my limited experience with this.. This work may also be of
> interest to the Raspberry Pi / BeagleBoard folks, would also love to hear
> some opinions about how to solve the CMAKE_SYSTEM_NAME problem, that will
> also affect cross-compilation for those uses. In any case, any hints or
> collaborators would be most welcome.
>
> Geordie
>
>
> _______________________________________________
> swift-dev mailing list
> swift-dev@swift.org
> https://lists.swift.org/mailman/listinfo/swift-dev
>

--
Regards,
Tom

"Where's the kaboom!? There was supposed to be an earth-shattering
kaboom!" Marvin Martian
Director, Linaro Mobile Group
Tech Lead, GPGPU
Linaro.org │ Open source software for ARM SoCs
irc: tgall_foo | skype : tom_gall


(Dmitri Gribenko) #4

Unfortunately CMake only supports one C compiler and one linker in one
CMake invocation. The "CMake way" for cross-compilation is to invoke
CMake once for every part of the build that requires a different set
of tools. Thus, for Swift, we would need to invoke CMake once for
building the tools running on the host (the swiftc running on OS X)
with the host toolchain (clang from Xcode), and once for the Android
target with the Android toolchain and the just-built Swift to build
the standard library.

The disadvantage to this approach is that there are many CMake
invocations, and many ninja invocations. This is bad for the same
reasons why recursive make is bad. [1] So we would like to keep the
current scheme for as many targets as possible (OS X native, OS X to
iOS cross-compilation, Linux native etc.), and use the multi-CMake
scheme only where strictly required.

[1] http://aegis.sourceforge.net/auug97.pdf

Dmitri

···

On Mon, Jan 18, 2016 at 2:44 PM, Geordie Jay via swift-dev <swift-dev@swift.org> wrote:

I'm in discussions about this with some others over at
https://github.com/SwiftAndroid/swift/issues/13

Basically the Swift build process as is isn't made for arbitrary
cross-compiling. The iOS cross-compiling from OSX relies on some happy
accidents, e.g. that they're all Apple platforms, and isn't robust. So we're
discussing some alternatives that would eventually also benefit your porting
effort.

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/


(Geordie J) #5

Hi Dimitri, thanks for the enlightening read. I'll keep those ideas in mind.

By "Linux native" do you mean compiling eg. Linux arm from Linux x86_64
with the current scheme, and only running multiple invocations when
compiling for mutually ABI-incompatible platforms (eg. osx->android)?

As it stands that exact scenario seems to build ok with the current method,
I "just" got stuck at the linking phase. I did have the impression I was
fighting the system the whole time though, and it was pretty hard to keep a
mental model of what was going on.

My concern is that maintaining the two different schemes will be even more
confusing than maintaining one convoluted single-invocation scheme. Would
like to hear some more opinions about this.

Geordie

···

Dmitri Gribenko <gribozavr@gmail.com> schrieb am Di., 19. Jan. 2016 um 01:47:

On Mon, Jan 18, 2016 at 2:44 PM, Geordie Jay via swift-dev > <swift-dev@swift.org> wrote:
> I'm in discussions about this with some others over at
> https://github.com/SwiftAndroid/swift/issues/13
>
> Basically the Swift build process as is isn't made for arbitrary
> cross-compiling. The iOS cross-compiling from OSX relies on some happy
> accidents, e.g. that they're all Apple platforms, and isn't robust. So
we're
> discussing some alternatives that would eventually also benefit your
porting
> effort.

Unfortunately CMake only supports one C compiler and one linker in one
CMake invocation. The "CMake way" for cross-compilation is to invoke
CMake once for every part of the build that requires a different set
of tools. Thus, for Swift, we would need to invoke CMake once for
building the tools running on the host (the swiftc running on OS X)
with the host toolchain (clang from Xcode), and once for the Android
target with the Android toolchain and the just-built Swift to build
the standard library.

The disadvantage to this approach is that there are many CMake
invocations, and many ninja invocations. This is bad for the same
reasons why recursive make is bad. [1] So we would like to keep the
current scheme for as many targets as possible (OS X native, OS X to
iOS cross-compilation, Linux native etc.), and use the multi-CMake
scheme only where strictly required.

[1] http://aegis.sourceforge.net/auug97.pdf

Dmitri

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/


(Dmitri Gribenko) #6

I meant building for the platform itself. Compiling Linux arm from
Linux x86_64 would likely require the two-step approach.

Dmitri

···

On Mon, Jan 18, 2016 at 5:46 PM, Geordie Jay <geojay@gmail.com> wrote:

Hi Dimitri, thanks for the enlightening read. I'll keep those ideas in mind.

By "Linux native" do you mean compiling eg. Linux arm from Linux x86_64 with
the current scheme, and only running multiple invocations when compiling for
mutually ABI-incompatible platforms (eg. osx->android)?

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/


(Geordie J) #7

Ok I'm confused as to what you mean now. I can't imagine how it'd make
sense to run CMake multiple times to build from one host for its own
platform (save the recursive make approach, which in itself never crossed
our mind AFIK, but you mentioned this is a separate issue anyway).

The suggestion was to run CMake once per compilation target, being invoked
from build-script(-impl, for now). That would give us the benefit of
CMAKE_SYSTEM_NAME providing the target system (as opposed to the host, as
is now the case), with CMAKE_HOST_SYSTEM_NAME available when we need it.
This would lead to splitting out the CMake directives in a more natural
way. I also understand (maybe incorrectly) that this would keep in-code
definitions like #if __APPLE__ and objc interop "automatically" valid
without the need for hacks or further intervention from further CMake
patches.

Based on what you wrote I understood that the above setup may be
undesirable for OS X->iOS compilation. Now that I've slept on it I'm
actually not sure why. Referring to the article you sent, each target's DAG
should be atomic and independent of one another (this may well be the point
where I'm missing something). Also, the build output for each target is
kept independent, meaning it wouldn't need to be rescanned from foreign
targets' CMake / ninja runs.

I'm interested to hear your thoughts about this

Geordie

···

Dmitri Gribenko <gribozavr@gmail.com> schrieb am Di., 19. Jan. 2016 um 02:51:

On Mon, Jan 18, 2016 at 5:46 PM, Geordie Jay <geojay@gmail.com> wrote:
> Hi Dimitri, thanks for the enlightening read. I'll keep those ideas in
mind.
>
> By "Linux native" do you mean compiling eg. Linux arm from Linux x86_64
with
> the current scheme, and only running multiple invocations when compiling
for
> mutually ABI-incompatible platforms (eg. osx->android)?

I meant building for the platform itself. Compiling Linux arm from
Linux x86_64 would likely require the two-step approach.

Dmitri

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/


(Dmitri Gribenko) #8

To build a Swift distribution, we need to build two pieces: the Swift
compiler and the standard library.

When cross-compiling, you can build two different kinds of compilers:
a compiler that runs on your host machine, or the compiler that runs
on the target.

To build the standard library, you need to use the Swift compiler that
runs on the host and a Clang that runs on the host, but both
configured to target your target platform.

Thus, if you want to cross-compile to Linux arm from OS X, you would
need to use two or three CMake invocations:

(1) to build a Swift compiler that runs on OS X,

(2) use (1) to build a standard library that runs on Linux arm,

(3) build a Swift compiler that runs on Linux arm.

There is a dependency edge between (1) and (2), but they are in
different CMake invocations.

When cross-compiling for iOS, tvOS and watchOS, there are many CMake
invocations of the second kind -- in fact, multiple for every platform
because of many slices. And, even more, since those platforms use fat
libraries, there needs to be a step that creates them from separate
slices.

That's why I'm comparing this to "recursive make": if we use the CMake
approach to cross-compiling with multiple CMake invocations, since we
are building the compiler itself, we would be crating dependencies in
the graph that CMake does not know about, and we would require some
code to orchestrate the build. Just like recursive make does in its
Makefiles.

Using build-script to orchestrate this build would be a natural
choice, but it would break many of the current workflows, where
developers rely on quickly iterating in one build directory, invoking
'ninja check-swift' directly to rebulid the compiler, all the
downstream dependencies, and run tests.

Dmitri

···

On Tue, Jan 19, 2016 at 2:50 AM, Geordie Jay <geojay@gmail.com> wrote:

Ok I'm confused as to what you mean now. I can't imagine how it'd make sense
to run CMake multiple times to build from one host for its own platform

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/


(Geordie J) #9

I'm still trying to grasp the fundamental difference in approaches here,
especially since you say there are multiple CMake runs already. More
importantly, I'd like to fully understand what's important to keep the
same, or at least its desired outcome, which I'm pretty sure is the (1)-(2)
cross-boundary dependency staying intact.

Is the difference that the cross-compilation dynamic targets in the current
paradigm are set up via CMake (rather than build-script)? Presumably this
leaves the the loop that builds the various targets "unrolled" and always
in CMake's output, instead of recreating the CMake files multiple times per
build-script run?

As to the workflow, what would stop devs from just having a global bash
alias to "check-swift" that invokes the build-script, achieving the same
effect?

···

Dmitri Gribenko <gribozavr@gmail.com> schrieb am Di., 19. Jan. 2016 um 12:09:

On Tue, Jan 19, 2016 at 2:50 AM, Geordie Jay <geojay@gmail.com> wrote:
> Ok I'm confused as to what you mean now. I can't imagine how it'd make
sense
> to run CMake multiple times to build from one host for its own platform

To build a Swift distribution, we need to build two pieces: the Swift
compiler and the standard library.

When cross-compiling, you can build two different kinds of compilers:
a compiler that runs on your host machine, or the compiler that runs
on the target.

To build the standard library, you need to use the Swift compiler that
runs on the host and a Clang that runs on the host, but both
configured to target your target platform.

Thus, if you want to cross-compile to Linux arm from OS X, you would
need to use two or three CMake invocations:

(1) to build a Swift compiler that runs on OS X,

(2) use (1) to build a standard library that runs on Linux arm,

(3) build a Swift compiler that runs on Linux arm.

There is a dependency edge between (1) and (2), but they are in
different CMake invocations.

When cross-compiling for iOS, tvOS and watchOS, there are many CMake
invocations of the second kind -- in fact, multiple for every platform
because of many slices. And, even more, since those platforms use fat
libraries, there needs to be a step that creates them from separate
slices.

That's why I'm comparing this to "recursive make": if we use the CMake
approach to cross-compiling with multiple CMake invocations, since we
are building the compiler itself, we would be crating dependencies in
the graph that CMake does not know about, and we would require some
code to orchestrate the build. Just like recursive make does in its
Makefiles.

Using build-script to orchestrate this build would be a natural
choice, but it would break many of the current workflows, where
developers rely on quickly iterating in one build directory, invoking
'ninja check-swift' directly to rebulid the compiler, all the
downstream dependencies, and run tests.

Dmitri

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/


(Tom Birch) #10

What do you propose then? As I understand it, there are roughly two options:

1) Split the build of swiftc and stdlib into two CMake invocations,
requiring a separate CMake configure step for each build type of the SDK.
2) Keep things as they are with a single CMake invocation, and wrap
invocations of the toolchain (either with custom CMake commands or shell
scripts) to call the right tool with the right flags for each build type of
the SDK.

I think (1) is more likely to result in a cleaner, more maintainable
buildsystem as more cross-compile targets are added, but as you mentioned,
may lead to longer build times and broken workflows. Maybe the dependencies
could be fixed by using ExternalProject_Add.

I think (2) will initially be easier, but will pollute the "leaf" CMake
functions/targets with target-specific details, as already seems to be
happening in AddSwift.cmake.

Is there another approach I'm not considering? What is more likely to be
accepted into apple/swift master?

cheers,
Tom

···

On Tue, Jan 19, 2016 at 3:09 AM Dmitri Gribenko via swift-dev < swift-dev@swift.org> wrote:

That's why I'm comparing this to "recursive make": if we use the CMake
approach to cross-compiling with multiple CMake invocations, since we
are building the compiler itself, we would be crating dependencies in
the graph that CMake does not know about, and we would require some
code to orchestrate the build. Just like recursive make does in its
Makefiles.

Using build-script to orchestrate this build would be a natural
choice, but it would break many of the current workflows, where
developers rely on quickly iterating in one build directory, invoking
'ninja check-swift' directly to rebulid the compiler, all the
downstream dependencies, and run tests.


(Dmitri Gribenko) #11

I'm proposing we do (1) for new cross-compilation targets (like OS X
to Linux, or Linux x86_64 to Linux arm), but keep the current scheme
for Darwin.

To keep existing workflows working, I would suggest that native builds
keep building the standard library in the same CMake invocation as the
compiler.

Optionally, cross-compiling builds can unconditionally invoke the
CMake build tool recursively for cross-compilation targets after the
compiler is built, to erase the difference between native builds and
cross-compiling.

Dmitri

···

On Wed, Jan 20, 2016 at 1:21 PM, Tom Birch <froody@gmail.com> wrote:

On Tue, Jan 19, 2016 at 3:09 AM Dmitri Gribenko via swift-dev > <swift-dev@swift.org> wrote:

That's why I'm comparing this to "recursive make": if we use the CMake
approach to cross-compiling with multiple CMake invocations, since we
are building the compiler itself, we would be crating dependencies in
the graph that CMake does not know about, and we would require some
code to orchestrate the build. Just like recursive make does in its
Makefiles.

Using build-script to orchestrate this build would be a natural
choice, but it would break many of the current workflows, where
developers rely on quickly iterating in one build directory, invoking
'ninja check-swift' directly to rebulid the compiler, all the
downstream dependencies, and run tests.

What do you propose then? As I understand it, there are roughly two options:

1) Split the build of swiftc and stdlib into two CMake invocations,
requiring a separate CMake configure step for each build type of the SDK.
2) Keep things as they are with a single CMake invocation, and wrap
invocations of the toolchain (either with custom CMake commands or shell
scripts) to call the right tool with the right flags for each build type of
the SDK.

I think (1) is more likely to result in a cleaner, more maintainable
buildsystem as more cross-compile targets are added, but as you mentioned,
may lead to longer build times and broken workflows. Maybe the dependencies
could be fixed by using ExternalProject_Add.

I think (2) will initially be easier, but will pollute the "leaf" CMake
functions/targets with target-specific details, as already seems to be
happening in AddSwift.cmake.

Is there another approach I'm not considering? What is more likely to be
accepted into apple/swift master?

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/


(Tom Birch) #12

Ok, thanks, I'll run with that. I
see SWIFT_NATIVE_(LLVM|CLANG|SWIFT)_TOOLS_PATH, is currently used/supported
anywhere? My current plan is to:
1) Build everything (llvm/clang, cmark, swift) for macosx-x86_64
2) Setup SWIFT_NATIVE_*_TOOLS_PATH to point to the respective dirs created
in (1)
3) Create a swift-android-armv7 build dir
4) Invoke CMake in swift-android-armv7 with vars from (2), plus a
Toolchain-android-armv7.cmake to set CMAKE_SYSTEM_NAME, CMAKE_SYSROOT, etc
for the android build

Ideally I'd only build the stdlib and tests for android, skipping the tools
and and llvm/clang builds. Does this seem feasible? I know the runtime
depends on llvm headers, but I can either use the macosx-x86_64 llvm
headers, or do a partial headers-only install of llvm-android-armv7. Are
there any binaries/tools needed to be built for the target (i.e
android-armv7) in order to build stdlib? Anything else I should know/watch
out for?

cheers,
Tom

···

On Wed, Jan 20, 2016 at 1:43 PM Dmitri Gribenko <gribozavr@gmail.com> wrote:

On Wed, Jan 20, 2016 at 1:21 PM, Tom Birch <froody@gmail.com> wrote:
> On Tue, Jan 19, 2016 at 3:09 AM Dmitri Gribenko via swift-dev > > <swift-dev@swift.org> wrote:
>>
>> That's why I'm comparing this to "recursive make": if we use the CMake
>> approach to cross-compiling with multiple CMake invocations, since we
>> are building the compiler itself, we would be crating dependencies in
>> the graph that CMake does not know about, and we would require some
>> code to orchestrate the build. Just like recursive make does in its
>> Makefiles.
>>
>> Using build-script to orchestrate this build would be a natural
>> choice, but it would break many of the current workflows, where
>> developers rely on quickly iterating in one build directory, invoking
>> 'ninja check-swift' directly to rebulid the compiler, all the
>> downstream dependencies, and run tests.
>
>
> What do you propose then? As I understand it, there are roughly two
options:
>
> 1) Split the build of swiftc and stdlib into two CMake invocations,
> requiring a separate CMake configure step for each build type of the SDK.
> 2) Keep things as they are with a single CMake invocation, and wrap
> invocations of the toolchain (either with custom CMake commands or shell
> scripts) to call the right tool with the right flags for each build type
of
> the SDK.
>
> I think (1) is more likely to result in a cleaner, more maintainable
> buildsystem as more cross-compile targets are added, but as you
mentioned,
> may lead to longer build times and broken workflows. Maybe the
dependencies
> could be fixed by using ExternalProject_Add.
>
> I think (2) will initially be easier, but will pollute the "leaf" CMake
> functions/targets with target-specific details, as already seems to be
> happening in AddSwift.cmake.
>
> Is there another approach I'm not considering? What is more likely to be
> accepted into apple/swift master?

I'm proposing we do (1) for new cross-compilation targets (like OS X
to Linux, or Linux x86_64 to Linux arm), but keep the current scheme
for Darwin.

To keep existing workflows working, I would suggest that native builds
keep building the standard library in the same CMake invocation as the
compiler.

Optionally, cross-compiling builds can unconditionally invoke the
CMake build tool recursively for cross-compilation targets after the
compiler is built, to erase the difference between native builds and
cross-compiling.

Dmitri

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/


(Dmitri Gribenko) #13

Ok, thanks, I'll run with that. I see
SWIFT_NATIVE_(LLVM|CLANG|SWIFT)_TOOLS_PATH, is currently used/supported
anywhere?

Yes, it is supported and can be used to compile the libraries with an
existing swift compiler, while cross-compiling the compiler. It can
be used for some cross-compilation workflows.

My current plan is to:
1) Build everything (llvm/clang, cmark, swift) for macosx-x86_64
2) Setup SWIFT_NATIVE_*_TOOLS_PATH to point to the respective dirs created
in (1)
3) Create a swift-android-armv7 build dir
4) Invoke CMake in swift-android-armv7 with vars from (2), plus a
Toolchain-android-armv7.cmake to set CMAKE_SYSTEM_NAME, CMAKE_SYSROOT, etc
for the android build

Right, except the step (2) actually happens inside of step (4).
That's exactly how it is supposed to work.

Ideally I'd only build the stdlib and tests for android, skipping the tools
and and llvm/clang builds. Does this seem feasible? I know the runtime
depends on llvm headers, but I can either use the macosx-x86_64 llvm
headers, or do a partial headers-only install of llvm-android-armv7. Are
there any binaries/tools needed to be built for the target (i.e
android-armv7) in order to build stdlib?

Yes, you can do that with appropriate skip-build-* flags, but you
would still need to configure llvm/clang. build-script should take
care of that if you give it appropriate flags.

Anything else I should know/watch
out for?

Nothing that I know of right now.

Dmitri

···

On Thu, Jan 21, 2016 at 11:04 AM, Tom Birch <froody@gmail.com> wrote:

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/


(Chris Bieneman) #14

Can I provide an alternate suggestion?

Clang can be cross-compiled for alternate platforms with seemingly a single CMake invocation. This is accomplished by having a model where the user configures the cross-build, and LLVM's CMake detects that you are cross compiling and it handles configuring the host tools and hooking the dependencies up.

This does lead to some pretty gnarly CMake scripting, but I think it provides a very good user experience.

As an example instructions for cross-compiling LLVM are here: http://llvm.org/docs/GettingStarted.html#cross-compiling-llvm

That simple configuration command handles everything, all a user has to do is run ninja once.

-Chris

···

Sent from my iPad

On Jan 21, 2016, at 11:38 AM, Dmitri Gribenko via swift-dev <swift-dev@swift.org> wrote:

On Thu, Jan 21, 2016 at 11:04 AM, Tom Birch <froody@gmail.com> wrote:
Ok, thanks, I'll run with that. I see
SWIFT_NATIVE_(LLVM|CLANG|SWIFT)_TOOLS_PATH, is currently used/supported
anywhere?

Yes, it is supported and can be used to compile the libraries with an
existing swift compiler, while cross-compiling the compiler. It can
be used for some cross-compilation workflows.

My current plan is to:
1) Build everything (llvm/clang, cmark, swift) for macosx-x86_64
2) Setup SWIFT_NATIVE_*_TOOLS_PATH to point to the respective dirs created
in (1)
3) Create a swift-android-armv7 build dir
4) Invoke CMake in swift-android-armv7 with vars from (2), plus a
Toolchain-android-armv7.cmake to set CMAKE_SYSTEM_NAME, CMAKE_SYSROOT, etc
for the android build

Right, except the step (2) actually happens inside of step (4).
That's exactly how it is supposed to work.

Ideally I'd only build the stdlib and tests for android, skipping the tools
and and llvm/clang builds. Does this seem feasible? I know the runtime
depends on llvm headers, but I can either use the macosx-x86_64 llvm
headers, or do a partial headers-only install of llvm-android-armv7. Are
there any binaries/tools needed to be built for the target (i.e
android-armv7) in order to build stdlib?

Yes, you can do that with appropriate skip-build-* flags, but you
would still need to configure llvm/clang. build-script should take
care of that if you give it appropriate flags.

Anything else I should know/watch
out for?

Nothing that I know of right now.

Dmitri

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/
_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev


(Dmitri Gribenko) #15

Does that ninja command invoke multiple sub-ninja commands?

Dmitri

···

On Fri, Jan 22, 2016 at 9:26 AM, ChrisBieneman <beanz@apple.com> wrote:

Can I provide an alternate suggestion?

Clang can be cross-compiled for alternate platforms with seemingly a single CMake invocation. This is accomplished by having a model where the user configures the cross-build, and LLVM's CMake detects that you are cross compiling and it handles configuring the host tools and hooking the dependencies up.

This does lead to some pretty gnarly CMake scripting, but I think it provides a very good user experience.

As an example instructions for cross-compiling LLVM are here: http://llvm.org/docs/GettingStarted.html#cross-compiling-llvm

That simple configuration command handles everything, all a user has to do is run ninja once.

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/


(Chris Bieneman) #16

Can I provide an alternate suggestion?

Clang can be cross-compiled for alternate platforms with seemingly a single CMake invocation. This is accomplished by having a model where the user configures the cross-build, and LLVM's CMake detects that you are cross compiling and it handles configuring the host tools and hooking the dependencies up.

This does lead to some pretty gnarly CMake scripting, but I think it provides a very good user experience.

As an example instructions for cross-compiling LLVM are here: http://llvm.org/docs/GettingStarted.html#cross-compiling-llvm

That simple configuration command handles everything, all a user has to do is run ninja once.

Does that ninja command invoke multiple sub-ninja commands?

Yes. The top-level ninja will put them in the console job pool which results in their output being directly piped to the parent, and only one will execute at a time which allows them to not conflict with each other.

Alternatively if a user were to use make, it just becomes a recursive make call and the standard make IPC gets used to coordinate between the processes.

-Chris

···

On Jan 22, 2016, at 9:30 AM, Dmitri Gribenko <gribozavr@gmail.com> wrote:
On Fri, Jan 22, 2016 at 9:26 AM, ChrisBieneman <beanz@apple.com> wrote:

Dmitri

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/


(Dmitri Gribenko) #17

Well, that's bad, here's why.

Building the Swift standard library has two phases: a very parallel
one, and a strictly serial one. If you run all ninja invocations
serially, you will be increasing the compilation time by about 8x for
a full build for Apple operating systems (approx. 1 hour in total,
unacceptable). If you run them all in parallel, you will
oversubscribe the machine during the parallel phase, and it will start
swapping.

Dmitri

···

On Fri, Jan 22, 2016 at 9:50 AM, Chris Bieneman <beanz@apple.com> wrote:

On Jan 22, 2016, at 9:30 AM, Dmitri Gribenko <gribozavr@gmail.com> wrote:

On Fri, Jan 22, 2016 at 9:26 AM, ChrisBieneman <beanz@apple.com> wrote:

Can I provide an alternate suggestion?

Clang can be cross-compiled for alternate platforms with seemingly a single CMake invocation. This is accomplished by having a model where the user configures the cross-build, and LLVM's CMake detects that you are cross compiling and it handles configuring the host tools and hooking the dependencies up.

This does lead to some pretty gnarly CMake scripting, but I think it provides a very good user experience.

As an example instructions for cross-compiling LLVM are here: http://llvm.org/docs/GettingStarted.html#cross-compiling-llvm

That simple configuration command handles everything, all a user has to do is run ninja once.

Does that ninja command invoke multiple sub-ninja commands?

Yes. The top-level ninja will put them in the console job pool which results in their output being directly piped to the parent, and only one will execute at a time which allows them to not conflict with each other.

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/


(Chris Bieneman) #18

What are the very parallel and very serial phases doing?

-Chris

···

On Jan 22, 2016, at 10:03 AM, Dmitri Gribenko <gribozavr@gmail.com> wrote:

On Fri, Jan 22, 2016 at 9:50 AM, Chris Bieneman <beanz@apple.com <mailto:beanz@apple.com>> wrote:

On Jan 22, 2016, at 9:30 AM, Dmitri Gribenko <gribozavr@gmail.com> wrote:

On Fri, Jan 22, 2016 at 9:26 AM, ChrisBieneman <beanz@apple.com> wrote:

Can I provide an alternate suggestion?

Clang can be cross-compiled for alternate platforms with seemingly a single CMake invocation. This is accomplished by having a model where the user configures the cross-build, and LLVM's CMake detects that you are cross compiling and it handles configuring the host tools and hooking the dependencies up.

This does lead to some pretty gnarly CMake scripting, but I think it provides a very good user experience.

As an example instructions for cross-compiling LLVM are here: http://llvm.org/docs/GettingStarted.html#cross-compiling-llvm

That simple configuration command handles everything, all a user has to do is run ninja once.

Does that ninja command invoke multiple sub-ninja commands?

Yes. The top-level ninja will put them in the console job pool which results in their output being directly piped to the parent, and only one will execute at a time which allows them to not conflict with each other.

Well, that's bad, here's why.

Building the Swift standard library has two phases: a very parallel
one, and a strictly serial one. If you run all ninja invocations
serially, you will be increasing the compilation time by about 8x for
a full build for Apple operating systems (approx. 1 hour in total,
unacceptable). If you run them all in parallel, you will
oversubscribe the machine during the parallel phase, and it will start
swapping.

Dmitri

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com <mailto:gribozavr@gmail.com>>*/


(Dmitri Gribenko) #19

All phases are compiling different libraries. The serial part is the
first stage when we compile the core library, that every other library
depends on, and another serial stage is StdlibUnittest, that depends
on many other libraries, but just takes too long to compile, and its
compilation outlives the parallel stage when we still have other work
to do.

Dmitri

···

On Fri, Jan 22, 2016 at 10:10 AM, Chris Bieneman <beanz@apple.com> wrote:

What are the very parallel and very serial phases doing?

-Chris

On Jan 22, 2016, at 10:03 AM, Dmitri Gribenko <gribozavr@gmail.com> wrote:

On Fri, Jan 22, 2016 at 9:50 AM, Chris Bieneman <beanz@apple.com> wrote:

On Jan 22, 2016, at 9:30 AM, Dmitri Gribenko <gribozavr@gmail.com> wrote:

On Fri, Jan 22, 2016 at 9:26 AM, ChrisBieneman <beanz@apple.com> wrote:

Can I provide an alternate suggestion?

Clang can be cross-compiled for alternate platforms with seemingly a single
CMake invocation. This is accomplished by having a model where the user
configures the cross-build, and LLVM's CMake detects that you are cross
compiling and it handles configuring the host tools and hooking the
dependencies up.

This does lead to some pretty gnarly CMake scripting, but I think it
provides a very good user experience.

As an example instructions for cross-compiling LLVM are here:
http://llvm.org/docs/GettingStarted.html#cross-compiling-llvm

That simple configuration command handles everything, all a user has to do
is run ninja once.

Does that ninja command invoke multiple sub-ninja commands?

Yes. The top-level ninja will put them in the console job pool which results
in their output being directly piped to the parent, and only one will
execute at a time which allows them to not conflict with each other.

Well, that's bad, here's why.

Building the Swift standard library has two phases: a very parallel
one, and a strictly serial one. If you run all ninja invocations
serially, you will be increasing the compilation time by about 8x for
a full build for Apple operating systems (approx. 1 hour in total,
unacceptable). If you run them all in parallel, you will
oversubscribe the machine during the parallel phase, and it will start
swapping.

Dmitri

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/