Fix a bug in the split build model where we generate a dependency on the
swiftmodule of a target that does not emit a swiftmodule.
This fix drops the erroneous swiftmodule dependency edge, avoiding the
broken dependency graph. Incremental builds still work with the new
model because of the swiftmodule dependency edges between Swift
compilation steps.
Fixes: #26922
The nested Swift module structure is recommended for Swift projects.
This structure has an outer directory called
`<Swift_MODULE_NAME>.swiftmodule` that contains generated files for the
interface. The binary swift modules, textual swift interface, and other
supplemental outputs that make up the interface to a Swift library all
go in this outer directory with the Swift module triple as the filename
followed by the appropriate file extension based on what that file
contains.
Issue: #19284
Account for changes to upstream ninja:
* commit `5d93f2da28` (Add exit code to the failed target, 2024-12-03)
* commit `311bf93416` (Propagate jobs' exit codes to the ninja's exit code,
2024-12-03)
This patch makes the `Swift_MODULE_DIRECTORY` property behave more like
the other output directory properties, allowing generator expressions
and fixing the behavior with multi-config generators.
Issue: #26010
Setting `CMAKE_INSTALL_NAME_DIR` or the `INSTALL_NAME_DIR` on Swift
targets had no effect when CMP0157 was set to `NEW`. This was a result
of missing the `<TARGET_INSTALLNAME_DIR>` before the `<TARGET_SONAME>`.
Fix that and add a test to verify that the install name directory is
included in the install name.
Fixes: #26175
Place `.swiftmodule` files a subdirectory named after the configuration.
Fixes: #25864Fixes: #25997
- Swift/RunCMakeTest.cmake:
- CMP0157-OLD was enabled for Xcode, where it works.
- A test was added that verifies .swiftmodule's are generated into
separate directories with multi-config generators.
- Tests/SwiftOnly/CMakeLists.txt: tests were added that validate that
cross-subdirectory module dependencies (via target_link_libraries)
work.
Also factor out testing that's common across Xcode and Ninja.* generators.
- Ninja expected output files were extended to accept directories named
after the configuration in paths.
- Tests that previously ran with Ninja were allowed to run with Ninja
Multi-Config.
- Swift/RunCMakeTest.cmake:
- Checks for conditions where little or no testing could be done
were moved to the top of the file, with return()s to limit nesting
of the remainder of the code ("Early bailouts").
- CMP0157 tests, which were being performed for all generators, were
factored out into a block at the top of the file.
- RunCMake_TEST_OPTIONS is set initially for all multi-config
generators and list(APPEND)'ed-to in each block() where it was previously
set() and unset().
Upstream ninja commit `8e6c741a4b` ("explain" debug prints just before
each command is run, 2022-01-06) changed the `ninja -d explain` output
for our test case. The `IncrementalSwift-second` case primarily needs
to match stdout, so update our stderr expectation to work for either
form of ninja's output.
Top-level code only works as part of executables, which breaks when
`CMAKE_TRY_COMPILE_TARGET_TYPE` is set to `STATIC_LIBRARY`. This patch
fixes the test to something agnostic between executables and libraries
while still verifying that we can import types from the standard
library.
Fixes: #25984
By default, Ninja displays the full build command for the object which
is very verbose. Warnings are often lost in the noise, and compile
errors take some searching to find. If a build step fails, Ninja will
still print out the full build command, so there's no loss of useful
information.
Fixes: #25853
Executables that don't export a public API should not emit a
swiftmodule, but the swift modulename is observable from within the
program, so we should still set the module name on executable builds.
Fixes: #25710
Unlike C/C++, Swift compiles all sources in a module at once. This can
quickly overwhelm the commandline length limit on Windows, so it is
useful to place the source files in the response file.
Issue: #25572
This was accidentally removed when the command templates were
reorganized to introduce the new policy. Restore the flag in the shared
library creation to ensure that we emit the import libraries to the
correct location.
The `-static` is important for the emission of the module as it is
serialized into the swiftmodule which then is used by the Swift frontend
to decide how to link to the symbol (via the GOT or not, or the IAT on
Windows). This repairs building static libraries with Swift on Windows.
The swift toolchain leaves output files untouched
if there are no meaningful input changes; without
restat, this causes ninja to needlessly rebuild
targets that are not actually out-of-date
Fixes: #25496
Swift compile commands need to have all source files in the module
specified in the compile command or LSP systems will report errors on
missing types that are defined in other source files in the same module.
Issue: #25491
The CMP0157 old behavior omitted the output-file-map after the Swift
build split because we stopped calling `EmitSwiftDependencyInfo` when we
could not split the build because we didn't call
`WriteObjectBuildStatement`. If we can't split the build, then we still
need to include the OFM information to not break incremental builds.
Splitting the Swift build into an object build and a separate link step,
instead of building and linking in one step. The immediate benefit is
LSP support because we are able to emit compile-commands for Swift files
now. Additionally, it is possible to specify flags to the compile step,
enabling folks to emit C and C++ headers from their Swift builds for
C/C++ interop, without needing custom commands. Eventually, this gives
us a path toward working object libraries.
Object Libraries:
- Object libraries don't work today because CMake doesn't emit targets
for object libraries into the Ninja build file.
- tl;dr: Object libraries work if they aren't WMO. Still need work to
make WMO'd object libraries work.
Object libraries still don't completely work with this patch because,
while we emit the targets, the `TARGET_OBJECTS` generator expression
expansion has a separate mechanism for determining what the names of
the objects are based on the input source files, so targets that
depend on an object library built with a whole-module optimization
will depend on objects based on the name of the source file instead
of the actual emitted object file.
These features require being able to accurately model wholemodule builds
though, because we actually need to track object files and WMO affects
what objects are emitted. For that, we require CMP0157 use the NEW
policy. When it's OLD, we have to fall back on the old behavior and
cannot provide object libraries or the compile-commands for LSP.
Issue: #25308
Add a `CMAKE_Swift_COMPILATION_MODE` variable and corresponding
`Swift_COMPILATION_MODE` target property to control the compilation
mode. Select among `wholemodule`, `singlefile`, and `incremental`.
Add policy CMP0157 to remove the default `-wmo` flags in favor of the
abstract setting.
Issue: #25366
For policy-specific tests, use the version before the policy was
introduced. Otherwise, use 3.5 where possible.
Also, remove `cmake_minimum_required()` and `project()` calls from
individual cases where they are handled by `CMakeLists.txt`.
Ensure that we're actually trying to rebuild libB when the public
interface for libA changes. Without handling the swiftmodule dependency
edge correctly, we would only get a linker error because libA didn't
have the symbol that libB depended on. With the fix, we get a proper
compiler error because ninja knows to rebuild the intermediate libB
when the public interface of libA changes. This is more actionable.
This patch adds support for tracking the swiftmodules for executables
exporting symbols.
This fixes a bug in the earlier implementation around emitting the
swiftmodule. Previously, the code would use
`CMAKE_EXE_EXPORTS_Swift_FLAG` to inject the `-emit-module`, and module
path information into the `CMAKE_Swift_LINK_EXECUTABLE` rule. Because
Swift skips the build step and only runs during the link phase, these
flags were injected in `cmNinjaNormalTargetGenerator::ComputeLinkCmd`
instead of `cmLocalGenerator::GetTargetFlags` where it is done normally.
Unfortunately, injecting in `ComputeLinkCmd` didn't do anything because
we have a `linkCmd` so `ComputeLinkCmd` exits early, before the
EXE_EXPORT flags get added to the link command.
Instead of playing with that flag, CMake checks
`CMAKE_Swift_LINK_EXECUTABLE_WITH_EXPORTS` and uses that as the link
rule if it exists and falls back on `CMAKE_Swift_LINK_EXECUTABLE`. I've
defined that variable in terms of `CMAKE_Swift_LINK_EXECUTABLE` with the
necessary additional flags for emitting the swift module instead. This
has the same end effect as the desired behavior, but simplifies things a
bit.
Since we're generating the swiftmodule for executables with exports,
I've also updated the dependency graph to include the swiftmodule as an
output in the build dependency graph if the executable has exports.
Tests updated:
- RunCMake/NoWorkToDo:
Ensure that the build graph does not result in unnecessary rebuilds
with exporting executables.
- SwiftOnly:
Ensure that we can consume functions defined in the executable by a
library getting linked into said executable.
Swift doesn't emit swiftmodules for executables, so we shouldn't put it
in dependency graph. Ninja sees the "missing" dependency and always
tries to rebuild/re-link the target.
Currently, the compiler does not synthesize the correct entry point for
the application and passing the subsystem flag does not work the same
way with the Swift linker language. Add a check to prevent the
application of `WIN32_EXECUTABLE` to Swift executables until they can be
properly supported. This will prevent the need for a future policy
change.
Closes: #19325
It's relatively complex to determine in advance if a Xcode, SDK,
and Deployment Target configuration is capable of running Swift.
For example the following combinations do not work:
* deployment target < OS X 10.9
* Xcode 6.2 and macosx10.9 SDK
* Xcode 7 Beta 6 and macosx10.10 SDK
Until we found out how to query Xcode for Swift support in a reliable
way, the RunCMake.Swift test cases will be restricted to negative ones.
Allow the `Swift` language to be enabled with the Xcode generator for
Xcode >= 6.1. Reject it on other generators and with older Xcode
versions. Since Apple is the only vendor implementing the language
right now, the compiler id can be just `Apple`.