Skip to content
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

CMake: fix missing SWIFT_CONCURRENCY_GLOBAL_EXECUTOR value #65795

Merged
merged 4 commits into from
May 17, 2023

Conversation

MaxDesiatov
Copy link
Contributor

@MaxDesiatov MaxDesiatov commented May 9, 2023

SWIFT_CONCURRENCY_GLOBAL_EXECUTOR is defined in stdlib/cmake/modules/StdlibOptions.cmake, which is not included during the first pass of evaluation of the root CMakeLists.txt. It is available on subsequent evaluations after the value is stored in CMake cache. This led to subtle bugs, where usr/lib/swift_static/linux/static-stdlib-args.lnk didn't contain certain flags on clean toolchain builds, but did contain them in incremental builds.

Not having these autolinking flags in toolchain builds leads to errors when statically linking executables on Linux.

Additionally, since are trivial tests previously didn't link Dispatch statically, the didn't expose a bug where %import-static-libdispatch substitution had a missing value. To fix that I had to update lit.cfg and clean up some of the related path computations to infer a correct substitution value.

Resolves some of the errors reported in #65097.

`SWIFT_CONCURRENCY_GLOBAL_EXECUTOR` is defined in `stdlib/cmake/modules/StdlibOptions.cmake`, which is not included during the first pass of evaluation of the root `CMakeLists.txt`. It is available on subsequent evaluations after the value is stored in CMake cache. This led to subtle bugs, where `usr/lib/swift_static/linux/static-stdlib-args.lnk` didn't contain certain flags on clean toolchain builds, but did contain them in incremental builds.

Not having these autolinking flags in toolchain builds leads to errors when statically linking executables on Linux.
@MaxDesiatov
Copy link
Contributor Author

@swift-ci test

@MaxDesiatov
Copy link
Contributor Author

@swift-ci build toolchain

@MaxDesiatov
Copy link
Contributor Author

Running a first pass of tests before running cross-repo integration tests...

@MaxDesiatov MaxDesiatov added bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. Linux Platform: Linux build-script Area → utils: The build script cmake static libraries swift-autolink-extract Area → compiler → legacy driver: the 'swift-autolink-extract' mode labels May 9, 2023
@al45tair
Copy link
Contributor

al45tair commented May 9, 2023

Potentially resolves #65097.

Isn't this going to auto-close that issue? So either it does resolve it, or we should adjust the message wording here?

@MaxDesiatov
Copy link
Contributor Author

MaxDesiatov commented May 9, 2023

I'm not merging this one until we have appropriate integration tests enabled and passing, will update the wording after that.

@MaxDesiatov MaxDesiatov requested a review from artemcm as a code owner May 10, 2023 13:05
@MaxDesiatov
Copy link
Contributor Author

@swift-ci test

@MaxDesiatov
Copy link
Contributor Author

@swift-ci build toolchain

Comment on lines -1600 to -1601
make_path(libdispatch_static_artifact_dir, 'src', 'swift', 'libswiftDispatch.a'),
make_path(libdispatch_swift_static_module_dir, 'Dispatch.swiftmodule')]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We don't need a Swift overlay for Dispatch to statically linked a simple executable, Dispatch is used directly without an overlay from the concurrency runtime.

