-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[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
[build-script] Compute targets in build-script
#2880
Conversation
/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 |
After this PR land, direct use of |
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 |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
@rintaro I agree about the |
target.name | ||
for target in stdlib_targets]) | ||
targets_group.add_argument( | ||
"--build-stdlib-deployment-targets", |
There was a problem hiding this comment.
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
?
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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)
I think |
# 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. |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
LGTM modulo comments! |
|
||
return { | ||
"SWIFT_STDLIB_TARGETS": " ".join(swift_stdlib_targets), | ||
"SWIFT_SDKS": " ".join(sorted(swift_sdks)), |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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).
04a916f
to
10f7c47
Compare
@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 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() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Can we reorder these, so the configure targets come first?
- I don't really like the names here. It starts with
needed_deployment_targets
- how/why is it needed? It should be calledstdlib_targets_to_configure
, but that's a bit strange because it would look likestdlib_targets_to_build
, except_to_build
doesn't actually containstdlib-deployment-target
s, 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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
build-script
build-script
# 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 \ |
There was a problem hiding this comment.
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!
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 anexecutable_format
and check forMach-O
instead; it's technically more accurate and that's useful information for cross-compilers anyway. I builtllvm-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.
There was a problem hiding this comment.
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...
There was a problem hiding this comment.
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.
827dfec
to
b112623
Compare
Rebased after landing #2919 |
@swift-ci please Python lint |
@swift-ci please smoke test |
Linux test failure definitely my fault, investigating. |
cc35486
to
f8da62a
Compare
Turns out Linux bash didn't behave the same way in parsing environment variables, fixed to normalize out @swift-ci please smoke test |
Linux failure is unrelated -- OS X failure is based on a misunderstanding of mine about the |
- 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.
f8da62a
to
d515078
Compare
@swift-ci please smoke test |
Linux failure is unrelated, and got a LGTM from @gribozavr |
#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.
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 tobuild-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:
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
Validation Testing
Lint Testing
Note: Only members of the Apple organization can trigger swift-ci.