Commit 3be96f70 authored by David Owens II's avatar David Owens II

Merge pull request #54 from AnarchyTools/umbrella_headers

Umbrella Headers 2: The Rainy Day
parents aa022ca0 defd7f81
Pipeline #1105 passed with stage
......@@ -15,6 +15,23 @@
import Foundation
import atpkg
/**Synthesize a module map.
- parameter name: The name of the module to synthesize
- parameter umbrellaHeader: A path to the umbrella header. The path must be relative to the exported module map file.
- returns String contents of the synthesized modulemap
*/
private func synthesizeModuleMap(name: String, umbrellaHeader: String?) -> String {
var s = ""
s += "module \(name) {\n"
if let u = umbrellaHeader {
s += " umbrella header \"\(u)\"\n"
}
s += "\n"
s += "}\n"
return s
}
/**The ATllbuild tool builds a swift module via llbuild.
For more information on this tool, see `docs/attllbuild.md` */
final class ATllbuild : Tool {
......@@ -73,6 +90,11 @@ final class ATllbuild : Tool {
case Executable
case StaticLibrary
}
enum ModuleMapType {
case None
case Synthesized
}
/**
* Calculates the llbuild.yaml contents for the given configuration options
......@@ -196,6 +218,9 @@ final class ATllbuild : Tool {
case XCTestStrict = "xctest-strict"
case IncludeWithUser = "include-with-user"
case PublishProduct = "publish-product"
case UmbrellaHeader = "umbrella-header"
case ModuleMap = "module-map"
static var allOptions : [Options] {
return [
......@@ -214,7 +239,8 @@ final class ATllbuild : Tool {
XCTestify,
XCTestStrict,
IncludeWithUser,
PublishProduct
PublishProduct,
UmbrellaHeader
]
}
}
......@@ -238,9 +264,12 @@ final class ATllbuild : Tool {
//multiple invocations of atllbuild.
let _ = try? manager.removeItemAtPath(workDirectory + "/objects")
let _ = try? manager.removeItemAtPath(workDirectory + "/llbuildtmp")
let _ = try? manager.removeItemAtPath(workDirectory + "/include")
let _ = try? manager.createDirectoryAtPath(workDirectory, withIntermediateDirectories: false, attributes: nil)
let _ = try? manager.createDirectoryAtPath(workDirectory + "/products", withIntermediateDirectories: false, attributes: nil)
let _ = try? manager.createDirectoryAtPath(workDirectory + "/objects", withIntermediateDirectories: false, attributes: nil)
let _ = try? manager.createDirectoryAtPath(workDirectory + "/include", withIntermediateDirectories: false, attributes: nil)
//parse arguments
var linkWithProduct: [String] = []
......@@ -282,7 +311,25 @@ final class ATllbuild : Tool {
linkOptions.append(os)
}
}
//check for modulemaps
for product in linkWithProduct {
let productName = product.componentsSeparatedByString(".")[0]
let moduleMapPath = workDirectory + "/products/\(productName).modulemap"
if manager.fileExistsAtPath(moduleMapPath) {
print("a")
/*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)"
try! manager.createDirectoryAtPath(pathName, withIntermediateDirectories:false, attributes: nil)
try! manager.copyItemAtPath_SWIFTBUG(moduleMapPath, toPath: pathName + "/module.modulemap")
compileOptions.appendContentsOf(["-I",pathName])
}
}
guard let sourceDescriptions = task[Options.Source.rawValue]?.vector?.flatMap({$0.string}) else { fatalError("Can't find sources for atllbuild.") }
var sources = collectSources(sourceDescriptions, taskForCalculatingPath: task)
......@@ -306,9 +353,26 @@ final class ATllbuild : Tool {
sources.append(xcTestCaseProviderPath)
#endif
}
let moduleMap: ModuleMapType
if task[Options.ModuleMap.rawValue]?.string == "synthesized" {
moduleMap = .Synthesized
}
else {
moduleMap = .None
}
guard let name = task[Options.Name.rawValue]?.string else { fatalError("No name for atllbuild task") }
if let umbrellaHeader = task[Options.UmbrellaHeader.rawValue]?.string {
precondition(moduleMap == .Synthesized, ":\(Options.UmbrellaHeader.rawValue) \"synthesized\" must be used with the \(Options.UmbrellaHeader.rawValue) option")
let s = synthesizeModuleMap(name, umbrellaHeader: "Umbrella.h")
try! s.writeToFile(workDirectory+"/include/module.modulemap", atomically: false, encoding: NSUTF8StringEncoding)
try! manager.copyItemAtPath_SWIFTBUG(task.importedPath + umbrellaHeader, toPath: workDirectory + "/include/Umbrella.h")
compileOptions.append("-I")
compileOptions.append(workDirectory + "/include/")
compileOptions.append("-import-underlying-module")
}
let bootstrapOnly: Bool
if task[Options.BootstrapOnly.rawValue]?.bool == true {
......@@ -344,6 +408,14 @@ final class ATllbuild : Tool {
let yaml = llbuildyaml(sources, workdir: workDirectory, modulename: name, linkSDK: sdk, compileOptions: compileOptions, linkOptions: linkOptions, outputType: outputType, linkWithProduct: linkWithProduct, swiftCPath: swiftCPath)
let _ = try? yaml.writeToFile(llbuildyamlpath, atomically: false, encoding: NSUTF8StringEncoding)
if bootstrapOnly { return }
switch moduleMap {
case .None:
break
case .Synthesized:
let s = synthesizeModuleMap(name, umbrellaHeader: nil)
try! s.writeToFile(workDirectory + "/products/\(name).modulemap", atomically: false, encoding: NSUTF8StringEncoding)
}
//SR-566
let cmd = "\(SwiftBuildToolpath) -f \(llbuildyamlpath)"
......@@ -361,6 +433,14 @@ final class ATllbuild : Tool {
case .StaticLibrary:
try! copyByOverwriting("\(workDirectory)/products/\(name).a", toPath: "bin/\(name).a")
}
switch moduleMap {
case .None:
break
case .Synthesized:
try! copyByOverwriting("\(workDirectory)/products/\(name).modulemap", toPath: "bin/\(name).modulemap")
}
}
}
}
......
#define C_FLAG 1
\ No newline at end of file
(package
:name "umbrella_header"
:tasks {
:default {
:tool "atllbuild"
:sources ["foo.swift"]
:name "UmbrellaHeader"
:output-type "static-library"
:umbrella-header "UmbrellaHeader.h"
:module-map "synthesized"
:publish-product true
}
:build-test {
:tool "atllbuild"
:sources ["tests/**.swift"]
:name "UmbrellaHeaderTests"
:output-type "executable"
:xctestify true
:xctest-strict true
:dependencies ["default"]
:publish-product true
:link-with ["UmbrellaHeader.a"]
}
:check {
:tool "xctestrun"
:dependencies ["build-test"]
:test-executable "bin/UmbrellaHeaderTests"
}
}
)
\ No newline at end of file
func foo() {
print(C_FLAG)
}
\ No newline at end of file
import XCTest
import UmbrellaHeader
class MyTest : XCTestCase {
func testLoad() {
}
}
extension MyTest : XCTestCaseProvider {
var allTests : [(String, () throws -> Void)] {
return [
("testLoad", testLoad)
]
}
}
XCTMain([MyTest()])
......@@ -10,6 +10,10 @@ pwd
echo "****************SELF-HOSTING TEST**************"
$ATBUILD atbuild
echo "****************UMBRELLA TEST**************"
cd $DIR/tests/fixtures/umbrella_header
$ATBUILD check
echo "****************USER PATH TEST**************"
cd $DIR/tests/fixtures/user_paths
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment