Skip to content

pass fd to PackageDescription while parsing manifests instead of using SWIFT_DUMP_PACKAGE #169

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

Merged
merged 3 commits into from
Mar 9, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 21 additions & 11 deletions Sources/ManifestParser/Manifest+parse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import struct PackageType.Manifest
import func POSIX.realpath
import PackageDescription
import Utility
import func POSIX.fopen
import func libc.fileno
import func libc.unlink
import func libc.fclose

extension Manifest {
public init(path pathComponents: String..., baseURL: String) throws {
Expand Down Expand Up @@ -49,16 +53,10 @@ extension Manifest {

private func parse(manifestPath: String) throws -> String? {

// For now, we load the manifest by having Swift interpret it directly
// and using a special environment variable to trigger the PackageDescription
// library to dump the package (as TOML) at exit. Eventually, we should
// have two loading processes, one that loads only the the declarative
// package specification using the Swift compiler directly and validates
// it.
//
// FIXME: We also should make the mechanism for communicating the
// package between the PackageDescription module more robust, for example by passing
// in the id of another file descriptor to write the output onto.
// For now, we load the manifest by having Swift interpret it directly.
// Eventually, we should have two loading processes, one that loads only
// the the declarative package specification using the Swift compiler
// directly and validates it.

let libdir = Resources.runtimeLibPath

Expand All @@ -71,5 +69,17 @@ private func parse(manifestPath: String) throws -> String? {
#endif
cmd += [manifestPath]

return try popen(cmd, environment: ["SWIFT_DUMP_PACKAGE": "1"]).chuzzle()
//Create and open a temporary file to write toml to
let filePath = Path.join(manifestPath.parentDirectory, ".Package.toml")
let fp = try fopen(filePath, mode: .Write)
defer { fclose(fp) }

//Pass the fd in arguments
cmd += ["-fileno", "\(fileno(fp))"]
try system(cmd)

let toml = try File(path: filePath).enumerate().reduce("") { $0 + "\n" + $1 }
unlink(filePath) //Delete the temp file after reading it

return toml != "" ? toml : nil
}
26 changes: 16 additions & 10 deletions Sources/PackageDescription/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import Glibc
import Darwin.C
#endif


/// The description for a complete package.
public final class Package {
/// The description for a package dependency.
Expand Down Expand Up @@ -69,8 +68,10 @@ public final class Package {
// FIXME: This doesn't belong here, but for now is the mechanism we use
// to get the interpreter to dump the package when attempting to load a
// manifest.
if getenv("SWIFT_DUMP_PACKAGE") != nil {
dumpPackageAtExit(self)

if let fileNoOptIndex = Process.arguments.indexOf("-fileno"),
fileNo = Int32(Process.arguments[fileNoOptIndex + 1]) {
dumpPackageAtExit(self, fileNo: fileNo)
}
}
}
Expand Down Expand Up @@ -128,16 +129,21 @@ public func ==(lhs: Package.Dependency, rhs: Package.Dependency) -> Bool {

// MARK: Package Dumping

private var thePackageToDump: Package? = nil
private func dumpPackageAtExit(package: Package) {
private var dumpInfo: (package: Package, fileNo: Int32)? = nil
private func dumpPackageAtExit(package: Package, fileNo: Int32) {
func dump() {
print(thePackageToDump!.toTOML())
guard let dumpInfo = dumpInfo else { return }
let fd = fdopen(dumpInfo.fileNo, "w")
guard fd != nil else { return }
fputs(dumpInfo.package.toTOML(), fd)
for product in products {
print("[[products]]")
print(product.toTOML())
print()
fputs("[[products]]", fd)
fputs("\n", fd)
fputs(product.toTOML(), fd)
fputs("\n", fd)
}
fclose(fd)
}
thePackageToDump = package
dumpInfo = (package, fileNo)
atexit(dump)
}