Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate targets with same build settings as Xcode (related to #164) #166

Merged
merged 57 commits into from
Nov 20, 2014
Merged
Show file tree
Hide file tree
Changes from 54 commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
8ef9c82
Use Ruby built-in combination
mrackwitz Jul 4, 2014
46b90d1
Add missing param documentation for target_product_type
mrackwitz Jul 4, 2014
a51dffc
Add target_product_type as matching condition
mrackwitz Jul 4, 2014
833e33f
Add parameter language
mrackwitz Jul 4, 2014
31c730e
Allow missing combinations
mrackwitz Jul 4, 2014
572ce95
Add common build settings for Swift and Frameworks
mrackwitz Jul 4, 2014
c9ecd0b
Support both, key or value, for param target_product_type
mrackwitz Jul 4, 2014
afd2edb
Move bundle specific settings into constants
mrackwitz Jul 4, 2014
4194361
[Fixtures] Add Project with different targets
mrackwitz Jul 5, 2014
33f003d
[Fixtures] Dump the project file internal build settings to xcconfig …
mrackwitz Jul 5, 2014
e1c020d
[Spec] Add specs for common_build_settings
mrackwitz Jul 5, 2014
83a3f6c
[Spec] Don't dig to deep into Bacon
mrackwitz Jul 7, 2014
5ae36de
Add new settings to PROJECT_DEFAULT_BUILD_SETTINGS
mrackwitz Jul 7, 2014
886844d
[Spec] Don't generate a requirement for each key in settings, but ins…
mrackwitz Jul 7, 2014
db515d5
[Spec] Exclude expected base settings from built settings for other c…
mrackwitz Jul 7, 2014
3ab2285
Nest all keys in arrays
mrackwitz Jul 20, 2014
4058031
Fix extracting key value pairs from xcconfig files
mrackwitz Jul 20, 2014
a023ffe
[Spec] Fix comparison of array setting values
mrackwitz Jul 20, 2014
7db99af
No special handling for bundle product type
mrackwitz Jul 20, 2014
9f29175
Fix build settings for Xcode 6b2
mrackwitz Jul 20, 2014
798444c
[Spec] Added a spec for constants
mrackwitz Jul 20, 2014
371584f
[Spec] Choose other examples to test settings
mrackwitz Jul 20, 2014
d9477e2
[Fixtures] Add Project with different targets with Xcode 6b3
mrackwitz Jul 20, 2014
f99758e
[Fixtures] Update fixtures with Xcode 6b3
mrackwitz Jul 20, 2014
57ea9a9
Fix build settings for Xcode 6b3
mrackwitz Jul 20, 2014
376944e
[Spec] Rename new spec file
mrackwitz Jul 20, 2014
eec0a06
[Changelog] Use two empty lines between each version
mrackwitz Jul 20, 2014
cb3b71f
[Doc] Add missing parameter documentation to #new_target and #new_res…
mrackwitz Jul 20, 2014
721c639
[Doc] Document how to update build settings integration specs
mrackwitz Jul 20, 2014
7be5b84
[Fixtures] Re-dump xcconfig files with sorted keys
mrackwitz Aug 9, 2014
793de4d
Add a Command to dump build settings to xcconfigs
mrackwitz Aug 9, 2014
2929408
[Fixtures] Format changes to match output of the builtin command
mrackwitz Aug 9, 2014
aad5627
[Rakefile] Interactive guide through target creation
mrackwitz Aug 10, 2014
a5f5e89
[Doc] Update doc for new Rake tasks
mrackwitz Aug 10, 2014
0cdcc85
[Rakefile] Make the output less verbose
mrackwitz Aug 10, 2014
bc37041
[Fixtures] rake common_build_settings:targets
mrackwitz Aug 10, 2014
e6b44ce
[Fixtures] rake common_build_settings:dump
mrackwitz Aug 10, 2014
8f99508
[Fixtures] Update fixtures with Xcode 6.1
kylef Oct 27, 2014
35b33f4
[Constants] Fix build settings for Xcode 6.1
mrackwitz Nov 2, 2014
2edb331
[Refactor][Spec] Test each deployment target separately
mrackwitz Nov 2, 2014
fabeebc
[Spec] Fix test for revised build settings handling
mrackwitz Nov 2, 2014
0c60019
[Spec] Fix spec description
mrackwitz Nov 2, 2014
3975679
Let parameter target_product_type of #common_build_settings be :appli…
mrackwitz Nov 2, 2014
54138e1
[Spec] Expect another build setting due changed defaults in Xcode 6.1
mrackwitz Nov 2, 2014
6de1027
Pass target_product_type through
mrackwitz Nov 2, 2014
c7b94a6
[Doc] Added `framework` as acceptable value
mrackwitz Aug 31, 2014
3e89602
[Spec] Filter out spec helpers from stacktrace for failed tests
mrackwitz Sep 1, 2014
7878d39
[Spec] Remove tests for DNS_BLOCK_ASSERTIONS
mrackwitz Nov 3, 2014
529f3b4
[Rubocop] Apply autocorrect
mrackwitz Nov 3, 2014
d2533bf
[Rubocop][Lint/AmbiguousRegexpLiteral] Parenthesize method arguments
mrackwitz Nov 3, 2014
c17e795
[Rubocop][Style/RescueModifier] Use try instead of rescue modifier
mrackwitz Nov 3, 2014
f881e6b
[Rakefile] Remove redundant escape way
mrackwitz Nov 20, 2014
25f291d
[Changelog] Add entry for #166
mrackwitz Nov 20, 2014
5215839
[Rakefile] Fix comparisons in common_build_settings:target
mrackwitz Nov 20, 2014
b6fbbf1
[Style] Minor improvements
mrackwitz Nov 20, 2014
bc0b2d9
[Rakefile] Use Bundler for require
mrackwitz Nov 20, 2014
7163b7a
[Refactor] Use a commented Regexp in Free-Spacing Mode
mrackwitz Nov 20, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,44 @@
# Xcodeproj Changelog

## Master

##### Breaking

* `Constants` The build settings match now those from Xcode 6.1.
[Marius Rackwitz](https://github.com/mrackwitz)
[Kyle Fuller](https://github.com/kylef)
[Xcodeproj#166](https://github.com/CocoaPods/Xcodeproj/pull/166)


##### Enhancements

* `ProjectHelper` The `::common_build_settings` method supports now a new
parameter `language` to select the language used in the target. Acceptable
options are either `:objc` or `:swift`.
[Marius Rackwitz](https://github.com/mrackwitz)
[Xcodeproj#166](https://github.com/CocoaPods/Xcodeproj/pull/166)

* `ProjectHelper` Supports to create framework targets for iOS & OSX with the
correct build settings.
[Marius Rackwitz](https://github.com/mrackwitz)
[Xcodeproj#166](https://github.com/CocoaPods/Xcodeproj/pull/164)

* `Commands` Xcodeproj CLI has a new command `config-dump`, which allows to
read the build settings from all configurations of all targets of a given
Xcode project and serialize them to .xcconfig files.
[Marius Rackwitz](https://github.com/mrackwitz)
[Xcodeproj#166](https://github.com/CocoaPods/Xcodeproj/pull/166)


##### Development Enhancements

* `Rakefile` Brings a set of new tasks to interactively generate fixture targets
for all target configurations supported by Xcode to update the xcconfig
fixtures used for the new specs, which check the build settings constants.
[Marius Rackwitz](https://github.com/mrackwitz)
[Xcodeproj#166](https://github.com/CocoaPods/Xcodeproj/pull/166)


## 0.20.2

##### Bug Fixes
Expand Down Expand Up @@ -197,6 +236,7 @@
[Alessandro Orrù](https://github.com/alessandroorru)
[Xcodeproj#155](https://github.com/CocoaPods/Xcodeproj/pull/155)


## 0.17.0

###### Enhancements
Expand Down
124 changes: 124 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,107 @@ begin
@rvm_ruby_dir ||= File.expand_path('../..', `which ruby`.strip)
end

# Common Build settings
#-----------------------------------------------------------------------------#

namespace :common_build_settings do
PROJECT_PATH = 'Project/Project.xcodeproj'

task :prepare do
verbose false
cd 'spec/fixtures/CommonBuildSettings'
end

desc "Create a new empty project"
task :new_project => [:prepare] do
verbose false
require 'xcodeproj'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably use Bundler.require instead. Otherwise if the Rakefile isn't ran with bundler we will potentially be running the wrong Xcodeproj.

Most of the other tasks in our Rakefile's protect against this, such as running bacon via sh "bundle exec bacon #{args.spec_file}".

title "Setup Boilerplate"

confirm "Delete existing fixture project and all data"
rm_rf 'Project/*'

subtitle "Create a new fixture project"
Xcodeproj::Project.new(PROJECT_PATH).save

subtitle "Open the project …"
sh 'open "Project/Project.xcodeproj"'
end

desc "Interactive walkthrough for creating fixture targets"
task :targets => [:prepare] do
verbose false
require 'xcodeproj'

title "Create Targets"
subtitle "You will be guided how to *manually* create the needed targets."
subtitle "Each target name will been copied to your clipboard."
confirm "Make sure you have nothing unsaved there"

targets = {
"Objc_iOS_Native" => { platform: :ios, type: :application, language: :objc, how: "iOS > Master-Detail Application > Language: Objective-C" },
"Swift_iOS_Native" => { platform: :ios, type: :application, language: :swift, how: "iOS > Master-Detail Application > Language: Swift" },
"Objc_iOS_Framework" => { platform: :ios, type: :framework, language: :objc, how: "iOS > Cocoa Touch Framework > Language: Objective-C" },
"Swift_iOS_Framework" => { platform: :ios, type: :framework, language: :swift, how: "iOS > Cocoa Touch Framework > Language: Swift" },
"Objc_iOS_StaticLibrary" => { platform: :ios, type: :static_library, language: :objc, how: "iOS > Cocoa Touch Static Library" },
"Objc_OSX_Native" => { platform: :osx, type: :application, language: :objc, how: "OSX > Cocoa Application > Language: Objective-C" },
"Swift_OSX_Native" => { platform: :osx, type: :application, language: :swift, how: "OSX > Cocoa Application > Language: Swift" },
"Objc_OSX_Framework" => { platform: :osx, type: :framework, language: :objc, how: "OSX > Cocoa Framework > Language: Objective-C" },
"Swift_OSX_Framework" => { platform: :osx, type: :framework, language: :swift, how: "OSX > Cocoa Framework > Language: Swift" },
"Objc_OSX_StaticLibrary" => { platform: :osx, type: :static_library, language: :objc, how: "OSX > Library > Type: Static" },
"Objc_OSX_DynamicLibrary" => { platform: :osx, type: :dynamic_library, language: :objc, how: "OSX > Library > Type: Dynamic" },
"OSX_Bundle" => { platform: :osx, type: :bundle, how: "OSX > Bundle" },
}

targets.each do |name, attributes|
begin
sh "printf '#{name}' | pbcopy"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NSA IS WATCHING!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see above:

+ subtitle "Each target name will been copied to your clipboard."
+ confirm "Make sure you have nothing unsaved there"

Because this whole process is not completely automated and requires user interaction.

confirm "Create a target named '#{name}' by: #{attributes[:how]}", false

project = Xcodeproj::Project.open(PROJECT_PATH)
raise "Project couldn't be opened." if project.nil?

target = project.targets.find { |t| t.name == name }
raise "Target wasn't found." if target.nil?

raise "Platform doesn't match." unless target.platform_name == attributes[:platform]
raise "Type doesn't match." unless target.symbol_type == attributes[:type]

debug_config = target.build_configurations.find { |c| c.name == 'Debug' }
raise "Debug configuration is missing" if debug_config.nil?

release_config = target.build_configurations.find { |c| c.name == 'Release' }
raise "Release configuration is missing" if release_config.nil?

is_swift_present = debug_config.build_settings['SWIFT_OPTIMIZATION_LEVEL'] != nil
is_swift_expected = attributes[:language] == :swift
raise "Language doesn't match." unless is_swift_present == is_swift_expected

puts green("Target matches.")
puts
rescue StandardError => e
puts "#{red(e.message)} Try again."
retry
end
end

puts green("All targets were been successfully created.")
end

desc "Dump the build settings of the fixture project to xcconfig files"
task :dump => [:prepare] do
verbose false
sh "../../../bin/xcodeproj config-dump Project/Project.xcodeproj configs"
end

desc "Recreate the xcconfig files for the fixture project targets from scratch"
task :rebuild => [
:new_project,
:targets,
:dump,
]
end

#-----------------------------------------------------------------------------#

namespace :spec do
Expand Down Expand Up @@ -118,8 +219,31 @@ def yellow(string)
"\033[0;33m#{string}\e[0m"
end

# Colorizes a string to red.
#
def red(string)
"\033[0;31m#{string}\e[0m"
end

# Colorizes a string to green.
#
def green(string)
"\033[0;32m#{string}\e[0m"
end

# Colorizes a string to cyan.
#
def cyan(string)
"\n\033[0;36m#{string}\033[0m"
end

def confirm(message, decline_by_default=true)
options = ['y', 'n']
options[decline_by_default ? 1 : 0].upcase!
print yellow("#{message}: [#{options.join('/')}] ")
input = STDIN.gets.chomp
if input == options[1].downcase || (input == '' && decline_by_default)
puts red("Aborted by user.")
exit 1
end
end
4 changes: 3 additions & 1 deletion lib/xcodeproj/command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module Xcodeproj
require 'colored'

class Command
autoload :ConfigDump, 'xcodeproj/command/config_dump'
autoload :TargetDiff, 'xcodeproj/command/target_diff'
autoload :ProjectDiff, 'xcodeproj/command/project_diff'
autoload :Show, 'xcodeproj/command/show'
Expand Down Expand Up @@ -56,7 +57,7 @@ def shift_argument
end

def self.banner
commands = ['target-diff', 'project-diff', 'show', 'sort']
commands = ['config-dump', 'target-diff', 'project-diff', 'show', 'sort']
banner = "To see help for the available commands run:\n\n"
banner + commands.map { |cmd| " * $ xcodeproj #{cmd.green} --help" }.join("\n")
end
Expand Down Expand Up @@ -101,6 +102,7 @@ def self.parse(*argv)
String.send(:define_method, :colorize) { |string, _| string } if argv.option('--no-color')

command_class = case command_argument = argv.shift_argument
when 'config-dump' then ConfigDump
when 'target-diff' then TargetDiff
when 'project-diff' then ProjectDiff
when 'show' then Show
Expand Down
78 changes: 78 additions & 0 deletions lib/xcodeproj/command/config_dump.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
module Xcodeproj
class Command
class ConfigDump < Command
def self.banner
<<-eos.strip_heredoc
Dumps the build settings of all project targets for all configurations in
directories named by the target in given output directory.

$ config-dump PROJECT OUTPUT

It extracts common build settings in a per target base.xcconfig file.
If no `PROJECT` is specified then the current work directory is searched
for one.
If no `OUTPUT` is specified then the project directory will be used.%)
eos
end

def initialize(argv)
xcodeproj_path = argv.shift_argument
@xcodeproj_path = File.expand_path(xcodeproj_path) if xcodeproj_path

@output_path = Pathname(argv.shift_argument || '.')
unless @output_path.directory?
raise Informative, 'The output path must be a directory.'
end

super unless argv.empty?
end

def run
dump_all_configs(xcodeproj, 'Project')

xcodeproj.targets.each do |target|
dump_all_configs(target, target.name)
end
end

def dump_all_configs(configurable, name)
path = Pathname(name)

# Dump base configuration to file
base_settings = extract_common_settings!(configurable.build_configurations)
base_file_path = path + "#{name}_base.xcconfig"
dump_config_to_file(base_settings, base_file_path)

# Dump each configuration to file
configurable.build_configurations.each do |config|
settings = config.build_settings
dump_config_to_file(settings, path + "#{name}_#{config.name.downcase}.xcconfig", [base_file_path])
end
end

def extract_common_settings!(build_configurations)
# Grasp all common build settings
all_build_settings = build_configurations.map(&:build_settings)
common_build_settings = all_build_settings.reduce do |settings, config_build_settings|
settings.select { |key, value| value == config_build_settings[key] }
end

# Remove all common build settings from each configuration specific build settings
build_configurations.each do |config|
config.build_settings.reject! { |key| !common_build_settings[key].nil? }
end

common_build_settings
end

def dump_config_to_file(settings, file_path, includes = [])
dir = @output_path + file_path + '..'
dir.mkdir unless dir.exist?

config = Config.new(settings)
config.includes = includes
config.save_as(@output_path + file_path)
end
end
end
end
5 changes: 3 additions & 2 deletions lib/xcodeproj/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -294,8 +294,9 @@ def extract_include(line)
# entry is the value.
#
def extract_key_value(line)
key, value = line.split('=', 2)
if key && value
match = line.match(/([^=]*?(?:\[[^\]]*=?[^\]]*\])*)\s+=(.*)/)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is crazy

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if match
key, value = match[1], match[2]
[key.strip, value.strip]
else
[]
Expand Down
Loading