If the driver is only set up to get the frontend invocation (e.g. from sourcekitd), don't validate that we can link against ARCLite because
a) we don't care about link-time when we are only interested in the frontend invocation
b) finding arclite might cause us to find clang using xcrun which in turn can cause sourcekitd to hang.
rdar://50659268
The frontend supports this via new options -index-unit-output-path and
-index-unit-output-path-filelist that mirror -o and -output-filelist. These are
intended to allow sharing index data across builds in separate directories (so
different -o values) that are otherwise equivalent as far as the index data is
concerned (e.g. an ASAN build and a non-ASAN build) by supplying the same
-index-unit-output-path for both.
This change updates the driver to add these new options to the frontend
invocation 1) when a new "index-unit-output-path" entry is specified for one
or more input files in the -output-file-map json or 2) if -index-file is
specified, when a new -index-unit-output-path driver option is passed.
Resolves rdar://problem/74816412
Add a new swift-frontend driver option that extract APIs in the swift
module and print in JSON format. This is to allow tooling to understand
and process swift APIs without the need to be a swift compiler or
understand swift module/AST.
We've seen bad file descriptor errors in certain build environments (rdar://73157185) and retrying
opening those files seems to be a walkaround. In this change, we allow the
compiler to retry expanding reponse files in argument lists.
rdar://73892564
Remove this distinction without a difference. Originally, the thought
was to
1) Isolate the cross-module build infrastructure
2) Provide a signal to the driver that a dependency had swiftdeps info
in it
But the driver need only notice swiftmodule files as external
dependencies and try to extract that information if it can to divine the
signal it needs. Additionally, we can give it fingerprints as priors to
let it know there might be incremental info to be had.
We're going to play a dirty, dirty trick - but it'll make our users'
lives better in the end so stick with me here.
In order to build up an incremental compilation, we need two sources of
dependency information:
1) "Priors" - Swiftdeps with dependency information from the past
build(s)
2) "Posteriors" - Swiftdeps with dependencies from after we rebuild the
file or module or whatever
With normal swift files built in incremental mode, the priors are given by the
swiftdeps files which are generated parallel to a swift file and usually
placed in the build directory alongside the object files. Because we
have entries in the output file map, we can always know where these
swiftdeps files are. The priors are integrated by the driver and then
the build is scheduled. As the build runs and jobs complete, their
swiftdeps are reloaded and re-integrated. The resulting changes are then
traversed and more jobs are scheduled if necessary. These give us the
posteriors we desire.
A module flips this on its head. The swiftdeps information serialized
in a module functions as the *posterior* since the driver consuming the
module has no way of knowing how to rebuild the module, and because its
dependencies are, for all intents and purposes, fixed in time. The
missing piece of the puzzle is the priors. That is, we need some way of
knowing what the "past" interface of the module looked like so we can
compare it to the "present" interface. Moreover, we need to always know
where to look for these priors.
We solve this problem by serializing a file alongside the build record:
the "external" build record. This is given by a... creative encoding
of multiple source file dependency graphs into a single source file
dependency graph. The rough structure of this is:
SourceFile => interface <BUILD_RECORD>.external
| - Incremental External Dependency => interface <MODULE_1>.swiftmodule
| | - <dependency> ...
| | - <dependency> ...
| | - <dependency> ...
| - Incremental External Dependency => interface <MODULE_2>.swiftmodule
| | - <dependency> ...
| | - <dependency> ...
| - Incremental External Dependency => interface <MODULE_3>.swiftmodule
| - ...
Sorta, `cat`'ing a bunch of source file dependency graphs together but
with incremental external dependency nodes acting as glue.
Now for the trick:
We have to unpack this structure and integrate it to get our priors.
This is easy. The tricky bit comes in integrate itself. Because the
top-level source file node points directly at the external build record,
not the original swift modules that defined these dependency nodes, we
swap the key it wants to use (the external build record) for the
incremental external dependency acting as the "parent" of the dependency
node. We do this by following the arc we carefully laid down in the
structure above.
For rdar://69595010
Goes a long way towards rdar://48955139, rdar://64238133
In order to extract the module dependency graph from the compilation the driver just ran, define a separate semantic type to hold a result code and the graph itself.
The "wave" of a compilation job describes the number of indirections through other compile jobs the driver required to reach the decision to schedule a job. In incremental mode, it should always be the case that it takes no more than two complete waves to arrive at a fixpoint in the build. This is a natural consequence of the structure of the dependencies emitted by the Swift frontend - namely we rely on transitivity in dependency arcs.
A quick proof sketch: Suppose an arbitrary perturbation of the inputs to an incremental compilation session are made. In the first wave, dependency edges from the prior build's state (the "zeroeth wave") are loaded and the files corresponding to invalidated edges are scheduled into the first wave. Supposing the second wave is not the null set - the trivial case - there are additional arcs that were invalidated. Now suppose that there were a third wave. Take an arbitrary arc invalidated by this third wave. It must be the case that the file containing the use is not new - else it would be scheduled. Further it must be the case that its def was not invalidated by the zeroeth or first waves of compilation otherwise we would have scheduled it into the first or second waves. Finally, it must have a use that was discovered in the second wave. But in order for that use to have been included in the second wave, there must have been an invalidated arc created by the first wave. By transitivity of dependency arcs, there must therefore be a dependency arc from a definition invalidated in the first wave to our third wave job, which implies that the file would be scheduled into the second wave!
[Insert contradiction pig image here]
The Optional parameter here was being copied instead of being taken by
const reference. The expectation is that we call this function and
extract the data from a ModuleDepGraphNode node, but instead we were
extracting a copy which would promptly blow up.
Thanks ASAN!
A more durable form of #34218. Keep a side cache of externally-dependent
jobs for now. This ensures our pseudo-Jobs don't get prematurely
deallocated before the tracing machinery has had a chance to report the
structure of the Job graph.
rdar://70053563
Treat any incremental external depends like normal external depends. This will eventually become the fallback behavior for cross-module incremental builds.
LLVM, as of 77e0e9e17daf0865620abcd41f692ab0642367c4, now builds with
-Wsuggest-override. Let's clean up the swift sources rather than disable
the warning locally.
The driver can now schedule jobs which typecheck just-emitted module interfaces to ensure that they can be consumed later. This can be enabled manually by passing `-verify-emitted-module-interface` to the driver.
This commit adds LTO support for handling linker options and LLVM BC
emission. Even for ELF, swift-autolink-extract is unnecessary because
linker options are embeded in LLVM BC content when LTO.
This doesn't yet allow including C++ headers on platforms where libc++
isn't the default; see comments in UnixToolChains.cpp for details.
However, it does, for example, allow throwing and catching exceptions in C++
code used through interop, unblocking
https://github.com/apple/swift/pull/30674/files.
The flags (-enable-experimental-cxx-interop and -experimental-cxx-stdlib) carry
"experimental" in the name to emphasize that C++ interop is still an
experimental feature.
Co-authored-by: Michael Forster <forster@google.com>