Skip to content
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
2 changes: 2 additions & 0 deletions Sources/SWBCore/Settings/BuiltinMacros.swift
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,7 @@ public final class BuiltinMacros {
public static let INPUT_FILE_SUFFIX = BuiltinMacros.declareStringMacro("INPUT_FILE_SUFFIX")
public static let INSTALLHDRS_COPY_PHASE = BuiltinMacros.declareBooleanMacro("INSTALLHDRS_COPY_PHASE")
public static let INSTALLHDRS_SCRIPT_PHASE = BuiltinMacros.declareBooleanMacro("INSTALLHDRS_SCRIPT_PHASE")
public static let INSTALLLOC_DIRECTORY_CONTENTS = BuiltinMacros.declareBooleanMacro("INSTALLLOC_DIRECTORY_CONTENTS")
public static let INSTALLLOC_LANGUAGE = BuiltinMacros.declareStringListMacro("INSTALLLOC_LANGUAGE")
public static let INSTALLLOC_SCRIPT_PHASE = BuiltinMacros.declareBooleanMacro("INSTALLLOC_SCRIPT_PHASE")
public static let INSTALL_DIR = BuiltinMacros.declarePathMacro("INSTALL_DIR")
Expand Down Expand Up @@ -1877,6 +1878,7 @@ public final class BuiltinMacros {
INSTALLED_PRODUCT_ASIDES,
INSTALLHDRS_COPY_PHASE,
INSTALLHDRS_SCRIPT_PHASE,
INSTALLLOC_DIRECTORY_CONTENTS,
INSTALLLOC_LANGUAGE,
INSTALLLOC_SCRIPT_PHASE,
INSTALL_DIR,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,10 @@ class CopyFilesTaskProducer: FilesBasedBuildPhaseTaskProducerBase, FilesBasedBui
return
}
}
} else if scope.evaluate(BuiltinMacros.INSTALLLOC_DIRECTORY_CONTENTS), !ftb.isValidLocalizedContent(scope), context.workspaceContext.fs.isDirectory(ftb.absolutePath) {
// Treat any package or directory the same as a copied bundle and copy over the relevant lproj directories.
await addTasksForEmbeddedLocalizedBundle(ftb, buildFilesContext, scope, &tasks)
return
}
guard ftb.isValidLocalizedContent(scope) || targetBundleProduct else { return }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,10 @@ final class ResourcesTaskProducer: FilesBasedBuildPhaseTaskProducerBase, FilesBa
await addTasksForEmbeddedLocalizedBundle(ftb, buildFilesContext, scope, &tasks)
return
}
} else if scope.evaluate(BuiltinMacros.INSTALLLOC_DIRECTORY_CONTENTS), !ftb.isValidLocalizedContent(scope), context.workspaceContext.fs.isDirectory(ftb.absolutePath) {
// Treat any package or directory the same as a copied bundle and copy over the relevant lproj directories.
await addTasksForEmbeddedLocalizedBundle(ftb, buildFilesContext, scope, &tasks)
return
}
guard ftb.isValidLocalizedContent(scope) || targetBundleProduct else { return }
}
Expand Down
4 changes: 4 additions & 0 deletions Sources/SWBTestSupport/TestWorkspaces.swift
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,10 @@ package final class TestFile: TestInternalStructureItem, CustomStringConvertible
return "folder.documentationcatalog"
case ".tightbeam":
return "sourcecode.tightbeam"
case ".myPackage":
return "com.apple.package"
case "":
return "public.directory"
case let ext where ext.hasPrefix(".fake-"):
// If this is a fake extension, just return "file".
return "file"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,7 @@ fileprivate struct InstallLocTaskConstructionTests: CoreBasedTests {
results.checkNoDiagnostics()
}

// INSTALLLOC_LANGUAGE set to "ja"
// INSTALLLOC_LANGUAGE set to "zh_TW" and "ja"
let specificLangs = ["zh_TW", "ja"]
await tester.checkBuild(BuildParameters(action: .installLoc, configuration: "Debug", overrides: ["INSTALLLOC_LANGUAGE": specificLangs.joined(separator: " ")]), runDestination: .iOS, fs: fs) { results in
// Ignore all Gate, build directory, MkDir, and SymLink tasks.
Expand All @@ -653,6 +653,230 @@ fileprivate struct InstallLocTaskConstructionTests: CoreBasedTests {
}
}

