├── .gitignore
├── .swiftlint.yml
├── .travis.yml
├── Info.plist
├── LICENSE.txt
├── Package.swift
├── README.md
├── SMJobKit.podspec
├── SMJobKit.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── SMJobKit.xccheckout
└── xcshareddata
│ └── xcschemes
│ └── SMJobKit.xcscheme
├── SMJobKit.xcworkspace
├── contents.xcworkspacedata
└── xcshareddata
│ ├── IDEWorkspaceChecks.plist
│ └── SMJobKit.xccheckout
├── SampleApplication
├── SampleApplication.xcodeproj
│ └── project.pbxproj
├── SampleApplication
│ ├── AppDelegate.swift
│ ├── Base.lproj
│ │ └── MainMenu.xib
│ ├── SampleApplication-Bridging-Header.h
│ ├── SampleApplication-Info.plist
│ ├── SampleService.swift
│ └── en.lproj
│ │ ├── Credits.rtf
│ │ └── InfoPlist.strings
└── SampleService
│ ├── SampleService-Info.plist
│ ├── SampleService-Launchd.plist
│ └── main.m
├── Sources
└── SMJobKit
│ ├── BridgingHeader.h
│ ├── Client.swift
│ ├── ClientUtility.swift
│ └── ErrorTypes.swift
├── Tests
├── SMJobKitTests
│ ├── ClientTests.swift
│ ├── Info.plist
│ ├── MissingClient.swift
│ └── TestClient.swift
└── TestService
│ ├── Info.plist
│ ├── Launchd.plist
│ └── main.m
└── Xcode Templates
├── Application
└── SMJobKit-Based Application.xctemplate
│ ├── README-SMJobKit.md
│ ├── TemplateInfo.plist
│ └── ___VARIABLE_smjServiceName:RFC1034Identifier___.swift
└── Framework & Library
└── SMJobKit Service.xctemplate
├── TemplateIcon.icns
├── TemplateInfo.plist
├── ___PACKAGENAMEASIDENTIFIER___-Info.plist
├── ___PACKAGENAMEASIDENTIFIER___-Launchd.plist
└── main.m
/.gitignore:
--------------------------------------------------------------------------------
1 | xcuserdata
2 | .build
3 |
--------------------------------------------------------------------------------
/.swiftlint.yml:
--------------------------------------------------------------------------------
1 | disabled_rules:
2 | - line_length
3 | - type_name
4 | force_cast: warning
5 | force_try: warning
6 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: objective-c
2 | xcode_workspace: SMJobKit.xcworkspace
3 | xcode_scheme: SMJobKit
4 | osx_image: xcode10.2
5 |
--------------------------------------------------------------------------------
/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | English
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | ${PRODUCT_NAME}
17 | CFBundlePackageType
18 | FMWK
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | NSHumanReadableCopyright
26 | Apache License 2.0
27 | NSPrincipalClass
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
203 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:4.2
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "SMJobKit",
8 | products: [
9 | // Products define the executables and libraries produced by a package, and make them visible to other packages.
10 | .library(
11 | name: "SMJobKit",
12 | targets: ["SMJobKit"])
13 | ],
14 | dependencies: [
15 | // Dependencies declare other packages that this package depends on.
16 | // .package(url: /* package url */, from: "1.0.0"),
17 | ],
18 | targets: [
19 | // Targets are the basic building blocks of a package. A target can define a module or a test suite.
20 | // Targets can depend on other targets in this package, and on products in packages which this package depends on.
21 | .target(
22 | name: "SMJobKit",
23 | dependencies: []),
24 | .testTarget(
25 | name: "SMJobKitTests",
26 | dependencies: ["SMJobKit"])
27 | ],
28 | swiftLanguageVersions: [.v4, .v4_2, .version("5")]
29 | )
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | SMJobKit
2 | ========
3 |
4 | Using SMJobBless and friends is rather… painful. SMJobKit does everything in its power to
5 | alleviate that and get you back to writing awesome macOS apps.
6 |
7 | SMJobKit is more than just a framework/library to link against. It gives you:
8 |
9 | * A Xcode target template for SMJobBless-ready launchd services, completely configured for proper
10 | code signing!
11 |
12 | * A client abstraction that manages installing/upgrading your app's service(s).
13 |
14 | * A service library that pulls in as little additional code as possible. Less surface area for
15 | security vulnerabilities!
16 |
17 |
18 | Project Configuration
19 | ---------------------
20 |
21 | To get started, pull the SMJobKit project into your own project or workspace. Have your application
22 | depend on the SMJobKit framework, and hit build. In addition to building the framework, this also
23 | causes the Xcode template to install its self into `~/Library/Developer/Xcode/Templates`.
24 |
25 | Next, you should set up your service helper/target: Add a new _SMJobKit Service_ target to the
26 | project. This is relatively configuration-heavy, so you should probably build it right away to make
27 | sure everything is properly configured (and your code signing certificates are in order). You may
28 | want to review the [template's documentation](https://github.com/IngmarStein/SMJobKit/tree/master/Xcode%20Templates/Framework%20%26%20Library/SMJobKit%20Service.xctemplate)
29 | for an in-depth explanation of what it is doing for you.
30 |
31 | Finally, you need to add a Copy Files build phase to your application target. The destination
32 | should be "Wrapper" with a subpath of `Contents/Library/LaunchServices`. Add the service's built
33 | product to the list. Make sure you add a dependency on your service target!
34 |
35 | And, hopefully, that's all you need to do in order to configure your project!
36 |
37 |
38 | Client Abstraction
39 | ------------------
40 |
41 | You'll want to create a subclass of `Client` in your application, and override
42 | `serviceIdentifier` at the very least.
43 |
--------------------------------------------------------------------------------
/SMJobKit.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = "SMJobKit"
3 | s.version = "0.0.21"
4 | s.swift_version = '5.0'
5 | s.summary = "Framework that simplifies SMJobBless."
6 | s.homepage = "https://github.com/IngmarStein/SMJobKit"
7 | s.authors = { "Ian MacLeod" => "ian@nevir.net", "Ingmar Stein" => "IngmarStein@gmail.com" }
8 | s.source = { :git => "https://github.com/IngmarStein/SMJobKit.git", :tag => "0.0.19" }
9 | s.platform = :osx, '10.9'
10 | s.source_files = 'Sources/**/*.{h,swift}'
11 | s.framework = 'ServiceManagement', 'Security'
12 | s.requires_arc = true
13 | s.static_framework = true
14 | s.public_header_files = 'Sources/*.h'
15 | s.license = { :type => "Apache License, Version 2.0", :file => "LICENSE.txt" }
16 | s.description = <<-DESC
17 | Using SMJobBless and friends is rather ...painful. SMJobKit does everything in its power to alleviate that and get you back to writing awesome macOS apps.
18 |
19 | SMJobKit is more than just a framework/library to link against. It gives you:
20 | - A Xcode target template for SMJobBless-ready launchd services, completely configured for proper code signing!
21 | - A client abstraction that manages installing/upgrading your app's service(s).
22 | - A service library that pulls in as little additional code as possible. Less surface area for security vulnerabilities!
23 | DESC
24 | end
25 |
--------------------------------------------------------------------------------
/SMJobKit.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 51;
7 | objects = {
8 |
9 | /* Begin PBXAggregateTarget section */
10 | 3CCC06D015AA823000C84BE1 /* Xcode Templates */ = {
11 | isa = PBXAggregateTarget;
12 | buildConfigurationList = 3CCC06D115AA823000C84BE1 /* Build configuration list for PBXAggregateTarget "Xcode Templates" */;
13 | buildPhases = (
14 | 3CD9BC9715B24DBF00F0007B /* Copy Templates */,
15 | );
16 | dependencies = (
17 | );
18 | name = "Xcode Templates";
19 | productName = "SMJobKit Service Template";
20 | };
21 | /* End PBXAggregateTarget section */
22 |
23 | /* Begin PBXBuildFile section */
24 | 3C2BFAB515AB33020011FA52 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C2BFAB415AB33020011FA52 /* main.m */; };
25 | 3C2BFABE15AB33EF0011FA52 /* net.nevir.SMJobKitTests.TestService in Copy Services */ = {isa = PBXBuildFile; fileRef = 3C2BFAB015AB33020011FA52 /* net.nevir.SMJobKitTests.TestService */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
26 | 3CA1508F15A91179001CF9F8 /* SMJobKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3CA1507115A91179001CF9F8 /* SMJobKit.framework */; };
27 | 95340BA21AC83DB400DE4879 /* ErrorTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95340BA11AC83DB400DE4879 /* ErrorTypes.swift */; };
28 | 95340BA41AC84C9C00DE4879 /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95340BA31AC84C9C00DE4879 /* Client.swift */; };
29 | 95340BA61AC8555D00DE4879 /* MissingClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95340BA51AC8555D00DE4879 /* MissingClient.swift */; };
30 | 95340BA81AC855A100DE4879 /* TestClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95340BA71AC855A100DE4879 /* TestClient.swift */; };
31 | 95340BAA1AC855DE00DE4879 /* ClientTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95340BA91AC855DE00DE4879 /* ClientTests.swift */; };
32 | 956253011AC837A900D93E91 /* ClientUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 956253001AC837A900D93E91 /* ClientUtility.swift */; };
33 | /* End PBXBuildFile section */
34 |
35 | /* Begin PBXContainerItemProxy section */
36 | 3C2BFABF15AB34070011FA52 /* PBXContainerItemProxy */ = {
37 | isa = PBXContainerItemProxy;
38 | containerPortal = 3CA1506715A91179001CF9F8 /* Project object */;
39 | proxyType = 1;
40 | remoteGlobalIDString = 3C2BFAAF15AB33020011FA52;
41 | remoteInfo = TestService;
42 | };
43 | 3CA1508D15A91179001CF9F8 /* PBXContainerItemProxy */ = {
44 | isa = PBXContainerItemProxy;
45 | containerPortal = 3CA1506715A91179001CF9F8 /* Project object */;
46 | proxyType = 1;
47 | remoteGlobalIDString = 3CA1507015A91179001CF9F8;
48 | remoteInfo = SMJobKit;
49 | };
50 | /* End PBXContainerItemProxy section */
51 |
52 | /* Begin PBXCopyFilesBuildPhase section */
53 | 3C2BFABD15AB33CB0011FA52 /* Copy Services */ = {
54 | isa = PBXCopyFilesBuildPhase;
55 | buildActionMask = 2147483647;
56 | dstPath = Contents/Library/LaunchServices;
57 | dstSubfolderSpec = 1;
58 | files = (
59 | 3C2BFABE15AB33EF0011FA52 /* net.nevir.SMJobKitTests.TestService in Copy Services */,
60 | );
61 | name = "Copy Services";
62 | runOnlyForDeploymentPostprocessing = 0;
63 | };
64 | /* End PBXCopyFilesBuildPhase section */
65 |
66 | /* Begin PBXFileReference section */
67 | 3C2BFAB015AB33020011FA52 /* net.nevir.SMJobKitTests.TestService */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = net.nevir.SMJobKitTests.TestService; sourceTree = BUILT_PRODUCTS_DIR; };
68 | 3C2BFAB415AB33020011FA52 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
69 | 3C2BFAB615AB33020011FA52 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
70 | 3C2BFAB715AB33020011FA52 /* Launchd.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Launchd.plist; sourceTree = ""; };
71 | 3C560DAD15A9460E00A05BC2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
72 | 3CA1507115A91179001CF9F8 /* SMJobKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SMJobKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
73 | 3CA1507C15A91179001CF9F8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = ../Info.plist; sourceTree = ""; };
74 | 3CA1508915A91179001CF9F8 /* SMJobKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SMJobKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
75 | 3CA150A115A911A0001CF9F8 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = text; path = README.md; sourceTree = ""; };
76 | 3CA150A215A911A7001CF9F8 /* LICENSE.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE.txt; sourceTree = ""; };
77 | 3CCC06D515AA837E00C84BE1 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
78 | 3CCC06D615AA837E00C84BE1 /* TemplateIcon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = TemplateIcon.icns; sourceTree = ""; };
79 | 3CCC06D715AA837E00C84BE1 /* TemplateInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = TemplateInfo.plist; sourceTree = ""; };
80 | 3CD9BC9815B2503F00F0007B /* ___PACKAGENAMEASIDENTIFIER___-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "___PACKAGENAMEASIDENTIFIER___-Info.plist"; sourceTree = ""; };
81 | 3CD9BC9915B2503F00F0007B /* ___PACKAGENAMEASIDENTIFIER___-Launchd.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "___PACKAGENAMEASIDENTIFIER___-Launchd.plist"; sourceTree = ""; };
82 | 3CD9BCD315B2632D00F0007B /* TemplateInfo.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = TemplateInfo.plist; sourceTree = ""; };
83 | 3CFB0E2015B37DE400FA0E6B /* README-SMJobKit.md */ = {isa = PBXFileReference; lastKnownFileType = text; path = "README-SMJobKit.md"; sourceTree = ""; };
84 | 95340BA11AC83DB400DE4879 /* ErrorTypes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ErrorTypes.swift; path = SMJobKit/ErrorTypes.swift; sourceTree = ""; };
85 | 95340BA31AC84C9C00DE4879 /* Client.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Client.swift; path = SMJobKit/Client.swift; sourceTree = ""; };
86 | 95340BA51AC8555D00DE4879 /* MissingClient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MissingClient.swift; sourceTree = ""; };
87 | 95340BA71AC855A100DE4879 /* TestClient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestClient.swift; sourceTree = ""; };
88 | 95340BA91AC855DE00DE4879 /* ClientTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClientTests.swift; sourceTree = ""; };
89 | 956253001AC837A900D93E91 /* ClientUtility.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ClientUtility.swift; path = SMJobKit/ClientUtility.swift; sourceTree = ""; };
90 | 958CB2A81AC95B6300D4FE65 /* ___VARIABLE_smjServiceName:RFC1034Identifier___.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "___VARIABLE_smjServiceName:RFC1034Identifier___.swift"; sourceTree = ""; };
91 | 95CA05321B934371000ABDCE /* BridgingHeader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = BridgingHeader.h; path = SMJobKit/BridgingHeader.h; sourceTree = ""; };
92 | /* End PBXFileReference section */
93 |
94 | /* Begin PBXFrameworksBuildPhase section */
95 | 3C2BFAAE15AB33020011FA52 /* Frameworks */ = {
96 | isa = PBXFrameworksBuildPhase;
97 | buildActionMask = 2147483647;
98 | files = (
99 | );
100 | runOnlyForDeploymentPostprocessing = 0;
101 | };
102 | 3CA1506D15A91179001CF9F8 /* Frameworks */ = {
103 | isa = PBXFrameworksBuildPhase;
104 | buildActionMask = 2147483647;
105 | files = (
106 | );
107 | runOnlyForDeploymentPostprocessing = 0;
108 | };
109 | 3CA1508515A91179001CF9F8 /* Frameworks */ = {
110 | isa = PBXFrameworksBuildPhase;
111 | buildActionMask = 2147483647;
112 | files = (
113 | 3CA1508F15A91179001CF9F8 /* SMJobKit.framework in Frameworks */,
114 | );
115 | runOnlyForDeploymentPostprocessing = 0;
116 | };
117 | /* End PBXFrameworksBuildPhase section */
118 |
119 | /* Begin PBXGroup section */
120 | 3C2BFA8815AB2E570011FA52 /* Supporting Files */ = {
121 | isa = PBXGroup;
122 | children = (
123 | 95CA05321B934371000ABDCE /* BridgingHeader.h */,
124 | 3CA1507C15A91179001CF9F8 /* Info.plist */,
125 | );
126 | name = "Supporting Files";
127 | sourceTree = "";
128 | };
129 | 3C2BFA8915AB2E870011FA52 /* Public */ = {
130 | isa = PBXGroup;
131 | children = (
132 | 95340BA31AC84C9C00DE4879 /* Client.swift */,
133 | 95340BA11AC83DB400DE4879 /* ErrorTypes.swift */,
134 | );
135 | name = Public;
136 | path = ..;
137 | sourceTree = "";
138 | };
139 | 3C2BFA8A15AB2E8F0011FA52 /* Private */ = {
140 | isa = PBXGroup;
141 | children = (
142 | 956253001AC837A900D93E91 /* ClientUtility.swift */,
143 | );
144 | name = Private;
145 | path = ..;
146 | sourceTree = "";
147 | };
148 | 3C2BFAA815AB30EB0011FA52 /* Supporting Files */ = {
149 | isa = PBXGroup;
150 | children = (
151 | 3C560DAD15A9460E00A05BC2 /* Info.plist */,
152 | );
153 | name = "Supporting Files";
154 | sourceTree = "";
155 | };
156 | 3C2BFAA915AB31240011FA52 /* Fixtures */ = {
157 | isa = PBXGroup;
158 | children = (
159 | 95340BA51AC8555D00DE4879 /* MissingClient.swift */,
160 | 95340BA71AC855A100DE4879 /* TestClient.swift */,
161 | );
162 | name = Fixtures;
163 | sourceTree = "";
164 | };
165 | 3C2BFAB315AB33020011FA52 /* TestService */ = {
166 | isa = PBXGroup;
167 | children = (
168 | 3C2BFAB415AB33020011FA52 /* main.m */,
169 | 3C2BFAB615AB33020011FA52 /* Info.plist */,
170 | 3C2BFAB715AB33020011FA52 /* Launchd.plist */,
171 | );
172 | path = TestService;
173 | sourceTree = "";
174 | };
175 | 3C560DAB15A9460E00A05BC2 /* Tests */ = {
176 | isa = PBXGroup;
177 | children = (
178 | 3C560DAC15A9460E00A05BC2 /* SMJobKitTests */,
179 | 3C2BFAB315AB33020011FA52 /* TestService */,
180 | );
181 | path = Tests;
182 | sourceTree = "";
183 | };
184 | 3C560DAC15A9460E00A05BC2 /* SMJobKitTests */ = {
185 | isa = PBXGroup;
186 | children = (
187 | 95340BA91AC855DE00DE4879 /* ClientTests.swift */,
188 | 3C2BFAA915AB31240011FA52 /* Fixtures */,
189 | 3C2BFAA815AB30EB0011FA52 /* Supporting Files */,
190 | );
191 | path = SMJobKitTests;
192 | sourceTree = "";
193 | };
194 | 3CA1506515A91179001CF9F8 = {
195 | isa = PBXGroup;
196 | children = (
197 | 3CA150A115A911A0001CF9F8 /* README.md */,
198 | 3CA150A215A911A7001CF9F8 /* LICENSE.txt */,
199 | 3CA1507A15A91179001CF9F8 /* Sources */,
200 | 3C560DAB15A9460E00A05BC2 /* Tests */,
201 | 3CCC07AA15AA949400C84BE1 /* Xcode Templates */,
202 | 3CA1507215A91179001CF9F8 /* Products */,
203 | );
204 | sourceTree = "";
205 | };
206 | 3CA1507215A91179001CF9F8 /* Products */ = {
207 | isa = PBXGroup;
208 | children = (
209 | 3CA1507115A91179001CF9F8 /* SMJobKit.framework */,
210 | 3CA1508915A91179001CF9F8 /* SMJobKitTests.xctest */,
211 | 3C2BFAB015AB33020011FA52 /* net.nevir.SMJobKitTests.TestService */,
212 | );
213 | name = Products;
214 | sourceTree = "";
215 | };
216 | 3CA1507A15A91179001CF9F8 /* Sources */ = {
217 | isa = PBXGroup;
218 | children = (
219 | 9568253422B447610027EB49 /* SMJobKit */,
220 | 3C2BFA8815AB2E570011FA52 /* Supporting Files */,
221 | );
222 | path = Sources;
223 | sourceTree = "";
224 | };
225 | 3CCC06C515AA810D00C84BE1 /* SMJobKit Service.xctemplate */ = {
226 | isa = PBXGroup;
227 | children = (
228 | 3CD9BC9815B2503F00F0007B /* ___PACKAGENAMEASIDENTIFIER___-Info.plist */,
229 | 3CD9BC9915B2503F00F0007B /* ___PACKAGENAMEASIDENTIFIER___-Launchd.plist */,
230 | 3CCC06D515AA837E00C84BE1 /* main.m */,
231 | 3CCC06D615AA837E00C84BE1 /* TemplateIcon.icns */,
232 | 3CCC06D715AA837E00C84BE1 /* TemplateInfo.plist */,
233 | );
234 | path = "SMJobKit Service.xctemplate";
235 | sourceTree = "";
236 | };
237 | 3CCC07AA15AA949400C84BE1 /* Xcode Templates */ = {
238 | isa = PBXGroup;
239 | children = (
240 | 3CD9BCCF15B2632D00F0007B /* Application */,
241 | 3CD9BC9615B24C2900F0007B /* Framework & Library */,
242 | );
243 | path = "Xcode Templates";
244 | sourceTree = "";
245 | };
246 | 3CD9BC9615B24C2900F0007B /* Framework & Library */ = {
247 | isa = PBXGroup;
248 | children = (
249 | 3CCC06C515AA810D00C84BE1 /* SMJobKit Service.xctemplate */,
250 | );
251 | path = "Framework & Library";
252 | sourceTree = "";
253 | };
254 | 3CD9BCCF15B2632D00F0007B /* Application */ = {
255 | isa = PBXGroup;
256 | children = (
257 | 3CD9BCD015B2632D00F0007B /* SMJobKit-Based Application.xctemplate */,
258 | );
259 | path = Application;
260 | sourceTree = "";
261 | };
262 | 3CD9BCD015B2632D00F0007B /* SMJobKit-Based Application.xctemplate */ = {
263 | isa = PBXGroup;
264 | children = (
265 | 958CB2A81AC95B6300D4FE65 /* ___VARIABLE_smjServiceName:RFC1034Identifier___.swift */,
266 | 3CFB0E2015B37DE400FA0E6B /* README-SMJobKit.md */,
267 | 3CD9BCD315B2632D00F0007B /* TemplateInfo.plist */,
268 | );
269 | path = "SMJobKit-Based Application.xctemplate";
270 | sourceTree = "";
271 | };
272 | 9568253422B447610027EB49 /* SMJobKit */ = {
273 | isa = PBXGroup;
274 | children = (
275 | 3C2BFA8915AB2E870011FA52 /* Public */,
276 | 3C2BFA8A15AB2E8F0011FA52 /* Private */,
277 | );
278 | path = SMJobKit;
279 | sourceTree = "";
280 | };
281 | /* End PBXGroup section */
282 |
283 | /* Begin PBXHeadersBuildPhase section */
284 | 3CA1506E15A91179001CF9F8 /* Headers */ = {
285 | isa = PBXHeadersBuildPhase;
286 | buildActionMask = 2147483647;
287 | files = (
288 | );
289 | runOnlyForDeploymentPostprocessing = 0;
290 | };
291 | /* End PBXHeadersBuildPhase section */
292 |
293 | /* Begin PBXNativeTarget section */
294 | 3C2BFAAF15AB33020011FA52 /* TestService */ = {
295 | isa = PBXNativeTarget;
296 | buildConfigurationList = 3C2BFAB815AB33020011FA52 /* Build configuration list for PBXNativeTarget "TestService" */;
297 | buildPhases = (
298 | 3C4C2B0C15ABF89300775A8B /* Preprocess Files */,
299 | 3C2BFAAD15AB33020011FA52 /* Sources */,
300 | 3C2BFAAE15AB33020011FA52 /* Frameworks */,
301 | );
302 | buildRules = (
303 | );
304 | dependencies = (
305 | );
306 | name = TestService;
307 | productName = TestService;
308 | productReference = 3C2BFAB015AB33020011FA52 /* net.nevir.SMJobKitTests.TestService */;
309 | productType = "com.apple.product-type.tool";
310 | };
311 | 3CA1507015A91179001CF9F8 /* SMJobKit */ = {
312 | isa = PBXNativeTarget;
313 | buildConfigurationList = 3CA1509B15A91179001CF9F8 /* Build configuration list for PBXNativeTarget "SMJobKit" */;
314 | buildPhases = (
315 | 3CA1506C15A91179001CF9F8 /* Sources */,
316 | 3CA1506D15A91179001CF9F8 /* Frameworks */,
317 | 3CA1506E15A91179001CF9F8 /* Headers */,
318 | 3CA1506F15A91179001CF9F8 /* Resources */,
319 | );
320 | buildRules = (
321 | );
322 | dependencies = (
323 | );
324 | name = SMJobKit;
325 | productName = SMJobKit;
326 | productReference = 3CA1507115A91179001CF9F8 /* SMJobKit.framework */;
327 | productType = "com.apple.product-type.framework";
328 | };
329 | 3CA1508815A91179001CF9F8 /* SMJobKitTests */ = {
330 | isa = PBXNativeTarget;
331 | buildConfigurationList = 3CA1509E15A91179001CF9F8 /* Build configuration list for PBXNativeTarget "SMJobKitTests" */;
332 | buildPhases = (
333 | 3CA1508415A91179001CF9F8 /* Sources */,
334 | 3CA1508515A91179001CF9F8 /* Frameworks */,
335 | 3C2BFABD15AB33CB0011FA52 /* Copy Services */,
336 | );
337 | buildRules = (
338 | );
339 | dependencies = (
340 | 3CA1508E15A91179001CF9F8 /* PBXTargetDependency */,
341 | 3C2BFAC015AB34070011FA52 /* PBXTargetDependency */,
342 | );
343 | name = SMJobKitTests;
344 | productName = SMJobKitTests;
345 | productReference = 3CA1508915A91179001CF9F8 /* SMJobKitTests.xctest */;
346 | productType = "com.apple.product-type.bundle.unit-test";
347 | };
348 | /* End PBXNativeTarget section */
349 |
350 | /* Begin PBXProject section */
351 | 3CA1506715A91179001CF9F8 /* Project object */ = {
352 | isa = PBXProject;
353 | attributes = {
354 | CLASSPREFIX = SMJ;
355 | LastSwiftUpdateCheck = 0700;
356 | LastTestingUpgradeCheck = 0630;
357 | LastUpgradeCheck = 1100;
358 | TargetAttributes = {
359 | 3C2BFAAF15AB33020011FA52 = {
360 | ProvisioningStyle = Manual;
361 | };
362 | 3CA1507015A91179001CF9F8 = {
363 | LastSwiftMigration = 1020;
364 | };
365 | };
366 | };
367 | buildConfigurationList = 3CA1506A15A91179001CF9F8 /* Build configuration list for PBXProject "SMJobKit" */;
368 | compatibilityVersion = "Xcode 10.0";
369 | developmentRegion = en;
370 | hasScannedForEncodings = 0;
371 | knownRegions = (
372 | en,
373 | Base,
374 | );
375 | mainGroup = 3CA1506515A91179001CF9F8;
376 | productRefGroup = 3CA1507215A91179001CF9F8 /* Products */;
377 | projectDirPath = "";
378 | projectRoot = "";
379 | targets = (
380 | 3CA1507015A91179001CF9F8 /* SMJobKit */,
381 | 3CA1508815A91179001CF9F8 /* SMJobKitTests */,
382 | 3C2BFAAF15AB33020011FA52 /* TestService */,
383 | 3CCC06D015AA823000C84BE1 /* Xcode Templates */,
384 | );
385 | };
386 | /* End PBXProject section */
387 |
388 | /* Begin PBXResourcesBuildPhase section */
389 | 3CA1506F15A91179001CF9F8 /* Resources */ = {
390 | isa = PBXResourcesBuildPhase;
391 | buildActionMask = 2147483647;
392 | files = (
393 | );
394 | runOnlyForDeploymentPostprocessing = 0;
395 | };
396 | /* End PBXResourcesBuildPhase section */
397 |
398 | /* Begin PBXShellScriptBuildPhase section */
399 | 3C4C2B0C15ABF89300775A8B /* Preprocess Files */ = {
400 | isa = PBXShellScriptBuildPhase;
401 | buildActionMask = 2147483647;
402 | files = (
403 | );
404 | inputPaths = (
405 | );
406 | name = "Preprocess Files";
407 | outputPaths = (
408 | );
409 | runOnlyForDeploymentPostprocessing = 0;
410 | shellPath = "/usr/bin/env ruby";
411 | shellScript = "# Generic preprocessing for ${ENV_VAR} with output to the build dir.\n\nrequire 'cgi'\nrequire 'fileutils'\n\nmissing_keys = ['BUILD_DIR', 'CODE_SIGN_IDENTITY', 'SMJ_PREPROCESS_FILES', 'SMJ_PREPROCESS_DIR'] - ENV.keys\nraise \"Missing required ENV values: #{missing_keys.inspect}\" if missing_keys.size > 0\n\n# SMJ_PREPROCESS_FILES is a comma-separated list of *relative* file paths to preprocess\n# and spit out into the SMJ_PREPROCESS_DIR (w/ the same relative paths as given)\nfiles_to_preprocess = ENV['SMJ_PREPROCESS_FILES'].split(',').map(&:strip)\n\n\n# Environment Cleanup\n# -------------------\ndummy_path = \"#{ENV['BUILD_DIR']}/SMJobKitCodeSigningDummy\"\n\nidentity = ENV['CODE_SIGN_IDENTITY']\n# If you use the generic code signing identity, chances are that it'll conflict.\nidentity = \"#{identity}:\" if identity.end_with? ' Developer'\n\n# We can't seem to get direct access to the code signing certificate that Xcode has\n# selected at this point :(\n`touch #{dummy_path}`\n`codesign --force --sign \"#{identity}\" \"#{dummy_path}\"`\nresult = `codesign --display --verbose --verbose \"#{dummy_path}\" 2>&1`\n`rm #{dummy_path}`\n\nENV['CODE_SIGN_IDENTITY'] = result[/Authority\\=(.*#{Regexp.escape(identity)}.*)/, 1]\n\n\n# Actual Preprocessing\n# --------------------\n\nfiles_to_preprocess.each do |path|\n target_path = File.join(ENV['SMJ_PREPROCESS_DIR'], path)\n FileUtils.mkpath File.dirname(target_path)\n\n open(path) do |input|\n open(target_path, 'w') do |output|\n # Specify macros via ${VAR_NAME} in the preprocessed file. Same as regular\n # Info.plist preprocessing.\n output.write input.read.gsub(/\\$\\{([A-Z_]+)\\}/) { CGI.escapeHTML(ENV[$1]) }\n end\n puts target_path\n end\nend\n";
412 | };
413 | 3CD9BC9715B24DBF00F0007B /* Copy Templates */ = {
414 | isa = PBXShellScriptBuildPhase;
415 | buildActionMask = 2147483647;
416 | files = (
417 | );
418 | inputPaths = (
419 | );
420 | name = "Copy Templates";
421 | outputPaths = (
422 | );
423 | runOnlyForDeploymentPostprocessing = 0;
424 | shellPath = "/usr/bin/env ruby";
425 | shellScript = "source_dir = \"Xcode Templates\"\ndest_dir = File.expand_path(\"~/Library/Developer/Xcode/Templates\")\n\nDir[\"#{source_dir}/*/*\"].each do |template|\n base_path = template[/([^\\/]+\\/[^\\/]+)$/, 1]\n target_path = File.join(dest_dir, base_path)\n\n `rm -rf \"#{target_path}\"`\n `mkdir -p \"#{File.dirname(target_path)}\"`\n `cp -R \"#{source_dir}/#{base_path}\" \"#{target_path}\"`\n\n puts \"Copied #{base_path}\"\nend\n";
426 | };
427 | /* End PBXShellScriptBuildPhase section */
428 |
429 | /* Begin PBXSourcesBuildPhase section */
430 | 3C2BFAAD15AB33020011FA52 /* Sources */ = {
431 | isa = PBXSourcesBuildPhase;
432 | buildActionMask = 2147483647;
433 | files = (
434 | 3C2BFAB515AB33020011FA52 /* main.m in Sources */,
435 | );
436 | runOnlyForDeploymentPostprocessing = 0;
437 | };
438 | 3CA1506C15A91179001CF9F8 /* Sources */ = {
439 | isa = PBXSourcesBuildPhase;
440 | buildActionMask = 2147483647;
441 | files = (
442 | 95340BA41AC84C9C00DE4879 /* Client.swift in Sources */,
443 | 95340BA21AC83DB400DE4879 /* ErrorTypes.swift in Sources */,
444 | 956253011AC837A900D93E91 /* ClientUtility.swift in Sources */,
445 | );
446 | runOnlyForDeploymentPostprocessing = 0;
447 | };
448 | 3CA1508415A91179001CF9F8 /* Sources */ = {
449 | isa = PBXSourcesBuildPhase;
450 | buildActionMask = 2147483647;
451 | files = (
452 | 95340BA61AC8555D00DE4879 /* MissingClient.swift in Sources */,
453 | 95340BA81AC855A100DE4879 /* TestClient.swift in Sources */,
454 | 95340BAA1AC855DE00DE4879 /* ClientTests.swift in Sources */,
455 | );
456 | runOnlyForDeploymentPostprocessing = 0;
457 | };
458 | /* End PBXSourcesBuildPhase section */
459 |
460 | /* Begin PBXTargetDependency section */
461 | 3C2BFAC015AB34070011FA52 /* PBXTargetDependency */ = {
462 | isa = PBXTargetDependency;
463 | target = 3C2BFAAF15AB33020011FA52 /* TestService */;
464 | targetProxy = 3C2BFABF15AB34070011FA52 /* PBXContainerItemProxy */;
465 | };
466 | 3CA1508E15A91179001CF9F8 /* PBXTargetDependency */ = {
467 | isa = PBXTargetDependency;
468 | target = 3CA1507015A91179001CF9F8 /* SMJobKit */;
469 | targetProxy = 3CA1508D15A91179001CF9F8 /* PBXContainerItemProxy */;
470 | };
471 | /* End PBXTargetDependency section */
472 |
473 | /* Begin XCBuildConfiguration section */
474 | 3C2BFAB915AB33020011FA52 /* Debug */ = {
475 | isa = XCBuildConfiguration;
476 | buildSettings = {
477 | CLANG_ENABLE_OBJC_WEAK = YES;
478 | CODE_SIGN_IDENTITY = "Developer ID Application";
479 | CODE_SIGN_STYLE = Manual;
480 | DEVELOPMENT_TEAM = ADVP2P7SJK;
481 | ENABLE_HARDENED_RUNTIME = YES;
482 | OTHER_LDFLAGS = (
483 | "-sectcreate",
484 | __TEXT,
485 | __info_plist,
486 | "\"$(SMJ_PREPROCESS_DIR)/Tests/TestService/Info.plist\"",
487 | "-sectcreate",
488 | __TEXT,
489 | __launchd_plist,
490 | "\"$(SMJ_PREPROCESS_DIR)/Tests/TestService/Launchd.plist\"",
491 | );
492 | PRODUCT_NAME = "net.nevir.SMJobKitTests.$(TARGET_NAME)";
493 | PROVISIONING_PROFILE_SPECIFIER = "";
494 | SKIP_INSTALL = YES;
495 | SMJ_PREPROCESS_DIR = "$(BUILD_DIR)/Preprocessed";
496 | SMJ_PREPROCESS_FILES = "Tests/TestService/Info.plist, Tests/TestService/Launchd.plist";
497 | };
498 | name = Debug;
499 | };
500 | 3C2BFABA15AB33020011FA52 /* Release */ = {
501 | isa = XCBuildConfiguration;
502 | buildSettings = {
503 | CLANG_ENABLE_OBJC_WEAK = YES;
504 | CODE_SIGN_IDENTITY = "Developer ID Application";
505 | CODE_SIGN_STYLE = Manual;
506 | DEVELOPMENT_TEAM = ADVP2P7SJK;
507 | ENABLE_HARDENED_RUNTIME = YES;
508 | OTHER_LDFLAGS = (
509 | "-sectcreate",
510 | __TEXT,
511 | __info_plist,
512 | "\"$(SMJ_PREPROCESS_DIR)/Tests/TestService/Info.plist\"",
513 | "-sectcreate",
514 | __TEXT,
515 | __launchd_plist,
516 | "\"$(SMJ_PREPROCESS_DIR)/Tests/TestService/Launchd.plist\"",
517 | );
518 | PRODUCT_NAME = "net.nevir.SMJobKitTests.$(TARGET_NAME)";
519 | PROVISIONING_PROFILE_SPECIFIER = "";
520 | SKIP_INSTALL = YES;
521 | SMJ_PREPROCESS_DIR = "$(BUILD_DIR)/Preprocessed";
522 | SMJ_PREPROCESS_FILES = "Tests/TestService/Info.plist, Tests/TestService/Launchd.plist";
523 | };
524 | name = Release;
525 | };
526 | 3CA1509915A91179001CF9F8 /* Debug */ = {
527 | isa = XCBuildConfiguration;
528 | buildSettings = {
529 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
530 | CLANG_ENABLE_MODULES = YES;
531 | CLANG_WARN_ASSIGN_ENUM = YES;
532 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
533 | CLANG_WARN_BOOL_CONVERSION = YES;
534 | CLANG_WARN_COMMA = YES;
535 | CLANG_WARN_CONSTANT_CONVERSION = YES;
536 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
537 | CLANG_WARN_EMPTY_BODY = YES;
538 | CLANG_WARN_ENUM_CONVERSION = YES;
539 | CLANG_WARN_INFINITE_RECURSION = YES;
540 | CLANG_WARN_INT_CONVERSION = YES;
541 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
542 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
543 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
544 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
545 | CLANG_WARN_STRICT_PROTOTYPES = YES;
546 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
547 | CLANG_WARN_UNREACHABLE_CODE = YES;
548 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
549 | COMBINE_HIDPI_IMAGES = YES;
550 | ENABLE_NS_ASSERTIONS = NO;
551 | ENABLE_STRICT_OBJC_MSGSEND = YES;
552 | ENABLE_TESTABILITY = YES;
553 | GCC_NO_COMMON_BLOCKS = YES;
554 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
555 | GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
556 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
557 | GCC_WARN_PEDANTIC = YES;
558 | GCC_WARN_UNDECLARED_SELECTOR = YES;
559 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
560 | GCC_WARN_UNUSED_FUNCTION = YES;
561 | GCC_WARN_UNUSED_VARIABLE = YES;
562 | MACOSX_DEPLOYMENT_TARGET = 10.9;
563 | ONLY_ACTIVE_ARCH = YES;
564 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
565 | SWIFT_VERSION = 5.0;
566 | };
567 | name = Debug;
568 | };
569 | 3CA1509A15A91179001CF9F8 /* Release */ = {
570 | isa = XCBuildConfiguration;
571 | buildSettings = {
572 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
573 | CLANG_ENABLE_MODULES = YES;
574 | CLANG_WARN_ASSIGN_ENUM = YES;
575 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
576 | CLANG_WARN_BOOL_CONVERSION = YES;
577 | CLANG_WARN_COMMA = YES;
578 | CLANG_WARN_CONSTANT_CONVERSION = YES;
579 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
580 | CLANG_WARN_EMPTY_BODY = YES;
581 | CLANG_WARN_ENUM_CONVERSION = YES;
582 | CLANG_WARN_INFINITE_RECURSION = YES;
583 | CLANG_WARN_INT_CONVERSION = YES;
584 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
585 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
586 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
587 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
588 | CLANG_WARN_STRICT_PROTOTYPES = YES;
589 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
590 | CLANG_WARN_UNREACHABLE_CODE = YES;
591 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
592 | COMBINE_HIDPI_IMAGES = YES;
593 | ENABLE_STRICT_OBJC_MSGSEND = YES;
594 | GCC_NO_COMMON_BLOCKS = YES;
595 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
596 | GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
597 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
598 | GCC_WARN_PEDANTIC = YES;
599 | GCC_WARN_UNDECLARED_SELECTOR = YES;
600 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
601 | GCC_WARN_UNUSED_FUNCTION = YES;
602 | GCC_WARN_UNUSED_VARIABLE = YES;
603 | MACOSX_DEPLOYMENT_TARGET = 10.9;
604 | SWIFT_COMPILATION_MODE = wholemodule;
605 | SWIFT_OPTIMIZATION_LEVEL = "-O";
606 | SWIFT_VERSION = 5.0;
607 | };
608 | name = Release;
609 | };
610 | 3CA1509C15A91179001CF9F8 /* Debug */ = {
611 | isa = XCBuildConfiguration;
612 | buildSettings = {
613 | CLANG_ENABLE_MODULES = YES;
614 | CLANG_ENABLE_OBJC_WEAK = YES;
615 | DEFINES_MODULE = YES;
616 | DYLIB_COMPATIBILITY_VERSION = 1;
617 | DYLIB_CURRENT_VERSION = 1;
618 | DYLIB_INSTALL_NAME_BASE = "@rpath";
619 | INFOPLIST_FILE = Info.plist;
620 | LD_RUNPATH_SEARCH_PATHS = (
621 | "$(inherited)",
622 | "@executable_path/../Frameworks",
623 | "@loader_path/Frameworks",
624 | );
625 | PRODUCT_BUNDLE_IDENTIFIER = "net.nevir.${PRODUCT_NAME:rfc1034identifier}";
626 | PRODUCT_NAME = SMJobKit;
627 | SKIP_INSTALL = YES;
628 | SWIFT_OBJC_BRIDGING_HEADER = Sources/SMJobKit/BridgingHeader.h;
629 | };
630 | name = Debug;
631 | };
632 | 3CA1509D15A91179001CF9F8 /* Release */ = {
633 | isa = XCBuildConfiguration;
634 | buildSettings = {
635 | CLANG_ENABLE_MODULES = YES;
636 | CLANG_ENABLE_OBJC_WEAK = YES;
637 | DEFINES_MODULE = YES;
638 | DYLIB_COMPATIBILITY_VERSION = 1;
639 | DYLIB_CURRENT_VERSION = 1;
640 | DYLIB_INSTALL_NAME_BASE = "@rpath";
641 | INFOPLIST_FILE = Info.plist;
642 | LD_RUNPATH_SEARCH_PATHS = (
643 | "$(inherited)",
644 | "@executable_path/../Frameworks",
645 | "@loader_path/Frameworks",
646 | );
647 | PRODUCT_BUNDLE_IDENTIFIER = "net.nevir.${PRODUCT_NAME:rfc1034identifier}";
648 | PRODUCT_NAME = SMJobKit;
649 | SKIP_INSTALL = YES;
650 | SWIFT_OBJC_BRIDGING_HEADER = Sources/SMJobKit/BridgingHeader.h;
651 | };
652 | name = Release;
653 | };
654 | 3CA1509F15A91179001CF9F8 /* Debug */ = {
655 | isa = XCBuildConfiguration;
656 | buildSettings = {
657 | CLANG_ENABLE_OBJC_WEAK = YES;
658 | COPY_PHASE_STRIP = NO;
659 | FRAMEWORK_SEARCH_PATHS = (
660 | "$(DEVELOPER_FRAMEWORKS_DIR)",
661 | "$(inherited)",
662 | );
663 | GCC_PREPROCESSOR_DEFINITIONS = (
664 | "DEBUG=1",
665 | "$(inherited)",
666 | );
667 | INFOPLIST_FILE = Tests/SMJobKitTests/Info.plist;
668 | LD_RUNPATH_SEARCH_PATHS = (
669 | "$(inherited)",
670 | "@executable_path/../Frameworks",
671 | "@loader_path/../Frameworks",
672 | );
673 | PRODUCT_BUNDLE_IDENTIFIER = "net.nevir.${PRODUCT_NAME:rfc1034identifier}";
674 | PRODUCT_NAME = SMJobKitTests;
675 | };
676 | name = Debug;
677 | };
678 | 3CA150A015A91179001CF9F8 /* Release */ = {
679 | isa = XCBuildConfiguration;
680 | buildSettings = {
681 | CLANG_ENABLE_OBJC_WEAK = YES;
682 | COPY_PHASE_STRIP = NO;
683 | FRAMEWORK_SEARCH_PATHS = (
684 | "$(DEVELOPER_FRAMEWORKS_DIR)",
685 | "$(inherited)",
686 | );
687 | INFOPLIST_FILE = Tests/SMJobKitTests/Info.plist;
688 | LD_RUNPATH_SEARCH_PATHS = (
689 | "$(inherited)",
690 | "@executable_path/../Frameworks",
691 | "@loader_path/../Frameworks",
692 | );
693 | PRODUCT_BUNDLE_IDENTIFIER = "net.nevir.${PRODUCT_NAME:rfc1034identifier}";
694 | PRODUCT_NAME = SMJobKitTests;
695 | };
696 | name = Release;
697 | };
698 | 3CCC06D215AA823000C84BE1 /* Debug */ = {
699 | isa = XCBuildConfiguration;
700 | buildSettings = {
701 | CLANG_ENABLE_OBJC_WEAK = YES;
702 | PRODUCT_NAME = SMJobKitTemplate;
703 | };
704 | name = Debug;
705 | };
706 | 3CCC06D315AA823000C84BE1 /* Release */ = {
707 | isa = XCBuildConfiguration;
708 | buildSettings = {
709 | CLANG_ENABLE_OBJC_WEAK = YES;
710 | PRODUCT_NAME = SMJobKitTemplate;
711 | };
712 | name = Release;
713 | };
714 | /* End XCBuildConfiguration section */
715 |
716 | /* Begin XCConfigurationList section */
717 | 3C2BFAB815AB33020011FA52 /* Build configuration list for PBXNativeTarget "TestService" */ = {
718 | isa = XCConfigurationList;
719 | buildConfigurations = (
720 | 3C2BFAB915AB33020011FA52 /* Debug */,
721 | 3C2BFABA15AB33020011FA52 /* Release */,
722 | );
723 | defaultConfigurationIsVisible = 0;
724 | defaultConfigurationName = Release;
725 | };
726 | 3CA1506A15A91179001CF9F8 /* Build configuration list for PBXProject "SMJobKit" */ = {
727 | isa = XCConfigurationList;
728 | buildConfigurations = (
729 | 3CA1509915A91179001CF9F8 /* Debug */,
730 | 3CA1509A15A91179001CF9F8 /* Release */,
731 | );
732 | defaultConfigurationIsVisible = 0;
733 | defaultConfigurationName = Release;
734 | };
735 | 3CA1509B15A91179001CF9F8 /* Build configuration list for PBXNativeTarget "SMJobKit" */ = {
736 | isa = XCConfigurationList;
737 | buildConfigurations = (
738 | 3CA1509C15A91179001CF9F8 /* Debug */,
739 | 3CA1509D15A91179001CF9F8 /* Release */,
740 | );
741 | defaultConfigurationIsVisible = 0;
742 | defaultConfigurationName = Release;
743 | };
744 | 3CA1509E15A91179001CF9F8 /* Build configuration list for PBXNativeTarget "SMJobKitTests" */ = {
745 | isa = XCConfigurationList;
746 | buildConfigurations = (
747 | 3CA1509F15A91179001CF9F8 /* Debug */,
748 | 3CA150A015A91179001CF9F8 /* Release */,
749 | );
750 | defaultConfigurationIsVisible = 0;
751 | defaultConfigurationName = Release;
752 | };
753 | 3CCC06D115AA823000C84BE1 /* Build configuration list for PBXAggregateTarget "Xcode Templates" */ = {
754 | isa = XCConfigurationList;
755 | buildConfigurations = (
756 | 3CCC06D215AA823000C84BE1 /* Debug */,
757 | 3CCC06D315AA823000C84BE1 /* Release */,
758 | );
759 | defaultConfigurationIsVisible = 0;
760 | defaultConfigurationName = Release;
761 | };
762 | /* End XCConfigurationList section */
763 | };
764 | rootObject = 3CA1506715A91179001CF9F8 /* Project object */;
765 | }
766 |
--------------------------------------------------------------------------------
/SMJobKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/SMJobKit.xcodeproj/project.xcworkspace/xcshareddata/SMJobKit.xccheckout:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDESourceControlProjectFavoriteDictionaryKey
6 |
7 | IDESourceControlProjectIdentifier
8 | 83F83DB4-C14B-4167-820F-258BD46D7259
9 | IDESourceControlProjectName
10 | project
11 | IDESourceControlProjectOriginsDictionary
12 |
13 | 62999A12ECFCEE422C7E9695EF797E99914609D9
14 | https://github.com/IngmarStein/SMJobKit.git
15 |
16 | IDESourceControlProjectPath
17 | SMJobKit.xcodeproj/project.xcworkspace
18 | IDESourceControlProjectRelativeInstallPathDictionary
19 |
20 | 62999A12ECFCEE422C7E9695EF797E99914609D9
21 | ../..
22 |
23 | IDESourceControlProjectURL
24 | https://github.com/IngmarStein/SMJobKit.git
25 | IDESourceControlProjectVersion
26 | 111
27 | IDESourceControlProjectWCCIdentifier
28 | 62999A12ECFCEE422C7E9695EF797E99914609D9
29 | IDESourceControlProjectWCConfigurations
30 |
31 |
32 | IDESourceControlRepositoryExtensionIdentifierKey
33 | public.vcs.git
34 | IDESourceControlWCCIdentifierKey
35 | 62999A12ECFCEE422C7E9695EF797E99914609D9
36 | IDESourceControlWCCName
37 | SMJobKit
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/SMJobKit.xcodeproj/xcshareddata/xcschemes/SMJobKit.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
42 |
48 |
49 |
50 |
51 |
52 |
62 |
63 |
69 |
70 |
71 |
72 |
78 |
79 |
85 |
86 |
87 |
88 |
90 |
91 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/SMJobKit.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/SMJobKit.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/SMJobKit.xcworkspace/xcshareddata/SMJobKit.xccheckout:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDESourceControlProjectFavoriteDictionaryKey
6 |
7 | IDESourceControlProjectIdentifier
8 | 5DAC43F9-C716-4349-8B0F-ABB94D1AFD46
9 | IDESourceControlProjectName
10 | SMJobKit
11 | IDESourceControlProjectOriginsDictionary
12 |
13 | 62999A12ECFCEE422C7E9695EF797E99914609D9
14 | https://github.com/IngmarStein/SMJobKit.git
15 |
16 | IDESourceControlProjectPath
17 | SMJobKit.xcworkspace
18 | IDESourceControlProjectRelativeInstallPathDictionary
19 |
20 | 62999A12ECFCEE422C7E9695EF797E99914609D9
21 | ..
22 |
23 | IDESourceControlProjectURL
24 | https://github.com/IngmarStein/SMJobKit.git
25 | IDESourceControlProjectVersion
26 | 111
27 | IDESourceControlProjectWCCIdentifier
28 | 62999A12ECFCEE422C7E9695EF797E99914609D9
29 | IDESourceControlProjectWCConfigurations
30 |
31 |
32 | IDESourceControlRepositoryExtensionIdentifierKey
33 | public.vcs.git
34 | IDESourceControlWCCIdentifierKey
35 | 62999A12ECFCEE422C7E9695EF797E99914609D9
36 | IDESourceControlWCCName
37 | SMJobKit
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/SampleApplication/SampleApplication.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 47;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 3CE185A515C64C1000A8FB57 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3CE185A315C64C1000A8FB57 /* InfoPlist.strings */; };
11 | 3CE185AB15C64C1000A8FB57 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 3CE185A915C64C1000A8FB57 /* Credits.rtf */; };
12 | 3CE185B115C64C1000A8FB57 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3CE185AF15C64C1000A8FB57 /* MainMenu.xib */; };
13 | 3CE185C415C64C1000A8FB57 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 3CE185C315C64C1000A8FB57 /* main.m */; };
14 | 3CE185CF15C64C2A00A8FB57 /* net.nevir.SMJobKit.SampleApplication.SampleService in Copy Services */ = {isa = PBXBuildFile; fileRef = 3CE185BC15C64C1000A8FB57 /* net.nevir.SMJobKit.SampleApplication.SampleService */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
15 | 3CE185D115C64CA500A8FB57 /* SMJobKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3CE185D015C64CA500A8FB57 /* SMJobKit.framework */; };
16 | 9591AC7F1AC88345000C58EC /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9591AC7E1AC88345000C58EC /* AppDelegate.swift */; };
17 | 9591AC811AC8858E000C58EC /* SampleService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9591AC801AC8858E000C58EC /* SampleService.swift */; };
18 | /* End PBXBuildFile section */
19 |
20 | /* Begin PBXContainerItemProxy section */
21 | 3CE185BE15C64C1000A8FB57 /* PBXContainerItemProxy */ = {
22 | isa = PBXContainerItemProxy;
23 | containerPortal = 3CE1858B15C64C1000A8FB57 /* Project object */;
24 | proxyType = 1;
25 | remoteGlobalIDString = 3CE185BB15C64C1000A8FB57;
26 | remoteInfo = SampleService;
27 | };
28 | /* End PBXContainerItemProxy section */
29 |
30 | /* Begin PBXCopyFilesBuildPhase section */
31 | 3CE1859415C64C1000A8FB57 /* Copy Services */ = {
32 | isa = PBXCopyFilesBuildPhase;
33 | buildActionMask = 2147483647;
34 | dstPath = Contents/Library/LaunchServices;
35 | dstSubfolderSpec = 1;
36 | files = (
37 | 3CE185CF15C64C2A00A8FB57 /* net.nevir.SMJobKit.SampleApplication.SampleService in Copy Services */,
38 | );
39 | name = "Copy Services";
40 | runOnlyForDeploymentPostprocessing = 0;
41 | };
42 | /* End PBXCopyFilesBuildPhase section */
43 |
44 | /* Begin PBXFileReference section */
45 | 3CE1859615C64C1000A8FB57 /* SampleApplication.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SampleApplication.app; sourceTree = BUILT_PRODUCTS_DIR; };
46 | 3CE185A215C64C1000A8FB57 /* SampleApplication-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SampleApplication-Info.plist"; sourceTree = ""; };
47 | 3CE185A415C64C1000A8FB57 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
48 | 3CE185AA15C64C1000A8FB57 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; };
49 | 3CE185BC15C64C1000A8FB57 /* net.nevir.SMJobKit.SampleApplication.SampleService */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = net.nevir.SMJobKit.SampleApplication.SampleService; sourceTree = BUILT_PRODUCTS_DIR; };
50 | 3CE185C315C64C1000A8FB57 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
51 | 3CE185C515C64C1000A8FB57 /* SampleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SampleService-Info.plist"; sourceTree = ""; };
52 | 3CE185C615C64C1000A8FB57 /* SampleService-Launchd.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SampleService-Launchd.plist"; sourceTree = ""; };
53 | 3CE185D015C64CA500A8FB57 /* SMJobKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SMJobKit.framework; path = "../../../Library/Developer/Xcode/DerivedData/SMJobKit-fliesfietiliwshiebehkxithcjq/Build/Products/Debug/SMJobKit.framework"; sourceTree = ""; };
54 | 3CE185D215C64CAA00A8FB57 /* libSMJService.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libSMJService.a; path = "../../../Library/Developer/Xcode/DerivedData/SMJobKit-fliesfietiliwshiebehkxithcjq/Build/Products/Debug/libSMJService.a"; sourceTree = ""; };
55 | 957C3A4D22652F030092A8F5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; };
56 | 9591AC7D1AC88345000C58EC /* SampleApplication-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SampleApplication-Bridging-Header.h"; sourceTree = ""; };
57 | 9591AC7E1AC88345000C58EC /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
58 | 9591AC801AC8858E000C58EC /* SampleService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SampleService.swift; sourceTree = ""; };
59 | /* End PBXFileReference section */
60 |
61 | /* Begin PBXFrameworksBuildPhase section */
62 | 3CE1859115C64C1000A8FB57 /* Frameworks */ = {
63 | isa = PBXFrameworksBuildPhase;
64 | buildActionMask = 2147483647;
65 | files = (
66 | 3CE185D115C64CA500A8FB57 /* SMJobKit.framework in Frameworks */,
67 | );
68 | runOnlyForDeploymentPostprocessing = 0;
69 | };
70 | 3CE185BA15C64C1000A8FB57 /* Frameworks */ = {
71 | isa = PBXFrameworksBuildPhase;
72 | buildActionMask = 2147483647;
73 | files = (
74 | );
75 | runOnlyForDeploymentPostprocessing = 0;
76 | };
77 | /* End PBXFrameworksBuildPhase section */
78 |
79 | /* Begin PBXGroup section */
80 | 3CE1858915C64C1000A8FB57 = {
81 | isa = PBXGroup;
82 | children = (
83 | 3CE185A015C64C1000A8FB57 /* SampleApplication */,
84 | 3CE185C215C64C1000A8FB57 /* SampleService */,
85 | 3CE1859915C64C1000A8FB57 /* Frameworks */,
86 | 3CE1859715C64C1000A8FB57 /* Products */,
87 | );
88 | sourceTree = "";
89 | };
90 | 3CE1859715C64C1000A8FB57 /* Products */ = {
91 | isa = PBXGroup;
92 | children = (
93 | 3CE1859615C64C1000A8FB57 /* SampleApplication.app */,
94 | 3CE185BC15C64C1000A8FB57 /* net.nevir.SMJobKit.SampleApplication.SampleService */,
95 | );
96 | name = Products;
97 | sourceTree = "";
98 | };
99 | 3CE1859915C64C1000A8FB57 /* Frameworks */ = {
100 | isa = PBXGroup;
101 | children = (
102 | 3CE185D215C64CAA00A8FB57 /* libSMJService.a */,
103 | 3CE185D015C64CA500A8FB57 /* SMJobKit.framework */,
104 | );
105 | name = Frameworks;
106 | sourceTree = "";
107 | };
108 | 3CE185A015C64C1000A8FB57 /* SampleApplication */ = {
109 | isa = PBXGroup;
110 | children = (
111 | 9591AC7E1AC88345000C58EC /* AppDelegate.swift */,
112 | 3CE185AF15C64C1000A8FB57 /* MainMenu.xib */,
113 | 3CE185B415C64C1000A8FB57 /* Service Clients */,
114 | 3CE185A115C64C1000A8FB57 /* Supporting Files */,
115 | );
116 | path = SampleApplication;
117 | sourceTree = "";
118 | };
119 | 3CE185A115C64C1000A8FB57 /* Supporting Files */ = {
120 | isa = PBXGroup;
121 | children = (
122 | 3CE185A915C64C1000A8FB57 /* Credits.rtf */,
123 | 3CE185A315C64C1000A8FB57 /* InfoPlist.strings */,
124 | 9591AC7D1AC88345000C58EC /* SampleApplication-Bridging-Header.h */,
125 | 3CE185A215C64C1000A8FB57 /* SampleApplication-Info.plist */,
126 | );
127 | name = "Supporting Files";
128 | sourceTree = "";
129 | };
130 | 3CE185B415C64C1000A8FB57 /* Service Clients */ = {
131 | isa = PBXGroup;
132 | children = (
133 | 9591AC801AC8858E000C58EC /* SampleService.swift */,
134 | );
135 | name = "Service Clients";
136 | sourceTree = "";
137 | };
138 | 3CE185C215C64C1000A8FB57 /* SampleService */ = {
139 | isa = PBXGroup;
140 | children = (
141 | 3CE185C315C64C1000A8FB57 /* main.m */,
142 | 3CE185C515C64C1000A8FB57 /* SampleService-Info.plist */,
143 | 3CE185C615C64C1000A8FB57 /* SampleService-Launchd.plist */,
144 | );
145 | path = SampleService;
146 | sourceTree = "";
147 | };
148 | /* End PBXGroup section */
149 |
150 | /* Begin PBXNativeTarget section */
151 | 3CE1859515C64C1000A8FB57 /* SampleApplication */ = {
152 | isa = PBXNativeTarget;
153 | buildConfigurationList = 3CE185CC15C64C1000A8FB57 /* Build configuration list for PBXNativeTarget "SampleApplication" */;
154 | buildPhases = (
155 | 3CE1859015C64C1000A8FB57 /* Sources */,
156 | 3CE1859115C64C1000A8FB57 /* Frameworks */,
157 | 3CE1859215C64C1000A8FB57 /* Resources */,
158 | 3CE1859415C64C1000A8FB57 /* Copy Services */,
159 | );
160 | buildRules = (
161 | );
162 | dependencies = (
163 | 3CE185BF15C64C1000A8FB57 /* PBXTargetDependency */,
164 | );
165 | name = SampleApplication;
166 | productName = SampleApplication;
167 | productReference = 3CE1859615C64C1000A8FB57 /* SampleApplication.app */;
168 | productType = "com.apple.product-type.application";
169 | };
170 | 3CE185BB15C64C1000A8FB57 /* SampleService */ = {
171 | isa = PBXNativeTarget;
172 | buildConfigurationList = 3CE185C915C64C1000A8FB57 /* Build configuration list for PBXNativeTarget "SampleService" */;
173 | buildPhases = (
174 | 3CE185B815C64C1000A8FB57 /* Preprocess Resources */,
175 | 3CE185B915C64C1000A8FB57 /* Sources */,
176 | 3CE185BA15C64C1000A8FB57 /* Frameworks */,
177 | );
178 | buildRules = (
179 | );
180 | dependencies = (
181 | );
182 | name = SampleService;
183 | productName = SampleService;
184 | productReference = 3CE185BC15C64C1000A8FB57 /* net.nevir.SMJobKit.SampleApplication.SampleService */;
185 | productType = "com.apple.product-type.tool";
186 | };
187 | /* End PBXNativeTarget section */
188 |
189 | /* Begin PBXProject section */
190 | 3CE1858B15C64C1000A8FB57 /* Project object */ = {
191 | isa = PBXProject;
192 | attributes = {
193 | LastSwiftUpdateCheck = 0700;
194 | LastUpgradeCheck = 1100;
195 | ORGANIZATIONNAME = "Ingmar Stein";
196 | };
197 | buildConfigurationList = 3CE1858E15C64C1000A8FB57 /* Build configuration list for PBXProject "SampleApplication" */;
198 | compatibilityVersion = "Xcode 6.3";
199 | developmentRegion = en;
200 | hasScannedForEncodings = 0;
201 | knownRegions = (
202 | en,
203 | Base,
204 | );
205 | mainGroup = 3CE1858915C64C1000A8FB57;
206 | productRefGroup = 3CE1859715C64C1000A8FB57 /* Products */;
207 | projectDirPath = "";
208 | projectRoot = "";
209 | targets = (
210 | 3CE1859515C64C1000A8FB57 /* SampleApplication */,
211 | 3CE185BB15C64C1000A8FB57 /* SampleService */,
212 | );
213 | };
214 | /* End PBXProject section */
215 |
216 | /* Begin PBXResourcesBuildPhase section */
217 | 3CE1859215C64C1000A8FB57 /* Resources */ = {
218 | isa = PBXResourcesBuildPhase;
219 | buildActionMask = 2147483647;
220 | files = (
221 | 3CE185A515C64C1000A8FB57 /* InfoPlist.strings in Resources */,
222 | 3CE185AB15C64C1000A8FB57 /* Credits.rtf in Resources */,
223 | 3CE185B115C64C1000A8FB57 /* MainMenu.xib in Resources */,
224 | );
225 | runOnlyForDeploymentPostprocessing = 0;
226 | };
227 | /* End PBXResourcesBuildPhase section */
228 |
229 | /* Begin PBXShellScriptBuildPhase section */
230 | 3CE185B815C64C1000A8FB57 /* Preprocess Resources */ = {
231 | isa = PBXShellScriptBuildPhase;
232 | buildActionMask = 2147483647;
233 | files = (
234 | );
235 | inputPaths = (
236 | );
237 | name = "Preprocess Resources";
238 | outputPaths = (
239 | );
240 | runOnlyForDeploymentPostprocessing = 0;
241 | shellPath = "/usr/bin/env ruby";
242 | shellScript = "# Generic preprocessing for ${ENV_VAR} with output to the build dir.\n\nrequire 'cgi'\nrequire 'fileutils'\n\nmissing_keys = ['BUILD_DIR', 'CODE_SIGN_IDENTITY', 'SMJ_PREPROCESS_FILES', 'SMJ_PREPROCESS_DIR'] - ENV.keys\nraise \"Missing required ENV values: #{missing_keys.inspect}\" if missing_keys.size > 0\n\n# SMJ_PREPROCESS_FILES is a comma-separated list of *relative* file paths to preprocess\n# and spit out into the SMJ_PREPROCESS_DIR (w/ the same relative paths as given)\nfiles_to_preprocess = ENV['SMJ_PREPROCESS_FILES'].split(',').map(&:strip)\n\n\n# Environment Cleanup\n# -------------------\ndummy_path = \"#{ENV['BUILD_DIR']}/SMJobKitCodeSigningDummy\"\n\nidentity = ENV['CODE_SIGN_IDENTITY']\n# If you use the generic code signing identity, chances are that it'll conflict.\nidentity = \"#{identity}:\" if identity.end_with? ' Developer'\n\n# We can't seem to get direct access to the code signing certificate that Xcode has\n# selected at this point :(\n`touch #{dummy_path}`\n`codesign --force --sign \"#{identity}\" \"#{dummy_path}\"`\nresult = `codesign --display --verbose --verbose \"#{dummy_path}\" 2>&1`\n`rm #{dummy_path}`\n\nENV['FULL_CODE_SIGN_IDENTITY'] = result[/Authority\\=(.*#{Regexp.escape(identity)}.*)/, 1]\n\n\n# Actual Preprocessing\n# --------------------\n\nfiles_to_preprocess.each do |path|\n target_path = File.join(ENV['SMJ_PREPROCESS_DIR'], path)\n FileUtils.mkpath File.dirname(target_path)\n\n open(path) do |input|\n open(target_path, 'w') do |output|\n # Specify macros via ${VAR_NAME} in the preprocessed file. Same as regular\n # Info.plist preprocessing.\n output.write input.read.gsub(/\\$\\{([A-Z_]+)\\}/) { CGI.escapeHTML(ENV[$1]) }\n end\n puts target_path\n end\nend";
243 | };
244 | /* End PBXShellScriptBuildPhase section */
245 |
246 | /* Begin PBXSourcesBuildPhase section */
247 | 3CE1859015C64C1000A8FB57 /* Sources */ = {
248 | isa = PBXSourcesBuildPhase;
249 | buildActionMask = 2147483647;
250 | files = (
251 | 9591AC7F1AC88345000C58EC /* AppDelegate.swift in Sources */,
252 | 9591AC811AC8858E000C58EC /* SampleService.swift in Sources */,
253 | );
254 | runOnlyForDeploymentPostprocessing = 0;
255 | };
256 | 3CE185B915C64C1000A8FB57 /* Sources */ = {
257 | isa = PBXSourcesBuildPhase;
258 | buildActionMask = 2147483647;
259 | files = (
260 | 3CE185C415C64C1000A8FB57 /* main.m in Sources */,
261 | );
262 | runOnlyForDeploymentPostprocessing = 0;
263 | };
264 | /* End PBXSourcesBuildPhase section */
265 |
266 | /* Begin PBXTargetDependency section */
267 | 3CE185BF15C64C1000A8FB57 /* PBXTargetDependency */ = {
268 | isa = PBXTargetDependency;
269 | target = 3CE185BB15C64C1000A8FB57 /* SampleService */;
270 | targetProxy = 3CE185BE15C64C1000A8FB57 /* PBXContainerItemProxy */;
271 | };
272 | /* End PBXTargetDependency section */
273 |
274 | /* Begin PBXVariantGroup section */
275 | 3CE185A315C64C1000A8FB57 /* InfoPlist.strings */ = {
276 | isa = PBXVariantGroup;
277 | children = (
278 | 3CE185A415C64C1000A8FB57 /* en */,
279 | );
280 | name = InfoPlist.strings;
281 | sourceTree = "";
282 | };
283 | 3CE185A915C64C1000A8FB57 /* Credits.rtf */ = {
284 | isa = PBXVariantGroup;
285 | children = (
286 | 3CE185AA15C64C1000A8FB57 /* en */,
287 | );
288 | name = Credits.rtf;
289 | sourceTree = "";
290 | };
291 | 3CE185AF15C64C1000A8FB57 /* MainMenu.xib */ = {
292 | isa = PBXVariantGroup;
293 | children = (
294 | 957C3A4D22652F030092A8F5 /* Base */,
295 | );
296 | name = MainMenu.xib;
297 | sourceTree = "";
298 | };
299 | /* End PBXVariantGroup section */
300 |
301 | /* Begin XCBuildConfiguration section */
302 | 3CE185C715C64C1000A8FB57 /* Debug */ = {
303 | isa = XCBuildConfiguration;
304 | buildSettings = {
305 | ALWAYS_SEARCH_USER_PATHS = NO;
306 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
307 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
308 | CLANG_CXX_LIBRARY = "libc++";
309 | CLANG_ENABLE_MODULES = YES;
310 | CLANG_ENABLE_OBJC_ARC = YES;
311 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
312 | CLANG_WARN_BOOL_CONVERSION = YES;
313 | CLANG_WARN_COMMA = YES;
314 | CLANG_WARN_CONSTANT_CONVERSION = YES;
315 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
316 | CLANG_WARN_EMPTY_BODY = YES;
317 | CLANG_WARN_ENUM_CONVERSION = YES;
318 | CLANG_WARN_INFINITE_RECURSION = YES;
319 | CLANG_WARN_INT_CONVERSION = YES;
320 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
321 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
322 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
323 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
324 | CLANG_WARN_STRICT_PROTOTYPES = YES;
325 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
326 | CLANG_WARN_UNREACHABLE_CODE = YES;
327 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
328 | COPY_PHASE_STRIP = NO;
329 | ENABLE_STRICT_OBJC_MSGSEND = YES;
330 | ENABLE_TESTABILITY = YES;
331 | GCC_C_LANGUAGE_STANDARD = gnu99;
332 | GCC_DYNAMIC_NO_PIC = NO;
333 | GCC_ENABLE_OBJC_EXCEPTIONS = YES;
334 | GCC_NO_COMMON_BLOCKS = YES;
335 | GCC_OPTIMIZATION_LEVEL = 0;
336 | GCC_PREPROCESSOR_DEFINITIONS = (
337 | "DEBUG=1",
338 | "$(inherited)",
339 | );
340 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
341 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
342 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
343 | GCC_WARN_UNDECLARED_SELECTOR = YES;
344 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
345 | GCC_WARN_UNUSED_FUNCTION = YES;
346 | GCC_WARN_UNUSED_VARIABLE = YES;
347 | MACOSX_DEPLOYMENT_TARGET = 10.9;
348 | ONLY_ACTIVE_ARCH = YES;
349 | SDKROOT = macosx;
350 | };
351 | name = Debug;
352 | };
353 | 3CE185C815C64C1000A8FB57 /* Release */ = {
354 | isa = XCBuildConfiguration;
355 | buildSettings = {
356 | ALWAYS_SEARCH_USER_PATHS = NO;
357 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
358 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
359 | CLANG_CXX_LIBRARY = "libc++";
360 | CLANG_ENABLE_MODULES = YES;
361 | CLANG_ENABLE_OBJC_ARC = YES;
362 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
363 | CLANG_WARN_BOOL_CONVERSION = YES;
364 | CLANG_WARN_COMMA = YES;
365 | CLANG_WARN_CONSTANT_CONVERSION = YES;
366 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
367 | CLANG_WARN_EMPTY_BODY = YES;
368 | CLANG_WARN_ENUM_CONVERSION = YES;
369 | CLANG_WARN_INFINITE_RECURSION = YES;
370 | CLANG_WARN_INT_CONVERSION = YES;
371 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
372 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
373 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
374 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
375 | CLANG_WARN_STRICT_PROTOTYPES = YES;
376 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
377 | CLANG_WARN_UNREACHABLE_CODE = YES;
378 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
379 | COPY_PHASE_STRIP = YES;
380 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
381 | ENABLE_STRICT_OBJC_MSGSEND = YES;
382 | GCC_C_LANGUAGE_STANDARD = gnu99;
383 | GCC_ENABLE_OBJC_EXCEPTIONS = YES;
384 | GCC_NO_COMMON_BLOCKS = YES;
385 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
386 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
387 | GCC_WARN_UNDECLARED_SELECTOR = YES;
388 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
389 | GCC_WARN_UNUSED_FUNCTION = YES;
390 | GCC_WARN_UNUSED_VARIABLE = YES;
391 | MACOSX_DEPLOYMENT_TARGET = 10.9;
392 | SDKROOT = macosx;
393 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
394 | };
395 | name = Release;
396 | };
397 | 3CE185CA15C64C1000A8FB57 /* Debug */ = {
398 | isa = XCBuildConfiguration;
399 | buildSettings = {
400 | CODE_SIGN_IDENTITY = "Developer ID Application";
401 | ENABLE_HARDENED_RUNTIME = YES;
402 | OTHER_LDFLAGS = (
403 | "-sectcreate",
404 | __TEXT,
405 | __info_plist,
406 | "\"$(SMJ_PREPROCESS_DIR)/SampleService/SampleService-Info.plist\"",
407 | "-sectcreate",
408 | __TEXT,
409 | __launchd_plist,
410 | "\"$(SMJ_PREPROCESS_DIR)/SampleService/SampleService-Launchd.plist\"",
411 | );
412 | PARENT_APPLICATION_IDENTIFIER = "net.nevir.SMJobKit.$(PROJECT_NAME)";
413 | PRODUCT_NAME = "net.nevir.SMJobKit.$(PROJECT_NAME).$(TARGET_NAME)";
414 | SMJ_PREPROCESS_DIR = "$(BUILD_DIR)/Preprocessed";
415 | SMJ_PREPROCESS_FILES = "SampleService/SampleService-Info.plist, SampleService/SampleService-Launchd.plist";
416 | };
417 | name = Debug;
418 | };
419 | 3CE185CB15C64C1000A8FB57 /* Release */ = {
420 | isa = XCBuildConfiguration;
421 | buildSettings = {
422 | CODE_SIGN_IDENTITY = "Developer ID Application";
423 | ENABLE_HARDENED_RUNTIME = YES;
424 | OTHER_LDFLAGS = (
425 | "-sectcreate",
426 | __TEXT,
427 | __info_plist,
428 | "\"$(SMJ_PREPROCESS_DIR)/SampleService/SampleService-Info.plist\"",
429 | "-sectcreate",
430 | __TEXT,
431 | __launchd_plist,
432 | "\"$(SMJ_PREPROCESS_DIR)/SampleService/SampleService-Launchd.plist\"",
433 | );
434 | PARENT_APPLICATION_IDENTIFIER = "net.nevir.SMJobKit.$(PROJECT_NAME)";
435 | PRODUCT_NAME = "net.nevir.SMJobKit.$(PROJECT_NAME).$(TARGET_NAME)";
436 | SMJ_PREPROCESS_DIR = "$(BUILD_DIR)/Preprocessed";
437 | SMJ_PREPROCESS_FILES = "SampleService/SampleService-Info.plist, SampleService/SampleService-Launchd.plist";
438 | };
439 | name = Release;
440 | };
441 | 3CE185CD15C64C1000A8FB57 /* Debug */ = {
442 | isa = XCBuildConfiguration;
443 | buildSettings = {
444 | CLANG_ENABLE_MODULES = YES;
445 | CODE_SIGN_IDENTITY = "Developer ID Application";
446 | COMBINE_HIDPI_IMAGES = YES;
447 | ENABLE_HARDENED_RUNTIME = YES;
448 | INFOPLIST_FILE = "SampleApplication/SampleApplication-Info.plist";
449 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
450 | PRODUCT_BUNDLE_IDENTIFIER = "net.nevir.SMJobKit.${PRODUCT_NAME:rfc1034identifier}";
451 | PRODUCT_NAME = "$(TARGET_NAME)";
452 | SWIFT_OBJC_BRIDGING_HEADER = "SampleApplication/SampleApplication-Bridging-Header.h";
453 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
454 | SWIFT_VERSION = 4.2;
455 | WRAPPER_EXTENSION = app;
456 | };
457 | name = Debug;
458 | };
459 | 3CE185CE15C64C1000A8FB57 /* Release */ = {
460 | isa = XCBuildConfiguration;
461 | buildSettings = {
462 | CLANG_ENABLE_MODULES = YES;
463 | CODE_SIGN_IDENTITY = "Developer ID Application";
464 | COMBINE_HIDPI_IMAGES = YES;
465 | ENABLE_HARDENED_RUNTIME = YES;
466 | INFOPLIST_FILE = "SampleApplication/SampleApplication-Info.plist";
467 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
468 | PRODUCT_BUNDLE_IDENTIFIER = "net.nevir.SMJobKit.${PRODUCT_NAME:rfc1034identifier}";
469 | PRODUCT_NAME = "$(TARGET_NAME)";
470 | SWIFT_OBJC_BRIDGING_HEADER = "SampleApplication/SampleApplication-Bridging-Header.h";
471 | SWIFT_OPTIMIZATION_LEVEL = "-O";
472 | SWIFT_VERSION = 4.2;
473 | WRAPPER_EXTENSION = app;
474 | };
475 | name = Release;
476 | };
477 | /* End XCBuildConfiguration section */
478 |
479 | /* Begin XCConfigurationList section */
480 | 3CE1858E15C64C1000A8FB57 /* Build configuration list for PBXProject "SampleApplication" */ = {
481 | isa = XCConfigurationList;
482 | buildConfigurations = (
483 | 3CE185C715C64C1000A8FB57 /* Debug */,
484 | 3CE185C815C64C1000A8FB57 /* Release */,
485 | );
486 | defaultConfigurationIsVisible = 0;
487 | defaultConfigurationName = Release;
488 | };
489 | 3CE185C915C64C1000A8FB57 /* Build configuration list for PBXNativeTarget "SampleService" */ = {
490 | isa = XCConfigurationList;
491 | buildConfigurations = (
492 | 3CE185CA15C64C1000A8FB57 /* Debug */,
493 | 3CE185CB15C64C1000A8FB57 /* Release */,
494 | );
495 | defaultConfigurationIsVisible = 0;
496 | defaultConfigurationName = Release;
497 | };
498 | 3CE185CC15C64C1000A8FB57 /* Build configuration list for PBXNativeTarget "SampleApplication" */ = {
499 | isa = XCConfigurationList;
500 | buildConfigurations = (
501 | 3CE185CD15C64C1000A8FB57 /* Debug */,
502 | 3CE185CE15C64C1000A8FB57 /* Release */,
503 | );
504 | defaultConfigurationIsVisible = 0;
505 | defaultConfigurationName = Release;
506 | };
507 | /* End XCConfigurationList section */
508 | };
509 | rootObject = 3CE1858B15C64C1000A8FB57 /* Project object */;
510 | }
511 |
--------------------------------------------------------------------------------
/SampleApplication/SampleApplication/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // SampleApplication
4 | //
5 | // Created by Ingmar Stein on 29.03.15.
6 | // Copyright (c) 2015 Ian MacLeod. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 |
11 | @NSApplicationMain
12 | class AppDelegate: NSObject, NSApplicationDelegate {
13 | @IBOutlet private weak var window: NSWindow!
14 | @IBOutlet private var outputTextView: NSTextView!
15 | @IBOutlet private weak var bundledVersionLabel: NSTextField!
16 |
17 | func applicationDidFinishLaunching(_ notification: Notification) {
18 | updateStatus()
19 | }
20 |
21 | private func appendMessage(_ message: String) {
22 | self.outputTextView.string! += "\(message)\n"
23 | }
24 |
25 | @IBAction func installService(sender: AnyObject!) {
26 | // In order to test out SMJobKit,
27 | // SampleApplication is trying to install a new
28 | // helper tool. Type your password to allow this.
29 | do {
30 | try SampleService.installWithPrompt(prompt: "In order to test out SMJobKit,")
31 | appendMessage("Successfully installed SampleService")
32 | } catch let error {
33 | appendMessage("\(error)")
34 | }
35 |
36 | updateStatus()
37 | }
38 |
39 | private func updateStatus() {
40 | self.bundledVersionLabel.stringValue = SampleService.bundledVersion ?? "Unknown Version"
41 |
42 | SampleService.checkForProblems().map { self.appendMessage("\($0)") }
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/SampleApplication/SampleApplication/Base.lproj/MainMenu.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
651 |
652 |
653 |
654 |
655 |
656 |
657 |
658 |
659 |
660 |
661 |
662 |
663 |
664 |
665 |
675 |
676 |
677 |
678 |
679 |
680 |
681 |
682 |
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 |
692 |
693 |
694 |
695 |
696 |
697 |
698 |
699 |
700 |
701 |
702 |
703 |
704 |
705 |
706 |
707 |
708 |
709 |
710 |
711 |
712 |
713 |
714 |
715 |
716 |
717 |
718 |
719 |
720 |
721 |
722 |
723 |
724 |
725 |
726 |
727 |
728 |
729 |
730 |
731 |
732 |
733 |
734 |
735 |
736 |
737 |
738 |
739 |
740 |
741 |
742 |
743 |
744 |
745 |
746 |
747 |
748 |
749 |
750 |
751 |
752 |
753 |
754 |
755 |
756 |
757 |
758 |
759 |
760 |
761 |
762 |
763 |
764 |
765 |
766 |
767 |
768 |
769 |
770 |
771 |
772 |
773 |
774 |
775 |
776 |
777 |
778 |
779 |
780 |
781 |
782 |
783 |
--------------------------------------------------------------------------------
/SampleApplication/SampleApplication/SampleApplication-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | //
2 | // Use this file to import your target's public headers that you would like to expose to Swift.
3 | //
4 |
5 |
--------------------------------------------------------------------------------
/SampleApplication/SampleApplication/SampleApplication-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | ${PRODUCT_NAME}
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | LSApplicationCategoryType
26 | public.app-category.utilities
27 | LSMinimumSystemVersion
28 | ${MACOSX_DEPLOYMENT_TARGET}
29 | NSHumanReadableCopyright
30 | Copyright © 2012 Ian MacLeod. All rights reserved.
31 | NSMainNibFile
32 | MainMenu
33 | NSPrincipalClass
34 | NSApplication
35 | SMPrivilegedExecutables
36 |
37 | net.nevir.SMJobKit.[[[PROJECT_NAME]]].SampleService
38 | identifier net.nevir.SMJobKit.[[[PROJECT_NAME]]].SampleService and certificate leaf[subject.CN] = "[[[FULL_CODE_SIGN_IDENTITY]]]"
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/SampleApplication/SampleApplication/SampleService.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SampleService.swift
3 | // SampleApplication
4 | //
5 | // Created by Ingmar Stein on 29.03.15.
6 | // Copyright (c) 2015 Ian MacLeod. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 | import SMJobKit
11 |
12 | class SampleService: Client {
13 | override class var serviceIdentifier: String {
14 | return "net.nevir.SMJobKit.SampleApplication.SampleService"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/SampleApplication/SampleApplication/en.lproj/Credits.rtf:
--------------------------------------------------------------------------------
1 | {\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;}
2 | {\colortbl;\red255\green255\blue255;}
3 | \paperw9840\paperh8400
4 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural
5 |
6 | \f0\b\fs24 \cf0 Engineering:
7 | \b0 \
8 | Some people\
9 | \
10 |
11 | \b Human Interface Design:
12 | \b0 \
13 | Some other people\
14 | \
15 |
16 | \b Testing:
17 | \b0 \
18 | Hopefully not nobody\
19 | \
20 |
21 | \b Documentation:
22 | \b0 \
23 | Whoever\
24 | \
25 |
26 | \b With special thanks to:
27 | \b0 \
28 | Mom\
29 | }
30 |
--------------------------------------------------------------------------------
/SampleApplication/SampleApplication/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/SampleApplication/SampleService/SampleService-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleIdentifier
6 | ${PRODUCT_NAME}
7 | CFBundleInfoDictionaryVersion
8 | 6.0
9 | CFBundleName
10 | SampleService
11 | CFBundleVersion
12 | 0.01
13 | SMAuthorizedClients
14 |
15 | identifier ${PARENT_APPLICATION_IDENTIFIER} and certificate leaf[subject.CN] = "${FULL_CODE_SIGN_IDENTITY}"
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/SampleApplication/SampleService/SampleService-Launchd.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Label
6 | ${PRODUCT_NAME}
7 | MachServices
8 |
9 | ${PRODUCT_NAME}
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/SampleApplication/SampleService/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // SampleService
4 | //
5 | // Created by Ian MacLeod on 7/29/12.
6 | // Copyright (c) 2012 Ian MacLeod. All rights reserved.
7 | //
8 |
9 | int main(int argc, const char *argv[])
10 | {
11 | return 0;
12 | }
13 |
--------------------------------------------------------------------------------
/Sources/SMJobKit/BridgingHeader.h:
--------------------------------------------------------------------------------
1 | //
2 | // BridgingHeader.h
3 | // SMJobKit
4 | //
5 | // Created by Ingmar Stein on 30.08.15.
6 | //
7 | //
8 |
9 | #import
10 |
--------------------------------------------------------------------------------
/Sources/SMJobKit/Client.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Client.swift
3 | // SMJobKit
4 | //
5 | // Created by Ingmar Stein on 29.03.15.
6 | //
7 | //
8 |
9 | import Foundation
10 | import ServiceManagement
11 |
12 | open class Client {
13 |
14 | // MARK: - Abstract Interface
15 |
16 | open class var serviceIdentifier: String {
17 | fatalError("You need to implement serviceIdentifier!")
18 | }
19 |
20 | // MARK: - Public Interface
21 |
22 | public class var bundledVersion: String? {
23 | return try? ClientUtility.versionForBundlePath(bundledServicePath)
24 | }
25 |
26 | public class func installWithPrompt(prompt: String?) throws {
27 | let authRef = try ClientUtility.authWithRight(kSMRightBlessPrivilegedHelper, prompt: prompt)
28 |
29 | // Here's the good stuff
30 | var cfError: Unmanaged?
31 | if !SMJobBless(kSMDomainSystemLaunchd, cfIdentifier, authRef, &cfError) {
32 | let blessError = cfError!.takeRetainedValue()
33 | throw SMJError.unableToBless(blessError) // String(format: "SMJobBless failure (code %ld): %@", blessError.code, blessError.localizedDescription)
34 | }
35 |
36 | NSLog("%@ (%@) installed successfully", serviceIdentifier as NSString, bundledVersion! as NSString)
37 | }
38 |
39 | // MARK: - Diagnostics
40 |
41 | public class func checkForProblems() -> [Error] {
42 | var errors = [Error]()
43 |
44 | do {
45 | try _ = ClientUtility.versionForBundlePath(bundledServicePath)
46 | } catch let error {
47 | errors.append(error)
48 | }
49 |
50 | return errors
51 | }
52 |
53 | // MARK: - Service Information
54 |
55 | public class var bundledServicePath: String {
56 | let helperRelative = "Contents/Library/LaunchServices/\(serviceIdentifier)"
57 |
58 | return (Bundle(for: self).bundlePath as NSString).appendingPathComponent(helperRelative)
59 | }
60 |
61 | // MARK: - Utility
62 |
63 | private class var cfIdentifier: CFString {
64 | return serviceIdentifier as CFString
65 | }
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/Sources/SMJobKit/ClientUtility.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ClientUtility.swift
3 | // SMJobKit
4 | //
5 | // Created by Ingmar Stein on 29.03.15.
6 | //
7 | //
8 |
9 | import Foundation
10 | import Security
11 |
12 | final class ClientUtility {
13 |
14 | // MARK: - Bundle Introspection
15 |
16 | static func versionForBundlePath(_ bundlePath: String) throws -> String {
17 | // We can't use CFBundleCopyInfoDictionaryForURL, as it breaks our code signing validity.
18 | var codeRef: SecStaticCode?
19 |
20 | let url = NSURL(fileURLWithPath: bundlePath, isDirectory: false)
21 | let result = SecStaticCodeCreateWithPath(url, [], &codeRef)
22 | if result == noErr, let code = codeRef {
23 | var codeInfoRef: CFDictionary?
24 | let result2 = SecCodeCopySigningInformation(code, [], &codeInfoRef)
25 | if result2 == noErr, let codeInfo = codeInfoRef {
26 | let codeInfoDictionary = codeInfo as [NSObject: AnyObject]
27 | if let bundleInfo = codeInfoDictionary[kSecCodeInfoPList] as? [String: AnyObject] {
28 | if let value = bundleInfo["CFBundleVersion"] as? String {
29 | return value
30 | } else {
31 | throw SMJError.badBundleCodeSigningDictionary // "CFBundleVersion was not a string"
32 | }
33 | } else {
34 | throw SMJError.badBundleCodeSigningDictionary // "kSecCodeInfoPList was not a dictionary"
35 | }
36 | } else {
37 | throw SMJError.badBundleCodeSigningDictionary // String(format: "Failed to read code signing dictionary (OSStatus %d)", result2)
38 | }
39 | } else {
40 | if result == OSStatus(errSecCSUnsigned) {
41 | throw SMJError.unsignedBundle // "Encountered unsigned bundle"
42 | } else if result == OSStatus(errSecCSStaticCodeNotFound) {
43 | throw SMJError.bundleNotFound // "No bundle found at given path"
44 | } else {
45 | throw SMJError.badBundleSecurity(result) // String(format: "Failed to create SecStaticCodeRef (OSStatus %d)", result)
46 | }
47 | }
48 | }
49 |
50 | // MARK: - Authorization & Security
51 |
52 | static func authWithRight(_ rightName: String, prompt: String?) throws -> AuthorizationRef {
53 | let authorizationRight = (rightName as NSString).utf8String!
54 | let authItem = AuthorizationItem(name: authorizationRight, valueLength: 0, value: nil, flags: 0)
55 | let authItemPointer = UnsafeMutablePointer.allocate(capacity: 1)
56 | authItemPointer.initialize(to: authItem)
57 | defer {
58 | authItemPointer.deinitialize(count: 1)
59 | authItemPointer.deallocate()
60 | }
61 | var authRights = AuthorizationRights(count: 1, items: authItemPointer)
62 |
63 | var environment = AuthorizationEnvironment(count: 0, items: nil)
64 |
65 | if let prompt = prompt {
66 | let authorizationEnvironmentPrompt = (kAuthorizationEnvironmentPrompt as NSString).utf8String!
67 | let promptString = (prompt as NSString).utf8String!
68 | let envItem = AuthorizationItem(name: authorizationEnvironmentPrompt, valueLength: prompt.lengthOfBytes(using: String.Encoding.utf8), value: UnsafeMutablePointer(mutating: promptString), flags: UInt32(0))
69 | let envItemPointer = UnsafeMutablePointer.allocate(capacity: 1)
70 | envItemPointer.initialize(to: envItem)
71 | environment.count = 1
72 | environment.items = envItemPointer
73 | }
74 |
75 | let flags: AuthorizationFlags = [
76 | .interactionAllowed,
77 | .preAuthorize,
78 | .extendRights
79 | ]
80 |
81 | var authRef: AuthorizationRef?
82 | let status = AuthorizationCreate(&authRights, &environment, flags, &authRef)
83 | if let envItems = environment.items {
84 | envItems.deinitialize(count: Int(environment.count))
85 | envItems.deallocate()
86 | }
87 | if status == OSStatus(errAuthorizationSuccess) {
88 | return authRef!
89 | } else if status == OSStatus(errAuthorizationDenied) {
90 | throw SMJError.authorizationDenied // "The system denied the authorization request"
91 | } else if status == OSStatus(errAuthorizationCanceled) {
92 | throw SMJError.authorizationCanceled // "The user canceled the authorization request"
93 | } else if status == OSStatus(errAuthorizationInteractionNotAllowed) {
94 | throw SMJError.authorizationInteractionNotAllowed // "Not allowed to prompt the user for authorization"
95 | } else {
96 | throw SMJError.authorizationFailed(status) // String(format: "Unknown failure when calling AuthorizationCreate (OSStatus %d)", status)
97 | }
98 | }
99 |
100 | }
101 |
--------------------------------------------------------------------------------
/Sources/SMJobKit/ErrorTypes.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ErrorTypes.swift
3 | // SMJobKit
4 | //
5 | // Created by Ingmar Stein on 29.03.15.
6 | //
7 | //
8 |
9 | import Foundation
10 |
11 | public enum SMJError: Error {
12 |
13 | // A failure when referencing a bundle that doesn't exist (or bad perms)
14 | case bundleNotFound
15 | // A failure when trying to get the SecStaticCode for a bundle, but it is unsigned
16 | case unsignedBundle
17 | // Unknown failure when calling SecStaticCodeCreateWithPath
18 | case badBundleSecurity(OSStatus)
19 | // Unknown failure when calling SecCodeCopySigningInformation for a bundle
20 | case badBundleCodeSigningDictionary
21 |
22 | // Failure when calling SMJobBless
23 | case unableToBless(Error)
24 |
25 | // Authorization was denied by the system when asking a user for authorization
26 | case authorizationDenied
27 | // The user canceled a prompt for authorization
28 | case authorizationCanceled
29 | // Unable to prompt the user (interaction disallowed)
30 | case authorizationInteractionNotAllowed
31 | // Unknown failure when prompting the user for authorization
32 | case authorizationFailed(OSStatus)
33 |
34 | public var code: Int {
35 | switch self {
36 | case .bundleNotFound: return 1000
37 | case .unsignedBundle: return 1001
38 | case .badBundleSecurity: return 1002
39 | case .badBundleCodeSigningDictionary: return 1003
40 | case .unableToBless: return 1010
41 | case .authorizationDenied: return 1020
42 | case .authorizationCanceled: return 1021
43 | case .authorizationInteractionNotAllowed: return 1022
44 | case .authorizationFailed: return 1023
45 | }
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/Tests/SMJobKitTests/ClientTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ClientTests.swift
3 | // SMJobKit
4 | //
5 | // Created by Ingmar Stein on 29.03.15.
6 | //
7 | //
8 |
9 | import Cocoa
10 | import XCTest
11 | @testable import SMJobKit
12 |
13 | class ClientTests: XCTestCase {
14 |
15 | func testBundledVersion() {
16 | XCTAssert(TestClient.bundledVersion! == "0.01", "Missing/wrong version")
17 | XCTAssert(MissingClient.bundledVersion == nil, "Missing client should return nil")
18 | }
19 |
20 | func testForProblems() {
21 | XCTAssert(TestClient.checkForProblems().isEmpty, "TestService should not have problems")
22 |
23 | let errors = MissingClient.checkForProblems()
24 | XCTAssertEqual(errors.count, 1, "MissingService should have one error")
25 | if let error = errors.first! as? SMJError {
26 | switch error {
27 | case .bundleNotFound:
28 | break
29 | default:
30 | XCTAssert(false, "Missing service should be missing")
31 | }
32 | } else {
33 | XCTAssert(false, "Missing service should be missing")
34 | }
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/Tests/SMJobKitTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundlePackageType
14 | BNDL
15 | CFBundleShortVersionString
16 | 1.0
17 | CFBundleSignature
18 | ????
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Tests/SMJobKitTests/MissingClient.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SMJMissingClient.swift
3 | // SMJobKit
4 | //
5 | // Created by Ingmar Stein on 29.03.15.
6 | //
7 | //
8 |
9 | import SMJobKit
10 |
11 | class MissingClient: Client {
12 |
13 | override class var serviceIdentifier: String {
14 | return "net.nevir.SMJobKitTests.MissingService"
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/Tests/SMJobKitTests/TestClient.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SMJTestClient.swift
3 | // SMJobKit
4 | //
5 | // Created by Ingmar Stein on 29.03.15.
6 | //
7 | //
8 |
9 | import SMJobKit
10 |
11 | class TestClient: Client {
12 | override class var serviceIdentifier: String {
13 | return "net.nevir.SMJobKitTests.TestService"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Tests/TestService/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleIdentifier
6 | net.nevir.SMJobKitTests.TestService
7 | CFBundleInfoDictionaryVersion
8 | 6.0
9 | CFBundleName
10 | TestService
11 | CFBundleVersion
12 | 0.01
13 | SMAuthorizedClients
14 |
15 | identifier net.nevir.SMJobKit and certificate leaf[subject.CN] = "${CODE_SIGN_IDENTITY}"
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/Tests/TestService/Launchd.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Label
6 | net.nevir.SMJobKitTests.TestService
7 | MachServices
8 |
9 | net.nevir.SMJobKitTests.TestService
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Tests/TestService/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // TestService
4 | //
5 | // Created by Ian MacLeod on 7/9/12.
6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | int main(int argc, const char *argv[])
10 | {
11 | return 0;
12 | }
13 |
--------------------------------------------------------------------------------
/Xcode Templates/Application/SMJobKit-Based Application.xctemplate/README-SMJobKit.md:
--------------------------------------------------------------------------------
1 | Getting Started With Your SMJobKit-based Application
2 | ====================================================
3 |
4 | There are a few manual steps that you need to perform before you can build your application:
5 |
6 | 1. Add your service's binary (product) to the Copy Files build phase of your application (the phase
7 | for `Contents/Library/LaunchServices`).
8 |
9 | 2. Set up your application's target to link with `SMJobKit.framework`.
10 |
11 | Xcode templates can do a lot, but not everything! Plus, they're not really documented. If you
12 | know how to accomplish any of the above steps via template configuration, let me know, please :)
13 |
--------------------------------------------------------------------------------
/Xcode Templates/Application/SMJobKit-Based Application.xctemplate/TemplateInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Kind
6 | Xcode.Xcode3.ProjectTemplateUnitKind
7 | Identifier
8 | net.nevir.SMJobKit.Application
9 | InjectionTargets
10 |
11 | com.apple.dt.unit.cocoaApplication
12 |
13 | Options
14 |
15 |
16 | Identifier
17 | includeSMJobKitService
18 | Name
19 | Include SMJobKit Service
20 | SortOrder
21 | 1
22 | Description
23 | Whether the application should also bundle a SMJobKit-based system service.
24 | Type
25 | checkbox
26 | Default
27 | false
28 | Units
29 |
30 | true
31 |
32 |
33 | Components
34 |
35 |
36 | Identifier
37 | net.nevir.SMJobKit.Service
38 | Name
39 | ___VARIABLE_smjServiceName:RFC1034Identifier___
40 | Dependents
41 |
42 | 0
43 |
44 |
45 |
46 | Targets
47 |
48 |
49 | SharedSettings
50 |
51 | CODE_SIGN_IDENTITY
52 | Mac Developer
53 |
54 | BuildPhases
55 |
56 |
57 | Class
58 | ShellScript
59 | ShellPath
60 | /usr/bin/env ruby
61 | ShellScript
62 | # Postprocessing for your info.plist. Primarily so that we can inject your full dev certificate name.
63 |
64 | require 'cgi'
65 | require 'fileutils'
66 |
67 | missing_keys = ['BUILD_DIR', 'CODE_SIGN_IDENTITY', 'TARGET_BUILD_DIR', 'INFOPLIST_PATH'] - ENV.keys
68 | raise "Missing required ENV values: #{missing_keys.inspect}" if missing_keys.size > 0
69 |
70 | files_to_postprocess = [ENV['INFOPLIST_PATH']]
71 |
72 |
73 | # FULL_CODE_SIGN_IDENTITY
74 | # -----------------------
75 | dummy_path = "#{ENV['BUILD_DIR']}/SMJobKitCodeSigningDummy"
76 |
77 | identity = ENV['CODE_SIGN_IDENTITY']
78 | # If you use the generic code signing identity, chances are that it'll conflict.
79 | identity = "#{identity}:" if identity.end_with? ' Developer'
80 |
81 | # We can't seem to get direct access to the code signing certificate that Xcode has
82 | # selected at this point :(
83 | `touch #{dummy_path}`
84 | `codesign --force --sign "#{identity}" "#{dummy_path}"`
85 | result = `codesign --display --verbose --verbose "#{dummy_path}" 2>&1`
86 | `rm #{dummy_path}`
87 |
88 | ENV['FULL_CODE_SIGN_IDENTITY'] = result[/Authority\=(.*#{Regexp.escape(identity)}.*)/, 1]
89 |
90 |
91 | # Actual Preprocessing
92 | # --------------------
93 |
94 | files_to_postprocess.each do |path|
95 | target_path = File.join(ENV['TARGET_BUILD_DIR'], path)
96 |
97 | input = open(target_path).read
98 | open(target_path, 'w') do |output|
99 | # Specify macros via [[[VAR_NAME]]] to avoid clashes w/ regular plist preprocessing.
100 | output.write input.gsub(/\[\[\[([A-Z_]+)\]\]\]/) { CGI.escapeHTML(ENV[$1]) }
101 | end
102 | end
103 |
104 |
105 | Class
106 | CopyFiles
107 | DstPath
108 | Contents/Library/LaunchServices
109 | DstSubfolderSpec
110 | 1
111 |
112 |
113 |
114 |
115 | Nodes
116 |
117 | README-SMJobKit.md
118 | Info.plist:SMPrivilegedExecutables
119 | ___VARIABLE_smjServiceName:RFC1034Identifier___.swift
120 | AppDelegate.swift:implementation:methods:applicationDidFinishLaunching:installSMJServices
121 | AppDelegate.swift:implementation:methods:installServices
122 | AppDelegate.swift:implementation:methods:installServices:___VARIABLE_smjServiceName:RFC1034Identifier___
123 |
124 | Definitions
125 |
126 | README-SMJobKit.md
127 |
128 | Path
129 | README-SMJobKit.md
130 |
131 | Info.plist:SMPrivilegedExecutables
132 |
133 | <key>SMPrivilegedExecutables</key>
134 | <dict>
135 | <key>___VARIABLE_bundleIdentifierPrefix:bundleIdentifier___.[[[PROJECT_NAME]]].___VARIABLE_smjServiceName:RFC1034Identifier___</key>
136 | <string>identifier ___VARIABLE_bundleIdentifierPrefix:bundleIdentifier___.[[[PROJECT_NAME]]].___VARIABLE_smjServiceName:RFC1034Identifier___ and certificate leaf[subject.CN] = "[[[FULL_CODE_SIGN_IDENTITY]]]"</string>
137 | </dict>
138 |
139 | ___VARIABLE_smjServiceName:RFC1034Identifier___.swift
140 |
141 | Path
142 | ___VARIABLE_smjServiceName:RFC1034Identifier___.swift
143 | Group
144 | Service Clients
145 |
146 | AppDelegate.swift:implementation:methods:installServices
147 |
148 | Beginning
149 | private func installServices() {
150 | End
151 | }
152 | Indent
153 | 1
154 |
155 | AppDelegate.swift:implementation:methods:installServices:___VARIABLE_smjServiceName:RFC1034Identifier___
156 | if ___VARIABLE_smjServiceName:RFC1034Identifier___.isLatestVersionInstalled {
157 | return
158 | }
159 |
160 | var error: NSError? = nil
161 | // The user will be prompted with the following:
162 | //
163 | // <Your Custom Message Here>
164 | // ___VARIABLE_productName___ is trying to install a new
165 | // helper tool. Type your password to allow this.
166 | if !___VARIABLE_smjServiceName:RFC1034Identifier___.installWithPrompt("<Your Custom Message Here>", error:&error) {
167 | // Let the user know something went wrong!
168 | }
169 | AppDelegate.swift:implementation:methods:applicationDidFinishLaunching:installSMJServices
170 | installServices()
171 |
172 |
173 |
174 |
175 |
176 |
177 | Identifier
178 | smjServiceName
179 | Required
180 |
181 | Name
182 | Service Name
183 | SortOrder
184 | 2
185 | Description
186 | The SMJobKit service's base name
187 | EmptyReplacement
188 | ServiceName
189 | Type
190 | text
191 | RequiredOptions
192 |
193 | includeSMJobKitService
194 | true
195 |
196 |
197 |
198 | Identifier
199 | smjServiceBundleIdentifier
200 | Name
201 | Service Identifier
202 | SortOrder
203 | 2
204 | NotPersisted
205 |
206 | Description
207 | Your new service's bundle and launchd identifier
208 | Default
209 | ___VARIABLE_bundleIdentifierPrefix:bundleIdentifier___.___VARIABLE_productName:RFC1034Identifier___.___VARIABLE_smjServiceName:RFC1034Identifier___
210 | Type
211 | static
212 | RequiredOptions
213 |
214 | includeSMJobKitService
215 | true
216 |
217 |
218 |
219 |
220 |
221 |
--------------------------------------------------------------------------------
/Xcode Templates/Application/SMJobKit-Based Application.xctemplate/___VARIABLE_smjServiceName:RFC1034Identifier___.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // ___PACKAGENAME___
4 | //
5 | // Created by ___FULLUSERNAME___ on ___DATE___.
6 | //___COPYRIGHT___
7 | //
8 |
9 | import SMJobKit
10 |
11 | class ___FILEBASENAMEASIDENTIFIER___: Client {
12 |
13 | override class var serviceIdentifier: String {
14 | return "___VARIABLE_bundleIdentifierPrefix:bundleIdentifier___.___VARIABLE_productName___.___VARIABLE_smjServiceName:RFC1034Identifier___"
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/Xcode Templates/Framework & Library/SMJobKit Service.xctemplate/TemplateIcon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IngmarStein/SMJobKit/4ed936712e6994a037581d33e1afbadda15e3394/Xcode Templates/Framework & Library/SMJobKit Service.xctemplate/TemplateIcon.icns
--------------------------------------------------------------------------------
/Xcode Templates/Framework & Library/SMJobKit Service.xctemplate/TemplateInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Kind
6 | Xcode.Xcode3.ProjectTemplateUnitKind
7 | Identifier
8 | net.nevir.SMJobKit.Service
9 | Concrete
10 |
11 | Description
12 | This template builds a SMJobKit Service
13 | SortOrder
14 | 3
15 | Ancestors
16 |
17 | com.apple.dt.unit.macReferenceCounting
18 |
19 | Options
20 |
21 |
22 | Identifier
23 | productName
24 | Required
25 |
26 | Name
27 | Service Name
28 | NotPersisted
29 |
30 | Description
31 | Your new SMJobKit service's name
32 | EmptyReplacement
33 | ServiceName
34 | Type
35 | text
36 |
37 |
38 | Identifier
39 | bundleIdentifierPrefix
40 | Required
41 |
42 | Name
43 | Company Identifier
44 | Description
45 | Your company's bundle identifier prefix
46 | EmptyReplacement
47 | com.yourcompany
48 | Type
49 | text
50 |
51 |
52 | Identifier
53 | bundleIdentifier
54 | Name
55 | Bundle Identifier
56 | NotPersisted
57 |
58 | Description
59 | Your new service's bundle and launchd identifier
60 | Default
61 | ___VARIABLE_bundleIdentifierPrefix:bundleIdentifier___.<Project>.___VARIABLE_productName___
62 | Type
63 | static
64 |
65 |
66 | Project
67 |
68 | SharedSettings
69 |
70 | CODE_SIGN_IDENTITY
71 | Mac Developer
72 | GCC_C_LANGUAGE_STANDARD
73 | gnu99
74 | GCC_WARN_ABOUT_RETURN_TYPE
75 | YES
76 | GCC_WARN_UNINITIALIZED_AUTOS
77 | YES
78 | GCC_WARN_UNUSED_VARIABLE
79 | YES
80 | ALWAYS_SEARCH_USER_PATHS
81 | NO
82 |
83 | Configurations
84 |
85 | Debug
86 |
87 | GCC_OPTIMIZATION_LEVEL
88 | 0
89 | GCC_PREPROCESSOR_DEFINITIONS
90 | DEBUG=1 $(inherited)
91 | COPY_PHASE_STRIP
92 | NO
93 | GCC_DYNAMIC_NO_PIC
94 | NO
95 |
96 | Release
97 |
98 | COPY_PHASE_STRIP
99 | YES
100 |
101 |
102 |
103 | Targets
104 |
105 |
106 | ProductType
107 | com.apple.product-type.tool
108 | SharedSettings
109 |
110 | PRODUCT_NAME
111 | ___VARIABLE_bundleIdentifierPrefix:bundleIdentifier___.$(PROJECT_NAME).$(TARGET_NAME)
112 | PARENT_APPLICATION_IDENTIFIER
113 | ___VARIABLE_bundleIdentifierPrefix:bundleIdentifier___.$(PROJECT_NAME)
114 | SMJ_PREPROCESS_DIR
115 | $(BUILD_DIR)/Preprocessed
116 | SMJ_PREPROCESS_FILES
117 | ___PACKAGENAME___/___PACKAGENAMEASIDENTIFIER___-Info.plist, ___PACKAGENAME___/___PACKAGENAMEASIDENTIFIER___-Launchd.plist
118 | OTHER_LDFLAGS
119 | -sectcreate __TEXT __info_plist "$(SMJ_PREPROCESS_DIR)/___PACKAGENAME___/___PACKAGENAMEASIDENTIFIER___-Info.plist" -sectcreate __TEXT __launchd_plist "$(SMJ_PREPROCESS_DIR)/___PACKAGENAME___/___PACKAGENAMEASIDENTIFIER___-Launchd.plist"
120 |
121 | BuildPhases
122 |
123 |
124 | Class
125 | ShellScript
126 | ShellPath
127 | /usr/bin/env ruby
128 | ShellScript
129 | # Generic preprocessing for ${ENV_VAR} with output to the build dir.
130 |
131 | require 'cgi'
132 | require 'fileutils'
133 |
134 | missing_keys = ['BUILD_DIR', 'CODE_SIGN_IDENTITY', 'SMJ_PREPROCESS_FILES', 'SMJ_PREPROCESS_DIR'] - ENV.keys
135 | raise "Missing required ENV values: #{missing_keys.inspect}" if missing_keys.size > 0
136 |
137 | # SMJ_PREPROCESS_FILES is a comma-separated list of *relative* file paths to preprocess
138 | # and spit out into the SMJ_PREPROCESS_DIR (w/ the same relative paths as given)
139 | files_to_preprocess = ENV['SMJ_PREPROCESS_FILES'].split(',').map(&:strip)
140 |
141 |
142 | # Environment Cleanup
143 | # -------------------
144 | dummy_path = "#{ENV['BUILD_DIR']}/SMJobKitCodeSigningDummy"
145 |
146 | identity = ENV['CODE_SIGN_IDENTITY']
147 | # If you use the generic code signing identity, chances are that it'll conflict.
148 | identity = "#{identity}:" if identity.end_with? ' Developer'
149 |
150 | # We can't seem to get direct access to the code signing certificate that Xcode has
151 | # selected at this point :(
152 | `touch #{dummy_path}`
153 | `codesign --force --sign "#{identity}" "#{dummy_path}"`
154 | result = `codesign --display --verbose --verbose "#{dummy_path}" 2>&1`
155 | `rm #{dummy_path}`
156 |
157 | ENV['FULL_CODE_SIGN_IDENTITY'] = result[/Authority\=(.*#{Regexp.escape(identity)}.*)/, 1]
158 |
159 |
160 | # Actual Preprocessing
161 | # --------------------
162 |
163 | files_to_preprocess.each do |path|
164 | target_path = File.join(ENV['SMJ_PREPROCESS_DIR'], path)
165 | FileUtils.mkpath File.dirname(target_path)
166 |
167 | open(path) do |input|
168 | open(target_path, 'w') do |output|
169 | # Specify macros via ${VAR_NAME} in the preprocessed file. Same as regular
170 | # Info.plist preprocessing.
171 | output.write input.read.gsub(/\$\{([A-Z_]+)\}/) { CGI.escapeHTML(ENV[$1]) }
172 | end
173 | puts target_path
174 | end
175 | end
176 |
177 |
178 | Class
179 | Sources
180 |
181 |
182 | Class
183 | Frameworks
184 |
185 |
186 | Frameworks
187 |
188 | Foundation
189 |
190 |
191 |
192 | Nodes
193 |
194 | main.m
195 | ___PACKAGENAMEASIDENTIFIER___-Info.plist
196 | ___PACKAGENAMEASIDENTIFIER___-Launchd.plist
197 |
198 | Definitions
199 |
200 | main.m
201 |
202 | Path
203 | main.m
204 |
205 | ___PACKAGENAMEASIDENTIFIER___-Info.plist
206 |
207 | Path
208 | ___PACKAGENAMEASIDENTIFIER___-Info.plist
209 |
210 | ___PACKAGENAMEASIDENTIFIER___-Launchd.plist
211 |
212 | Path
213 | ___PACKAGENAMEASIDENTIFIER___-Launchd.plist
214 |
215 |
216 |
217 |
218 |
--------------------------------------------------------------------------------
/Xcode Templates/Framework & Library/SMJobKit Service.xctemplate/___PACKAGENAMEASIDENTIFIER___-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleIdentifier
6 | ${PRODUCT_NAME}
7 | CFBundleInfoDictionaryVersion
8 | 6.0
9 | CFBundleName
10 | ___PACKAGENAMEASIDENTIFIER___
11 | CFBundleVersion
12 | 0.01
13 | SMAuthorizedClients
14 |
15 | identifier ${PARENT_APPLICATION_IDENTIFIER} and certificate leaf[subject.CN] = "${FULL_CODE_SIGN_IDENTITY}"
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/Xcode Templates/Framework & Library/SMJobKit Service.xctemplate/___PACKAGENAMEASIDENTIFIER___-Launchd.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Label
6 | ${PRODUCT_NAME}
7 | MachServices
8 |
9 | ${PRODUCT_NAME}
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Xcode Templates/Framework & Library/SMJobKit Service.xctemplate/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // ___PACKAGENAME___
4 | //
5 | // Created by ___FULLUSERNAME___ on ___DATE___.
6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved.
7 | //
8 |
9 | int main(int argc, const char *argv[])
10 | {
11 | return 0;
12 | }
13 |
--------------------------------------------------------------------------------