ambient-xcode 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,71 @@
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
@@ -0,0 +1,4 @@
1
+ require_relative 'dsl/main_scope'
2
+ require_relative 'dsl/plist_scope'
3
+ require_relative 'dsl/scheme_scope'
4
+ require_relative 'dsl/target_scope'
@@ -0,0 +1,160 @@
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++0x"
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[sdk=iphoneos*]", "iPhone Developer"
35
+ option "COPY_PHASE_STRIP", false
36
+
37
+ option "ENABLE_STRICT_OBJC_MSGSEND", true
38
+ option "GCC_C_LANGUAGE_STANDARD", "gnu99"
39
+ option "GCC_NO_COMMON_BLOCKS", true
40
+ option "SDKROOT", "iphoneos"
41
+ option "IPHONEOS_DEPLOYMENT_TARGET", "9.0"
42
+
43
+ scheme "Debug" do
44
+ option "DEBUG_INFORMATION_FORMAT", "dwarf"
45
+ option "ENABLE_TESTABILITY", true
46
+ option "MTL_ENABLE_DEBUG_INFO", true
47
+ option "ONLY_ACTIVE_ARCH", true
48
+ option "GCC_DYNAMIC_NO_PIC", false
49
+ option "GCC_OPTIMIZATION_LEVEL", "0"
50
+ option "GCC_PREPROCESSOR_DEFINITIONS", ["DEBUG=1", "$(inherited)"]
51
+ option "SWIFT_OPTIMIZATION_LEVEL", "-Onone" if swift
52
+ end
53
+
54
+ scheme "Release" do
55
+ option "DEBUG_INFORMATION_FORMAT", "dwarf-with-dsym"
56
+ option "ENABLE_NS_ASSERTIONS", false
57
+ option "MTL_ENABLE_DEBUG_INFO", false
58
+ option "VALIDATE_PRODUCT", true
59
+ end
60
+
61
+ target project_name do
62
+ option "INFOPLIST_FILE", "#{project_name}/Info.plist"
63
+ option "PRODUCT_BUNDLE_IDENTIFIER", "#{prefix}#{project_name}"
64
+ option "ASSETCATALOG_COMPILER_APPICON_NAME", "AppIcon"
65
+ option "LD_RUNPATH_SEARCH_PATHS", "$(inherited) @executable_path/Frameworks"
66
+ option "PRODUCT_NAME", "$(TARGET_NAME)"
67
+ end
68
+
69
+ if tests
70
+ target test_target do
71
+ option "INFOPLIST_FILE", "#{project_name}Tests/Info.plist"
72
+ option "BUNDLE_LOADER", "$(TEST_HOST)"
73
+ option "TEST_HOST", "$(BUILT_PRODUCTS_DIR)/#{project_name}.app/#{project_name}"
74
+ option "PRODUCT_BUNDLE_IDENTIFIER", "#{prefix}#{project_name}Tests"
75
+ option "LD_RUNPATH_SEARCH_PATHS", "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"
76
+ option "PRODUCT_NAME", "$(TARGET_NAME)"
77
+ end
78
+ end
79
+
80
+ if ui_tests
81
+ target ui_test_target do
82
+ option "INFOPLIST_FILE", "#{project_name}UITests/Info.plist"
83
+ option "TEST_TARGET_NAME", "#{project_name}"
84
+ option "PRODUCT_BUNDLE_IDENTIFIER", "#{prefix}#{project_name}UITests"
85
+ option "LD_RUNPATH_SEARCH_PATHS", "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"
86
+ option "USES_XCTRUNNER", "YES"
87
+ option "PRODUCT_NAME", "$(TARGET_NAME)"
88
+ end
89
+ end
90
+ end
91
+
92
+ def enable_extra_warnings_and_static_analyser!
93
+ warnings = %w(GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED
94
+ GCC_WARN_MISSING_PARENTHESES
95
+ GCC_WARN_ABOUT_RETURN_TYPE
96
+ GCC_WARN_SIGN_COMPARE
97
+ GCC_WARN_CHECK_SWITCH_STATEMENTS
98
+ GCC_WARN_UNUSED_FUNCTION
99
+ GCC_WARN_UNUSED_LABEL
100
+ GCC_WARN_UNUSED_VALUE
101
+ GCC_WARN_UNUSED_VARIABLE
102
+ GCC_WARN_SHADOW
103
+ GCC_WARN_64_TO_32_BIT_CONVERSION
104
+ GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS
105
+ GCC_WARN_UNDECLARED_SELECTOR
106
+ GCC_WARN_TYPECHECK_CALLS_TO_PRINTF
107
+ GCC_WARN_UNINITIALIZED_AUTOS
108
+ CLANG_WARN_INT_CONVERSION
109
+ CLANG_WARN_ENUM_CONVERSION
110
+ CLANG_WARN_CONSTANT_CONVERSION
111
+ CLANG_WARN_BOOL_CONVERSION
112
+ CLANG_WARN_EMPTY_BODY
113
+ CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION
114
+ CLANG_WARN__DUPLICATE_METHOD_MATCH
115
+ GCC_WARN_64_TO_32_BIT_CONVERSION
116
+ RUN_CLANG_STATIC_ANALYZER
117
+ GCC_TREAT_WARNINGS_AS_ERRORS)
118
+ warnings.each { |w| option(w, true) }
119
+ end
120
+
121
+ def enable_default_warnings!
122
+ truthy = %w(CLANG_WARN_BOOL_CONVERSION
123
+ CLANG_WARN_CONSTANT_CONVERSION
124
+ CLANG_WARN_EMPTY_BODY
125
+ CLANG_WARN_ENUM_CONVERSION
126
+ CLANG_WARN_INT_CONVERSION
127
+ CLANG_WARN_UNREACHABLE_CODE
128
+ CLANG_WARN__DUPLICATE_METHOD_MATCH
129
+ GCC_WARN_64_TO_32_BIT_CONVERSION
130
+ GCC_WARN_UNDECLARED_SELECTOR
131
+ GCC_WARN_UNUSED_FUNCTION
132
+ GCC_WARN_UNUSED_VARIABLE)
133
+ error = %w(CLANG_WARN_DIRECT_OBJC_ISA_USAGE
134
+ CLANG_WARN_OBJC_ROOT_CLASS
135
+ GCC_WARN_ABOUT_RETURN_TYPE)
136
+ aggressive = %w(GCC_WARN_UNINITIALIZED_AUTOS)
137
+
138
+ truthy.each { |w| option(w, true) }
139
+ error.each { |w| option(w, "YES_ERROR") }
140
+ aggressive.each { |w| option(w, "YES_AGGRESSIVE") }
141
+ end
142
+
143
+ def target(name, &block)
144
+ TargetScope.new(application, name).configure(&block)
145
+ end
146
+
147
+ def use_defaults_for_everything_not_specified_in_this_file!
148
+ application.configure { @use_defaults = true }
149
+ end
150
+
151
+ def scheme(name, parent: nil, &block)
152
+ SchemeScope.new(application, nil, name, parent).configure(&block)
153
+ end
154
+
155
+ def plist(path, &block)
156
+ PlistScope.new(application, path).configure(&block)
157
+ end
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,21 @@
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
@@ -0,0 +1,40 @@
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
@@ -0,0 +1,36 @@
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
@@ -0,0 +1,33 @@
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
@@ -0,0 +1,29 @@
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
@@ -0,0 +1,83 @@
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