├── .gitignore
├── example
├── images
│ └── Constant.png
├── Ambientfile
├── Ambientfile-objc
└── Ambientfile-verbose
├── lib
├── ambient
│ ├── dsl.rb
│ ├── dsl
│ │ ├── plist_scope.rb
│ │ ├── target_scope.rb
│ │ ├── scheme_scope.rb
│ │ └── main_scope.rb
│ ├── plist_helper.rb
│ ├── init.rb
│ ├── capabilities_helper.rb
│ ├── project_creation.rb
│ ├── project_helper.rb
│ └── application.rb
└── ambient.rb
├── templates
└── ios
│ ├── PRODUCTNAME.xcodeproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── project.pbxproj
│ └── PRODUCTNAME
│ ├── ViewController.swift
│ ├── Assets.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
│ ├── Base.lproj
│ ├── Main.storyboard
│ └── LaunchScreen.storyboard
│ ├── Info.plist
│ └── AppDelegate.swift
├── ambient-xcode.gemspec
├── bin
└── ambient
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 |
3 | tags
4 |
--------------------------------------------------------------------------------
/example/images/Constant.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dan2552/ambient-xcode/HEAD/example/images/Constant.png
--------------------------------------------------------------------------------
/lib/ambient/dsl.rb:
--------------------------------------------------------------------------------
1 | require_relative 'dsl/main_scope'
2 | require_relative 'dsl/plist_scope'
3 | require_relative 'dsl/scheme_scope'
4 | require_relative 'dsl/target_scope'
5 |
--------------------------------------------------------------------------------
/example/Ambientfile:
--------------------------------------------------------------------------------
1 | PROJECT = "MyProject"
2 | PREFIX = "com.organization."
3 |
4 | base_ios_settings! PROJECT,
5 | prefix: PREFIX,
6 | tests: true,
7 | ui_tests: true
8 |
--------------------------------------------------------------------------------
/templates/ios/PRODUCTNAME.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/Ambientfile-objc:
--------------------------------------------------------------------------------
1 | PROJECT = "MyProject"
2 | PREFIX = "com.organization."
3 |
4 | base_ios_settings! PROJECT,
5 | prefix: PREFIX,
6 | tests: true,
7 | ui_tests: true,
8 | swift: false
9 |
--------------------------------------------------------------------------------
/lib/ambient.rb:
--------------------------------------------------------------------------------
1 | require 'xcodeproj'
2 | require 'plist'
3 |
4 | require_relative 'ambient/project_helper'
5 | require_relative 'ambient/capabilities_helper'
6 | require_relative 'ambient/plist_helper'
7 | require_relative 'ambient/dsl'
8 | require_relative 'ambient/project_creation'
9 | require_relative 'ambient/init'
10 | require_relative 'ambient/application'
11 |
--------------------------------------------------------------------------------
/templates/ios/PRODUCTNAME/ViewController.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 |
3 | class ViewController: UIViewController {
4 | override func viewDidLoad() {
5 | super.viewDidLoad()
6 | // Do any additional setup after loading the view, typically from a nib.
7 | }
8 |
9 | override func didReceiveMemoryWarning() {
10 | super.didReceiveMemoryWarning()
11 | // Dispose of any resources that can be recreated.
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/lib/ambient/dsl/plist_scope.rb:
--------------------------------------------------------------------------------
1 | module Ambient
2 | module DSL
3 | class PlistScope
4 | attr_reader :application,
5 | :helper
6 |
7 | def initialize(application, path)
8 | @application = application
9 | @helper = PlistHelper.new(path)
10 | end
11 |
12 | def configure(&block)
13 | instance_eval(&block)
14 | end
15 |
16 | def entry(key, value)
17 | helper.add_entry(key, value)
18 | end
19 | end
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/lib/ambient/plist_helper.rb:
--------------------------------------------------------------------------------
1 | module Ambient
2 | class PlistHelper
3 | attr_reader :path
4 |
5 | def initialize(path)
6 | @path = path
7 | end
8 |
9 | def add_entry(key, value)
10 | plist_as_dictionary[key] = value
11 | puts "applying to plist: #{path} #{key}"
12 | save
13 | end
14 |
15 | private
16 |
17 | def plist_as_dictionary
18 | @plist_as_dictionary ||= Plist::parse_xml(path)
19 | end
20 |
21 | def to_plist
22 | plist_as_dictionary.to_plist
23 | end
24 |
25 | def save
26 | File.open(path, 'w') { |file| file.write(to_plist) }
27 | end
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/lib/ambient/init.rb:
--------------------------------------------------------------------------------
1 | module Ambient
2 | class Init
3 | attr_reader :path,
4 | :project_name,
5 | :project_prefix
6 |
7 | def initialize(path = nil, project_name = nil, project_prefix = nil)
8 | @path = path || Dir.pwd
9 | @project_name = project_name || "MyProject"
10 | @project_prefix = project_prefix || "com.#{@project_name.downcase}."
11 | end
12 |
13 | def create_ambientfile
14 | puts "# Creating Ambientfile..."
15 | write_file
16 | puts "File created at #{filepath}"
17 | end
18 |
19 | private
20 |
21 | def write_file
22 | File.open(filepath, 'w') { |file| file.write(contents) }
23 | end
24 |
25 | def filepath
26 | "#{path}/Ambientfile"
27 | end
28 |
29 | def contents
30 | "base_ios_settings! \"#{project_name}\", prefix: \"#{project_prefix}\"\n"
31 | end
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/ambient-xcode.gemspec:
--------------------------------------------------------------------------------
1 | lib = File.expand_path('../lib', __FILE__)
2 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3 |
4 | Gem::Specification.new do |gem|
5 | gem.name = 'ambient-xcode'
6 | gem.version = '0.8.1'
7 | gem.authors = ['Daniel Inkpen']
8 | gem.email = ['dan2552@gmail.com']
9 | gem.description = %q{CLI for configuring Xcode projects from a Ruby file.}
10 | gem.summary = %q{Define your environment settings all in one easy to read Ruby file.}
11 | gem.homepage = 'https://github.com/Dan2552/ambient'
12 | gem.license = 'MIT'
13 |
14 | gem.add_dependency 'xcodeproj', '~> 1.5', '>= 1.5.0'
15 | gem.add_dependency 'plist', '~> 3.2', '>= 3.2.0'
16 |
17 | gem.files = `git ls-files`.split($/)
18 | gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
19 | gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
20 | gem.require_paths = ['lib']
21 | end
22 |
--------------------------------------------------------------------------------
/lib/ambient/dsl/target_scope.rb:
--------------------------------------------------------------------------------
1 | module Ambient
2 | module DSL
3 | class TargetScope
4 | attr_reader :application,
5 | :name
6 |
7 | def initialize(application, name)
8 | @application = application
9 | @name = name
10 | end
11 |
12 | def configure(&block)
13 | instance_eval(&block)
14 | end
15 |
16 | def option(option_name, value)
17 | target_name = @name
18 | application.configure { set_option(option_name, value, target: target_name) }
19 | end
20 |
21 | def scheme(name, parent: nil, &block)
22 | SchemeScope.new(application, self, name, parent).configure(&block)
23 | end
24 |
25 | def capability(capability_name)
26 | target_name = @name
27 | application.configure { set_capability(target_name, capability_name) }
28 | end
29 |
30 | def development_team(team_name)
31 | target_name = @name
32 | application.configure { set_development_team(target_name, team_name) }
33 | end
34 | end
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/lib/ambient/dsl/scheme_scope.rb:
--------------------------------------------------------------------------------
1 | module Ambient
2 | module DSL
3 | class SchemeScope
4 | attr_reader :application
5 |
6 | def initialize(application, target, name, parent)
7 | @application = application
8 | @target = target
9 | @name = name
10 | @parent = parent
11 |
12 | application.configure do
13 | set_parent_scheme(
14 | target: target && target.name,
15 | child: name,
16 | parent: parent
17 | )
18 | end
19 | end
20 |
21 | def configure(&block)
22 | if block
23 | instance_eval(&block)
24 | end
25 | end
26 |
27 | def option(option_name, value)
28 | target = @target
29 | name = @name
30 | parent = @parent
31 |
32 | if target
33 | application.configure { set_option(option_name, value, target: target.name, scheme: name, parent: parent) }
34 | else
35 | application.configure { set_option(option_name, value, scheme: name, parent: parent) }
36 | end
37 | end
38 | end
39 | end
40 | end
41 |
--------------------------------------------------------------------------------
/bin/ambient:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require 'fileutils'
3 |
4 | $:.push File.expand_path("../../lib", __FILE__)
5 |
6 | require 'ambient'
7 |
8 | def print_help
9 | print_version
10 | puts ""
11 | puts "usage: "
12 | puts "$ ambient COMMAND"
13 | puts ""
14 | puts "Commands:"
15 | puts "+ [no arguments]\tApplies the settings from the Ambientfile"
16 | puts "+ init\t\t\tCreates an Ambientfile in the current directory"
17 | puts "+ new NAME\t\tCreates a new iOS Xcode project with given name"
18 | puts "+ [anything else]\tApplies the settings from the file name supplied"
19 | end
20 |
21 | def print_version
22 | path = File.expand_path("../../", __FILE__)
23 | gem_contents = File.read("#{path}/ambient-xcode.gemspec")
24 | match = gem_contents.match /^\s*gem.version\s*= ('|")(.*)('|")/
25 | puts "ambient-xcode #{match[2]}"
26 | end
27 |
28 | if ARGV[0] == "init"
29 | Ambient::Init.new.create_ambientfile
30 | elsif ARGV[0] == "new"
31 | Ambient::ProjectCreation.new(Dir.pwd, ARGV[1]).create_ios_project
32 | elsif ARGV[0] == "help" || ARGV[0] == "--help"
33 | print_help
34 | elsif ARGV[0] == "version" || ARGV[0] == "--version" || ARGV[0] == "-v"
35 | print_version
36 | else
37 | Ambient::Application.new.run_ambientfile(ARGV[0])
38 | end
39 |
--------------------------------------------------------------------------------
/templates/ios/PRODUCTNAME/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "ipad",
35 | "size" : "29x29",
36 | "scale" : "1x"
37 | },
38 | {
39 | "idiom" : "ipad",
40 | "size" : "29x29",
41 | "scale" : "2x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "40x40",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "40x40",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "76x76",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "76x76",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
--------------------------------------------------------------------------------
/templates/ios/PRODUCTNAME/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/templates/ios/PRODUCTNAME/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 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 | UISupportedInterfaceOrientations~ipad
40 |
41 | UIInterfaceOrientationPortrait
42 | UIInterfaceOrientationPortraitUpsideDown
43 | UIInterfaceOrientationLandscapeLeft
44 | UIInterfaceOrientationLandscapeRight
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/templates/ios/PRODUCTNAME/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/templates/ios/PRODUCTNAME/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 |
3 | @UIApplicationMain
4 | class AppDelegate: UIResponder, UIApplicationDelegate {
5 | var window: UIWindow?
6 |
7 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
8 | // Override point for customization after application launch.
9 | return true
10 | }
11 |
12 | func applicationWillResignActive(_ application: UIApplication) {
13 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
14 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
15 | }
16 |
17 | func applicationDidEnterBackground(_ application: UIApplication) {
18 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
19 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
20 | }
21 |
22 | func applicationWillEnterForeground(_ application: UIApplication) {
23 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
24 | }
25 |
26 | func applicationDidBecomeActive(_ application: UIApplication) {
27 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
28 | }
29 |
30 | func applicationWillTerminate(_ application: UIApplication) {
31 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/lib/ambient/capabilities_helper.rb:
--------------------------------------------------------------------------------
1 | module Ambient
2 | class CapabilitiesHelper
3 | CAPABILITIES = {
4 | application_group_ios: "ApplicationGroups.iOS",
5 | background_modes: "BackgroundModes",
6 | data_protection: "DataProtection",
7 | game_center: "GameCenter",
8 | healthkit: "HealthKit",
9 | health_kit: "HealthKit",
10 | homekit: "HomeKit",
11 | home_kit: "HomeKit",
12 | in_app_purchase: "InAppPurchase",
13 | inter_app_audio: "InterAppAudio",
14 | keychain: "Keychain",
15 | maps: "Maps.iOS",
16 | apple_pay: "OMC",
17 | passbook: "Passbook",
18 | wallet: "Passbook",
19 | safari_keychain: "SafariKeychain",
20 | personal_vpn: "VPNLite",
21 | wireless_accessory_configuration: "WAC",
22 | icloud: "iCloud"
23 | }
24 |
25 | def initialize(project, target)
26 | @project = project
27 | @target = target
28 | end
29 |
30 | def clear_capabilities
31 | capabilities.delete_if { |_, _| true } if capabilities
32 | end
33 |
34 | def enable_capability(capability)
35 | capabilities[capability_key(capability)] = {"enabled"=>"1"}
36 | end
37 |
38 | def disable_capability(capability)
39 | capabilities.delete(capability_key(capability))
40 | end
41 |
42 | def set_development_team(team)
43 | target_attributes["DevelopmentTeam"] = team
44 | end
45 |
46 | private
47 |
48 | def capabilities
49 | target_attributes["SystemCapabilities"]
50 | end
51 |
52 | def target_attributes
53 | unless @project.root_object.attributes["TargetAttributes"]
54 | @project.root_object.attributes["TargetAttributes"] = {}
55 | end
56 |
57 | unless @project.root_object.attributes["TargetAttributes"][@target.uuid]
58 | @project.root_object.attributes["TargetAttributes"][@target.uuid] = {}
59 | end
60 |
61 | @project.root_object.attributes["TargetAttributes"][@target.uuid]
62 | end
63 |
64 | def capability_key(capability)
65 | capability = CAPABILITIES[capability] || capability.to_s
66 | prefix = "com.apple."
67 | capability = "#{prefix}#{capability}" unless capability.start_with? prefix
68 | capability
69 | end
70 | end
71 | end
72 |
--------------------------------------------------------------------------------
/lib/ambient/project_creation.rb:
--------------------------------------------------------------------------------
1 | module Ambient
2 | class ProjectCreation
3 | attr_reader :path,
4 | :name
5 |
6 | def initialize(path, name)
7 | @path = path
8 | @name = name.gsub(/\W/, "")
9 | check_name!
10 | end
11 |
12 | def create_ios_project
13 | check_already_exists!
14 | puts "# Setting up project..."
15 | copy_from_template
16 | rename_project_to_name
17 | find_and_replace_instances_of_template_to_name
18 | create_ambientfile
19 | run_ambientfile
20 | end
21 |
22 | private
23 |
24 | def check_already_exists!
25 | return unless File.exists?(project_path)
26 |
27 | puts "😱 #{name} already exists in the current directory"
28 | exit 1
29 | end
30 |
31 | def check_name!
32 | return if name
33 |
34 | puts "😱 You must specify a project name when creating a new project"
35 | puts "e.g. `ambient new MyProject`"
36 | exit(1)
37 | end
38 |
39 | def run_ambientfile
40 | Application.new(project_path).run_ambientfile
41 | end
42 |
43 | def create_ambientfile
44 | Init.new(project_path, name).create_ambientfile
45 | end
46 |
47 | def copy_from_template
48 | FileUtils.copy_entry ios_template_path, project_path
49 | end
50 |
51 | def rename_project_to_name
52 | FileUtils.mv "#{project_path}/PRODUCTNAME",
53 | "#{project_path}/#{name}"
54 | FileUtils.mv "#{project_path}/PRODUCTNAME.xcodeproj",
55 | "#{project_path}/#{name}.xcodeproj"
56 | end
57 |
58 | def find_and_replace_instances_of_template_to_name
59 | files_in_project.each do |file|
60 | find_and_replace(file, "PRODUCTNAME", name)
61 | end
62 | end
63 |
64 | def project_path
65 | path + "/#{name}"
66 | end
67 |
68 | def ios_template_path
69 | File.expand_path("../../../templates/ios", __FILE__)
70 | end
71 |
72 | def files_in_project
73 | Dir.glob(project_path + '/**/*').select { |path| File.file?(path) }
74 | end
75 |
76 | def find_and_replace(path, old, new)
77 | text = File.read(path)
78 | replace = text.gsub(old, new)
79 | return if text == replace
80 | File.open(path, "w") { |file| file.puts replace }
81 | end
82 | end
83 | end
84 |
--------------------------------------------------------------------------------
/example/Ambientfile-verbose:
--------------------------------------------------------------------------------
1 | use_defaults_for_everything_not_specified_in_this_file!
2 | enable_default_warnings!
3 |
4 | option "ALWAYS_SEARCH_USER_PATHS", false
5 | option "CLANG_CXX_LANGUAGE_STANDARD", "gnu++0x"
6 | option "CLANG_CXX_LIBRARY", "libc++"
7 | option "CLANG_ENABLE_MODULES", true
8 | option "CLANG_ENABLE_OBJC_ARC", true
9 |
10 | option "CODE_SIGN_IDENTITY[sdk=iphoneos*]", "iPhone Developer"
11 | option "COPY_PHASE_STRIP", false
12 |
13 | option "ENABLE_STRICT_OBJC_MSGSEND", true
14 | option "GCC_C_LANGUAGE_STANDARD", "gnu99"
15 | option "GCC_NO_COMMON_BLOCKS", true
16 | option "SDKROOT", "iphoneos"
17 | option "IPHONEOS_DEPLOYMENT_TARGET", "9.0"
18 |
19 | scheme "Debug" do
20 | option "DEBUG_INFORMATION_FORMAT", "dwarf"
21 | option "ENABLE_TESTABILITY", true
22 | option "MTL_ENABLE_DEBUG_INFO", true
23 | option "ONLY_ACTIVE_ARCH", true
24 | option "GCC_DYNAMIC_NO_PIC", false
25 | option "GCC_OPTIMIZATION_LEVEL", "0"
26 | option "GCC_PREPROCESSOR_DEFINITIONS", ["DEBUG=1", "$(inherited)"]
27 | option "SWIFT_OPTIMIZATION_LEVEL", "-Onone"
28 | end
29 |
30 | scheme "Release" do
31 | option "DEBUG_INFORMATION_FORMAT", "dwarf-with-dsym"
32 | option "ENABLE_NS_ASSERTIONS", false
33 | option "MTL_ENABLE_DEBUG_INFO", false
34 | option "VALIDATE_PRODUCT", true
35 | end
36 |
37 | target "#{PROJECT}" do
38 | option "INFOPLIST_FILE", "#{PROJECT}/Info.plist"
39 | option "PRODUCT_BUNDLE_IDENTIFIER", "#{PREFIX}#{PROJECT}"
40 | option "ASSETCATALOG_COMPILER_APPICON_NAME", "AppIcon"
41 | option "LD_RUNPATH_SEARCH_PATHS", "$(inherited) @executable_path/Frameworks"
42 | option "PRODUCT_NAME", "$(TARGET_NAME)"
43 | end
44 |
45 | target "#{PROJECT}Tests" do
46 | option "INFOPLIST_FILE", "#{PROJECT}Tests/Info.plist"
47 | option "BUNDLE_LOADER", "$(TEST_HOST)"
48 | option "TEST_HOST", "$(BUILT_PRODUCTS_DIR)/#{PROJECT}.app/#{PROJECT}"
49 | option "PRODUCT_BUNDLE_IDENTIFIER", "#{PREFIX}#{PROJECT}Tests"
50 | option "LD_RUNPATH_SEARCH_PATHS", "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"
51 | option "PRODUCT_NAME", "$(TARGET_NAME)"
52 | end
53 |
54 | target "#{PROJECT}UITests" do
55 | option "INFOPLIST_FILE", "#{PROJECT}UITests/Info.plist"
56 | option "TEST_TARGET_NAME", "#{PROJECT}"
57 | option "PRODUCT_BUNDLE_IDENTIFIER", "#{PREFIX}#{PROJECT}UITests"
58 | option "LD_RUNPATH_SEARCH_PATHS", "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"
59 | option "USES_XCTRUNNER", "YES"
60 | option "PRODUCT_NAME", "$(TARGET_NAME)"
61 | end
62 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | > [!WARNING]
2 | > You shouldn't use this, it's not maintained and probably doesn't work with latest versions of things. Looks like maybe https://github.com/yonaskolb/XcodeGen might be similar
3 |
4 | Ambient environment for Xcode projects
5 | ======================================
6 |
7 | Ambient lets you define all of your Xcode project environment settings all in one easy to read Ruby file, and re-apply it to your Xcode project to ensure settings are correct.
8 |
9 | An `xcconfig` file can be used in order to help abstract your settings away from the main project file. The disadvantage of `xcconfig` files though is that they can still be overridden by settings defined in the project. Ambient doesn't have this issue as it simply overwrites the values in the project file.
10 |
11 |
12 | Installation
13 | ============
14 |
15 | Simply run:
16 | ```bash
17 | gem install ambient-xcode
18 | ```
19 |
20 | Or if you use Bundler, add the following to your `Gemfile`:
21 | ```ruby
22 | gem "ambient-xcode"
23 | ```
24 |
25 | Usage
26 | =====
27 |
28 | Create an `Ambientfile` defining your project in the same directory as your `*.xcodeproj` file.
29 |
30 | Here's a sample of the `Ambientfile` structure:
31 | ```ruby
32 | base_ios_settings! "MyProject"
33 |
34 | target "MyProject" do
35 | capability :healthkit
36 | capability :apple_pay
37 |
38 | scheme "Debug" do
39 | option "PRODUCT_NAME", "Debug"
40 | option "BUNDLE_DISPLAY_NAME_SUFFIX", "uk.danielgreen.MyProject"
41 | end
42 | end
43 |
44 | plist("MyProject/Info.plist") do
45 | entry "LSApplicationQueriesSchemes", [ "dbapi-2", "dbapi-8-emm"]
46 | end
47 | ```
48 |
49 | Run `ambient` from the command line to write your settings into your project:
50 | ```
51 | usage:
52 | $ ambient COMMAND
53 |
54 | Commands:
55 | + [no arguments] Applies the settings from the Ambientfile
56 | + init Creates an Ambientfile in the current directory
57 | + new NAME Creates a new iOS Xcode project with given name
58 | + [anything else] Applies the settings from the file name supplied
59 | ```
60 |
61 | You can also have more than one `Ambientfile` for the same project. Just name it something else and run `ambient [filename]` (e.g. `ambient Ambientfile-enterprise`). Use `use_settings_from` to inherit settings:
62 |
63 | ```ruby
64 | use_settings_from 'Ambientfile'
65 |
66 | target "Monies" do
67 | development_team "341MONEY25"
68 | capability :apple_pay
69 | end
70 | ```
71 |
72 |
73 | Notes
74 | =====
75 |
76 | - The [example Ambientfile](https://github.com/Dan2552/ambient-xcode/blob/master/example/Ambientfile) or [example Ambientfile-objc](https://github.com/Dan2552/ambient-xcode/blob/master/example/Ambientfile-objc) matches the exact settings of a new iOS project.
77 | - Use the `use_defaults_for_everything_not_specified_in_this_file!` setting to ensure your project file is clean. Warning though: this setting will clear all your targets' settings, so be sure to define absolutely every setting in the `Ambientfile` if you want to use this.
78 | - When defining settings directly within a target, the setting is set to each scheme.
79 | - The name of the constants used for `option` is located in the **Quick Help** section in Xcode
80 | 
81 |
82 | Possible future features
83 | ========================
84 |
85 | - Automatic editing of `.entitlements`
86 | - Helper method to change build phases to default
87 | - Version number + build number
88 | - Provisioning profiles from searching by name rather than storing a uuid (so it actually works across teams)
89 | - Ability to not have to commit `*.xcodeproj` into version control (maybe too far?)
90 |
--------------------------------------------------------------------------------
/lib/ambient/project_helper.rb:
--------------------------------------------------------------------------------
1 | module Ambient
2 | class ProjectHelper
3 | attr_reader :path
4 |
5 | def initialize(path)
6 | @path = path
7 | projects = Dir.glob(path + '/*.xcodeproj')
8 | @project = Xcodeproj::Project.open(projects.first)
9 | end
10 |
11 | def reset_project_to_defaults
12 | @project.build_configurations.each do |configuration|
13 | build_settings = configuration.build_settings
14 | build_settings.each { |k, _| build_settings.delete(k) }
15 | end
16 | end
17 |
18 | def reset_targets_to_defaults
19 | @project.targets.each do |target|
20 | @project.build_configurations.each do |configuration|
21 | build_settings = target.build_configuration_list.build_settings(configuration.to_s)
22 | build_settings.each { |k, _| build_settings.delete(k) }
23 | end
24 | end
25 | end
26 |
27 | def reset_capabilities_to_defaults
28 | @project.targets.each do |target|
29 | CapabilitiesHelper.new(@project, target).clear_capabilities
30 | end
31 | end
32 |
33 | def process_project_options(options)
34 | @project.build_configurations.each do |configuration|
35 | options.each do |key, value|
36 | configuration.build_settings[key] = value
37 | configuration.build_settings.delete(key) if value == nil
38 | end
39 | end
40 | end
41 |
42 | def process_shared_target_options(shared_target_options)
43 | @project.targets.each do |target|
44 | options = shared_target_options[target.to_s]
45 | if options
46 | @project.build_configurations.each do |configuration|
47 | target.build_configuration_list.build_settings(configuration.to_s).merge!(options)
48 | end
49 | end
50 | end
51 | end
52 |
53 | def process_target_options(target_options)
54 | @project.targets.each do |target|
55 | options = target_options[target.to_s]
56 | if options
57 | @project.build_configurations.each do |configuration|
58 | scheme_options = options[configuration.to_s]
59 | if scheme_options
60 | target.build_configuration_list.build_settings(configuration.to_s).merge!(scheme_options)
61 | end
62 | end
63 | end
64 | end
65 | end
66 |
67 | def process_capabilities(capabilities_hash)
68 | capabilities_hash.each do |target_name, capabilities|
69 | @project.targets.each do |target|
70 | if target_name == target.to_s
71 | helper = CapabilitiesHelper.new(@project, target)
72 | capabilities.each { |c| helper.enable_capability(c) }
73 | end
74 | end
75 | end
76 | end
77 |
78 | def process_scheme_options(options)
79 | @project.build_configurations.each do |configuration|
80 | scheme_options = options[configuration.to_s] || {}
81 | scheme_options.each do |key, value|
82 | configuration.build_settings[key] = value
83 | configuration.build_settings.delete(key) if value == nil
84 | end
85 | end
86 | end
87 |
88 | def process_development_teams(development_teams)
89 | development_teams.each do |target_name, development_team|
90 | @project.targets.each do |target|
91 | if target_name == target.to_s
92 | helper = CapabilitiesHelper.new(@project, target)
93 | helper.set_development_team(development_team)
94 | end
95 | end
96 | end
97 | end
98 |
99 | def print_info
100 | puts ""
101 | puts "Targets:"
102 | @project.targets.each { |t| puts "- #{t.to_s}" }
103 | puts ""
104 | puts "Build configurations:"
105 | @project.build_configurations.each { |c| puts "- #{c.to_s}" }
106 | puts ""
107 | end
108 |
109 | def save_changes
110 | @project.save
111 | end
112 | end
113 | end
114 |
--------------------------------------------------------------------------------
/lib/ambient/application.rb:
--------------------------------------------------------------------------------
1 | module Ambient
2 | class Application
3 | attr_reader :path
4 |
5 | def initialize(path = nil)
6 | @path = path || Dir.pwd
7 |
8 | @use_defaults = false
9 | @project_options = {}
10 | @shared_target_options = {}
11 | @target_options = {}
12 | @scheme_options = {}
13 | @parents = {}
14 | @capabilities = {}
15 | @development_teams = {}
16 | end
17 |
18 | def run_ambientfile(file = nil)
19 | setup_project(file || "Ambientfile")
20 | end
21 |
22 | def configure(&block)
23 | instance_eval(&block)
24 | end
25 |
26 | private
27 |
28 | def project_helper
29 | @project_helper ||= ProjectHelper.new(path)
30 | end
31 |
32 | def set_parent_scheme(target: nil, child: nil, parent: nil)
33 | target = target || :all
34 | @parents[target] ||= {}
35 | @parents[target][child] = parent
36 | end
37 |
38 | def set_option(option, value, target: nil, scheme: nil, parent: nil)
39 | value = "YES" if value == true
40 | value = "NO" if value == false
41 | value = nil if value == :default
42 |
43 | if target
44 | if scheme
45 | @target_options[target] ||= {}
46 | @target_options[target][scheme] ||= {}
47 | @target_options[target][scheme][option] = value
48 | else
49 | @shared_target_options[target] ||= {}
50 | @shared_target_options[target][option] = value
51 | end
52 | else
53 | if scheme
54 | @scheme_options[scheme] ||= {}
55 | @scheme_options[scheme][option] = value
56 | else
57 | @project_options[option] = value
58 | end
59 | end
60 | end
61 |
62 | def set_capability(target_name, capability_name)
63 | capabilities = @capabilities[target_name] ||= []
64 | capabilities << capability_name
65 | end
66 |
67 | def set_development_team(target_name, team_name)
68 | @development_teams[target_name] = team_name
69 | end
70 |
71 | def setup_project(ambientfile)
72 | read(ambientfile)
73 | project_helper.print_info
74 | reset_project_to_defaults if @use_defaults
75 | reset_targets_to_defaults if @use_defaults
76 | reset_capabilites_to_defaults if @use_defaults
77 | load_in_parent_scheme_values
78 | process_project_options
79 | process_scheme_options
80 | process_shared_target_options
81 | process_target_options
82 | process_capabilities
83 | process_development_teams
84 | project_helper.save_changes
85 | end
86 |
87 | def reset_project_to_defaults
88 | puts "resetting project settings to xcode default settings"
89 | project_helper.reset_project_to_defaults
90 | end
91 |
92 | def reset_targets_to_defaults
93 | puts "resetting target settings to xcode default settings"
94 | project_helper.reset_targets_to_defaults
95 | end
96 |
97 | def reset_capabilites_to_defaults
98 | puts "resetting capabilities to xcode default settings"
99 | project_helper.reset_capabilities_to_defaults
100 | end
101 |
102 | def process_project_options
103 | puts "applying ambient project settings"
104 | project_helper.process_project_options(@project_options)
105 | end
106 |
107 | def process_scheme_options
108 | puts "applying ambient scheme settings"
109 | project_helper.process_scheme_options(@scheme_options)
110 | end
111 |
112 | def process_shared_target_options
113 | puts "applying ambient shared target settings"
114 | project_helper.process_shared_target_options(@shared_target_options)
115 | end
116 |
117 | def process_target_options
118 | puts "applying ambient target settings"
119 | project_helper.process_target_options(@target_options)
120 | end
121 |
122 | def process_capabilities
123 | puts "applying ambient capabilities"
124 | project_helper.process_capabilities(@capabilities)
125 | end
126 |
127 | def process_development_teams
128 | puts "applying ambient development teams"
129 | project_helper.process_development_teams(@development_teams)
130 | end
131 |
132 | def load_in_parent_scheme_values
133 | @parents.each do |target, parents|
134 | parents.each do |child, parent|
135 | if parent
136 | if target == :all
137 | puts "Identified #{child} as a child of #{parent}"
138 | child_options = @scheme_options[child]
139 | parent_options = @scheme_options[parent]
140 | else
141 | target_options = @target_options[target]
142 | child_options = target_options[child]
143 | parent_options = target_options[parent]
144 | end
145 | child_options.merge!(parent_options) { |_, child, _| child }
146 | end
147 | end
148 | end
149 | end
150 |
151 | def read(filename)
152 | puts "# Reading settings from #{filename}"
153 | ambient = File.join(path, filename)
154 |
155 | unless File.exists?(ambient)
156 | puts "😱 #{filename} not found in current directory."
157 | exit 1
158 | end
159 |
160 | DSL::MainScope.new(self).instance_eval do
161 | eval(File.read(ambient))
162 | end
163 | end
164 | end
165 | end
166 |
--------------------------------------------------------------------------------
/lib/ambient/dsl/main_scope.rb:
--------------------------------------------------------------------------------
1 | module Ambient
2 | module DSL
3 | class MainScope
4 | attr_reader :application
5 |
6 | def initialize(application)
7 | @application = application
8 | end
9 |
10 | def use_settings_from(filename)
11 | application.configure { run_ambientfile(filename) }
12 | end
13 |
14 | def option(name, value)
15 | application.configure { set_option(name, value) }
16 | end
17 |
18 | def base_ios_settings!(project_name, prefix: "", tests: false, ui_tests: false, swift: true, target: nil, test_target: nil, ui_test_target: nil)
19 | use_defaults_for_everything_not_specified_in_this_file!
20 | enable_default_warnings!
21 |
22 | target ||= "project_name"
23 | test_target ||= "#{project_name}Tests"
24 | ui_test_target ||= "#{project_name}UITests"
25 | tests = true if test_target
26 | ui_tests = true if ui_test_target
27 |
28 | option "ALWAYS_SEARCH_USER_PATHS", false
29 | option "CLANG_CXX_LANGUAGE_STANDARD", "gnu++14"
30 | option "CLANG_CXX_LIBRARY", "libc++"
31 | option "CLANG_ENABLE_MODULES", true
32 | option "CLANG_ENABLE_OBJC_ARC", true
33 |
34 | option "CODE_SIGN_IDENTITY", "iPhone Developer"
35 | option "COPY_PHASE_STRIP", false
36 |
37 | option "ENABLE_STRICT_OBJC_MSGSEND", true
38 | option "GCC_C_LANGUAGE_STANDARD", "gnu11"
39 | option "GCC_NO_COMMON_BLOCKS", true
40 | option "SDKROOT", "iphoneos"
41 | option "IPHONEOS_DEPLOYMENT_TARGET", "10.0"
42 | option "SWIFT_VERSION", "3.0"
43 |
44 | scheme "Debug" do
45 | option "DEBUG_INFORMATION_FORMAT", "dwarf"
46 | option "ENABLE_TESTABILITY", true
47 | option "MTL_ENABLE_DEBUG_INFO", true
48 | option "ONLY_ACTIVE_ARCH", true
49 | option "GCC_DYNAMIC_NO_PIC", false
50 | option "GCC_OPTIMIZATION_LEVEL", "0"
51 | option "GCC_PREPROCESSOR_DEFINITIONS", ["DEBUG=1", "$(inherited)"]
52 | option "SWIFT_OPTIMIZATION_LEVEL", "-Onone" if swift
53 | option "SWIFT_ACTIVE_COMPILATION_CONDITIONS", "DEBUG"
54 | end
55 |
56 | scheme "Release" do
57 | option "DEBUG_INFORMATION_FORMAT", "dwarf-with-dsym"
58 | option "ENABLE_NS_ASSERTIONS", false
59 | option "MTL_ENABLE_DEBUG_INFO", false
60 | option "VALIDATE_PRODUCT", true
61 | option "SWIFT_OPTIMIZATION_LEVEL", "-Owholemodule"
62 | end
63 |
64 | target project_name do
65 | option "INFOPLIST_FILE", "#{project_name}/Info.plist"
66 | option "PRODUCT_BUNDLE_IDENTIFIER", "#{prefix}#{project_name}"
67 | option "ASSETCATALOG_COMPILER_APPICON_NAME", "AppIcon"
68 | option "LD_RUNPATH_SEARCH_PATHS", "$(inherited) @executable_path/Frameworks"
69 | option "PRODUCT_NAME", "$(TARGET_NAME)"
70 | end
71 |
72 | if tests
73 | target test_target do
74 | option "INFOPLIST_FILE", "#{project_name}Tests/Info.plist"
75 | option "BUNDLE_LOADER", "$(TEST_HOST)"
76 | option "TEST_HOST", "$(BUILT_PRODUCTS_DIR)/#{project_name}.app/#{project_name}"
77 | option "PRODUCT_BUNDLE_IDENTIFIER", "#{prefix}#{project_name}Tests"
78 | option "LD_RUNPATH_SEARCH_PATHS", "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"
79 | option "PRODUCT_NAME", "$(TARGET_NAME)"
80 | end
81 | end
82 |
83 | if ui_tests
84 | target ui_test_target do
85 | option "INFOPLIST_FILE", "#{project_name}UITests/Info.plist"
86 | option "TEST_TARGET_NAME", "#{project_name}"
87 | option "PRODUCT_BUNDLE_IDENTIFIER", "#{prefix}#{project_name}UITests"
88 | option "LD_RUNPATH_SEARCH_PATHS", "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"
89 | option "USES_XCTRUNNER", "YES"
90 | option "PRODUCT_NAME", "$(TARGET_NAME)"
91 | end
92 | end
93 | end
94 |
95 | def enable_extra_warnings_and_static_analyser!
96 | warnings = %w(GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED
97 | GCC_WARN_MISSING_PARENTHESES
98 | GCC_WARN_ABOUT_RETURN_TYPE
99 | GCC_WARN_SIGN_COMPARE
100 | GCC_WARN_CHECK_SWITCH_STATEMENTS
101 | GCC_WARN_UNUSED_FUNCTION
102 | GCC_WARN_UNUSED_LABEL
103 | GCC_WARN_UNUSED_VALUE
104 | GCC_WARN_UNUSED_VARIABLE
105 | GCC_WARN_SHADOW
106 | GCC_WARN_64_TO_32_BIT_CONVERSION
107 | GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS
108 | GCC_WARN_UNDECLARED_SELECTOR
109 | GCC_WARN_TYPECHECK_CALLS_TO_PRINTF
110 | GCC_WARN_UNINITIALIZED_AUTOS
111 | CLANG_WARN_INT_CONVERSION
112 | CLANG_WARN_ENUM_CONVERSION
113 | CLANG_WARN_CONSTANT_CONVERSION
114 | CLANG_WARN_BOOL_CONVERSION
115 | CLANG_WARN_EMPTY_BODY
116 | CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION
117 | CLANG_WARN__DUPLICATE_METHOD_MATCH
118 | GCC_WARN_64_TO_32_BIT_CONVERSION
119 | RUN_CLANG_STATIC_ANALYZER
120 | GCC_TREAT_WARNINGS_AS_ERRORS
121 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING
122 | CLANG_WARN_COMMA
123 | CLANG_WARN_DOCUMENTATION_COMMENTS
124 | CLANG_WARN_INFINITE_RECURSION
125 | CLANG_WARN_RANGE_LOOP_ANALYSIS
126 | CLANG_WARN_STRICT_PROTOTYPES
127 | CLANG_WARN_SUSPICIOUS_MOVE)
128 | warnings.each { |w| option(w, true) }
129 |
130 | option "CLANG_WARN_UNGUARDED_AVAILABILITY", "YES_AGGRESSIVE"
131 | end
132 |
133 | def enable_default_warnings!
134 | truthy = %w(CLANG_WARN_BOOL_CONVERSION
135 | CLANG_WARN_CONSTANT_CONVERSION
136 | CLANG_WARN_EMPTY_BODY
137 | CLANG_WARN_ENUM_CONVERSION
138 | CLANG_WARN_INT_CONVERSION
139 | CLANG_WARN_UNREACHABLE_CODE
140 | CLANG_WARN__DUPLICATE_METHOD_MATCH
141 | GCC_WARN_64_TO_32_BIT_CONVERSION
142 | GCC_WARN_UNDECLARED_SELECTOR
143 | GCC_WARN_UNUSED_FUNCTION
144 | GCC_WARN_UNUSED_VARIABLE)
145 | error = %w(CLANG_WARN_DIRECT_OBJC_ISA_USAGE
146 | CLANG_WARN_OBJC_ROOT_CLASS
147 | GCC_WARN_ABOUT_RETURN_TYPE)
148 | aggressive = %w(GCC_WARN_UNINITIALIZED_AUTOS)
149 |
150 | truthy.each { |w| option(w, true) }
151 | error.each { |w| option(w, "YES_ERROR") }
152 | aggressive.each { |w| option(w, "YES_AGGRESSIVE") }
153 | end
154 |
155 | def target(name, &block)
156 | TargetScope.new(application, name).configure(&block)
157 | end
158 |
159 | def use_defaults_for_everything_not_specified_in_this_file!
160 | application.configure { @use_defaults = true }
161 | end
162 |
163 | def scheme(name, parent: nil, &block)
164 | SchemeScope.new(application, nil, name, parent).configure(&block)
165 | end
166 |
167 | def plist(path, &block)
168 | PlistScope.new(application, path).configure(&block)
169 | end
170 | end
171 | end
172 | end
173 |
--------------------------------------------------------------------------------
/templates/ios/PRODUCTNAME.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 48;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | AB04CB941EEC68E000947BB1 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB04CB931EEC68E000947BB1 /* AppDelegate.swift */; };
11 | AB04CB961EEC68E000947BB1 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB04CB951EEC68E000947BB1 /* ViewController.swift */; };
12 | AB04CB991EEC68E000947BB1 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AB04CB971EEC68E000947BB1 /* Main.storyboard */; };
13 | AB04CB9B1EEC68E000947BB1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AB04CB9A1EEC68E000947BB1 /* Assets.xcassets */; };
14 | AB04CB9E1EEC68E000947BB1 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AB04CB9C1EEC68E000947BB1 /* LaunchScreen.storyboard */; };
15 | /* End PBXBuildFile section */
16 |
17 | /* Begin PBXFileReference section */
18 | AB04CB901EEC68E000947BB1 /* PRODUCTNAME.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PRODUCTNAME.app; sourceTree = BUILT_PRODUCTS_DIR; };
19 | AB04CB931EEC68E000947BB1 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
20 | AB04CB951EEC68E000947BB1 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
21 | AB04CB981EEC68E000947BB1 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
22 | AB04CB9A1EEC68E000947BB1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
23 | AB04CB9D1EEC68E000947BB1 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
24 | AB04CB9F1EEC68E000947BB1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
25 | /* End PBXFileReference section */
26 |
27 | /* Begin PBXFrameworksBuildPhase section */
28 | AB04CB8D1EEC68E000947BB1 /* Frameworks */ = {
29 | isa = PBXFrameworksBuildPhase;
30 | buildActionMask = 2147483647;
31 | files = (
32 | );
33 | runOnlyForDeploymentPostprocessing = 0;
34 | };
35 | /* End PBXFrameworksBuildPhase section */
36 |
37 | /* Begin PBXGroup section */
38 | AB04CB871EEC68E000947BB1 = {
39 | isa = PBXGroup;
40 | children = (
41 | AB04CB921EEC68E000947BB1 /* PRODUCTNAME */,
42 | AB04CB911EEC68E000947BB1 /* Products */,
43 | );
44 | sourceTree = "";
45 | };
46 | AB04CB911EEC68E000947BB1 /* Products */ = {
47 | isa = PBXGroup;
48 | children = (
49 | AB04CB901EEC68E000947BB1 /* PRODUCTNAME.app */,
50 | );
51 | name = Products;
52 | sourceTree = "";
53 | };
54 | AB04CB921EEC68E000947BB1 /* PRODUCTNAME */ = {
55 | isa = PBXGroup;
56 | children = (
57 | AB04CB931EEC68E000947BB1 /* AppDelegate.swift */,
58 | AB04CB951EEC68E000947BB1 /* ViewController.swift */,
59 | AB04CB971EEC68E000947BB1 /* Main.storyboard */,
60 | AB04CB9A1EEC68E000947BB1 /* Assets.xcassets */,
61 | AB04CB9C1EEC68E000947BB1 /* LaunchScreen.storyboard */,
62 | AB04CB9F1EEC68E000947BB1 /* Info.plist */,
63 | );
64 | path = PRODUCTNAME;
65 | sourceTree = "";
66 | };
67 | /* End PBXGroup section */
68 |
69 | /* Begin PBXNativeTarget section */
70 | AB04CB8F1EEC68E000947BB1 /* PRODUCTNAME */ = {
71 | isa = PBXNativeTarget;
72 | buildConfigurationList = AB04CBA21EEC68E000947BB1 /* Build configuration list for PBXNativeTarget "PRODUCTNAME" */;
73 | buildPhases = (
74 | AB04CB8C1EEC68E000947BB1 /* Sources */,
75 | AB04CB8D1EEC68E000947BB1 /* Frameworks */,
76 | AB04CB8E1EEC68E000947BB1 /* Resources */,
77 | );
78 | buildRules = (
79 | );
80 | dependencies = (
81 | );
82 | name = PRODUCTNAME;
83 | productName = PRODUCTNAME;
84 | productReference = AB04CB901EEC68E000947BB1 /* PRODUCTNAME.app */;
85 | productType = "com.apple.product-type.application";
86 | };
87 | /* End PBXNativeTarget section */
88 |
89 | /* Begin PBXProject section */
90 | AB04CB881EEC68E000947BB1 /* Project object */ = {
91 | isa = PBXProject;
92 | attributes = {
93 | LastSwiftUpdateCheck = 0900;
94 | LastUpgradeCheck = 0900;
95 | ORGANIZATIONNAME = ORGANIZATION;
96 | TargetAttributes = {
97 | AB04CB8F1EEC68E000947BB1 = {
98 | CreatedOnToolsVersion = 9.0;
99 | };
100 | };
101 | };
102 | buildConfigurationList = AB04CB8B1EEC68E000947BB1 /* Build configuration list for PBXProject "PRODUCTNAME" */;
103 | compatibilityVersion = "Xcode 8.0";
104 | developmentRegion = en;
105 | hasScannedForEncodings = 0;
106 | knownRegions = (
107 | en,
108 | Base,
109 | );
110 | mainGroup = AB04CB871EEC68E000947BB1;
111 | productRefGroup = AB04CB911EEC68E000947BB1 /* Products */;
112 | projectDirPath = "";
113 | projectRoot = "";
114 | targets = (
115 | AB04CB8F1EEC68E000947BB1 /* PRODUCTNAME */,
116 | );
117 | };
118 | /* End PBXProject section */
119 |
120 | /* Begin PBXResourcesBuildPhase section */
121 | AB04CB8E1EEC68E000947BB1 /* Resources */ = {
122 | isa = PBXResourcesBuildPhase;
123 | buildActionMask = 2147483647;
124 | files = (
125 | AB04CB9E1EEC68E000947BB1 /* LaunchScreen.storyboard in Resources */,
126 | AB04CB9B1EEC68E000947BB1 /* Assets.xcassets in Resources */,
127 | AB04CB991EEC68E000947BB1 /* Main.storyboard in Resources */,
128 | );
129 | runOnlyForDeploymentPostprocessing = 0;
130 | };
131 | /* End PBXResourcesBuildPhase section */
132 |
133 | /* Begin PBXSourcesBuildPhase section */
134 | AB04CB8C1EEC68E000947BB1 /* Sources */ = {
135 | isa = PBXSourcesBuildPhase;
136 | buildActionMask = 2147483647;
137 | files = (
138 | AB04CB961EEC68E000947BB1 /* ViewController.swift in Sources */,
139 | AB04CB941EEC68E000947BB1 /* AppDelegate.swift in Sources */,
140 | );
141 | runOnlyForDeploymentPostprocessing = 0;
142 | };
143 | /* End PBXSourcesBuildPhase section */
144 |
145 | /* Begin PBXVariantGroup section */
146 | AB04CB971EEC68E000947BB1 /* Main.storyboard */ = {
147 | isa = PBXVariantGroup;
148 | children = (
149 | AB04CB981EEC68E000947BB1 /* Base */,
150 | );
151 | name = Main.storyboard;
152 | sourceTree = "";
153 | };
154 | AB04CB9C1EEC68E000947BB1 /* LaunchScreen.storyboard */ = {
155 | isa = PBXVariantGroup;
156 | children = (
157 | AB04CB9D1EEC68E000947BB1 /* Base */,
158 | );
159 | name = LaunchScreen.storyboard;
160 | sourceTree = "";
161 | };
162 | /* End PBXVariantGroup section */
163 |
164 | /* Begin XCBuildConfiguration section */
165 | AB04CBA01EEC68E000947BB1 /* Debug */ = {
166 | isa = XCBuildConfiguration;
167 | buildSettings = {
168 | ALWAYS_SEARCH_USER_PATHS = NO;
169 | CLANG_ANALYZER_NONNULL = YES;
170 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
171 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
172 | CLANG_CXX_LIBRARY = "libc++";
173 | CLANG_ENABLE_MODULES = YES;
174 | CLANG_ENABLE_OBJC_ARC = YES;
175 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
176 | CLANG_WARN_BOOL_CONVERSION = YES;
177 | CLANG_WARN_COMMA = YES;
178 | CLANG_WARN_CONSTANT_CONVERSION = YES;
179 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
180 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
181 | CLANG_WARN_EMPTY_BODY = YES;
182 | CLANG_WARN_ENUM_CONVERSION = YES;
183 | CLANG_WARN_INFINITE_RECURSION = YES;
184 | CLANG_WARN_INT_CONVERSION = YES;
185 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
186 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
187 | CLANG_WARN_STRICT_PROTOTYPES = YES;
188 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
189 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
190 | CLANG_WARN_UNREACHABLE_CODE = YES;
191 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
192 | CODE_SIGN_IDENTITY = "iPhone Developer";
193 | COPY_PHASE_STRIP = NO;
194 | DEBUG_INFORMATION_FORMAT = dwarf;
195 | ENABLE_STRICT_OBJC_MSGSEND = YES;
196 | ENABLE_TESTABILITY = YES;
197 | GCC_C_LANGUAGE_STANDARD = gnu11;
198 | GCC_DYNAMIC_NO_PIC = NO;
199 | GCC_NO_COMMON_BLOCKS = YES;
200 | GCC_OPTIMIZATION_LEVEL = 0;
201 | GCC_PREPROCESSOR_DEFINITIONS = (
202 | "DEBUG=1",
203 | "$(inherited)",
204 | );
205 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
206 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
207 | GCC_WARN_UNDECLARED_SELECTOR = YES;
208 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
209 | GCC_WARN_UNUSED_FUNCTION = YES;
210 | GCC_WARN_UNUSED_VARIABLE = YES;
211 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
212 | MTL_ENABLE_DEBUG_INFO = YES;
213 | ONLY_ACTIVE_ARCH = YES;
214 | SDKROOT = iphoneos;
215 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
216 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
217 | };
218 | name = Debug;
219 | };
220 | AB04CBA11EEC68E000947BB1 /* Release */ = {
221 | isa = XCBuildConfiguration;
222 | buildSettings = {
223 | ALWAYS_SEARCH_USER_PATHS = NO;
224 | CLANG_ANALYZER_NONNULL = YES;
225 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
226 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
227 | CLANG_CXX_LIBRARY = "libc++";
228 | CLANG_ENABLE_MODULES = YES;
229 | CLANG_ENABLE_OBJC_ARC = YES;
230 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
231 | CLANG_WARN_BOOL_CONVERSION = YES;
232 | CLANG_WARN_COMMA = YES;
233 | CLANG_WARN_CONSTANT_CONVERSION = YES;
234 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
235 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
236 | CLANG_WARN_EMPTY_BODY = YES;
237 | CLANG_WARN_ENUM_CONVERSION = YES;
238 | CLANG_WARN_INFINITE_RECURSION = YES;
239 | CLANG_WARN_INT_CONVERSION = YES;
240 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
241 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
242 | CLANG_WARN_STRICT_PROTOTYPES = YES;
243 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
244 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
245 | CLANG_WARN_UNREACHABLE_CODE = YES;
246 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
247 | CODE_SIGN_IDENTITY = "iPhone Developer";
248 | COPY_PHASE_STRIP = NO;
249 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
250 | ENABLE_NS_ASSERTIONS = NO;
251 | ENABLE_STRICT_OBJC_MSGSEND = YES;
252 | GCC_C_LANGUAGE_STANDARD = gnu11;
253 | GCC_NO_COMMON_BLOCKS = YES;
254 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
255 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
256 | GCC_WARN_UNDECLARED_SELECTOR = YES;
257 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
258 | GCC_WARN_UNUSED_FUNCTION = YES;
259 | GCC_WARN_UNUSED_VARIABLE = YES;
260 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
261 | MTL_ENABLE_DEBUG_INFO = NO;
262 | SDKROOT = iphoneos;
263 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
264 | VALIDATE_PRODUCT = YES;
265 | };
266 | name = Release;
267 | };
268 | AB04CBA31EEC68E000947BB1 /* Debug */ = {
269 | isa = XCBuildConfiguration;
270 | buildSettings = {
271 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
272 | INFOPLIST_FILE = PRODUCTNAME/Info.plist;
273 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
274 | PRODUCT_BUNDLE_IDENTIFIER = com.organization.PRODUCTNAME;
275 | PRODUCT_NAME = "$(TARGET_NAME)";
276 | SWIFT_VERSION = 4.0;
277 | TARGETED_DEVICE_FAMILY = "1,2";
278 | };
279 | name = Debug;
280 | };
281 | AB04CBA41EEC68E000947BB1 /* Release */ = {
282 | isa = XCBuildConfiguration;
283 | buildSettings = {
284 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
285 | INFOPLIST_FILE = PRODUCTNAME/Info.plist;
286 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
287 | PRODUCT_BUNDLE_IDENTIFIER = com.organization.PRODUCTNAME;
288 | PRODUCT_NAME = "$(TARGET_NAME)";
289 | SWIFT_VERSION = 4.0;
290 | TARGETED_DEVICE_FAMILY = "1,2";
291 | };
292 | name = Release;
293 | };
294 | /* End XCBuildConfiguration section */
295 |
296 | /* Begin XCConfigurationList section */
297 | AB04CB8B1EEC68E000947BB1 /* Build configuration list for PBXProject "PRODUCTNAME" */ = {
298 | isa = XCConfigurationList;
299 | buildConfigurations = (
300 | AB04CBA01EEC68E000947BB1 /* Debug */,
301 | AB04CBA11EEC68E000947BB1 /* Release */,
302 | );
303 | defaultConfigurationIsVisible = 0;
304 | defaultConfigurationName = Release;
305 | };
306 | AB04CBA21EEC68E000947BB1 /* Build configuration list for PBXNativeTarget "PRODUCTNAME" */ = {
307 | isa = XCConfigurationList;
308 | buildConfigurations = (
309 | AB04CBA31EEC68E000947BB1 /* Debug */,
310 | AB04CBA41EEC68E000947BB1 /* Release */,
311 | );
312 | defaultConfigurationIsVisible = 0;
313 | };
314 | /* End XCConfigurationList section */
315 | };
316 | rootObject = AB04CB881EEC68E000947BB1 /* Project object */;
317 | }
318 |
--------------------------------------------------------------------------------