Skip to content

[build-script] Compute targets in build-script #2880

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

Merged
merged 7 commits into from
Jun 9, 2016

Conversation

ddunbar
Copy link
Contributor

@ddunbar ddunbar commented Jun 4, 2016

What's in this pull request?

This is a work-in-progress branch to move the computation of the target list up to build-script. It does size by inventing a new mechanism to pass host-specific variables down to build-script-impl, and it also factors out explicit objects for platform/target to attach metadata to.

Finally, this branch itself doesn't actually remove the build-script-impl logic. Instead, it runs both implementations and asserts that they compute the same result -- the logic itself is hairy so this has been a good source of catching bugs in the implementation for all the different flag combinations.

Resolved bug number: (SR-)


Before merging this pull request to apple/swift repository:

  • Test pull request on Swift continuous integration.

Triggering Swift CI

The swift-ci is triggered by writing a comment on this PR addressed to the GitHub user @swift-ci. Different tests will run depending on the specific comment that you use. The currently available comments are:

Smoke Testing

Platform Comment
All supported platforms @swift-ci Please smoke test
All supported platforms @swift-ci Please smoke test and merge
OS X platform @swift-ci Please smoke test OS X platform
Linux platform @swift-ci Please smoke test Linux platform

Validation Testing

Platform Comment
All supported platforms @swift-ci Please test
All supported platforms @swift-ci Please test and merge
OS X platform @swift-ci Please test OS X platform
OS X platform @swift-ci Please benchmark
Linux platform @swift-ci Please test Linux platform

Lint Testing

Language Comment
Python @swift-ci Please Python lint

Note: Only members of the Apple organization can trigger swift-ci.

@ddunbar
Copy link
Contributor Author

ddunbar commented Jun 4, 2016

/cc @gribozavr @rintaro @modocache

I'd like to clean this up a bit more before landing, but I'm posting it now in case anyone has feedback on the approach. The good news is that this will allow us to start ripping out much more of the code in build-script-impl once it lands and we are comfortable ripping out the validation logic.

@rintaro
Copy link
Member

rintaro commented Jun 4, 2016

After this PR land, direct use of build-script-impl is almost impossible.
I think, it's time to hide it in Python package directory.
master...rintaro:build-script-hide-impl

self.name = name
self.targets = [Target(self, arch) for arch in archs]
self.sdk_name = name.upper() if sdk_name is None else sdk_name
self.is_darwin = is_darwin
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the is_darwin flag here? Couldn't we just check if a Platform is a DarwinPlatform or not via the class hierarchy?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it is just ends up being a lot more verbose for clients (and we branch on this frequently). I could of course have just made it a computed property using that, though, which makes more sense... I will fix that.

@ddunbar
Copy link
Contributor Author

ddunbar commented Jun 6, 2016

@rintaro I agree about the build-script becoming unusable, but I'm not sure if it is worth moving it... my hope is that we continue to iterate quickly on just eliminating it, and in practice anyone using it has to migrate no matter what.

