Merge branch 'master' into test-coverage

This commit is contained in:
Yuta Saito 2019-10-27 12:58:30 +09:00
commit 3d58b3d104
14 changed files with 405 additions and 31 deletions

View File

@ -8,6 +8,11 @@
#### Fixed
- Add base localisation by default even if no base localised files were found. Fixes warning in Xcode 11 [#685](https://github.com/yonaskolb/XcodeGen/pull/685) @yonaskolb
- Don't generate CFBundleExecutable in default generated Info.plist for `bundle` target types [#689](https://github.com/yonaskolb/XcodeGen/pull/689) @FranzBusch
- Fixed resolving relative paths with custom project destination [#681](https://github.com/yonaskolb/XcodeGen/pull/681) @giginet
- Fixed resolving relative paths for Info.plist [#683](https://github.com/yonaskolb/XcodeGen/pull/683)
- Fixed macOS unit test target TEST_HOST [#696](https://github.com/yonaskolb/XcodeGen/pull/696) @mjarvis
## 2.9.0

View File

@ -25,7 +25,7 @@ pod 'Fabric'
pod 'Crashlytics'
script_phase :name => 'Run Fabric',
:script => '"${PODS_ROOT}/Fabric/run"'
:script => '"${PODS_ROOT}/Fabric/run"',
:input_files => ['$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)']
```

View File

@ -204,10 +204,10 @@ Settings are merged in the following order: groups, base, configs.
- `TEST_TARGET_NAME`: for ui tests that target an application
- `TEST_HOST`: for unit tests that target an application
- [ ] **dependencies**: **[[Dependency](#dependency)]** - Dependencies for the target
- [ ] **info**: **[Plist](#plist)** - If defined, this will generate and write an `Info.plist` to the specified path and use it by setting the `INFOPLIST_FILE` build setting for every configuration, unless `INFOPLIST_FILE` is already defined in **settings** for this configuration. The following properties are generated automatically, the rest will have to be provided.
- [ ] **info**: **[Plist](#plist)** - If defined, this will generate and write an `Info.plist` to the specified path and use it by setting the `INFOPLIST_FILE` build setting for every configuration, unless `INFOPLIST_FILE` is already defined in **settings** for this configuration. The following properties are generated automatically if appropriate, the rest will have to be provided.
- `CFBundleIdentifier`
- `CFBundleInfoDictionaryVersion`
- `CFBundleExecutable`
- `CFBundleExecutable` **Not generated for targets of type bundle**
- `CFBundleName`
- `CFBundleDevelopmentRegion`
- `CFBundleShortVersionString`

View File

@ -125,7 +125,7 @@ class GenerateCommand: Command {
let xcodeProject: XcodeProj
do {
let projectGenerator = ProjectGenerator(project: project)
xcodeProject = try projectGenerator.generateXcodeProject()
xcodeProject = try projectGenerator.generateXcodeProject(in: projectDirectory)
} catch {
throw GenerationError.generationError(error)
}

View File

@ -30,7 +30,7 @@ public class FileWriter {
for target in project.targets {
// write Info.plist
if let plist = target.info {
let properties = infoPlistGenerator.generateProperties(target: target).merged(plist.properties)
let properties = infoPlistGenerator.generateProperties(for: target).merged(plist.properties)
try writePlist(properties, path: plist.path)
}

View File

@ -8,20 +8,26 @@ public class InfoPlistGenerator {
Default info plist attributes taken from:
/Applications/Xcode.app/Contents/Developer/Library/Xcode/Templates/Project Templates/Base/Base_DefinitionsInfoPlist.xctemplate/TemplateInfo.plist
*/
var defaultInfoPlist: [String: Any] = {
private func generateDefaultInfoPlist(for target: Target) -> [String: Any] {
var dictionary: [String: Any] = [:]
dictionary["CFBundleIdentifier"] = "$(PRODUCT_BUNDLE_IDENTIFIER)"
dictionary["CFBundleInfoDictionaryVersion"] = "6.0"
dictionary["CFBundleExecutable"] = "$(EXECUTABLE_NAME)"
dictionary["CFBundleName"] = "$(PRODUCT_NAME)"
dictionary["CFBundleDevelopmentRegion"] = "$(DEVELOPMENT_LANGUAGE)"
dictionary["CFBundleShortVersionString"] = "1.0"
dictionary["CFBundleVersion"] = "1"
return dictionary
}()
public func generateProperties(target: Target) -> [String: Any] {
var targetInfoPlist = defaultInfoPlist
// Bundles should not contain any CFBundleExecutable otherwise they will be rejected when uploading.
if target.type != .bundle {
dictionary["CFBundleExecutable"] = "$(EXECUTABLE_NAME)"
}
return dictionary
}
public func generateProperties(for target: Target) -> [String: Any] {
var targetInfoPlist = generateDefaultInfoPlist(for: target)
switch target.type {
case .uiTestBundle,
.unitTestBundle:

View File

@ -9,6 +9,7 @@ public class PBXProjGenerator {
let project: Project
let pbxProj: PBXProj
let projectDirectory: Path?
let carthageResolver: CarthageDependencyResolver
var sourceGenerator: SourceGenerator!
@ -24,11 +25,14 @@ public class PBXProjGenerator {
var generated = false
public init(project: Project) {
public init(project: Project, projectDirectory: Path? = nil) {
self.project = project
carthageResolver = CarthageDependencyResolver(project: project)
pbxProj = PBXProj(rootObject: nil, objectVersion: project.objectVersion)
sourceGenerator = SourceGenerator(project: project, pbxProj: pbxProj)
self.projectDirectory = projectDirectory
sourceGenerator = SourceGenerator(project: project,
pbxProj: pbxProj,
projectDirectory: projectDirectory)
}
@discardableResult
@ -859,7 +863,7 @@ public class PBXProjGenerator {
searchForPlist = false
}
if let plistPath = plistPath {
buildSettings["INFOPLIST_FILE"] = (try? plistPath.relativePath(from: project.basePath)) ?? plistPath
buildSettings["INFOPLIST_FILE"] = (try? plistPath.relativePath(from: projectDirectory ?? project.basePath)) ?? plistPath
}
}
@ -894,7 +898,11 @@ public class PBXProjGenerator {
if dependency.type == .target,
let dependencyTarget = project.getTarget(dependency.reference),
dependencyTarget.type.isApp {
buildSettings["TEST_HOST"] = "$(BUILT_PRODUCTS_DIR)/\(dependencyTarget.productName).app/\(dependencyTarget.productName)"
if dependencyTarget.platform == .macOS {
buildSettings["TEST_HOST"] = "$(BUILT_PRODUCTS_DIR)/\(dependencyTarget.productName).app/Contents/MacOS/\(dependencyTarget.productName)"
} else {
buildSettings["TEST_HOST"] = "$(BUILT_PRODUCTS_DIR)/\(dependencyTarget.productName).app/\(dependencyTarget.productName)"
}
break
}
}

View File

@ -13,10 +13,11 @@ public class ProjectGenerator {
self.project = project
}
public func generateXcodeProject() throws -> XcodeProj {
public func generateXcodeProject(in projectDirectory: Path? = nil) throws -> XcodeProj {
// generate PBXProj
let pbxProjGenerator = PBXProjGenerator(project: project)
let pbxProjGenerator = PBXProjGenerator(project: project,
projectDirectory: projectDirectory)
let pbxProj = try pbxProjGenerator.generate()
// generate Schemes

View File

@ -13,6 +13,7 @@ struct SourceFile {
class SourceGenerator {
var rootGroups: Set<PBXFileElement> = []
private let projectDirectory: Path?
private var fileReferencesByPath: [String: PBXFileElement] = [:]
private var groupsByPath: [Path: PBXGroup] = [:]
private var variantGroupsByPath: [Path: PBXVariantGroup] = [:]
@ -30,9 +31,18 @@ class SourceGenerator {
private(set) var knownRegions: Set<String> = []
init(project: Project, pbxProj: PBXProj) {
init(project: Project, pbxProj: PBXProj, projectDirectory: Path?) {
self.project = project
self.pbxProj = pbxProj
self.projectDirectory = projectDirectory
}
private func resolveGroupPath(_ path: Path, isTopLevelGroup: Bool) -> String {
if isTopLevelGroup, let relativePath = try? path.relativePath(from: projectDirectory ?? project.basePath).string {
return relativePath
} else {
return path.lastComponent
}
}
@discardableResult
@ -286,9 +296,8 @@ class SourceGenerator {
let isTopLevelGroup = (isBaseGroup && !createIntermediateGroups) || isRootPath
let groupName = name ?? path.lastComponent
let groupPath = isTopLevelGroup ?
((try? path.relativePath(from: project.basePath)) ?? path).string :
path.lastComponent
let groupPath = resolveGroupPath(path, isTopLevelGroup: isTopLevelGroup)
let group = PBXGroup(
children: children,
sourceTree: .group,

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>

View File

@ -0,0 +1,26 @@
import XCTest
class TestProjectTests: XCTestCase {
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
}
func testExample() {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
func testPerformanceExample() {
// This is an example of a performance test case.
measure {
// Put the code you want to measure the time of here.
}
}
}

View File

@ -81,6 +81,7 @@
768648ED7E93B6D888574144 /* module.modulemap in CopyFiles */ = {isa = PBXBuildFile; fileRef = F2950763C4C568CC85021D18 /* module.modulemap */; };
7A0DABBEA55B06E148C665A8 /* StaticLibrary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AC91042453E18DF74BA1C0F /* StaticLibrary.swift */; };
7A8C78212CEAC6452DFAB00E /* FrameworkFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A5F527F2590C14956518174 /* FrameworkFile.swift */; };
7C8FF0B857E390417134C10F /* Result.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D296BB7355994040E197A1EE /* Result.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
7F658343A505B824321E086B /* Headers in Headers */ = {isa = PBXBuildFile; fileRef = 2E1E747C7BC434ADB80CC269 /* Headers */; settings = {ATTRIBUTES = (Public, ); }; };
803B7CE086CFBA409F9D1ED7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 108BB29172D27BE3BD1E7F35 /* Assets.xcassets */; };
900CFAD929CAEE3861127627 /* MyBundle.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 7B5068D64404C61A67A18458 /* MyBundle.bundle */; };
@ -99,6 +100,7 @@
B2D43A31C184E34EF9CB743C /* Framework.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 8A9274BE42A03DC5DA1FAD04 /* Framework.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
B47F2629BFE5853767C8BB5E /* Contacts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FDB2B6A77D39CD5602F2125F /* Contacts.framework */; };
B49D3A51787E362DE4D0E78A /* SomeXPCService.xpc in CopyFiles */ = {isa = PBXBuildFile; fileRef = 70A8E15C81E454DC950C59F0 /* SomeXPCService.xpc */; };
B9F3C9E77019EC3423A7F5D8 /* TestProjectTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87DF9DCA8399E3214A7E27CF /* TestProjectTests.swift */; };
BAA1C1E3828F5D43546AF997 /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 0BB1B49A91B892152D68ED76 /* libc++.tbd */; };
BD1419893577E6CEDF8CBA83 /* Result.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 0C5AC2545AE4D4F7F44E2E9B /* Result.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
BD95416F2005199F6B3572CF /* Framework.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 41FC82ED1C4C3B7B3D7B2FB7 /* Framework.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
@ -175,6 +177,13 @@
remoteGlobalIDString = 13E8C5AB873CEE21E18E552F;
remoteInfo = StaticLibrary_ObjC_iOS;
};
610412261F48A0A36C32FC5C /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0FBAE303E3CFC2ABAC876A77 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 020A320BB3736FCDE6CC4E70;
remoteInfo = App_macOS;
};
7F4EAACE4AD6CF285B7D3308 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0FBAE303E3CFC2ABAC876A77 /* Project object */;
@ -306,6 +315,17 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
6CB76DFA8662672C4245AF41 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
7C8FF0B857E390417134C10F /* Result.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
7FAF0BBB3DE701EBE5DBE810 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
@ -411,11 +431,13 @@
/* Begin PBXFileReference section */
020E4DA91C9132845CAFDC5D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
039F208D1138598CE060F140 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
056A43A09CE7E88D578696D8 /* StaticLibrary_ObjC.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = StaticLibrary_ObjC.a; sourceTree = BUILT_PRODUCTS_DIR; };
068EDF47F0B087F6A4052AC0 /* Empty.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Empty.h; sourceTree = "<group>"; };
0704B6CAFBB53E0EBB08F6B3 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
09B82F603D981398F38D762E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
0B193CC6D2B3003418A550B6 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/LocalizedStoryboard.strings; sourceTree = "<group>"; };
0B9D98D935F2C69A1F5BA539 /* App_macOS_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = App_macOS_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
0BB1B49A91B892152D68ED76 /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; };
0C5AC2545AE4D4F7F44E2E9B /* Result.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Result.framework; sourceTree = "<group>"; };
0D09D243DBCF9D32E239F1E8 /* App_watchOS Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "App_watchOS Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
@ -466,6 +488,7 @@
7F1A2F579A6F79C62DDA0571 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7FDC16E1938AA114B67D87A9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Interface.storyboard; sourceTree = "<group>"; };
814822136AF3C64428D69DD6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
87DF9DCA8399E3214A7E27CF /* TestProjectTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestProjectTests.swift; sourceTree = "<group>"; };
8A9274BE42A03DC5DA1FAD04 /* Framework.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Framework.framework; sourceTree = BUILT_PRODUCTS_DIR; };
8CAF6C55B555E3E1352645B6 /* ExtensionDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionDelegate.swift; sourceTree = "<group>"; };
93C033648A37D95027845BD3 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
@ -662,6 +685,7 @@
FC81A3ED177CE9DA68D09941 /* App_iOS_Tests */,
0D039F2E62354C7C8E283BE6 /* App_iOS_UITests */,
EE78B4FBD0137D1975C47D76 /* App_macOS */,
6DE1C805DC13547F27FD86C6 /* App_macOS_Tests */,
BAE6C12745737019DC9E98BF /* App_watchOS */,
795B8D70B674C850B57DD39D /* App_watchOS Extension */,
6DBE0EE90642BB3F6E58AD43 /* Configs */,
@ -740,6 +764,15 @@
path = Configs;
sourceTree = "<group>";
};
6DE1C805DC13547F27FD86C6 /* App_macOS_Tests */ = {
isa = PBXGroup;
children = (
039F208D1138598CE060F140 /* Info.plist */,
87DF9DCA8399E3214A7E27CF /* TestProjectTests.swift */,
);
path = App_macOS_Tests;
sourceTree = "<group>";
};
795B8D70B674C850B57DD39D /* App_watchOS Extension */ = {
isa = PBXGroup;
children = (
@ -813,6 +846,7 @@
CB77A637470A3CDA2BDDBE99 /* App_iOS_Tests.xctest */,
13EEAB58665D79C15184D9D0 /* App_iOS_UITests.xctest */,
B1C33BB070583BE3B0EC0E68 /* App_iOS.app */,
0B9D98D935F2C69A1F5BA539 /* App_macOS_Tests.xctest */,
33F6DCDC37D2E66543D4965D /* App_macOS.app */,
0D09D243DBCF9D32E239F1E8 /* App_watchOS Extension.appex */,
A680BE9F68A255B0FB291AE6 /* App_watchOS.app */,
@ -1293,6 +1327,23 @@
productReference = 6177CC6263783487E93F7F4D /* Framework.framework */;
productType = "com.apple.product-type.framework";
};
71E2BDAC4B8E8FC2BBF75C55 /* App_macOS_Tests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 62C52A55CB8D3BD9A055FD14 /* Build configuration list for PBXNativeTarget "App_macOS_Tests" */;
buildPhases = (
8A616537E6E1BEAB59E069C7 /* Sources */,
6CB76DFA8662672C4245AF41 /* Embed Frameworks */,
);
buildRules = (
);
dependencies = (
8B1B6143B8996B3CF0FE61C5 /* PBXTargetDependency */,
);
name = App_macOS_Tests;
productName = App_macOS_Tests;
productReference = 0B9D98D935F2C69A1F5BA539 /* App_macOS_Tests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
7D3D92034F4F203C140574F0 /* StaticLibrary_ObjC_watchOS */ = {
isa = PBXNativeTarget;
buildConfigurationList = 0129D8A8DCD54069136D90F7 /* Build configuration list for PBXNativeTarget "StaticLibrary_ObjC_watchOS" */;
@ -1490,6 +1541,9 @@
0867B0DACEF28C11442DE8F7 = {
ProvisioningStyle = Automatic;
};
71E2BDAC4B8E8FC2BBF75C55 = {
TestTargetID = 020A320BB3736FCDE6CC4E70;
};
BF3693DCA6182D7AEC410AFC = {
CUSTOM = value;
};
@ -1517,6 +1571,7 @@
DC2F16BAA6E13B44AB62F888 /* App_iOS_Tests */,
F674B2CFC4738EEC49BAD0DA /* App_iOS_UITests */,
020A320BB3736FCDE6CC4E70 /* App_macOS */,
71E2BDAC4B8E8FC2BBF75C55 /* App_macOS_Tests */,
208179651927D1138D19B5AD /* App_watchOS */,
307AE3FA155FFD09B74AE351 /* App_watchOS Extension */,
B61ED4688789B071275E2B7A /* EntitledApp */,
@ -1889,6 +1944,14 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
8A616537E6E1BEAB59E069C7 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B9F3C9E77019EC3423A7F5D8 /* TestProjectTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
8FD76C583F8C166F974F4BE2 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@ -2062,6 +2125,11 @@
target = 578C80E461E675508CED5DC3 /* StaticLibrary_ObjC_macOS */;
targetProxy = DECF0B88B325A158E4E1D9AE /* PBXContainerItemProxy */;
};
8B1B6143B8996B3CF0FE61C5 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 020A320BB3736FCDE6CC4E70 /* App_macOS */;
targetProxy = 610412261F48A0A36C32FC5C /* PBXContainerItemProxy */;
};
981D116D40DBA0407D0E0E94 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 834F55973F05AC8A18144DB0 /* iMessageApp */;
@ -2474,6 +2542,28 @@
};
name = "Test Debug";
};
12BCDE0EFCEE621B881E424C /* Test Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/Mac",
);
INFOPLIST_FILE = App_macOS_Tests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/../Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = "com.project.App-macOS-Tests";
SDKROOT = macosx;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/App_macOS.app/Contents/MacOS/App_macOS";
TEST_TARGET_NAME = App_macOS;
};
name = "Test Release";
};
1341099486D8FE68A99CB5FE /* Test Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@ -3000,6 +3090,28 @@
};
name = "Production Debug";
};
44C2FD12D7D26D71D8150C76 /* Test Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/Mac",
);
INFOPLIST_FILE = App_macOS_Tests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/../Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = "com.project.App-macOS-Tests";
SDKROOT = macosx;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/App_macOS.app/Contents/MacOS/App_macOS";
TEST_TARGET_NAME = App_macOS;
};
name = "Test Debug";
};
4621C6C8A78FBB1CF4078178 /* Production Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
@ -3154,6 +3266,50 @@
};
name = "Production Debug";
};
4F029A78B7BAB85B1E284798 /* Production Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/Mac",
);
INFOPLIST_FILE = App_macOS_Tests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/../Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = "com.project.App-macOS-Tests";
SDKROOT = macosx;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/App_macOS.app/Contents/MacOS/App_macOS";
TEST_TARGET_NAME = App_macOS;
};
name = "Production Debug";
};
4FA4DE89FDED9F49FAABED58 /* Production Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/Mac",
);
INFOPLIST_FILE = App_macOS_Tests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/../Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = "com.project.App-macOS-Tests";
SDKROOT = macosx;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/App_macOS.app/Contents/MacOS/App_macOS";
TEST_TARGET_NAME = App_macOS;
};
name = "Production Release";
};
511E983641E821858100107B /* Production Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@ -5413,6 +5569,28 @@
};
name = "Production Release";
};
EBD2F70285E21FFAB1C23D01 /* Staging Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/Mac",
);
INFOPLIST_FILE = App_macOS_Tests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/../Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = "com.project.App-macOS-Tests";
SDKROOT = macosx;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/App_macOS.app/Contents/MacOS/App_macOS";
TEST_TARGET_NAME = App_macOS;
};
name = "Staging Release";
};
EC3A16C2887B72837F84904A /* Production Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
@ -5573,6 +5751,28 @@
};
name = "Test Release";
};
FB472DFA702C8A3B55153F97 /* Staging Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/Mac",
);
INFOPLIST_FILE = App_macOS_Tests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/../Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = "com.project.App-macOS-Tests";
SDKROOT = macosx;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/App_macOS.app/Contents/MacOS/App_macOS";
TEST_TARGET_NAME = App_macOS;
};
name = "Staging Debug";
};
FBC34FE61DA25D0516C15B60 /* Staging Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
@ -5784,6 +5984,19 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = "";
};
62C52A55CB8D3BD9A055FD14 /* Build configuration list for PBXNativeTarget "App_macOS_Tests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
4F029A78B7BAB85B1E284798 /* Production Debug */,
4FA4DE89FDED9F49FAABED58 /* Production Release */,
FB472DFA702C8A3B55153F97 /* Staging Debug */,
EBD2F70285E21FFAB1C23D01 /* Staging Release */,
44C2FD12D7D26D71D8150C76 /* Test Debug */,
12BCDE0EFCEE621B881E424C /* Test Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = "";
};
62D7BB889799B73F7E8B798F /* Build configuration list for PBXNativeTarget "App_iOS" */ = {
isa = XCConfigurationList;
buildConfigurations = (

View File

@ -228,6 +228,13 @@ targets:
sources: App_iOS_UITests
dependencies:
- target: App_iOS
App_macOS_Tests:
type: bundle.unit-test
platform: macOS
sources: App_macOS_Tests
dependencies:
- target: App_macOS
XPC Service:
type: xpc-service

View File

@ -971,16 +971,17 @@ class ProjectGeneratorTests: XCTestCase {
let infoPlistFile = tempPath + plist.path
let data: Data = try infoPlistFile.read()
let infoPlist = try PropertyListSerialization.propertyList(from: data, options: [], format: nil) as! [String: Any]
var expectedInfoPlist: [String: Any] = [:]
expectedInfoPlist["CFBundleIdentifier"] = "$(PRODUCT_BUNDLE_IDENTIFIER)"
expectedInfoPlist["CFBundleInfoDictionaryVersion"] = "6.0"
expectedInfoPlist["CFBundleExecutable"] = "$(EXECUTABLE_NAME)"
expectedInfoPlist["CFBundleName"] = "$(PRODUCT_NAME)"
expectedInfoPlist["CFBundleDevelopmentRegion"] = "$(DEVELOPMENT_LANGUAGE)"
expectedInfoPlist["CFBundleShortVersionString"] = "1.0"
expectedInfoPlist["CFBundleVersion"] = "1"
expectedInfoPlist["CFBundlePackageType"] = "APPL"
expectedInfoPlist["UISupportedInterfaceOrientations"] = ["UIInterfaceOrientationPortrait", "UIInterfaceOrientationLandscapeLeft"]
let expectedInfoPlist: [String: Any] = [
"CFBundleIdentifier": "$(PRODUCT_BUNDLE_IDENTIFIER)",
"CFBundleInfoDictionaryVersion": "6.0",
"CFBundleName": "$(PRODUCT_NAME)",
"CFBundleExecutable": "$(EXECUTABLE_NAME)",
"CFBundleDevelopmentRegion": "$(DEVELOPMENT_LANGUAGE)",
"CFBundleShortVersionString": "1.0",
"CFBundleVersion": "1",
"CFBundlePackageType": "APPL",
"UISupportedInterfaceOrientations": ["UIInterfaceOrientationPortrait", "UIInterfaceOrientationLandscapeLeft"]
]
try expect(NSDictionary(dictionary: expectedInfoPlist).isEqual(to: infoPlist)).beTrue()
}
@ -1002,6 +1003,82 @@ class ProjectGeneratorTests: XCTestCase {
// generated plist should not be in buildsettings
try expect(targetConfig.buildSettings["INFOPLIST_FILE"] as? String) == predefinedPlistPath
}
$0.it("generate info.plist doesn't generate CFBundleExecutable for targets with type bundle") {
let plist = Plist(path: "Info.plist", attributes: [:])
let tempPath = Path.temporary + "info"
let project = Project(basePath: tempPath, name: "", targets: [Target(name: "", type: .bundle, platform: .iOS, info: plist)])
let pbxProject = try project.generatePbxProj()
let writer = FileWriter(project: project)
try writer.writePlists()
guard let targetConfig = pbxProject.nativeTargets.first?.buildConfigurationList?.buildConfigurations.first else {
throw failure("Couldn't find Target config")
}
try expect(targetConfig.buildSettings["INFOPLIST_FILE"] as? String) == plist.path
let infoPlistFile = tempPath + plist.path
let data: Data = try infoPlistFile.read()
let infoPlist = try PropertyListSerialization.propertyList(from: data, options: [], format: nil) as! [String: Any]
let expectedInfoPlist: [String: Any] = [
"CFBundleIdentifier": "$(PRODUCT_BUNDLE_IDENTIFIER)",
"CFBundleInfoDictionaryVersion": "6.0",
"CFBundleName": "$(PRODUCT_NAME)",
"CFBundleDevelopmentRegion": "$(DEVELOPMENT_LANGUAGE)",
"CFBundleShortVersionString": "1.0",
"CFBundleVersion": "1",
"CFBundlePackageType": "BNDL"
]
try expect(NSDictionary(dictionary: expectedInfoPlist).isEqual(to: infoPlist)).beTrue()
}
}
}
func testGenerateXcodeProjectWithDestination() throws {
let groupName = "App_iOS"
let sourceDirectory = fixturePath + "TestProject" + groupName
let frameworkWithSources = Target(
name: "MyFramework",
type: .framework,
platform: .iOS,
sources: [TargetSource(path: sourceDirectory.string)]
)
describe("generateXcodeProject") {
$0.context("without projectDirectory") {
$0.it("generate groups") {
let project = Project(name: "test", targets: [frameworkWithSources])
let generator = ProjectGenerator(project: project)
let generatedProject = try generator.generateXcodeProject()
let group = generatedProject.pbxproj.groups.first(where: { $0.nameOrPath == groupName })
try expect(group?.path) == "App_iOS"
}
}
$0.context("with projectDirectory") {
$0.it("generate groups") {
let destinationPath = fixturePath
let project = Project(name: "test", targets: [frameworkWithSources])
let generator = ProjectGenerator(project: project)
let generatedProject = try generator.generateXcodeProject(in: destinationPath)
let group = generatedProject.pbxproj.groups.first(where: { $0.nameOrPath == groupName })
try expect(group?.path) == "TestProject/App_iOS"
}
$0.it("generate Info.plist") {
let destinationPath = fixturePath
let project = Project(name: "test", targets: [frameworkWithSources])
let generator = ProjectGenerator(project: project)
let generatedProject = try generator.generateXcodeProject(to: destinationPath)
let plists = generatedProject.pbxproj.buildConfigurations.compactMap { $0.buildSettings["INFOPLIST_FILE"] as? Path }
try expect(plists.count) == 2
for plist in plists {
try expect(plist) == "TestProject/App_iOS/Info.plist"
}
}
}
}
}
}