/// Test an App that has a directory or package (not an explicit bundle) in resources phase
@Test(.requireSDKs(.macOS))
func embeddedDirectoriesInResources() async throws {
try await withTemporaryDirectory { tmpDir in
let srcRoot = tmpDir.join("srcroot")

let testProject = TestProject(
"aProject",
sourceRoot: srcRoot,
groupTree: TestGroup(
"SomeFiles", path: "Sources",
children: [
TestFile("MyFolder"),
TestFile("MyPackage.myPackage"),
]),
buildConfigurations: [
TestBuildConfiguration(
"Debug",
buildSettings: [
"PRODUCT_NAME": "$(TARGET_NAME)",
"INSTALLLOC_DIRECTORY_CONTENTS": "YES"
]),
],
targets: [
TestStandardTarget(
"App",
type: .application,
buildPhases: [
TestResourcesBuildPhase([
"MyFolder",
"MyPackage.myPackage"
], onlyForDeployment: false)
]
)
])
let tester = try await TaskConstructionTester(getCore(), testProject)
let fs = PseudoFS()
var languageComponentPathGroupings: [(lang: String, component: String, path: Path)] = []
for pathComponent in ["MyFolder", "MyPackage.myPackage"] {
let bundlePath = srcRoot.join("Sources/\(pathComponent)", preserveRoot: true, normalize: true)
try fs.createDirectory(bundlePath, recursive: true)
try fs.write(bundlePath.join("Info.plist"), contents: "LocTest")

for lang in ["en", "ja", "zh_TW"] {
let path = bundlePath.join("\(lang).lproj", preserveRoot: true, normalize: true)
try fs.createDirectory(path, recursive: false)
try fs.write(path.join("Localizable.strings"), contents: "LocTest")
languageComponentPathGroupings += [(lang, pathComponent, path)]
}
}

await tester.checkBuild(BuildParameters(action: .installLoc, configuration: "Debug"), runDestination: .iOS, fs: fs) { results in
// Ignore all Gate, build directory, SymLink, and MkDir tasks.
results.checkTasks(.matchRuleType("Gate")) { _ in }
results.checkTasks(.matchRuleType("CreateBuildDirectory")) { _ in }
results.checkTasks(.matchRuleType("SymLink")) { _ in }
results.checkTasks(.matchRuleType("MkDir")) { _ in }
results.checkTasks(.matchRuleType("WriteAuxiliaryFile")) { _ in }
results.checkTasks(.matchRuleType("ProcessInfoPlistFile")) { _ in }

results.checkTarget("App") { target in
for (language, component, path) in languageComponentPathGroupings {
results.checkTask(.matchTarget(target), .matchRule(["CpResource", "/tmp/aProject.dst/Applications/App.app/Contents/Resources/\(component)/\(language).lproj", path.str])) { _ in }
}
}
results.checkNoTask()
results.checkNoDiagnostics()
}

// INSTALLLOC_LANGUAGE set to "ja"
await tester.checkBuild(BuildParameters(action: .installLoc, configuration: "Debug", overrides: ["INSTALLLOC_LANGUAGE": "ja"]), runDestination: .iOS, fs: fs) { results in
// Ignore all Gate, build directory, MkDir, and SymLink tasks.
results.checkTasks(.matchRuleType("Gate")) { _ in }
results.checkTasks(.matchRuleType("CreateBuildDirectory")) { _ in }
results.checkTasks(.matchRuleType("MkDir")) { _ in }
results.checkTasks(.matchRuleType("SymLink")) { _ in }
results.checkTasks(.matchRuleType("LinkStoryboards")) { _ in }
results.checkTasks(.matchRuleType("WriteAuxiliaryFile")) { _ in }

results.checkTarget("App") { target in
for (language, component, path) in languageComponentPathGroupings where language == "ja" {
results.checkTask(.matchTarget(target), .matchRule(["CpResource", "/tmp/aProject.dst/Applications/App.app/Contents/Resources/\(component)/\(language).lproj", path.str])) { _ in }
}
}

results.checkNoTask()
results.checkNoDiagnostics()
}

// INSTALLLOC_LANGUAGE set to "zh_TW" and "ja"
let specificLangs = ["zh_TW", "ja"]
await tester.checkBuild(BuildParameters(action: .installLoc, configuration: "Debug", overrides: ["INSTALLLOC_LANGUAGE": specificLangs.joined(separator: " ")]), runDestination: .iOS, fs: fs) { results in
// Ignore all Gate, build directory, MkDir, and SymLink tasks.
results.checkTasks(.matchRuleType("Gate")) { _ in }
results.checkTasks(.matchRuleType("CreateBuildDirectory")) { _ in }
results.checkTasks(.matchRuleType("MkDir")) { _ in }
results.checkTasks(.matchRuleType("SymLink")) { _ in }
results.checkTasks(.matchRuleType("LinkStoryboards")) { _ in }
results.checkTasks(.matchRuleType("WriteAuxiliaryFile")) { _ in }

results.checkTarget("App") { target in
for (language, component, path) in languageComponentPathGroupings where specificLangs.contains(language) {
results.checkTask(.matchTarget(target), .matchRule(["CpResource", "/tmp/aProject.dst/Applications/App.app/Contents/Resources/\(component)/\(language).lproj", path.str])) { _ in }
}
}

results.checkNoTask()
results.checkNoDiagnostics()
}
}
}

/// Test an App that has a directory or package (not an explicit bundle) in copy files phase
@Test(.requireSDKs(.macOS))
func embeddedDirectoriesInCopyFiles() async throws {
try await withTemporaryDirectory { tmpDir in
let srcRoot = tmpDir.join("srcroot")

let testProject = TestProject(
"aProject",
sourceRoot: srcRoot,
groupTree: TestGroup(
"SomeFiles", path: "Sources",
children: [
TestFile("MyFolder"),
TestFile("MyPackage.myPackage"),
]),
buildConfigurations: [
TestBuildConfiguration(
"Debug",
buildSettings: [
"PRODUCT_NAME": "$(TARGET_NAME)",
"INSTALLLOC_DIRECTORY_CONTENTS": "YES"
]),
],
targets: [
TestStandardTarget(
"App",
type: .application,
buildPhases: [
TestCopyFilesBuildPhase([
"MyFolder",
"MyPackage.myPackage"
], destinationSubfolder: .absolute, destinationSubpath: "/tmp/CustomPath", onlyForDeployment: false)
]
)
])
let tester = try await TaskConstructionTester(getCore(), testProject)
let fs = PseudoFS()
var languageComponentPathGroupings: [(lang: String, component: String, path: Path)] = []
for pathComponent in ["MyFolder", "MyPackage.myPackage"] {
let bundlePath = srcRoot.join("Sources/\(pathComponent)", preserveRoot: true, normalize: true)
try fs.createDirectory(bundlePath, recursive: true)
try fs.write(bundlePath.join("Info.plist"), contents: "LocTest")

for lang in ["en", "ja", "zh_TW"] {
let path = bundlePath.join("\(lang).lproj", preserveRoot: true, normalize: true)
try fs.createDirectory(path, recursive: false)
try fs.write(path.join("Localizable.strings"), contents: "LocTest")
languageComponentPathGroupings += [(lang, pathComponent, path)]
}
}

await tester.checkBuild(BuildParameters(action: .installLoc, configuration: "Debug"), runDestination: .iOS, fs: fs) { results in
// Ignore all Gate, build directory, SymLink, and MkDir tasks.
results.checkTasks(.matchRuleType("Gate")) { _ in }
results.checkTasks(.matchRuleType("CreateBuildDirectory")) { _ in }
results.checkTasks(.matchRuleType("SymLink")) { _ in }
results.checkTasks(.matchRuleType("MkDir")) { _ in }
results.checkTasks(.matchRuleType("WriteAuxiliaryFile")) { _ in }
results.checkTasks(.matchRuleType("ProcessInfoPlistFile")) { _ in }

results.checkTarget("App") { target in
for (language, component, path) in languageComponentPathGroupings {
results.checkTask(.matchTarget(target), .matchRule(["Copy", "/tmp/aProject.dst/tmp/CustomPath/\(component)/\(language).lproj", path.str])) { _ in }
}
}
results.checkNoTask()
results.checkNoDiagnostics()
}

// INSTALLLOC_LANGUAGE set to "ja"
await tester.checkBuild(BuildParameters(action: .installLoc, configuration: "Debug", overrides: ["INSTALLLOC_LANGUAGE": "ja"]), runDestination: .iOS, fs: fs) { results in
// Ignore all Gate, build directory, MkDir, and SymLink tasks.
results.checkTasks(.matchRuleType("Gate")) { _ in }
results.checkTasks(.matchRuleType("CreateBuildDirectory")) { _ in }
results.checkTasks(.matchRuleType("MkDir")) { _ in }
results.checkTasks(.matchRuleType("SymLink")) { _ in }
results.checkTasks(.matchRuleType("LinkStoryboards")) { _ in }
results.checkTasks(.matchRuleType("WriteAuxiliaryFile")) { _ in }

results.checkTarget("App") { target in
for (language, component, path) in languageComponentPathGroupings where language == "ja" {
results.checkTask(.matchTarget(target), .matchRule(["Copy", "/tmp/aProject.dst/tmp/CustomPath/\(component)/\(language).lproj", path.str])) { _ in }
}
}

results.checkNoTask()
results.checkNoDiagnostics()
}

// INSTALLLOC_LANGUAGE set to "zh_TW" and "ja"
let specificLangs = ["zh_TW", "ja"]
await tester.checkBuild(BuildParameters(action: .installLoc, configuration: "Debug", overrides: ["INSTALLLOC_LANGUAGE": specificLangs.joined(separator: " ")]), runDestination: .iOS, fs: fs) { results in
// Ignore all Gate, build directory, MkDir, and SymLink tasks.
results.checkTasks(.matchRuleType("Gate")) { _ in }
results.checkTasks(.matchRuleType("CreateBuildDirectory")) { _ in }
results.checkTasks(.matchRuleType("MkDir")) { _ in }
results.checkTasks(.matchRuleType("SymLink")) { _ in }
results.checkTasks(.matchRuleType("LinkStoryboards")) { _ in }
results.checkTasks(.matchRuleType("WriteAuxiliaryFile")) { _ in }

results.checkTarget("App") { target in
for (language, component, path) in languageComponentPathGroupings where specificLangs.contains(language) {
results.checkTask(.matchTarget(target), .matchRule(["Copy", "/tmp/aProject.dst/tmp/CustomPath/\(component)/\(language).lproj", path.str])) { _ in }
}
}

results.checkNoTask()
results.checkNoDiagnostics()
}
}
}

/// Test an App that has a bundle (not the product of a target) in copy files phase
@Test(.requireSDKs(.iOS))
func warningForMissingExternalBundles() async throws {
Expand Down
Loading