target.name
for target in stdlib_targets])
targets_group.add_argument(
"--build-stdlib-deployment-targets",
Copy link
Contributor

@gribozavr gribozavr Jun 6, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to have a consistent model (from the user's perspective) between cross-compiling the tools and the library. What about --cross-compile-tools-for-targets and --cross-compile-stdlib-for-targets?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm just porting over existing names from build-script-impl, can we separate out renames/behavior changes? Or are you trying to ensure it gets cleaned up as we port?

Copy link
Contributor

@gribozavr gribozavr Jun 6, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be OK with adding these as FIXMEs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I'm not even sure I understand the comment. This flag is just a filter on --stdlib-deployment-targets... what makes those names more consistent?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, re-reading now I see that my initial message was confusing. What I meant is:

--cross-compile-hosts       => --cross-compile-tools-for-hosts
--stdlib-deployment-targets => --cross-compile-stdlib-for-targets

Does this make sense?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I take it we're not supporting cross-compiling for NxM hosts and targets?

That is, --cross-compile-stdlib-for-targets might be confused with some future option to specify which stdlibs are compiled for the cross-compiled hosts (e.g. I might be on OSX, building a linux-armv7 compiler capable of targeting itself and linux-x86_64). Currently, cross-compiled hosts can only target themselves. If you want anything else, you need to build it for the build machine and manually copy it over.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I take it we're not supporting cross-compiling for NxM hosts and targets?

I can totally see adding support for building N cross-stdlibs in one run, but I would prefer to limit ourselves to cross-compiling just one compiler, which I think is the common case. If you think cross-compiling multiple compilers would be easy to support, I don't have objections in principle -- especially if there is a compelling usecase.

Copy link
Contributor

@karwa karwa Jun 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, actually I was just thinking maybe we shouldn't concat these? How about this for an interface:

--cross-compile-host linux-armv7 \
--cross-compile-stdlib-targets linux-armv7 linux-x86_64 \
--cross-compile-host linux-x86_64 \
--cross-compile-stdlib-targets linux-x86_64 linux-armv7 android-armv7 \

If we get a list of lists, we can match up the host with the list of stdlib targets. That would be very cool, and opens up some possibilities:

How about we replace it with a verb? Merge --stdlib-deployment-targets with --cross-compile-stdlib-deployment-targets, in to --target, so you can go:

./build-script -R \
--target macos-x86_64 \  # First time, it's for the local host
--cross-compile-for linux-armv7 \
--target linux-armv7 linux-x86_64 \ # now it's for args.cross_compile_for[idx-1]
--cross-compile-for linux-x86_64 \
--target linux-x86_64 linux-armv7 android-armv7 \

This would work nicely with the explicit build/test lists, and any other options you might want to specify per-host.

We already support multiple hosts in one run. I don't think there's any difference between supporting one foreign host or supporting several. It's just another spin of the loop.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a small difference -- for example, we lipo together the foreign compilers for different Darwin slices. But we could just say that if we build any cross-compile any compilers for Darwin hosts, we will lipo them together.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what we do at the moment. Any lipo-able hosts will get merged together unless you tell it to skip that step (again, should really be opt-in instead of opt-out, but only the Darwin hosts are lipo-able anyway)

@gribozavr
Copy link
Contributor

@rintaro I agree about the build-script becoming unusable, but I'm not sure if it is worth moving it...

I think build-script-impl has been not suitable for manual use for a long time already. The only time I would expect someone to call it directly is while debugging it. I don't think moving the file is worth the churn.

# w.r.t. testing, but it was actually unused.

# As a special case, Darwin embedded non-simulator platforms have
# different behavior for the test condition.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually hope that this would become a general pattern for all non-native targets that require a separate device to run the tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, will clarify that (and maybe model explicitly in the Platform object)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing that still confuses me: under what circumstances can we run all tests for those platforms? Is my reading of the build script correct in that that is not currently ever possible?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call. Currently, support for testing iOS devices is not open source. I was thinking about something like a flag which allows you to tell build-script which devices you have, for example, --on-device-tests=iphoneos-arm64 Linux-armv7, or maybe just --on-device-tests (implying "all"), and then build-script will run on-device tests unless explicitly asked to run the host-only tests. Does this make sense, or is it too much magic?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense to me... it matches the behavior of lit for example which just tries to run all of the tests which are supported by the configuration you are building, but leaves it up to user to verify that the all the tests you actually wanted to run are running.

I do think it would be good to have some notes printed about when classes of tests are going to be skipped because of missing support.

@gribozavr
Copy link
Contributor

LGTM modulo comments!


return {
"SWIFT_STDLIB_TARGETS": " ".join(swift_stdlib_targets),
"SWIFT_SDKS": " ".join(sorted(swift_sdks)),
Copy link
Contributor

@karwa karwa Jun 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't matter if swift_sdks are sorted, only that they are unique. We used sort -u as a cheap-and-cheerful way to do that in build-script-impl. If you try to configure iphoneos-armv7 and iphoneos-armv7s, they'll both get resolved to IOS. Then when you try to configure for IOS;IOS, CMake will complain about the duplicate.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I understand. The reason why we sort here is so that the refactor validation logic inside build-script-impl works (because we compute the exact same result).

@ddunbar ddunbar force-pushed the build-script-compute-targets branch from 04a916f to 10f7c47 Compare June 8, 2016 15:55
@ddunbar
Copy link
Contributor Author

ddunbar commented Jun 8, 2016

@gribozavr @rintaro @karwa pushed an updated version which I am personally happy with, and would like to land ASAP and address feedback in follow on work.

This PR depends on #2919, and I will rebase once that lands.

I have completely reworked the last commit in this sequence to factor out a helper object, add additional comments, and respond to feedback. I have tried to structure this in such a way that it will be useful when we are doing all of the build-script interactions ourselves (not via build-script-impl).

The other commits in the sequence are basically unchanged, so I recommend focusing only on that one for re-reviewing purposes.

self.targets_to_test = []
self.benchmark_targets_to_build = []
self.benchmark_targets_to_run = []
self.sdks_to_configure = set()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Can we reorder these, so the configure targets come first?
  2. I don't really like the names here. It starts with needed_deployment_targets - how/why is it needed? It should be called stdlib_targets_to_configure, but that's a bit strange because it would look like stdlib_targets_to_build, except _to_build doesn't actually contain stdlib-deployment-targets, it contains Swift build targets.

I would suggest the following:

needed_deployment_targets -> stdlib_targets_to_configure
needed_deployment_targets_to_build -> stdlib_targets_to_build
stdlib_targets_to_build -> swift_stdlib_build_targets
targets_to_test -> swift_test_run_targets
benchmark_targets_to_build -> swift_benchmark_build_targets
benchmark_targets_to_run -> swift_benchmark_run_targets

These are all internal to the build script, so as long as we pass the correct ones along to -impl we should be okay.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's your justification for including swift_ in some of the names? This is all related to Swift, so I didn't feel its inclusion was adding any clarity.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are the build targets that we'll get by configuring swift. stdlib-deployment-targets aren't unique to the 'swift' product and might get used elsewhere - for example when compiling Foundation; it's a target library, so we should really loop over all those targets and build for them.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah! That makes sense -- swift there is a reference to swift the individual project among many. In that case I like your names, I will revise.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pushed update with revised variable names and the comment above this.

@ddunbar ddunbar changed the title [WIP] [build-script] Compute targets in build-script [build-script] Compute targets in build-script Jun 8, 2016
# For platforms which normally require a connected device to
# test, the default behavior is to run tests that only require
# the host (i.e., they do not attempt to execute).
if deployment_platform.is_darwin and \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only place we use it, right? Seems easy enough to make generalised. I mean, if this were written in Swift, the compiler would go bananas at you checking for the existence of instance variables based solely on another instance variable. We should set a good example!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what you mean, are you talking about the is_darwin flag? Yes it is the only use currently, but I believe there are other places we will need it as the build-script-impl merging progresses.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We only have comparable checks in two places:

  • if a target has darwin symbols (i.e. whether or not we should dsymutil -- but we could generalise that as an executable_format and check for Mach-O instead; it's technically more accurate and that's useful information for cross-compilers anyway. I built llvm-dsymutil for linux, and if I had any Mach-Os on there I needed to strip, I'd be using it.)
  • Whether or not to lipo. Could also go under the Mach-O heading.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This, however, doesn't include examples like the one I pasted above, where we have code duplication that is doing the same thing for three different Darwin embedded platforms, but hadn't been factored into common code.

IMHO, factoring it into common code (even using is_darwin) is monotonic improvement that then makes it easier to generalize to a non-Darwin attribute. So I see this as a step in the direction you want...

Copy link
Contributor

@karwa karwa Jun 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That wasn't a great example; host tests are soon not going to be Darwin-exclusive. The fact that they are exclusive isn't actually inherent to Darwin; it's a limitation of what we have implemented right now. That's actually a great example of why not to hide everything behind is_darwin-esque magic IMO.

Maybe it's bikeshedding, but this is how it starts. Once that is_darwin flag is in there, it'll be used for everything.

@ddunbar ddunbar force-pushed the build-script-compute-targets branch 2 times, most recently from 827dfec to b112623 Compare June 8, 2016 21:08
@ddunbar
Copy link
Contributor Author

ddunbar commented Jun 8, 2016

Rebased after landing #2919

@ddunbar
Copy link
Contributor Author

ddunbar commented Jun 8, 2016

@swift-ci please Python lint

@ddunbar
Copy link
Contributor Author

ddunbar commented Jun 8, 2016

@swift-ci please smoke test

@ddunbar
Copy link
Contributor Author

ddunbar commented Jun 8, 2016

Linux test failure definitely my fault, investigating.

@ddunbar ddunbar force-pushed the build-script-compute-targets branch 2 times, most recently from cc35486 to f8da62a Compare June 8, 2016 22:15
@ddunbar
Copy link
Contributor Author

ddunbar commented Jun 8, 2016

Turns out Linux bash didn't behave the same way in parsing environment variables, fixed to normalize out - -> _.

@swift-ci please smoke test

@ddunbar
Copy link
Contributor Author

ddunbar commented Jun 8, 2016

Linux failure is unrelated -- OS X failure is based on a misunderstanding of mine about the shell API, which I intend to adjust in #2959.

ddunbar added 7 commits June 8, 2016 17:22
 - This isn't yet used, but we need an easy way for `build-script` to
   pass host-specific variables down to `build-script-impl`.

 - I don't think it is worth complicating the main argument parsing
   logic with a syntax for passing associative arrays on the command
   line, so this just passes them via environment variables.

 - Part of SR-237.
 - This is so that we can have a place to attach the additional metadata we need
   on platform or target specific behaviors.
 - This adds several platform/target properties used to configure the default
   behavior for a build.

 - This also adds an API to find a target from a name.
 - Introduces a new `HostSpecificConfiguration` which holds the computed
   information for each host we need to use.

 - This relies on the functionality to pass host-specific variables to the
   script via environment variables.

 - The computation itself has been cleaned up a tiny bit (mostly via using
   the factored out platform/target properties), but is otherwise a straight
   port of the logic from `build-script-impl`.

 - This commit does not yet remove that code from `build-script-impl`; instead
   it validates that the two implementations are computing the same result.
   This is useful right now for testing the validity of the port.
@ddunbar ddunbar force-pushed the build-script-compute-targets branch from f8da62a to d515078 Compare June 9, 2016 00:24
@ddunbar
Copy link
Contributor Author

ddunbar commented Jun 9, 2016

@swift-ci please smoke test

@ddunbar
Copy link
Contributor Author

ddunbar commented Jun 9, 2016

Linux failure is unrelated, and got a LGTM from @gribozavr

@ddunbar ddunbar merged commit 8a2fd16 into swiftlang:master Jun 9, 2016
@gribozavr gribozavr mentioned this pull request Jun 9, 2016
2 tasks
modocache added a commit that referenced this pull request Jun 9, 2016
#2880 appends a `Target` instance
to an array of strings when building Android. This causes a syntax
error when building Android. Fix the error to repair the Android
build.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants