diff --git a/atpkg b/atpkg index e8203454fc75d572f0d9a6232084b335312893d7..d089d2587ca133695d017941d6fbd41e8c145a60 160000 --- a/atpkg +++ b/atpkg @@ -1 +1 @@ -Subproject commit e8203454fc75d572f0d9a6232084b335312893d7 +Subproject commit d089d2587ca133695d017941d6fbd41e8c145a60 diff --git a/attools/src/atllbuild.swift b/attools/src/atllbuild.swift index 99e40428212968f0cdeecdee31f6d3ebeae97021..265b0f2de26ca6b5ecfeace1285d57e9b2c0e2e7 100644 --- a/attools/src/atllbuild.swift +++ b/attools/src/atllbuild.swift @@ -31,6 +31,54 @@ import atpkg return s } + private struct Atbin { + let manifest: Package + let path: Path + + var name: String { return manifest.name } + + init(path: Path) { + self.path = path + self.manifest = try! Package(filepath: path.appending("compiled.atpkg"), overlay: [], focusOnTask: nil) + } + + var linkDirective: String { + return path.appending(self.manifest.payload!).description + } + + var moduleName: String { + let n = self.manifest.payload! + if n.hasSuffix(".a") { + return n.subString(toIndex: n.characters.index(n.characters.endIndex, offsetBy: -2)) + } + if n.hasSuffix(".dylib") { + return n.subString(toIndex: n.characters.index(n.characters.endIndex, offsetBy: -6)) + } + if n.hasSuffix(".so") { + return n.subString(toIndex: n.characters.index(n.characters.endIndex, offsetBy: -3)) + } + fatalError("Unknown payload \(n)") + } + + var swiftModule: Path? { + let modulePath = self.path + (Platform.targetPlatform.description + ".swiftmodule") + if FS.fileExists(path: modulePath) { return modulePath } + return nil + } + + var clangModule: Path? { + let modulePath = self.path + "module.modulemap" + if FS.fileExists(path: modulePath) { return modulePath } + return nil + } + + var swiftDoc: Path? { + let docPath = Path(Platform.targetPlatform.description + ".swiftDoc") + if FS.fileExists(path: docPath) { return docPath } + return nil + } + } + /**The ATllbuild tool builds a swift module via llbuild. For more information on this tool, see `docs/attllbuild.md` */ @@ -74,7 +122,7 @@ final class ATllbuild : Tool { * - parameter enableWMO: Whether to use `enable-whole-module-optimization`, see https://github.com/aciidb0mb3r/swift-llbuild/blob/cfd7aa4e6e14797112922ae12ae7f3af997a41c6/docs/buildsystem.rst * - returns: The string contents for llbuild.yaml suitable for processing by swift-build-tool */ - func llbuildyaml(sources: [Path], workdir: Path, modulename: String, linkSDK: Bool, compileOptions: [String], linkOptions: [String], outputType: OutputType, linkWithProduct:[String], swiftCPath: Path, executableName: String, enableWMO: Bool) -> String { + private func llbuildyaml(sources: [Path], workdir: Path, modulename: String, linkSDK: Bool, compileOptions: [String], linkOptions: [String], outputType: OutputType, linkWithProduct:[String], linkWithAtbin:[Atbin], swiftCPath: Path, executableName: String, enableWMO: Bool) -> String { let productPath = workdir.appending("products") //this format is largely undocumented, but I reverse-engineered it from SwiftPM. var yaml = "client:\n name: swift-build\n\n" @@ -141,7 +189,8 @@ final class ATllbuild : Tool { //this crazy syntax is how sbt declares a dependency var llbuild_inputs = [""] llbuild_inputs += objects - let builtProducts = linkWithProduct.map { (workdir + ("products/"+$0)).description } + var builtProducts = linkWithProduct.map { (workdir + ("products/"+$0)).description } + builtProducts += linkWithAtbin.map {$0.linkDirective} llbuild_inputs += builtProducts let executablePath = productPath.appending(executableName) yaml += " inputs: \(llbuild_inputs)\n" @@ -178,7 +227,8 @@ final class ATllbuild : Tool { yaml += " tool: shell\n" var llbuild_inputs = [""] llbuild_inputs += objects - let builtProducts = linkWithProduct.map { (workdir + ("products/"+$0)).description } + var builtProducts = linkWithProduct.map { (workdir + ("products/"+$0)).description } + builtProducts += linkWithAtbin.map {$0.linkDirective} llbuild_inputs += builtProducts yaml += " inputs: \(llbuild_inputs)\n" let libPath = productPath.appending(modulename + Platform.targetPlatform.dynamicLibraryExtension) @@ -204,7 +254,8 @@ final class ATllbuild : Tool { case CompileOptions = "compile-options" case LinkOptions = "link-options" case LinkSDK = "link-sdk" - case LinkWithProduct = "link-with" + case LinkWithProduct = "link-with-product" + case LinkWithAtbin = "link-with-atbin" case SwiftCPath = "swiftc-path" case XCTestify = "xctestify" case XCTestStrict = "xctest-strict" @@ -231,6 +282,7 @@ final class ATllbuild : Tool { LinkOptions, LinkSDK, LinkWithProduct, + LinkWithAtbin, SwiftCPath, XCTestify, XCTestStrict, @@ -293,6 +345,34 @@ final class ATllbuild : Tool { linkWithProduct.append(p) } } + + ///DEPRECATED PRODUCT CHECK + if let arr_ = task["link-with"] { + print("Warning: link-with is deprecated; please use link-with-product or link-with-atbin") + sleep(5) + guard let arr = arr_.vector else { + fatalError("Non-vector link directive \(arr_)") + } + for product in arr { + guard var p = product.string else { fatalError("non-string product \(product)") } + if p.hasSuffix(".dynamic") { + p.replace(searchTerm: ".dynamic", replacement: Platform.targetPlatform.dynamicLibraryExtension) + } + linkWithProduct.append(p) + } + } + + var linkWithAtbin: [Atbin] = [] + if let arr_ = task[Options.LinkWithAtbin.rawValue] { + guard let arr = arr_.vector else { + fatalError("Non-vector link directive \(arr_)") + } + for product in arr { + guard var p = product.string else { fatalError("non-string product \(product)") } + linkWithAtbin.append(Atbin(path: task.importedPath.appending(p))) + } + } + guard case .some(.StringLiteral(let outputTypeString)) = task[Options.OutputType.rawValue] else { fatalError("No \(Options.OutputType.rawValue) for task \(task)") } @@ -308,6 +388,16 @@ final class ATllbuild : Tool { } } + //copy the atbin module / swiftdoc into our include directory + let includeAtbinPath = workDirectory + "include/atbin" + let _ = try? FS.createDirectory(path: includeAtbinPath, intermediate: true) + for atbin in linkWithAtbin { + if let path = atbin.swiftModule { + try! FS.copyItem(from: path, to: Path("\(includeAtbinPath)/\(atbin.moduleName).swiftmodule")) + } + } + if linkWithAtbin.count > 0 { compileOptions.append(contentsOf: ["-I",includeAtbinPath.description])} + if let includePaths = task[Options.IncludeWithUser.rawValue]?.vector { for path_s in includePaths { guard let path = path_s.string else { fatalError("Non-string path \(path_s)") } @@ -337,23 +427,34 @@ final class ATllbuild : Tool { linkOptions.append(contentsOf: ["-embed-bitcode"]) } + + //check for modulemaps + /*per http://clang.llvm.org/docs/Modules.html#command-line-parameters, pretty much + the only way to do this is to create a file called `module.modulemap`. That + potentially conflicts with other modulemaps, so we give it its own directory, namespaced + by the product name. */ + func installModuleMap(moduleMapPath: Path, productName: String) { + let includePathName = workDirectory + "include/\(productName)" + let _ = try? FS.createDirectory(path: includePathName, intermediate: true) + do { + try FS.copyItem(from: moduleMapPath, to: includePathName.appending("module.modulemap")) + } catch { + fatalError("Could not copy modulemap to \(includePathName): \(error)") + } + compileOptions.append(contentsOf: ["-I", includePathName.description]) + } for product in linkWithProduct { let productName = product.split(character: ".")[0] let moduleMapPath = workDirectory + "products/\(productName).modulemap" if FS.fileExists(path: moduleMapPath) { - /*per http://clang.llvm.org/docs/Modules.html#command-line-parameters, pretty much - the only way to do this is to create a file called `module.modulemap`. That - potentially conflicts with other modulemaps, so we give it its own directory, namespaced - by the product name. */ - let pathName = workDirectory + "include/\(productName)" - let _ = try? FS.createDirectory(path: pathName, intermediate: true) - do { - try FS.copyItem(from: moduleMapPath, to: pathName.appending("module.modulemap")) - } catch { - fatalError("Could not copy modulemap to \(pathName): \(error)") - } - compileOptions.append(contentsOf: ["-I", pathName.description]) + installModuleMap(moduleMapPath: moduleMapPath, productName: productName) + } + } + + for product in linkWithAtbin { + if let moduleMapPath = product.clangModule { + installModuleMap(moduleMapPath: moduleMapPath, productName: product.name) } } @@ -531,7 +632,7 @@ final class ATllbuild : Tool { } else { enableWMO = false } - let yaml = llbuildyaml(sources: sources, workdir: workDirectory, modulename: name, linkSDK: sdk, compileOptions: compileOptions, linkOptions: linkOptions, outputType: outputType, linkWithProduct: linkWithProduct, swiftCPath: swiftCPath, executableName: executableName, enableWMO: enableWMO) + let yaml = llbuildyaml(sources: sources, workdir: workDirectory, modulename: name, linkSDK: sdk, compileOptions: compileOptions, linkOptions: linkOptions, outputType: outputType, linkWithProduct: linkWithProduct, linkWithAtbin: linkWithAtbin, swiftCPath: swiftCPath, executableName: executableName, enableWMO: enableWMO) let _ = try? yaml.write(to: llbuildyamlpath) if bootstrapOnly { return } diff --git a/tests/fixtures/atbin/build.atpkg b/tests/fixtures/atbin/build.atpkg index 392c9ef923a2bffd0686d4d26a7873643445eb29..dd1105084deaeb7f7da50abb5f1dbe58e1ba02c0 100644 --- a/tests/fixtures/atbin/build.atpkg +++ b/tests/fixtures/atbin/build.atpkg @@ -25,6 +25,24 @@ :module-map "synthesized" } + :use-satbin { + :tool "atllbuild" + :name "usesatbin" + :output-type "executable" + :sources ["use/**.swift"] + :dependencies ["satbin"] + :link-with-atbin ["bin/staticatbin.atbin"] + } + + :use-datbin { + :tool "atllbuild" + :name "usesatbin" + :output-type "executable" + :sources ["used/**.swift"] + :dependencies ["datbin"] + :link-with-atbin ["bin/dynamicatbin.atbin"] + } + :dlib { :tool "atllbuild" :name "dlib" @@ -37,7 +55,7 @@ ;; a corner case of the platform logic; we want to match ;; the dependencies platforms :dependencies ["slib"] - :link-with ["slib.a"] + :link-with-product ["slib.a"] } :exec { @@ -76,6 +94,11 @@ :platforms ["ios-x86_64" "ios-i386"] } + :use { + :tool "nop" + :dependencies ["use-satbin" "use-datbin"] + } + :default { :tool "nop" :dependencies ["datbin" "satbin" "ebin" "simatbin"] diff --git a/tests/fixtures/atbin/lib/lib.swift b/tests/fixtures/atbin/lib/lib.swift index b59cf93e97378e99528c4f7055157e00bde95203..3b63c17141a192ce54644f343b3d6b6a878cd700 100644 --- a/tests/fixtures/atbin/lib/lib.swift +++ b/tests/fixtures/atbin/lib/lib.swift @@ -1 +1 @@ -public class Foo { } \ No newline at end of file +public class Foo {public init() { }} \ No newline at end of file diff --git a/tests/fixtures/atbin/use/main.swift b/tests/fixtures/atbin/use/main.swift new file mode 100644 index 0000000000000000000000000000000000000000..68e38caed31879006b3c274d4648fafcec99d7f8 --- /dev/null +++ b/tests/fixtures/atbin/use/main.swift @@ -0,0 +1,3 @@ +import slib +let f = Foo() +print(f) \ No newline at end of file diff --git a/tests/fixtures/atbin/used/main.swift b/tests/fixtures/atbin/used/main.swift new file mode 100644 index 0000000000000000000000000000000000000000..b7789fec20a57d43cb02baf0927cecc3aac3fac2 --- /dev/null +++ b/tests/fixtures/atbin/used/main.swift @@ -0,0 +1,3 @@ +import dlib +let f = Foo() +print(f) \ No newline at end of file diff --git a/tests/fixtures/dynamic_library/build.atpkg b/tests/fixtures/dynamic_library/build.atpkg index 2d1eae8c9671a57da8e2ced7177820c76cac6602..84bb7f8067e853ee49e22c186b00e1dc23c978e4 100644 --- a/tests/fixtures/dynamic_library/build.atpkg +++ b/tests/fixtures/dynamic_library/build.atpkg @@ -13,7 +13,7 @@ :output-type "dynamic-library" :name "dynamicBar" :sources ["src/bar.swift"] - :link-with ["dynamicFoo.dynamic"] + :link-with-product ["dynamicFoo.dynamic"] } :default { :dependencies ["foo" "bar"] @@ -21,7 +21,7 @@ :output-type "executable" :name "dynamic_library_tester" :sources ["src/main.swift"] - :link-with ["dynamicBar.dynamic" "dynamicFoo.dynamic"] + :link-with-product ["dynamicBar.dynamic" "dynamicFoo.dynamic"] } } ) \ No newline at end of file diff --git a/tests/fixtures/umbrella_header/build.atpkg b/tests/fixtures/umbrella_header/build.atpkg index 2b99b7bbdafd05e71727018063155e39cc1af5d2..c7ca2e41a022fe6feb19aa0e9608e71b6aa5b57a 100644 --- a/tests/fixtures/umbrella_header/build.atpkg +++ b/tests/fixtures/umbrella_header/build.atpkg @@ -21,7 +21,7 @@ :xctest-strict true :dependencies ["default"] :publish-product true - :link-with ["UmbrellaHeader.a"] + :link-with-product ["UmbrellaHeader.a"] } :check { diff --git a/tests/fixtures/xcs/build.atpkg b/tests/fixtures/xcs/build.atpkg index c3e16ede639a8d22c8fb935ab7ac43881d674629..9d842bc3128c412a497385a0c53319dca9755e3d 100644 --- a/tests/fixtures/xcs/build.atpkg +++ b/tests/fixtures/xcs/build.atpkg @@ -17,7 +17,7 @@ :dependencies ["build-lib"] :xctestify true :xctest-strict true - :link-with ["Foo.a"] + :link-with-product ["Foo.a"] } :run-tests { :tool "xctestrun" diff --git a/tests/fixtures/xcs_strict/build.atpkg b/tests/fixtures/xcs_strict/build.atpkg index 50ef29147a631ca0421160e36e42f34f067f0ad7..6da3a9014989fd03c6e10c9fd05160f3c9ad6378 100644 --- a/tests/fixtures/xcs_strict/build.atpkg +++ b/tests/fixtures/xcs_strict/build.atpkg @@ -17,7 +17,7 @@ :dependencies ["build-lib"] :xctestify true :xctest-strict true - :link-with ["Foo.a"] + :link-with-product ["Foo.a"] } :run-tests { :tool "xctestrun" diff --git a/tests/test.sh b/tests/test.sh index b057f988e68cfff1dd6f807d2b368ce8ccf050a6..d2243cc3473e49d22b3a5f6c873c0aa90571bd87 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -97,6 +97,8 @@ $ATBUILD check echo "****************ATBIN TEST**************" cd $DIR/tests/fixtures/atbin +$ATBUILD use + $ATBUILD #did we build all the things we were supposed to?