swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.66k stars 10.38k forks source link

Interop: Compiling with C++17 or higher on Ubuntu 22.04 fails with cyclic header dependencies in libstdc++ #75661

Closed ADKaster closed 2 months ago

ADKaster commented 3 months ago

Description

When building on a Linux system with libstdc++ higher than version 10 (the current version is 14, and Ubuntu Jammy ships 11) there is a cyclic dependency in the clang module graph for the standard library.

The check in <prefix>//lib/swift/linux/libstdcxx.h includes <execution> in c++17 or higher modes. With libstdc++-11-dev or higher and libtbb-dev, installed, this introduces a cyclic dependency between the _Builtin_intrinsics module and std.

Reproduction

With the following 3 files, the issue is easy to see with the official swift 6.0 snapshot docker containers:

Lib.h

#include <memory>

#include <stdio.h>

void foo() { puts("hi");  }

module.modulemap

module lib {
    header "Lib.h"
}

main.swift

import lib

print("hi")

After putting all these 4 files in one directory, the error can be reproduced with the following shell commands that launch a swift nightly docker container, and installs libtbb-dev.

docker run -it --rm -v $PWD:/workspace swiftlang/swift:nightly-6.0-jammy
apt update && apt install -y libtbb-dev
swiftc -emit-executable -o test -Xcc -std=c++17 -cxx-interoperability-mode=default -I /workspace /workspace/main.swift

The error is as follows:

- error: cyclic dependency in module 'std': std -> _Builtin_intrinsics -> std ``` /workspace/Lib.h:1:10: note: while building module 'std' imported from /workspace/Lib.h:1: 1 | #include | `- note: while building module 'std' imported from /workspace/Lib.h:1: 2 | 3 | #include /usr/include/tbb/../oneapi/tbb/detail/_machine.h:42:10: note: while building module '_Builtin_intrinsics' imported from /usr/include/tbb/../oneapi/tbb/detail/_machine.h:42: 40 | #endif 41 | #if __TBB_x86_64 || __TBB_x86_32 42 | #include // _mm_pause | `- note: while building module '_Builtin_intrinsics' imported from /usr/include/tbb/../oneapi/tbb/detail/_machine.h:42: 43 | #endif 44 | #if (_WIN32) :2:10: note: in file included from :2: 1 | extern "C" { 2 | #include "immintrin.h" | `- note: in file included from :2: 3 | } 4 | extern "C" { /usr/lib/swift/clang/include/immintrin.h:26:10: note: in file included from /usr/lib/swift/clang/include/immintrin.h:26: 24 | #if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ 25 | defined(__SSE__) 26 | #include | `- note: in file included from /usr/lib/swift/clang/include/immintrin.h:26: 27 | #endif 28 | /usr/lib/swift/clang/include/xmmintrin.h:31:10: note: in file included from /usr/lib/swift/clang/include/xmmintrin.h:31: 29 | * a standard library to provide allocation routines. */ 30 | #if __STDC_HOSTED__ 31 | #include | `- note: in file included from /usr/lib/swift/clang/include/xmmintrin.h:31: 32 | #endif 33 | /usr/lib/swift/clang/include/mm_malloc.h:13:10: note: in file included from /usr/lib/swift/clang/include/mm_malloc.h:13: 11 | #define __MM_MALLOC_H 12 | 13 | #include | `- note: in file included from /usr/lib/swift/clang/include/mm_malloc.h:13: 14 | 15 | #ifdef _WIN32 /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/stdlib.h:36:11: error: cyclic dependency in module 'std': std -> _Builtin_intrinsics -> std 34 | #define _GLIBCXX_STDLIB_H 1 35 | 36 | # include | `- error: cyclic dependency in module 'std': std -> _Builtin_intrinsics -> std 37 | 38 | using std::abort; /workspace/Lib.h:1:10: note: while building module 'std' imported from /workspace/Lib.h:1: 1 | #include | `- note: while building module 'std' imported from /workspace/Lib.h:1: 2 | 3 | #include :1:10: note: in file included from :1: 1 | #include "libstdcxx.h" | `- note: in file included from :1: 2 | #include "algorithm" 3 | #include "bitset" /usr/lib/swift/linux/libstdcxx.h:6:10: note: in file included from /usr/lib/swift/linux/libstdcxx.h:6: 4 | // Only include if tbb is installed. 5 | #if __has_include("execution") && __has_include() 6 | #include "execution" | `- note: in file included from /usr/lib/swift/linux/libstdcxx.h:6: 7 | #endif 8 | /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/execution:32:11: note: in file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/execution:32: 30 | #if __cplusplus >= 201703L 31 | # include 32 | # include | `- note: in file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/execution:32: 33 | 34 | # define _PSTL_EXECUTION_POLICIES_DEFINED 1 /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/pstl/glue_execution_defs.h:50:10: note: in file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/pstl/glue_execution_defs.h:50: 48 | } // namespace std 49 | 50 | #include "algorithm_impl.h" | `- note: in file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/pstl/glue_execution_defs.h:50: 51 | #include "numeric_impl.h" 52 | #include "parallel_backend.h" /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/pstl/algorithm_impl.h:22:10: note: in file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/pstl/algorithm_impl.h:22: 20 | #include "memory_impl.h" 21 | #include "parallel_backend_utils.h" 22 | #include "parallel_backend.h" | `- note: in file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/pstl/algorithm_impl.h:22: 23 | #include "parallel_impl.h" 24 | #include "unseq_backend_simd.h" /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/pstl/parallel_backend.h:20:14: note: in file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/pstl/parallel_backend.h:20: 18 | } 19 | #elif defined(_PSTL_PAR_BACKEND_TBB) 20 | # include "parallel_backend_tbb.h" | `- note: in file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/pstl/parallel_backend.h:20: 21 | namespace __pstl 22 | { /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/pstl/parallel_backend_tbb.h:19:10: note: in file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/pstl/parallel_backend_tbb.h:19: 17 | 18 | // Bring in minimal required subset of Intel TBB 19 | #include | `- note: in file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/pstl/parallel_backend_tbb.h:19: 20 | #include 21 | #include /usr/include/tbb/blocked_range.h:17:10: note: in file included from /usr/include/tbb/blocked_range.h:17: 15 | */ 16 | 17 | #include "../oneapi/tbb/blocked_range.h" | `- note: in file included from /usr/include/tbb/blocked_range.h:17: 18 | /usr/include/tbb/../oneapi/tbb/blocked_range.h:22:10: note: in file included from /usr/include/tbb/../oneapi/tbb/blocked_range.h:22: 20 | #include 21 | 22 | #include "detail/_range_common.h" | `- note: in file included from /usr/include/tbb/../oneapi/tbb/blocked_range.h:22: 23 | #include "detail/_namespace_injection.h" 24 | /usr/include/tbb/../oneapi/tbb/detail/_range_common.h:21:10: note: in file included from /usr/include/tbb/../oneapi/tbb/detail/_range_common.h:21: 19 | 20 | #include "_config.h" 21 | #include "_utils.h" | `- note: in file included from /usr/include/tbb/../oneapi/tbb/detail/_range_common.h:21: 22 | #if __TBB_CPP20_CONCEPTS_PRESENT 23 | #include /usr/include/tbb/../oneapi/tbb/detail/_utils.h:26:10: note: in file included from /usr/include/tbb/../oneapi/tbb/detail/_utils.h:26: 24 | #include "_config.h" 25 | #include "_assert.h" 26 | #include "_machine.h" | `- note: in file included from /usr/include/tbb/../oneapi/tbb/detail/_utils.h:26: 27 | 28 | namespace tbb { /usr/include/tbb/../oneapi/tbb/detail/_machine.h:42:10: error: could not build module '_Builtin_intrinsics' 40 | #endif 41 | #if __TBB_x86_64 || __TBB_x86_32 42 | #include // _mm_pause | `- error: could not build module '_Builtin_intrinsics' 43 | #endif 44 | #if (_WIN32) :1:10: note: in file included from :1: 1 | #include "Lib.h" | `- note: in file included from :1: 2 | /workspace/Lib.h:1:10: error: could not build module 'std' 1 | #include | `- error: could not build module 'std' 2 | 3 | #include /workspace/main.swift:1:8: error: could not build C module 'lib' 1 | import lib | `- error: could not build C module 'lib' 2 | 3 | print("hi") ```

Removing the -Xcc -std=c++17 causes the error to go away, because we are no longer trying to use tbb/execution

Expected behavior

including any C++ standard library header in C++17, C++20, C++23 or C++26 mode should not error out the swift compiler.

The support for <execution> on Linux should either be removed or fixed for Swift 6.0.

Note that this was not an issue in the Ubuntu 20.04 containers, because they only ship libstdc++-10-dev.

Environment

swiftc -version: Swift version 6.0-dev (LLVM d83ae228657c9e1, Swift 038299666d5d822) Target: x86_64-unknown-linux-gnu

docker image list: swiftlang/swift nightly-6.0-jammy dbdffe58b5a0 13 hours ago 3.51GB

Additional information

https://forums.swift.org/t/swift-5-9-release-on-ubuntu-22-04-fails-to-build-std-module/67659/4

egorzhdan commented 2 months ago

I extracted https://github.com/swiftlang/swift/issues/76166 to track the future fix for this. Since this has a workaround and isn't blocking anymore, I am closing this issue.