diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/broken-stdlib-sdk/usr/lib/swift/Bad.swiftinterface b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/broken-stdlib-sdk/usr/lib/swift/Bad.swiftinterface new file mode 100644 index 0000000000000..001bd43893628 --- /dev/null +++ b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/broken-stdlib-sdk/usr/lib/swift/Bad.swiftinterface @@ -0,0 +1,4 @@ +// swift-interface-format-version: 1.0 +// swift-module-flags: + +garbage diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/broken-stdlib-sdk/usr/lib/swift/Good.swiftinterface b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/broken-stdlib-sdk/usr/lib/swift/Good.swiftinterface new file mode 100644 index 0000000000000..49939024691bf --- /dev/null +++ b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/broken-stdlib-sdk/usr/lib/swift/Good.swiftinterface @@ -0,0 +1,2 @@ +// swift-interface-format-version: 1.0 +// swift-module-flags: diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/broken-stdlib-sdk/usr/lib/swift/Swift.swiftinterface b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/broken-stdlib-sdk/usr/lib/swift/Swift.swiftinterface new file mode 100644 index 0000000000000..656039f83073c --- /dev/null +++ b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/broken-stdlib-sdk/usr/lib/swift/Swift.swiftinterface @@ -0,0 +1,4 @@ +// swift-interface-format-version: 1.0 +// swift-module-flags: -parse-stdlib + +garbage diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/iosmac-sdk/MacOSX.sdk/System/Library/Frameworks/FMWK.framework/Modules/FMWK.swiftmodule/x86_64.swiftinterface b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/iosmac-sdk/MacOSX.sdk/System/Library/Frameworks/FMWK.framework/Modules/FMWK.swiftmodule/x86_64.swiftinterface new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/iosmac-sdk/MacOSX.sdk/System/Library/Frameworks/Zippered.framework/Modules/Zippered.swiftmodule/x86_64-apple-ios-macabi.swiftinterface b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/iosmac-sdk/MacOSX.sdk/System/Library/Frameworks/Zippered.framework/Modules/Zippered.swiftmodule/x86_64-apple-ios-macabi.swiftinterface new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/iosmac-sdk/MacOSX.sdk/System/Library/Frameworks/Zippered.framework/Modules/Zippered.swiftmodule/x86_64-apple-macos.swiftinterface b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/iosmac-sdk/MacOSX.sdk/System/Library/Frameworks/Zippered.framework/Modules/Zippered.swiftmodule/x86_64-apple-macos.swiftinterface new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/iosmac-sdk/MacOSX.sdk/System/Library/Frameworks/Zippered.framework/Modules/Zippered.swiftmodule/x86_64.swiftinterface b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/iosmac-sdk/MacOSX.sdk/System/Library/Frameworks/Zippered.framework/Modules/Zippered.swiftmodule/x86_64.swiftinterface new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/iosmac-sdk/MacOSX.sdk/System/iOSSupport/System/Library/Frameworks/FMWK.framework/Modules/FMWK.swiftmodule/x86_64.swiftinterface b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/iosmac-sdk/MacOSX.sdk/System/iOSSupport/System/Library/Frameworks/FMWK.framework/Modules/FMWK.swiftmodule/x86_64.swiftinterface new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/iosmac-sdk/MacOSX.sdk/System/iOSSupport/usr/lib/swift/Foo.swiftmodule/x86_64.swiftinterface b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/iosmac-sdk/MacOSX.sdk/System/iOSSupport/usr/lib/swift/Foo.swiftmodule/x86_64.swiftinterface new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/iosmac-sdk/MacOSX.sdk/usr/lib/swift/Foo.swiftmodule/x86_64.swiftinterface b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/iosmac-sdk/MacOSX.sdk/usr/lib/swift/Foo.swiftmodule/x86_64.swiftinterface new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/mock-sdk/System/Library/Frameworks/BinaryOnly_BAD.framework/Modules/BinaryOnly_BAD.swiftmodule/xyz.swiftmodule b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/mock-sdk/System/Library/Frameworks/BinaryOnly_BAD.framework/Modules/BinaryOnly_BAD.swiftmodule/xyz.swiftmodule new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/mock-sdk/System/Library/Frameworks/FlatInterface_BAD.framework/Modules/FlatInterface_BAD.swiftinterface b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/mock-sdk/System/Library/Frameworks/FlatInterface_BAD.framework/Modules/FlatInterface_BAD.swiftinterface new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/mock-sdk/System/Library/Frameworks/FlatModule_BAD.framework/Modules/FlatModule_BAD.swiftmodule b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/mock-sdk/System/Library/Frameworks/FlatModule_BAD.framework/Modules/FlatModule_BAD.swiftmodule new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/mock-sdk/System/Library/Frameworks/HasNested_BAD.framework/Frameworks/Nested.framework/Modules/Nested.swiftmodule/xyz.swiftinterface b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/mock-sdk/System/Library/Frameworks/HasNested_BAD.framework/Frameworks/Nested.framework/Modules/Nested.swiftmodule/xyz.swiftinterface new file mode 100644 index 0000000000000..a56de7a7b6ab0 --- /dev/null +++ b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/mock-sdk/System/Library/Frameworks/HasNested_BAD.framework/Frameworks/Nested.framework/Modules/Nested.swiftmodule/xyz.swiftinterface @@ -0,0 +1,2 @@ +// swift-interface-format-version: 1.0 +// swift-module-flags: diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/mock-sdk/System/Library/Frameworks/Simple.framework/Modules/Simple.swiftmodule/xyz.swiftinterface b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/mock-sdk/System/Library/Frameworks/Simple.framework/Modules/Simple.swiftmodule/xyz.swiftinterface new file mode 100644 index 0000000000000..a56de7a7b6ab0 --- /dev/null +++ b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/mock-sdk/System/Library/Frameworks/Simple.framework/Modules/Simple.swiftmodule/xyz.swiftinterface @@ -0,0 +1,2 @@ +// swift-interface-format-version: 1.0 +// swift-module-flags: diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/mock-sdk/System/Library/PrivateFrameworks/PrivateSimple.framework/Modules/PrivateSimple.swiftmodule/xyz.swiftinterface b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/mock-sdk/System/Library/PrivateFrameworks/PrivateSimple.framework/Modules/PrivateSimple.swiftmodule/xyz.swiftinterface new file mode 100644 index 0000000000000..a56de7a7b6ab0 --- /dev/null +++ b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/mock-sdk/System/Library/PrivateFrameworks/PrivateSimple.framework/Modules/PrivateSimple.swiftmodule/xyz.swiftinterface @@ -0,0 +1,2 @@ +// swift-interface-format-version: 1.0 +// swift-module-flags: diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/mock-sdk/System/iOSSupport/System/Library/Frameworks/Simple.framework/Modules/Simple.swiftmodule/xyzzy.swiftinterface b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/mock-sdk/System/iOSSupport/System/Library/Frameworks/Simple.framework/Modules/Simple.swiftmodule/xyzzy.swiftinterface new file mode 100644 index 0000000000000..a56de7a7b6ab0 --- /dev/null +++ b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/mock-sdk/System/iOSSupport/System/Library/Frameworks/Simple.framework/Modules/Simple.swiftmodule/xyzzy.swiftinterface @@ -0,0 +1,2 @@ +// swift-interface-format-version: 1.0 +// swift-module-flags: diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/mock-sdk/System/iOSSupport/usr/lib/swift/Caramel.swiftmodule/xyz.swiftinterface b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/mock-sdk/System/iOSSupport/usr/lib/swift/Caramel.swiftmodule/xyz.swiftinterface new file mode 100644 index 0000000000000..a56de7a7b6ab0 --- /dev/null +++ b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/mock-sdk/System/iOSSupport/usr/lib/swift/Caramel.swiftmodule/xyz.swiftinterface @@ -0,0 +1,2 @@ +// swift-interface-format-version: 1.0 +// swift-module-flags: diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/mock-sdk/usr/lib/swift/Flat.swiftinterface b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/mock-sdk/usr/lib/swift/Flat.swiftinterface new file mode 100644 index 0000000000000..a56de7a7b6ab0 --- /dev/null +++ b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/mock-sdk/usr/lib/swift/Flat.swiftinterface @@ -0,0 +1,2 @@ +// swift-interface-format-version: 1.0 +// swift-module-flags: diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/mock-sdk/usr/lib/swift/Normal.swiftmodule/xyz.swiftinterface b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/mock-sdk/usr/lib/swift/Normal.swiftmodule/xyz.swiftinterface new file mode 100644 index 0000000000000..a56de7a7b6ab0 --- /dev/null +++ b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/mock-sdk/usr/lib/swift/Normal.swiftmodule/xyz.swiftinterface @@ -0,0 +1,2 @@ +// swift-interface-format-version: 1.0 +// swift-module-flags: diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/system-dependencies-sdk/usr/include/Platform.h b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/system-dependencies-sdk/usr/include/Platform.h new file mode 100644 index 0000000000000..07b56a9019469 --- /dev/null +++ b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/system-dependencies-sdk/usr/include/Platform.h @@ -0,0 +1,3 @@ +struct SomeCStruct { + int value; +}; diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/system-dependencies-sdk/usr/include/module.modulemap b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/system-dependencies-sdk/usr/include/module.modulemap new file mode 100644 index 0000000000000..8bd4c4bdec892 --- /dev/null +++ b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/system-dependencies-sdk/usr/include/module.modulemap @@ -0,0 +1,4 @@ +module Platform { + header "Platform.h" + export * +} diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/system-dependencies-sdk/usr/lib/swift/Swifty.swiftmodule/dummy-file-so-git-includes-this-otherwise-empty-directory b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/system-dependencies-sdk/usr/lib/swift/Swifty.swiftmodule/dummy-file-so-git-includes-this-otherwise-empty-directory new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/xfail-logs-framework/BadFMWK.framework/Modules/BadFMWK.swiftmodule/x86_64-apple-macos.swiftinterface b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/xfail-logs-framework/BadFMWK.framework/Modules/BadFMWK.swiftmodule/x86_64-apple-macos.swiftinterface new file mode 100644 index 0000000000000..001bd43893628 --- /dev/null +++ b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/xfail-logs-framework/BadFMWK.framework/Modules/BadFMWK.swiftmodule/x86_64-apple-macos.swiftinterface @@ -0,0 +1,4 @@ +// swift-interface-format-version: 1.0 +// swift-module-flags: + +garbage diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/xfails-sdk/usr/lib/swift/Bad.swiftinterface b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/xfails-sdk/usr/lib/swift/Bad.swiftinterface new file mode 100644 index 0000000000000..001bd43893628 --- /dev/null +++ b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/xfails-sdk/usr/lib/swift/Bad.swiftinterface @@ -0,0 +1,4 @@ +// swift-interface-format-version: 1.0 +// swift-module-flags: + +garbage diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/xfails-sdk/usr/lib/swift/Good.swiftinterface b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/xfails-sdk/usr/lib/swift/Good.swiftinterface new file mode 100644 index 0000000000000..49939024691bf --- /dev/null +++ b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/xfails-sdk/usr/lib/swift/Good.swiftinterface @@ -0,0 +1,2 @@ +// swift-interface-format-version: 1.0 +// swift-module-flags: diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/xfails-sdk/usr/lib/swift/Swift.swiftinterface b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/xfails-sdk/usr/lib/swift/Swift.swiftinterface new file mode 100644 index 0000000000000..854d6ebe051b7 --- /dev/null +++ b/test/ParseableInterface/swift_build_sdk_interfaces/Inputs/xfails-sdk/usr/lib/swift/Swift.swiftinterface @@ -0,0 +1,2 @@ +// swift-interface-format-version: 1.0 +// swift-module-flags: -parse-stdlib diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/check-only-mode.swift b/test/ParseableInterface/swift_build_sdk_interfaces/check-only-mode.swift new file mode 100644 index 0000000000000..981242997c7a7 --- /dev/null +++ b/test/ParseableInterface/swift_build_sdk_interfaces/check-only-mode.swift @@ -0,0 +1,33 @@ +// RUN: %empty-directory(%t) +// RUN: mkdir -p %t/sdk/usr/lib/swift/Normal.swiftmodule +// RUN: mkdir -p %t/sdk/System/Library/Frameworks/FMWK.framework/Modules/FMWK.swiftmodule + +// RUN: echo 'public func normal() {}' | %target-swift-frontend - -emit-parseable-module-interface-path %t/sdk/usr/lib/swift/Normal.swiftmodule/$(basename %target-swiftmodule-name .swiftmodule).swiftinterface -emit-module -o /dev/null -module-name Normal +// RUN: echo 'public func flat() {}' | %target-swift-frontend - -emit-parseable-module-interface-path %t/sdk/usr/lib/swift/Flat.swiftinterface -emit-module -o /dev/null -module-name Flat +// RUN: echo 'public func fmwk() {}' | %target-swift-frontend - -emit-parseable-module-interface-path %t/sdk/System/Library/Frameworks/FMWK.framework/Modules/FMWK.swiftmodule/$(basename %target-swiftmodule-name .swiftmodule).swiftinterface -emit-module -o /dev/null -module-name FMWK + +// RUN: %swift_build_sdk_interfaces -sdk %t/sdk -Fsystem %t/sdk/System/Library/Frameworks -v -o %t/prebuilt -check-only +// RUN: ls %t/prebuilt | %FileCheck %s +// CHECK-DAG: Normal.swiftmodule +// CHECK-DAG: Flat.swiftmodule +// CHECK-DAG: FMWK.swiftmodule + +// RUN: %target-typecheck-verify-swift -sdk %t/sdk -Fsystem %t/sdk/System/Library/Frameworks -I %t/sdk/usr/lib/swift/ -module-cache-path %t/MCP -prebuilt-module-cache-path %t/prebuilt +// RUN: %{python} %S/../ModuleCache/Inputs/check-is-forwarding-module.py %t/MCP/*.swiftmodule + +// Touch a file in the SDK (to make it look like it changed) and try again. +// In -check-only mode, this should force a rebuild. +// RUN: rm -rf %t/MCP +// RUN: %S/../ModuleCache/Inputs/make-old.py %t/sdk/usr/lib/swift/Normal.swiftmodule/$(basename %target-swiftmodule-name .swiftmodule).swiftinterface +// RUN: %target-typecheck-verify-swift -sdk %t/sdk -Fsystem %t/sdk/System/Library/Frameworks -I %t/sdk/usr/lib/swift/ -module-cache-path %t/MCP -prebuilt-module-cache-path %t/prebuilt +// RUN: not %{python} %S/../ModuleCache/Inputs/check-is-forwarding-module.py %t/MCP/Normal-*.swiftmodule + +import Normal +import Flat +import FMWK + +func test() { + normal() + flat() + fmwk() +} diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/compiler-crash.test-sh b/test/ParseableInterface/swift_build_sdk_interfaces/compiler-crash.test-sh new file mode 100644 index 0000000000000..8b7f48b97f6ec --- /dev/null +++ b/test/ParseableInterface/swift_build_sdk_interfaces/compiler-crash.test-sh @@ -0,0 +1,7 @@ +RUN: not %swift_build_sdk_interfaces -sdk %S/Inputs/mock-sdk/ -o %t/output -debug-crash-compiler 2>&1 | %FileCheck %s + +CHECK: Program arguments: +CHECK-SAME: -debug-crash-immediately +CHECK-SAME: {{.+}}.swiftinterface + +REQUIRES: asserts diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/compiler-uses-prebuilt.swift b/test/ParseableInterface/swift_build_sdk_interfaces/compiler-uses-prebuilt.swift new file mode 100644 index 0000000000000..8f1a424dd0eae --- /dev/null +++ b/test/ParseableInterface/swift_build_sdk_interfaces/compiler-uses-prebuilt.swift @@ -0,0 +1,59 @@ +// RUN: %empty-directory(%t) +// RUN: mkdir -p %t/sdk/usr/lib/swift/Normal.swiftmodule +// RUN: mkdir -p %t/sdk/System/Library/Frameworks/FMWK.framework/Modules/FMWK.swiftmodule + +// RUN: echo 'public func normal() {}' | %target-swift-frontend - -emit-parseable-module-interface-path %t/sdk/usr/lib/swift/Normal.swiftmodule/$(basename %target-swiftmodule-name .swiftmodule).swiftinterface -emit-module -o /dev/null -module-name Normal +// RUN: echo 'public func flat() {}' | %target-swift-frontend - -emit-parseable-module-interface-path %t/sdk/usr/lib/swift/Flat.swiftinterface -emit-module -o /dev/null -module-name Flat +// RUN: echo 'public func fmwk() {}' | %target-swift-frontend - -emit-parseable-module-interface-path %t/sdk/System/Library/Frameworks/FMWK.framework/Modules/FMWK.swiftmodule/$(basename %target-swiftmodule-name .swiftmodule).swiftinterface -emit-module -o /dev/null -module-name FMWK + +// RUN: %swift_build_sdk_interfaces -sdk %t/sdk -Fsystem %t/sdk/System/Library/Frameworks -v -o %t/prebuilt +// RUN: ls %t/prebuilt | %FileCheck %s +// CHECK-DAG: Normal.swiftmodule +// CHECK-DAG: Flat.swiftmodule +// CHECK-DAG: FMWK.swiftmodule + +// RUN: %target-typecheck-verify-swift -sdk %t/sdk -Fsystem %t/sdk/System/Library/Frameworks -I %t/sdk/usr/lib/swift/ -module-cache-path %t/MCP -prebuilt-module-cache-path %t/prebuilt +// RUN: %{python} %S/../ModuleCache/Inputs/check-is-forwarding-module.py %t/MCP/*.swiftmodule + +// Touch a file in the SDK (to make it look like it changed) and try again. +// This should still be able to use the prebuilt modules because they track +// content hashes, not just size+mtime. +// RUN: rm -rf %t/MCP +// RUN: %S/../ModuleCache/Inputs/make-old.py %t/sdk/usr/lib/swift/Normal.swiftmodule/$(basename %target-swiftmodule-name .swiftmodule).swiftinterface +// RUN: %target-typecheck-verify-swift -sdk %t/sdk -Fsystem %t/sdk/System/Library/Frameworks -I %t/sdk/usr/lib/swift/ -module-cache-path %t/MCP -prebuilt-module-cache-path %t/prebuilt +// RUN: ls %t/MCP/*.swiftmodule | %FileCheck -check-prefix CHECK-CACHE %s +// RUN: %{python} %S/../ModuleCache/Inputs/check-is-forwarding-module.py %t/MCP/*.swiftmodule + +// CHECK-CACHE-DAG: Normal-{{.+}}.swiftmodule +// CHECK-CACHE-DAG: Flat-{{.+}}.swiftmodule +// CHECK-CACHE-DAG: FMWK-{{.+}}.swiftmodule + +// Actually change a file in the SDK, to check that we're tracking dependencies +// at all. +// RUN: rm -rf %t/MCP +// RUN: echo "public func another()" >> %t/sdk/usr/lib/swift/Normal.swiftmodule/$(basename %target-swiftmodule-name .swiftmodule).swiftinterface +// RUN: %target-typecheck-verify-swift -sdk %t/sdk -Fsystem %t/sdk/System/Library/Frameworks -I %t/sdk/usr/lib/swift/ -module-cache-path %t/MCP -prebuilt-module-cache-path %t/prebuilt +// RUN: ls %t/MCP/*.swiftmodule | %FileCheck -check-prefix CHECK-CACHE %s +// RUN: not %{python} %S/../ModuleCache/Inputs/check-is-forwarding-module.py %t/MCP/Normal-*.swiftmodule +// RUN: %{python} %S/../ModuleCache/Inputs/check-is-forwarding-module.py %t/MCP/Flat-*.swiftmodule +// RUN: %{python} %S/../ModuleCache/Inputs/check-is-forwarding-module.py %t/MCP/FMWK-*.swiftmodule + +// Without the prebuilt cache everything should still work; it'll just take time +// because we have to build the interfaces. +// RUN: rm -rf %t/MCP +// RUN: %target-typecheck-verify-swift -sdk %t/sdk -Fsystem %t/sdk/System/Library/Frameworks -I %t/sdk/usr/lib/swift/ -module-cache-path %t/MCP +// RUN: ls %t/MCP/*.swiftmodule | %FileCheck -check-prefix CHECK-CACHE %s +// RUN: not %{python} %S/../ModuleCache/Inputs/check-is-forwarding-module.py %t/MCP/Normal-*.swiftmodule +// RUN: not %{python} %S/../ModuleCache/Inputs/check-is-forwarding-module.py %t/MCP/Flat-*.swiftmodule +// RUN: not %{python} %S/../ModuleCache/Inputs/check-is-forwarding-module.py %t/MCP/FMWK-*.swiftmodule + + +import Normal +import Flat +import FMWK + +func test() { + normal() + flat() + fmwk() +} diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/early-exits.test-sh b/test/ParseableInterface/swift_build_sdk_interfaces/early-exits.test-sh new file mode 100644 index 0000000000000..bf9f8ced03b7a --- /dev/null +++ b/test/ParseableInterface/swift_build_sdk_interfaces/early-exits.test-sh @@ -0,0 +1,8 @@ +RUN: not %swift_build_sdk_interfaces 2>&1 | %FileCheck -check-prefix NO-OUTPUT %s +NO-OUTPUT: argument -o is required + +RUN: not env -u SDKROOT %swift_build_sdk_interfaces -o %t 2>&1 | %FileCheck -check-prefix NO-SDK %s +NO-SDK: SDKROOT must be set + +RUN: not %swift_build_sdk_interfaces -o %t -sdk %S/nonexistent 2>&1 | %FileCheck -check-prefix BAD-SDK %s +BAD-SDK: invalid SDK: {{.+[/\\]nonexistent$}} diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/find-modules.test-sh b/test/ParseableInterface/swift_build_sdk_interfaces/find-modules.test-sh new file mode 100644 index 0000000000000..4e79d753dbb81 --- /dev/null +++ b/test/ParseableInterface/swift_build_sdk_interfaces/find-modules.test-sh @@ -0,0 +1,54 @@ +RUN: %swift_build_sdk_interfaces -sdk %S/Inputs/mock-sdk/ -v -n -o %t/output > %t.txt +RUN: %FileCheck %s < %t.txt +RUN: %FileCheck -check-prefix NEGATIVE %s < %t.txt + +CHECK-DAG: System/Library/Frameworks/Simple.framework/Modules/Simple.swiftmodule/xyz.swiftinterface -o {{.+}}output/Simple.swiftmodule/xyz.swiftmodule +CHECK-DAG: usr/lib/swift/Flat.swiftinterface -o {{.+}}output/Flat.swiftmodule +CHECK-DAG: usr/lib/swift/Normal.swiftmodule/xyz.swiftinterface -o {{.+}}output/Normal.swiftmodule/xyz.swiftmodule +CHECK-DAG: System/iOSSupport/System/Library/Frameworks/Simple.framework/Modules/Simple.swiftmodule/xyzzy.swiftinterface -o {{.+}}output/Simple.swiftmodule/xyzzy.swiftmodule +CHECK-DAG: System/iOSSupport/usr/lib/swift/Caramel.swiftmodule/xyz.swiftinterface -o {{.+}}output/Caramel.swiftmodule/xyz.swiftmodule + +NEGATIVE-NOT: BAD + +RUN: env SDKROOT=%S/Inputs/mock-sdk/ %swift_build_sdk_interfaces -v -n -o %t/output > %t.txt +RUN: %FileCheck %s < %t.txt +RUN: %FileCheck -check-prefix NEGATIVE %s < %t.txt + +# Make sure the stdlib is processed first. +RUN: %empty-directory(%t) +RUN: cp -r %S/Inputs/mock-sdk %t/sdk +RUN: mkdir %t/sdk/usr/lib/swift/Swift.swiftmodule +RUN: touch %t/sdk/usr/lib/swift/Swift.swiftmodule/abc.swiftinterface +RUN: touch %t/sdk/usr/lib/swift/Swift.swiftmodule/def.swiftinterface +RUN: %swift_build_sdk_interfaces -sdk %t/sdk -v -n -o %t/output | %FileCheck -check-prefix CHECK-WITH-STDLIB %s + +CHECK-WITH-STDLIB-NOT: .swiftinterface -o +CHECK-WITH-STDLIB: Swift.swiftmodule/{{abc|def}}.swiftinterface -o +CHECK-WITH-STDLIB-NOT: .swiftinterface -o +CHECK-WITH-STDLIB: Swift.swiftmodule/{{abc|def}}.swiftinterface -o +CHECK-WITH-STDLIB: .swiftinterface -o + +# ...unless we pass -skip-stdlib. +RUN: %swift_build_sdk_interfaces -sdk %t/sdk -v -n -o %t/output -skip-stdlib > %t.txt +RUN: %FileCheck -check-prefix CHECK-SKIP-STDLIB %s < %t.txt +RUN: %FileCheck -check-prefix NEGATIVE-SKIP-STDLIB %s < %t.txt + +CHECK-SKIP-STDLIB: .swiftinterface -o +NEGATIVE-SKIP-STDLIB-NOT: Swift.swiftmodule + +# Check custom searching based on positional arguments. +RUN: %swift_build_sdk_interfaces -sdk %S/Inputs/mock-sdk/ -v -n -o %t/output System/Library/PrivateFrameworks > %t.txt +RUN: %FileCheck -check-prefix CHECK-CUSTOM-PATHS %s < %t.txt +RUN: %FileCheck -check-prefix NEGATIVE-CUSTOM-PATHS %s < %t.txt + +CHECK-CUSTOM-PATHS-DAG: System/Library/PrivateFrameworks/PrivateSimple.framework/Modules/PrivateSimple.swiftmodule/xyz.swiftinterface -o {{.+}}output/PrivateSimple.swiftmodule/xyz.swiftmodule +CHECK-CUSTOM-PATHS-DAG: usr/lib/swift/Flat.swiftinterface -o {{.+}}output/Flat.swiftmodule +CHECK-CUSTOM-PATHS-DAG: usr/lib/swift/Normal.swiftmodule/xyz.swiftinterface -o {{.+}}output/Normal.swiftmodule/xyz.swiftmodule +CHECK-CUSTOM-PATHS-DAG: System/iOSSupport/usr/lib/swift/Caramel.swiftmodule/xyz.swiftinterface -o {{.+}}output/Caramel.swiftmodule/xyz.swiftmodule +NEGATIVE-CUSTOM-PATHS-NOT: System/Library/Frameworks/ + +RUN: %swift_build_sdk_interfaces -sdk %S/Inputs/mock-sdk/ -v -n -o %t/output System/Library/Frameworks System/Library/PrivateFrameworks > %t.txt +RUN: %FileCheck -check-prefix CHECK-CUSTOM-PATHS -check-prefix CHECK-NORMAL-PATHS %s < %t.txt +RUN: %FileCheck -check-prefix NEGATIVE %s < %t.txt + +CHECK-NORMAL-PATHS-DAG: System/Library/Frameworks/Simple.framework/Modules/Simple.swiftmodule/xyz.swiftinterface -o {{.+}}output/Simple.swiftmodule/xyz.swiftmodule diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/ignore-non-stdlib-failures.test-sh b/test/ParseableInterface/swift_build_sdk_interfaces/ignore-non-stdlib-failures.test-sh new file mode 100644 index 0000000000000..622542977e911 --- /dev/null +++ b/test/ParseableInterface/swift_build_sdk_interfaces/ignore-non-stdlib-failures.test-sh @@ -0,0 +1,18 @@ +RUN: not %swift_build_sdk_interfaces -sdk %S/Inputs/xfails-sdk/ -v -o %t/output | %FileCheck %s + +CHECK-DAG: # (FAIL) {{.+}}/Bad.swiftinterface +CHECK-DAG: # (PASS) {{.+}}/Good.swiftinterface + +RUN: %swift_build_sdk_interfaces -sdk %S/Inputs/xfails-sdk/ -v -o %t/output -ignore-non-stdlib-failures | %FileCheck -check-prefix=CHECK-IGNORING-FAILURES %s + +CHECK-IGNORING-FAILURES-DAG: # (XFAIL) {{.+}}/Bad.swiftinterface +CHECK-IGNORING-FAILURES-DAG: # (UPASS) {{.+}}/Good.swiftinterface + +RUN: not %swift_build_sdk_interfaces -sdk %S/Inputs/broken-stdlib-sdk/ -v -o %t/output | %FileCheck -check-prefix CHECK-BROKEN-STDLIB %s +RUN: not %swift_build_sdk_interfaces -sdk %S/Inputs/broken-stdlib-sdk/ -v -o %t/output -ignore-non-stdlib-failures | %FileCheck -check-prefix CHECK-BROKEN-STDLIB %s + +CHECK-BROKEN-STDLIB: # (FAIL) {{.+}}/Swift.swiftinterface +CHECK-BROKEN-STDLIB-NOT: {{^}}# + +RUN: not %swift_build_sdk_interfaces -sdk %S/Inputs/broken-stdlib-sdk/ -v -o %t/output -skip-stdlib | %FileCheck %s +RUN: %swift_build_sdk_interfaces -sdk %S/Inputs/broken-stdlib-sdk/ -v -o %t/output -skip-stdlib -ignore-non-stdlib-failures | %FileCheck -check-prefix=CHECK-IGNORING-FAILURES %s diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/iosmac.test-sh b/test/ParseableInterface/swift_build_sdk_interfaces/iosmac.test-sh new file mode 100644 index 0000000000000..f33c75ea1f06e --- /dev/null +++ b/test/ParseableInterface/swift_build_sdk_interfaces/iosmac.test-sh @@ -0,0 +1,14 @@ +RUN: %swift_build_sdk_interfaces -sdk %S/Inputs/iosmac-sdk/MacOSX.sdk/ -Fsystem-iosmac SECRET_SEARCH_PATH -v -n -o %t/output > %t.txt +RUN: %FileCheck %s < %t.txt +RUN: %FileCheck -check-prefix NEGATIVE %s < %t.txt + +CHECK-DAG: MacOSX.sdk/System/Library/Frameworks/FMWK.framework/Modules/FMWK.swiftmodule/x86_64.swiftinterface -o {{.+}}/output/FMWK.swiftmodule/x86_64-apple-macos.swiftmodule +CHECK-DAG: -Fsystem SECRET_SEARCH_PATH -Fsystem {{.+}}MacOSX.sdk/System/iOSSupport/System/Library/Frameworks {{.+}}MacOSX.sdk/System/iOSSupport/System/Library/Frameworks/FMWK.framework/Modules/FMWK.swiftmodule/x86_64.swiftinterface -o {{.+}}/output/FMWK.swiftmodule/x86_64-apple-ios-macabi.swiftmodule +CHECK-DAG: MacOSX.sdk/usr/lib/swift/Foo.swiftmodule/x86_64.swiftinterface -o {{.+}}output/Foo.swiftmodule/x86_64-apple-macos.swiftmodule +CHECK-DAG: -Fsystem SECRET_SEARCH_PATH -Fsystem {{.+}}MacOSX.sdk/System/iOSSupport/System/Library/Frameworks {{.+}}MacOSX.sdk/System/iOSSupport/usr/lib/swift/Foo.swiftmodule/x86_64.swiftinterface -o {{.+}}output/Foo.swiftmodule/x86_64-apple-ios-macabi.swiftmodule +CHECK-DAG: MacOSX.sdk/System/Library/Frameworks/Zippered.framework/Modules/Zippered.swiftmodule/x86_64.swiftinterface -o {{.+}}/output/Zippered.swiftmodule/x86_64-apple-macos.swiftmodule +CHECK-DAG: MacOSX.sdk/System/Library/Frameworks/Zippered.framework/Modules/Zippered.swiftmodule/x86_64-apple-macos.swiftinterface -o {{.+}}/output/Zippered.swiftmodule/x86_64-apple-macos.swiftmodule +CHECK-DAG: -Fsystem SECRET_SEARCH_PATH -Fsystem {{.+}}MacOSX.sdk/System/iOSSupport/System/Library/Frameworks {{.+}}MacOSX.sdk/System/Library/Frameworks/Zippered.framework/Modules/Zippered.swiftmodule/x86_64-apple-ios-macabi.swiftinterface -o {{.+}}/output/Zippered.swiftmodule/x86_64-apple-ios-macabi.swiftmodule + +NEGATIVE-NOT: iOSSupport{{.+}}{{macos|x86_64}}.swiftmodule +NEGATIVE-NOT: SECRET_SEARCH_PATH{{.+}}{{macos|x86_64}}.swiftmodule diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/lit.local.cfg b/test/ParseableInterface/swift_build_sdk_interfaces/lit.local.cfg new file mode 100644 index 0000000000000..1efcf05e864dd --- /dev/null +++ b/test/ParseableInterface/swift_build_sdk_interfaces/lit.local.cfg @@ -0,0 +1,11 @@ +# Make a local copy of the substitutions. +config.substitutions = list(config.substitutions) + +swift_build_sdk_interfaces = (r'env SWIFT_EXEC=%%swiftc_driver_plain %r ' + r'%%utils/swift_build_sdk_interfaces.py ' + r'%%mcp_opt' % + (sys.executable,)) +config.substitutions.insert(0, ('%swift_build_sdk_interfaces', + swift_build_sdk_interfaces)) + +config.suffixes.add('.py') diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/machine-parseable-monotonic-version.py b/test/ParseableInterface/swift_build_sdk_interfaces/machine-parseable-monotonic-version.py new file mode 100644 index 0000000000000..7eb37a11810de --- /dev/null +++ b/test/ParseableInterface/swift_build_sdk_interfaces/machine-parseable-monotonic-version.py @@ -0,0 +1,8 @@ +# RUN: %swift_build_sdk_interfaces -machine-parseable-monotonic-version | \ +# RUN: %{python} %s + +import sys + +lines = list(sys.stdin) +assert len(lines) == 1 +assert int(lines[0]) > 0 diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/track-system-dependencies.swift b/test/ParseableInterface/swift_build_sdk_interfaces/track-system-dependencies.swift new file mode 100644 index 0000000000000..d5cb814a1d322 --- /dev/null +++ b/test/ParseableInterface/swift_build_sdk_interfaces/track-system-dependencies.swift @@ -0,0 +1,35 @@ +// RUN: %empty-directory(%t) +// RUN: cp -r %S/Inputs/system-dependencies-sdk %t/sdk +// RUN: echo 'import Platform; public func usesCStruct(_: SomeCStruct?) {}' | %target-swift-frontend - -emit-parseable-module-interface-path %t/sdk/usr/lib/swift/Swifty.swiftmodule/$(basename %target-swiftmodule-name .swiftmodule).swiftinterface -emit-module -o /dev/null -module-name Swifty -sdk %t/sdk + +// RUN: %swift_build_sdk_interfaces -sdk %t/sdk -v -o %t/prebuilt +// RUN: ls %t/prebuilt | %FileCheck %s +// CHECK: Swifty.swiftmodule + +// RUN: %target-typecheck-verify-swift -sdk %t/sdk -I %t/sdk/usr/lib/swift/ -module-cache-path %t/MCP -prebuilt-module-cache-path %t/prebuilt +// RUN: %{python} %S/../ModuleCache/Inputs/check-is-forwarding-module.py %t/MCP/*.swiftmodule + +// Touch a file in the SDK (to make it look like it changed) and try again. +// This should still be able to use the prebuilt modules because they track +// content hashes, not just size+mtime. +// RUN: rm -rf %t/MCP +// RUN: %S/../ModuleCache/Inputs/make-old.py %t/sdk/usr/include/Platform.h +// RUN: %target-typecheck-verify-swift -sdk %t/sdk -I %t/sdk/usr/lib/swift/ -module-cache-path %t/MCP -prebuilt-module-cache-path %t/prebuilt +// RUN: %{python} %S/../ModuleCache/Inputs/check-is-forwarding-module.py %t/MCP/Swifty-*.swiftmodule + +// Actually change a file in the SDK, to check that we're tracking dependencies +// at all. +// RUN: rm -rf %t/MCP +// RUN: echo "void unrelated();" >> %t/sdk/usr/include/Platform.h +// RUN: %target-typecheck-verify-swift -sdk %t/sdk -I %t/sdk/usr/lib/swift/ -module-cache-path %t/MCP -prebuilt-module-cache-path %t/prebuilt +// RUN: not %{python} %S/../ModuleCache/Inputs/check-is-forwarding-module.py %t/MCP/Swifty-*.swiftmodule + +// Without the prebuilt cache everything should still work; it'll just take time +// because we have to build the interfaces. +// RUN: rm -rf %t/MCP +// RUN: %target-typecheck-verify-swift -sdk %t/sdk -I %t/sdk/usr/lib/swift/ -module-cache-path %t/MCP +// RUN: not %{python} %S/../ModuleCache/Inputs/check-is-forwarding-module.py %t/MCP/Swifty-*.swiftmodule + +import Swifty + +usesCStruct(nil) diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/xfail-logs.test-sh b/test/ParseableInterface/swift_build_sdk_interfaces/xfail-logs.test-sh new file mode 100644 index 0000000000000..ef5608793f519 --- /dev/null +++ b/test/ParseableInterface/swift_build_sdk_interfaces/xfail-logs.test-sh @@ -0,0 +1,36 @@ +RUN: %empty-directory(%t) +RUN: not %swift_build_sdk_interfaces -sdk %S/Inputs/xfails-sdk/ -o %t/output -log-path %t/logs | %FileCheck %s +RUN: %FileCheck -check-prefix PRINTS-ERROR %s < %t/logs/Bad-Bad-err.txt + +CHECK: # (FAIL) {{.+}}/Bad.swiftinterface + +PRINTS-ERROR: unresolved identifier 'garbage' + +RUN: %empty-directory(%t) +RUN: echo '["Good"]' > %t/xfails-good.json +RUN: not %swift_build_sdk_interfaces -sdk %S/Inputs/xfails-sdk/ -o %t/output -log-path %t/logs -xfails %t/xfails-good.json | %FileCheck -check-prefix=CHECK-XFAIL-GOOD %s +RUN: %FileCheck -check-prefix PRINTS-ERROR %s < %t/logs/Bad-Bad-err.txt + +CHECK-XFAIL-GOOD-DAG: # (FAIL) {{.+}}/Bad.swiftinterface +CHECK-XFAIL-GOOD-DAG: # (UPASS) {{.+}}/Good.swiftinterface + +RUN: %empty-directory(%t) +RUN: echo '["Good", "Bad"]' > %t/xfails-good-and-bad.json +RUN: %swift_build_sdk_interfaces -sdk %S/Inputs/xfails-sdk/ -o %t/output -log-path %t/logs -xfails %t/xfails-good-and-bad.json| %FileCheck -check-prefix=CHECK-XFAIL-GOOD-AND-BAD %s +RUN: %FileCheck -check-prefix PRINTS-ERROR %s < %t/logs/Bad-Bad-err.txt + +CHECK-XFAIL-GOOD-AND-BAD-DAG: # (XFAIL) {{.+}}/Bad.swiftinterface +CHECK-XFAIL-GOOD-AND-BAD-DAG: # (UPASS) {{.+}}/Good.swiftinterface + +RUN: %empty-directory(%t) +RUN: echo '["Bad"]' > %t/xfails-bad.json +RUN: %swift_build_sdk_interfaces -sdk %S/Inputs/xfails-sdk/ -o %t/output -log-path %t/logs -xfails %t/xfails-bad.json | %FileCheck -check-prefix=CHECK-XFAIL-BAD %s +RUN: %FileCheck -check-prefix PRINTS-ERROR %s < %t/logs/Bad-Bad-err.txt + +CHECK-XFAIL-BAD: # (XFAIL) {{.+}}/Bad.swiftinterface + +RUN: %empty-directory(%t) +RUN: not %swift_build_sdk_interfaces -sdk %t -o %t/output -log-path %t/logs %S/Inputs/xfail-logs-framework/ | %FileCheck -check-prefix=CHECK-FRAMEWORK %s +RUN: %FileCheck -check-prefix PRINTS-ERROR %s < %t/logs/BadFMWK-x86_64-apple-macos-err.txt + +CHECK-FRAMEWORK: # (FAIL) {{.+}}/BadFMWK.swiftmodule/x86_64-apple-macos.swiftinterface diff --git a/test/ParseableInterface/swift_build_sdk_interfaces/xfails.test-sh b/test/ParseableInterface/swift_build_sdk_interfaces/xfails.test-sh new file mode 100644 index 0000000000000..ee76775680eff --- /dev/null +++ b/test/ParseableInterface/swift_build_sdk_interfaces/xfails.test-sh @@ -0,0 +1,43 @@ +RUN: %empty-directory(%t) +RUN: not %swift_build_sdk_interfaces -sdk %S/Inputs/xfails-sdk/ -o %t/output 2> %t/stderr.txt | %FileCheck %s +RUN: %FileCheck -check-prefix PRINTS-ERROR %s < %t/stderr.txt +RUN: not %swift_build_sdk_interfaces -sdk %S/Inputs/xfails-sdk/ -v -o %t/output 2> %t/stderr.txt | %FileCheck -check-prefix CHECK-VERBOSE %s +RUN: %FileCheck -check-prefix PRINTS-ERROR %s < %t/stderr.txt + +CHECK: # (FAIL) {{.+}}/Bad.swiftinterface +CHECK-VERBOSE-DAG: # (FAIL) {{.+}}/Bad.swiftinterface +CHECK-VERBOSE-DAG: # (PASS) {{.+}}/Good.swiftinterface + +PRINTS-ERROR: unresolved identifier 'garbage' +HIDES-ERROR-NOT: unresolved identifier 'garbage' + +RUN: %empty-directory(%t) +RUN: echo '["Good"]' > %t/xfails-good.json +RUN: not %swift_build_sdk_interfaces -sdk %S/Inputs/xfails-sdk/ -o %t/output -xfails %t/xfails-good.json 2> %t/stderr.txt | %FileCheck -check-prefix=CHECK-XFAIL-GOOD %s +RUN: %FileCheck -check-prefix PRINTS-ERROR %s < %t/stderr.txt +RUN: not %swift_build_sdk_interfaces -sdk %S/Inputs/xfails-sdk/ -v -o %t/output -xfails %t/xfails-good.json 2> %t/stderr.txt | %FileCheck -check-prefix=CHECK-XFAIL-GOOD %s +RUN: %FileCheck -check-prefix PRINTS-ERROR %s < %t/stderr.txt + +CHECK-XFAIL-GOOD-DAG: # (FAIL) {{.+}}/Bad.swiftinterface +CHECK-XFAIL-GOOD-DAG: # (UPASS) {{.+}}/Good.swiftinterface + +RUN: %empty-directory(%t) +RUN: echo '["Good", "Bad"]' > %t/xfails-good-and-bad.json +RUN: %swift_build_sdk_interfaces -sdk %S/Inputs/xfails-sdk/ -o %t/output -xfails %t/xfails-good-and-bad.json 2> %t/stderr.txt | %FileCheck -check-prefix=CHECK-XFAIL-GOOD-AND-BAD %s +RUN: %FileCheck -check-prefix HIDES-ERROR -allow-empty %s < %t/stderr.txt +RUN: %swift_build_sdk_interfaces -sdk %S/Inputs/xfails-sdk/ -v -o %t/output -xfails %t/xfails-good-and-bad.json 2> %t/stderr.txt | %FileCheck -check-prefix=CHECK-XFAIL-GOOD-AND-BAD %s +RUN: %FileCheck -check-prefix PRINTS-ERROR %s < %t/stderr.txt + +CHECK-XFAIL-GOOD-AND-BAD-DAG: # (XFAIL) {{.+}}/Bad.swiftinterface +CHECK-XFAIL-GOOD-AND-BAD-DAG: # (UPASS) {{.+}}/Good.swiftinterface + +RUN: %empty-directory(%t) +RUN: echo '["Bad"]' > %t/xfails-bad.json +RUN: %swift_build_sdk_interfaces -sdk %S/Inputs/xfails-sdk/ -o %t/output -xfails %t/xfails-bad.json 2> %t/stderr.txt | %FileCheck -check-prefix=CHECK-XFAIL-BAD %s +RUN: %FileCheck -check-prefix HIDES-ERROR -allow-empty %s < %t/stderr.txt +RUN: %swift_build_sdk_interfaces -sdk %S/Inputs/xfails-sdk/ -v -o %t/output -xfails %t/xfails-bad.json 2> %t/stderr.txt | %FileCheck -check-prefix=CHECK-XFAIL-BAD-VERBOSE %s +RUN: %FileCheck -check-prefix PRINTS-ERROR %s < %t/stderr.txt + +CHECK-XFAIL-BAD: # (XFAIL) {{.+}}/Bad.swiftinterface +CHECK-XFAIL-BAD-VERBOSE-DAG: # (XFAIL) {{.+}}/Bad.swiftinterface +CHECK-XFAIL-BAD-VERBOSE-DAG: # (PASS) {{.+}}/Good.swiftinterface diff --git a/utils/swift_build_sdk_interfaces.py b/utils/swift_build_sdk_interfaces.py new file mode 100755 index 0000000000000..16612bae2dbf3 --- /dev/null +++ b/utils/swift_build_sdk_interfaces.py @@ -0,0 +1,432 @@ +#!/usr/bin/env python + +from __future__ import print_function + +import argparse +import errno +import itertools +import json +import multiprocessing +import os +import shutil +import subprocess +import sys +import traceback + +BARE_INTERFACE_SEARCH_PATHS = [ + "usr/lib/swift", + "System/iOSSupport/usr/lib/swift" +] +DEFAULT_FRAMEWORK_INTERFACE_SEARCH_PATHS = [ + "System/Library/Frameworks", + "System/iOSSupport/System/Library/Frameworks" +] +STDLIB_NAME = 'Swift' + +MONOTONIC_VERSION = 1 + + +def create_parser(): + parser = argparse.ArgumentParser( + description="Builds an SDK's swiftinterfaces into swiftmodules. " + "Always searches usr/lib/swift in addition to whichever " + "framework directories are passed on the command line.", + prog=os.path.basename(__file__), + usage='%(prog)s -o output/ [INTERFACE_SEARCH_DIRS]', + epilog='Environment variables: SDKROOT, SWIFT_EXEC, ' + 'SWIFT_FORCE_MODULE_LOADING') + parser.add_argument('interface_framework_dirs', nargs='*', + metavar='INTERFACE_SEARCH_DIRS', + help='Relative paths to search for frameworks with ' + 'interfaces (default: System/Library/Frameworks)') + parser.add_argument('-o', dest='output_dir', + help='Directory to which the output will be emitted ' + '(required)') + parser.add_argument('-j', dest='jobs', type=int, + help='The number of parallel jobs to execute ' + '(default: # of cores)') + parser.add_argument('-v', dest='verbose', action='store_true', + help='Print command invocations and progress info') + parser.add_argument('-n', dest='dry_run', action='store_true', + help='Dry run: don\'t actually run anything') + parser.add_argument('-sdk', default=os.getenv('SDKROOT'), + help='SDK to find frameworks and interfaces in ' + '(default: $SDKROOT)') + parser.add_argument('-F', dest='framework_dirs', metavar='DIR', + action='append', default=[], + help='Add additional framework search paths') + parser.add_argument('-Fsystem', '-iframework', + dest='system_framework_dirs', metavar='DIR', + action='append', default=[], + help='Add additional system framework search paths') + parser.add_argument('-Fsystem-iosmac', + dest='iosmac_system_framework_dirs', metavar='DIR', + action='append', default=[], + help='Add system framework search paths ' + 'for iOSMac only') + parser.add_argument('-I', dest='include_dirs', metavar='DIR', + action='append', default=[], + help='Add additional header/module search paths') + parser.add_argument('-module-cache-path', + help='Temporary directory to store intermediate info') + parser.add_argument('-log-path', + help='Directory to write stdout/stderr output to') + parser.add_argument('-skip-stdlib', action='store_true', + help='Don\'t build the standard library interface') + parser.add_argument('-disable-modules-validate-system-headers', + action='store_true', + help='Disable modules verification for system headers') + parser.add_argument('-xfails', metavar='PATH', + help='JSON file containing an array of the modules ' + 'expected to fail') + parser.add_argument('-check-only', action='store_true', + help='Assume the resulting modules will be thrown ' + 'away (may be faster)') + parser.add_argument('-ignore-non-stdlib-failures', action='store_true', + help='Treat all modules but the stdlib as XFAILed') + parser.add_argument('-debug-crash-compiler', action='store_true', + help='Have the compiler crash (for testing purposes)') + parser.add_argument('-machine-parseable-monotonic-version', + action='store_true', + help='For comparing versions of this tool') + return parser + + +def fatal(msg): + print(msg, file=sys.stderr) + sys.exit(1) + + +def run_command(args, dry_run): + if dry_run: + return (0, "", "") + proc = subprocess.Popen(args, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + try: + out, err = proc.communicate() + exitcode = proc.returncode + return (exitcode, out, err) + except KeyboardInterrupt: + proc.terminate() + raise + + +def make_dirs_if_needed(path, dry_run): + if dry_run: + return + try: + os.makedirs(path) + except OSError as e: + if e.errno != errno.EEXIST: + raise + + +class NegatedSet: + def __init__(self, contents): + self._contents = frozenset(contents) + + def __contains__(self, item): + return item not in self._contents + + +class ModuleFile: + def __init__(self, name, path, is_expected_to_fail): + self.name = name + self.path = path + self.is_expected_to_fail = is_expected_to_fail + + +def collect_slices(xfails, swiftmodule_dir): + if not os.path.isdir(swiftmodule_dir): + return + module_name, extension = \ + os.path.splitext(os.path.basename(swiftmodule_dir)) + assert extension == ".swiftmodule" + + is_xfail = module_name in xfails + for entry in os.listdir(swiftmodule_dir): + _, extension = os.path.splitext(entry) + if extension == ".swiftinterface": + yield ModuleFile(module_name, os.path.join(swiftmodule_dir, entry), + is_xfail) + + +def collect_framework_modules(sdk, xfails, sdk_relative_framework_dirs): + for sdk_relative_framework_dir in sdk_relative_framework_dirs: + framework_dir = os.path.join(sdk, sdk_relative_framework_dir) + if not os.access(framework_dir, os.R_OK): + continue + for entry in os.listdir(framework_dir): + path_without_extension, extension = os.path.splitext(entry) + if extension != ".framework": + continue + module_name = os.path.basename(path_without_extension) + swiftmodule = os.path.join(framework_dir, entry, "Modules", + module_name + ".swiftmodule") + if os.access(swiftmodule, os.R_OK): + for x in collect_slices(xfails, swiftmodule): + yield x + + +def collect_non_framework_modules(sdk, xfails, sdk_relative_search_dirs): + for sdk_relative_search_dir in sdk_relative_search_dirs: + search_dir = os.path.join(sdk, sdk_relative_search_dir) + for dir_path, _, file_names in os.walk(search_dir, followlinks=True): + if os.path.splitext(dir_path)[1] == ".swiftmodule": + for x in collect_slices(xfails, dir_path): + yield x + else: + for interface in file_names: + module_name, extension = os.path.splitext(interface) + if extension == ".swiftinterface": + is_xfail = module_name in xfails + yield ModuleFile(module_name, + os.path.join(dir_path, interface), + is_xfail) + + +def should_retry_compilation(stderr): + if "has been modified since the module file" in stderr: + return True + if "mismatched umbrella headers in submodule" in stderr: + return True + if "is out of date and needs to be rebuilt: signature mismatch" in stderr: + return True + if "current parser token 'include'" in stderr: + return True + if "current parser token 'import'" in stderr: + return True + return False + + +def run_with_module_cache_retry(command_args, module_cache_path, dry_run): + """Hack: runs a command several times, clearing the module cache if we get + an error about header files being modified during the run. + + This shouldn't be necessary (the cached PCM files should automatically be + regenerated) but there seems to still be a bug in Clang that we haven't + tracked down yet. + """ + RETRIES = 3 + attempts_stderr = "" + for r in range(RETRIES): + status, stdout, stderr = run_command(command_args, dry_run) + if status == 0: + break + if not should_retry_compilation(stderr): + break + if module_cache_path: + shutil.rmtree(module_cache_path, ignore_errors=True) + # If all retries fail, output information for each instance. + attempts_stderr += ( + "\n*** Compilation attempt {}/{} failed with modules bugs. " + "Error output:\n".format(r + 1, RETRIES)) + attempts_stderr += stderr + stderr = attempts_stderr + return (status, stdout, stderr) + + +def log_output_to_file(content, module_name, interface_base, label, log_path): + if not log_path: + return + if not content: + return + make_dirs_if_needed(log_path, dry_run=False) + log_name = module_name + "-" + interface_base + "-" + label + ".txt" + with open(os.path.join(log_path, log_name), "w") as output_file: + output_file.write(content) + + +def looks_like_iosmac(interface_base): + return 'ios-macabi' in interface_base + + +def rename_interface_for_iosmac_if_needed(interface_base, module_path): + """Hack: Both macOS and iOSMac use 'x86_64' as the short name for a module + interface file, and while we want to move away from this it's something we + need to handle in the short term. Manually rename these to the full form of + the target-specific module when we're obviously on macOS or iOSMac. + """ + if interface_base != 'x86_64': + return interface_base + if '/iOSSupport/' in module_path: + return 'x86_64-apple-ios-macabi' + if '/MacOS' in module_path: + return 'x86_64-apple-macos' + return interface_base + + +def process_module(module_file): + global args, shared_output_lock + try: + interface_base, _ = \ + os.path.splitext(os.path.basename(module_file.path)) + interface_base = \ + rename_interface_for_iosmac_if_needed(interface_base, + module_file.path) + + swiftc = os.getenv('SWIFT_EXEC', + os.path.join(os.path.dirname(__file__), 'swiftc')) + command_args = [ + swiftc, '-frontend', + '-build-module-from-parseable-interface', + '-sdk', args.sdk, + '-prebuilt-module-cache-path', args.output_dir, + '-track-system-dependencies' + ] + module_cache_path = "" + if args.module_cache_path: + module_cache_path = os.path.join(args.module_cache_path, + str(os.getpid())) + command_args += ('-module-cache-path', module_cache_path) + if args.debug_crash_compiler: + command_args += ('-debug-crash-immediately',) + if not args.check_only: + command_args += ( + '-serialize-parseable-module-interface-dependency-hashes',) + if args.disable_modules_validate_system_headers: + command_args += ( + '-disable-modules-validate-system-headers',) + + # FIXME: This shouldn't be necessary, but the module name is checked + # before the frontend action is. + if module_file.name == STDLIB_NAME: + command_args += ('-parse-stdlib',) + + if looks_like_iosmac(interface_base): + for system_framework_path in args.iosmac_system_framework_dirs: + command_args += ('-Fsystem', system_framework_path) + command_args += ('-Fsystem', os.path.join(args.sdk, "System", + "iOSSupport", "System", + "Library", "Frameworks")) + + for include_path in args.include_dirs: + command_args += ('-I', include_path) + for system_framework_path in args.system_framework_dirs: + command_args += ('-Fsystem', system_framework_path) + for framework_path in args.framework_dirs: + command_args += ('-F', framework_path) + + command_args += ('-module-name', module_file.name, module_file.path) + + output_path = os.path.join(args.output_dir, + module_file.name + ".swiftmodule") + + if interface_base != module_file.name: + make_dirs_if_needed(output_path, args.dry_run) + output_path = os.path.join(output_path, + interface_base + ".swiftmodule") + + command_args += ('-o', output_path) + + if args.verbose: + with shared_output_lock: + print("# Starting " + module_file.path) + print(' '.join(command_args)) + sys.stdout.flush() + status, stdout, stderr = run_with_module_cache_retry( + command_args, module_cache_path=module_cache_path, + dry_run=args.dry_run) + log_output_to_file(stdout, module_file.name, interface_base, "out", + log_path=args.log_path) + log_output_to_file(stderr, module_file.name, interface_base, "err", + log_path=args.log_path) + return (module_file, status, stdout, stderr) + except BaseException: + # We're catching everything here because we don't want to take down the + # other jobs. + return (module_file, 1, "", + "".join(traceback.format_exception(*sys.exc_info()))) + + +def set_up_child(parent_args, lock): + global args, shared_output_lock + args = parent_args + shared_output_lock = lock + + +def process_module_files(pool, module_files): + results = pool.imap_unordered(process_module, module_files) + + overall_exit_status = 0 + for (module_file, exit_status, stdout, stderr) in results: + with shared_output_lock: + if exit_status != 0: + print("# ", end="") + if module_file.is_expected_to_fail: + print("(XFAIL) ", end="") + else: + print("(FAIL) ", end="") + print(module_file.path) + if (not module_file.is_expected_to_fail) or args.verbose: + print(stdout, end="") + print(stderr, end="", file=sys.stderr) + elif module_file.is_expected_to_fail: + print("# (UPASS) " + module_file.path) + elif args.verbose: + print("# (PASS) " + module_file.path) + sys.stdout.flush() + if overall_exit_status == 0 and \ + not module_file.is_expected_to_fail: + overall_exit_status = exit_status + return overall_exit_status + + +def main(): + global args, shared_output_lock + parser = create_parser() + args = parser.parse_args() + + if args.machine_parseable_monotonic_version: + print(MONOTONIC_VERSION) + sys.exit(0) + + if 'SWIFT_FORCE_MODULE_LOADING' not in os.environ: + os.environ['SWIFT_FORCE_MODULE_LOADING'] = 'prefer-serialized' + + if not args.output_dir: + fatal("argument -o is required") + if not args.sdk: + fatal("SDKROOT must be set in the environment") + if not os.path.isdir(args.sdk): + fatal("invalid SDK: " + args.sdk) + + xfails = () + if args.ignore_non_stdlib_failures: + if args.xfails: + print("warning: ignoring -xfails because " + "-ignore-non-stdlib-failures was provided", file=sys.stderr) + xfails = NegatedSet((STDLIB_NAME,)) + elif args.xfails: + with open(args.xfails) as xfails_file: + xfails = json.load(xfails_file) + + make_dirs_if_needed(args.output_dir, args.dry_run) + shared_output_lock = multiprocessing.Lock() + pool = multiprocessing.Pool(args.jobs, set_up_child, + (args, shared_output_lock)) + + interface_framework_dirs = (args.interface_framework_dirs or + DEFAULT_FRAMEWORK_INTERFACE_SEARCH_PATHS) + + module_files = list(itertools.chain( + collect_non_framework_modules(args.sdk, xfails, + BARE_INTERFACE_SEARCH_PATHS), + collect_framework_modules(args.sdk, xfails, interface_framework_dirs))) + + if not args.skip_stdlib: + # Always do the stdlib first, so that we can use it in later steps + stdlib_module_files = ( + x for x in module_files if x.name == STDLIB_NAME) + status = process_module_files(pool, stdlib_module_files) + if status != 0: + sys.exit(status) + + non_stdlib_module_files = ( + x for x in module_files if x.name != STDLIB_NAME) + status = process_module_files(pool, non_stdlib_module_files) + sys.exit(status) + + +if __name__ == '__main__': + main()