@@ -1593,19 +1593,13 @@ elif (run_os in ['linux-gnu', 'linux-gnueabihf', 'freebsd', 'openbsd', 'windows-
config.import_libdispatch = ('-I %s -I %s -L %s'
% (libdispatch_source_dir, libdispatch_swift_module_dir, libdispatch_artifact_dir))

libdispatch_static_artifact_dir = config.libdispatch_static_build_path
libdispatch_swift_static_module_dir = make_path(libdispatch_static_artifact_dir, 'src', 'swift', 'swift')
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Overlay path deleted as unused.

@@ -1593,19 +1593,13 @@ elif (run_os in ['linux-gnu', 'linux-gnueabihf', 'freebsd', 'openbsd', 'windows-
config.import_libdispatch = ('-I %s -I %s -L %s'
% (libdispatch_source_dir, libdispatch_swift_module_dir, libdispatch_artifact_dir))

libdispatch_static_artifact_dir = config.libdispatch_static_build_path
libdispatch_swift_static_module_dir = make_path(libdispatch_static_artifact_dir, 'src', 'swift', 'swift')
libdispatch_static_artifact_dir = os.path.join(config.libdispatch_static_build_path, 'lib')
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added a lib component for easier reuse of this variable in subsequent expressions below this line.

libdispatch_static_artifacts = [
make_path(libdispatch_static_artifact_dir, 'src', 'libdispatch.a'),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Built artifacts are located in lib, not src.

Comment on lines -1604 to +1602
config.import_libdispatch_static = ('-I %s -I %s -L %s -L %s -L %s'
% (libdispatch_source_dir, libdispatch_swift_static_module_dir,
make_path(libdispatch_static_artifact_dir, 'src'),
make_path(libdispatch_static_artifact_dir, 'src', 'BlocksRuntime'),
make_path(libdispatch_static_artifact_dir, 'src', 'swift')))
config.import_libdispatch_static = '-L %s' % libdispatch_static_artifact_dir
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since neither the overlay nor the headers are used for static linking, this is simplified to a single library search path flag.

# WARNING: the order of components in a substitution name has to be different from the previous one, as lit does
# a pure string substitution without understanding that these components are grouped together. That is, the following
# subsitution name can't be `%import-libdispatch-static`, otherwise the first two components will be substituted with
# the value of `%import-libdispatch` substitution with `-static` string appended to it.
config.substitutions.append(('%import-static-libdispatch', getattr(config, 'import_libdispatch_static', '')))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

While working on this fix I attempted to rename this to %import-libdispatch-static for consistency, which led to a hard to debug test failure due to incorrect flags passed. Added a note about this substitution behavior for posterity.

@@ -1901,7 +1901,7 @@ for host in "${ALL_HOSTS[@]}"; do
-DSWIFT_PATH_TO_CMARK_BUILD:PATH="$(build_directory ${host} cmark)"
-DSWIFT_PATH_TO_LIBDISPATCH_SOURCE:PATH="${LIBDISPATCH_SOURCE_DIR}"
-DSWIFT_PATH_TO_LIBDISPATCH_BUILD:PATH="$(build_directory ${host} libdispatch)"
-DSWIFT_PATH_TO_LIBDISPATCH_STATIC_BUILD:PATH="$(build_directory ${host} libdispatch_static)"
-DSWIFT_PATH_TO_LIBDISPATCH_STATIC_BUILD:PATH="$(build_directory ${host} swift)/$(basename $(build_directory ${host} libdispatch))-static-prefix"
Copy link
Contributor Author

@MaxDesiatov MaxDesiatov May 10, 2023

Choose a reason for hiding this comment

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

Dispatch built as a dependency of the Swift compiler is located in the Swift build subdirectory, not in its own directory at the top level of the build. It also has that -static-prefix suffix (sic), which I haven't found where it's coming from, seems like it isn't passed to build-script-impl itself, so I'm hardcoding that suffix here for now.

Copy link
Contributor

Choose a reason for hiding this comment

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

IIRC, this is the dispatch built for the concurrency runtime. I think this will work for this use-case, but it is probably worth noting.

Copy link
Contributor Author

@MaxDesiatov MaxDesiatov May 10, 2023

Choose a reason for hiding this comment

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

For concurrency runtime and SourceKit IIUC

@MaxDesiatov
Copy link
Contributor Author

swiftlang/swift-integration-tests#78

@swift-ci build toolchain linux

@MaxDesiatov
Copy link
Contributor Author

@swift-ci build toolchain

@tomerd
Copy link
Contributor

tomerd commented May 10, 2023

seems reasonable to me. should any of this be separated into a dedicated "cleanup" PR, or do they all need to be done together?

@MaxDesiatov
Copy link
Contributor Author

MaxDesiatov commented May 10, 2023

They have to go together otherwise the Linux test suite will fail, like it did for 5897ab5 in the branch of this PR.

@tomerd
Copy link
Contributor

tomerd commented May 10, 2023

I meant the other order, ie first do the cleanup then fix the static linking initialization issue. but not a big deal either way

@MaxDesiatov
Copy link
Contributor Author

AFAIU this repository prefers merge commits, so commit separation will be preserved after the PR is merged. If having separate PRs would make the review easier I can split it, but the diff seems relatively small to me from that perspective.

CMakeLists.txt Outdated
@@ -202,6 +202,10 @@ set(SWIFT_HOST_VARIANT_ARCH "${SWIFT_HOST_VARIANT_ARCH_default}" CACHE STRING
# This is primarily to support building smaller or faster project files.
#

# Subsequent options may refer to `StdlibOptions`, which have to be defined first.
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/stdlib/cmake/modules)
include(StdlibOptions)
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of including StdlibOptions here, why don't we move the following into StdlibOptions?

# Use dispatch as the system scheduler by default.
# For convenience, we set this to false when concurrency is disabled.
set(SWIFT_CONCURRENCY_USES_DISPATCH FALSE)
if(SWIFT_ENABLE_EXPERIMENTAL_CONCURRENCY AND "${SWIFT_CONCURRENCY_GLOBAL_EXECUTOR}" STREQUAL "dispatch")
  set(SWIFT_CONCURRENCY_USES_DISPATCH TRUE)
endif()

AFAICT it is only used in the stdlib build, so really has no business being set in the root CMakeLists.txt

Copy link
Contributor

Choose a reason for hiding this comment

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

^ Was just thinking that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point, that's addressed now.

It is only used in the stdlib build, so really has no business being set in the root `CMakeLists.txt`.
@MaxDesiatov MaxDesiatov requested a review from drexin May 10, 2023 18:37
set(SWIFT_CONCURRENCY_USES_DISPATCH FALSE)
if(SWIFT_ENABLE_EXPERIMENTAL_CONCURRENCY AND "${SWIFT_CONCURRENCY_GLOBAL_EXECUTOR}" STREQUAL "dispatch")
set(SWIFT_CONCURRENCY_USES_DISPATCH TRUE)
endif()
Copy link
Contributor Author

@MaxDesiatov MaxDesiatov May 10, 2023

Choose a reason for hiding this comment

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

Moved to stdlib/cmake/modules/StdlibOptions.cmake

@MaxDesiatov
Copy link
Contributor Author

@swift-ci test

Copy link
Contributor

@etcwilde etcwilde left a comment

Choose a reason for hiding this comment

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

This is a fair bit better.

The sourcekit should be a misnomer coming from our build-soup (don't have to fix it now). We're not building dispatch for the "host", we're building it for the "target", so it may not work in a cross-compiling situation.

@MaxDesiatov
Copy link
Contributor Author

@swift-ci build toolchain

@MaxDesiatov
Copy link
Contributor Author

@swift-ci test linux

@MaxDesiatov MaxDesiatov merged commit 0fc3659 into main May 17, 2023
@MaxDesiatov MaxDesiatov deleted the maxd/fix-missing-cmake-value branch May 17, 2023 19:52
MaxDesiatov added a commit that referenced this pull request May 26, 2023
[5.9] CMake: fix missing `SWIFT_CONCURRENCY_GLOBAL_EXECUTOR`

Explanation: Resolves issues with static linking on Linux
Risk: Medium, affects Linux builds and top-level CMake declarations.
Original PR: #65795.
Reviewed by: @al45tair @drexin @etcwilde 
Resolves: some of the issues reported in #65097
Tests: Added in swiftlang/swift-integration-tests#115

`SWIFT_CONCURRENCY_GLOBAL_EXECUTOR` is defined in `stdlib/cmake/modules/StdlibOptions.cmake`, which is not included during the first pass of evaluation of the root `CMakeLists.txt`. It is available on subsequent evaluations after the value is stored in CMake cache. This led to subtle bugs, where `usr/lib/swift_static/linux/static-stdlib-args.lnk` didn't contain certain flags on clean toolchain builds, but did contain them in incremental builds.

Not having these autolinking flags in toolchain builds leads to errors when statically linking executables on Linux.

Additionally, since are trivial tests previously didn't link Dispatch statically, the didn't expose a bug where `%import-static-libdispatch` substitution had a missing value. To fix that I had to update `lit.cfg` and clean up some of the related path computations to infer a correct substitution value.

Resolves some of the errors reported in #65097.
MaxDesiatov added a commit that referenced this pull request Jun 1, 2023
[5.8] CMake: fix missing `SWIFT_CONCURRENCY_GLOBAL_EXECUTOR`

Explanation: Resolves issues with static linking on Linux
Risk: Medium, affects Linux builds and top-level CMake declarations.
Original PRs: #65795 and #64312 for `main`, #65824 and #64633 for `release/5.9`
Reviewed by: @al45tair @drexin @etcwilde 
Resolves: some of the issues reported in #65097, also resolves #58380
Tests: Added in swiftlang/swift-integration-tests#118

`SWIFT_CONCURRENCY_GLOBAL_EXECUTOR` is defined in `stdlib/cmake/modules/StdlibOptions.cmake`, which is not included during the first pass of evaluation of the root `CMakeLists.txt`. It is available on subsequent evaluations after the value is stored in CMake cache. This led to subtle bugs, where `usr/lib/swift_static/linux/static-stdlib-args.lnk` didn't contain certain flags on clean toolchain builds, but did contain them in incremental builds.

Not having these autolinking flags in toolchain builds leads to errors when statically linking executables on Linux.

Additionally, since our trivial lit tests previously didn't link Dispatch statically, they didn't expose a bug where `%import-static-libdispatch` substitution had a missing value. To fix that I had to update `lit.cfg` and clean up some of the related path computations to infer a correct substitution value.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. build-script Area → utils: The build script cmake Linux Platform: Linux static libraries swift-autolink-extract Area → compiler → legacy driver: the 'swift-autolink-extract' mode
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants