Commit c9ac09dd authored by Kyle Fuller's avatar Kyle Fuller

Merge pull request #2835 from CocoaPods/swift

Support for Frameworks / Swift
parents 36ca914e c5a799f3
......@@ -6,8 +6,31 @@ To install release candidates run `[sudo] gem install cocoapods --pre`
## Master
##### Highlighted Enhancement That Needs Testing
* Support Frameworks & Swift: CocoaPods now recognizes Swift source files and
builds dynamic frameworks when necessary. A project can explicitly
opt-in via `use_frameworks!` in the Podfile, or if any dependency contains
Swift code, all pods for that target will be integrated as frameworks.
As a pod author, you can change the module name of the built framework by
specifying a `module_name` in the podspec. The built frameworks are embedded into
the host application with a new shell script build phase in the user's
project allowing configuration-dependent pods.
[Marius Rackwitz](https://github.com/mrackwitz)
[#2835](https://github.com/CocoaPods/CocoaPods/issues/2835)
##### Breaking
* Bundle Resources into Frameworks: Previously all resources were compiled and
copied into the `mainBundle`. Now Pods have to use
`[NSBundle bundleForClass:<#Class from Pod#>]` to access provided resources
relative to the bundle.
[Boris Bügling](https://github.com/neonichu)
[#2835](https://github.com/CocoaPods/CocoaPods/issues/2730)
* Only the hooks specified by usage of the `plugin` directive of the `Podfile`
will be run. Additionally, plugins that depend on hooks will have to update to
specify their 'plugin name' when registering the hooks in order to make it
......
......@@ -7,7 +7,7 @@ GIT
GIT
remote: https://github.com/CocoaPods/Core.git
revision: c9c91c5296067ebf5af122ed87580e9f0479b47c
revision: a01ba8e384324922bd173a415330b0a95fb13c5d
branch: master
specs:
cocoapods-core (0.35.0)
......
![CocoaPods Logo](https://raw.github.com/CocoaPods/shared_resources/master/assets/cocoapods-banner-readme.png)
### CocoaPods: The Objective-C dependency manager
### CocoaPods: The Cocoa dependency manager
[![Build Status](http://img.shields.io/travis/CocoaPods/CocoaPods/master.svg?style=flat)](https://travis-ci.org/CocoaPods/CocoaPods)
[![Gem Version](http://img.shields.io/gem/v/cocoapods.svg?style=flat)](http://badge.fury.io/rb/cocoapods)
......
......@@ -225,26 +225,39 @@ begin
desc "Build all examples"
task :build do
Dir.chdir("examples/AFNetworking Example") do
puts "Installing Pods"
# pod_command = ENV['FROM_GEM'] ? 'sandbox-pod' : 'bundle exec ../../bin/sandbox-pod'
# TODO: The sandbox is blocking local git repos making bundler crash
pod_command = ENV['FROM_GEM'] ? 'sandbox-pod' : 'bundle exec ../../bin/pod'
execute_command "rm -rf Pods"
execute_command "#{pod_command} install --verbose --no-repo-update"
puts "Building example: AFNetworking Mac Example"
execute_command "xcodebuild -workspace 'AFNetworking Examples.xcworkspace' -scheme 'AFNetworking Example' clean build"
puts "Building example: AFNetworking iOS Example"
xcode_version = `xcodebuild -version`.scan(/Xcode (.*)\n/).first.first
major_version = xcode_version.split('.').first.to_i
# Specifically build against the simulator SDK so we don't have to deal with code signing.
if major_version > 5
execute_command "xcodebuild -workspace 'AFNetworking Examples.xcworkspace' -scheme 'AFNetworking iOS Example' clean build ONLY_ACTIVE_ARCH=NO -destination 'platform=iOS Simulator,name=iPhone 6'"
else
execute_command "xcodebuild -workspace 'AFNetworking Examples.xcworkspace' -scheme 'AFNetworking iOS Example' clean build ONLY_ACTIVE_ARCH=NO -destination 'platform=iOS Simulator,name=iPhone Retina (4-inch)'"
Bundler.require 'xcodeproj', :development
Dir['examples/*'].each do |dir|
Dir.chdir(dir) do
puts "Example: #{dir}"
puts " Installing Pods"
# pod_command = ENV['FROM_GEM'] ? 'sandbox-pod' : 'bundle exec ../../bin/sandbox-pod'
# TODO: The sandbox is blocking local git repos making bundler crash
pod_command = ENV['FROM_GEM'] ? 'sandbox-pod' : 'bundle exec ../../bin/pod'
execute_command "rm -rf Pods"
execute_command "#{pod_command} install --verbose --no-repo-update"
workspace_path = 'Examples.xcworkspace'
workspace = Xcodeproj::Workspace.new_from_xcworkspace(workspace_path)
workspace.schemes.each do |scheme_name, project_path|
next if scheme_name == 'Pods'
puts " Building scheme: #{scheme_name}"
project = Xcodeproj::Project.open(project_path)
target = project.targets.first
case target
when :osx
execute_command "xcodebuild -workspace '#{workspace_path}' -scheme '#{scheme_name}' clean build"
when :ios
xcode_version = `xcodebuild -version`.scan(/Xcode (.*)\n/).first.first
major_version = xcode_version.split('.').first.to_i
# Specifically build against the simulator SDK so we don't have to deal with code signing.
simulator_name = major_version > 5 ? 'iPhone 6' : 'iPhone Retina (4-inch)'
execute_command "xcodebuild -workspace '#{workspace_path}' -scheme '#{scheme_name}' clean build ONLY_ACTIVE_ARCH=NO -destination 'platform=iOS Simulator,name=#{simulator_name}"
end
end
end
end
end
......
......@@ -11,7 +11,7 @@ Gem::Specification.new do |s|
s.homepage = "https://github.com/CocoaPods/CocoaPods"
s.authors = ["Eloy Duran", "Fabio Pelosin"]
s.summary = "An Objective-C library package manager."
s.summary = "The Cocoa library package manager."
s.description = "CocoaPods manages library dependencies for your Xcode project.\n\n" \
"You specify the dependencies for your project in one easy text file. " \
"CocoaPods resolves dependencies between libraries, fetches source " \
......
......@@ -7,7 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
26E82B9975F54DA9BAC1E0C9 /* libPods-AFNetworking Example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6935B1E417A24F0E958977ED /* libPods-AFNetworking Example.a */; };
1A2265312C5CBC89CD477BF8 /* libPods-AFNetworking Example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 53BDE93051BED183E9F4D921 /* libPods-AFNetworking Example.a */; };
B304CCE8177D58DD00F4FC85 /* adn.cer in Resources */ = {isa = PBXBuildFile; fileRef = B304CCE7177D58DD00F4FC85 /* adn.cer */; };
F8129C001591061B009BFE23 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8129BFF1591061B009BFE23 /* Cocoa.framework */; };
F8129C321591073C009BFE23 /* AFAppDotNetAPIClient.m in Sources */ = {isa = PBXBuildFile; fileRef = F8129C251591073C009BFE23 /* AFAppDotNetAPIClient.m */; };
......@@ -20,7 +20,7 @@
/* Begin PBXFileReference section */
3C79D6B3AA6A1DBBAE48A944 /* Pods-AFNetworking Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AFNetworking Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AFNetworking Example/Pods-AFNetworking Example.debug.xcconfig"; sourceTree = "<group>"; };
6935B1E417A24F0E958977ED /* libPods-AFNetworking Example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AFNetworking Example.a"; sourceTree = BUILT_PRODUCTS_DIR; };
53BDE93051BED183E9F4D921 /* libPods-AFNetworking Example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AFNetworking Example.a"; sourceTree = BUILT_PRODUCTS_DIR; };
A67B777556EF5D95EAFA5CF8 /* Pods-AFNetworking Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AFNetworking Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-AFNetworking Example/Pods-AFNetworking Example.release.xcconfig"; sourceTree = "<group>"; };
B304CCE7177D58DD00F4FC85 /* adn.cer */ = {isa = PBXFileReference; lastKnownFileType = file; path = adn.cer; sourceTree = SOURCE_ROOT; };
F8129BFB1591061B009BFE23 /* AFNetworking Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "AFNetworking Example.app"; sourceTree = BUILT_PRODUCTS_DIR; };
......@@ -47,7 +47,7 @@
buildActionMask = 2147483647;
files = (
F8129C001591061B009BFE23 /* Cocoa.framework in Frameworks */,
26E82B9975F54DA9BAC1E0C9 /* libPods-AFNetworking Example.a in Frameworks */,
1A2265312C5CBC89CD477BF8 /* libPods-AFNetworking Example.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......@@ -90,7 +90,7 @@
children = (
F8129BFF1591061B009BFE23 /* Cocoa.framework */,
F8129C011591061B009BFE23 /* Other Frameworks */,
6935B1E417A24F0E958977ED /* libPods-AFNetworking Example.a */,
53BDE93051BED183E9F4D921 /* libPods-AFNetworking Example.a */,
);
name = Frameworks;
sourceTree = "<group>";
......@@ -169,7 +169,7 @@
F8129BF21591061B009BFE23 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0460;
LastUpgradeCheck = 0610;
};
buildConfigurationList = F8129BF51591061B009BFE23 /* Build configuration list for PBXProject "AFNetworking Mac Example" */;
compatibilityVersion = "Xcode 3.2";
......@@ -253,13 +253,16 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
......@@ -272,7 +275,9 @@
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.7;
ONLY_ACTIVE_ARCH = YES;
......@@ -284,20 +289,25 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.7;
SDKROOT = macosx;
......@@ -313,6 +323,7 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = Prefix.pch;
INFOPLIST_FILE = "Mac-Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
......@@ -327,6 +338,7 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = Prefix.pch;
INFOPLIST_FILE = "Mac-Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
......
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0500"
LastUpgradeVersion = "0610"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
......
......@@ -8,7 +8,7 @@
/* Begin PBXBuildFile section */
2982AD3217107C0000FFF048 /* adn.cer in Resources */ = {isa = PBXBuildFile; fileRef = 2982AD3117107C0000FFF048 /* adn.cer */; };
E5D2E13908F241ABAC3B554B /* libPods-AFNetworking iOS Example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D87F8FEDE4A4313B0D579A3 /* libPods-AFNetworking iOS Example.a */; };
9A67BEDAF4D3529C5380A3E2 /* libPods-AFNetworking iOS Example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DB1F7D464FF374F6931E274F /* libPods-AFNetworking iOS Example.a */; };
F8129C7415910C37009BFE23 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F8129C7215910C37009BFE23 /* AppDelegate.m */; };
F818101615E6A0C600EF93C2 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 50ABD6EC159FC2CE001BE42C /* MobileCoreServices.framework */; };
F88812F016C533D6003C8B8C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8E469E013957DF100DB05C8 /* Security.framework */; };
......@@ -35,11 +35,9 @@
/* Begin PBXFileReference section */
2982AD3117107C0000FFF048 /* adn.cer */ = {isa = PBXFileReference; lastKnownFileType = file; path = adn.cer; sourceTree = SOURCE_ROOT; };
50ABD6EC159FC2CE001BE42C /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };
5628C4E1DE6DDC806B14CF8D /* Pods-AFNetworking iOS Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AFNetworking iOS Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-AFNetworking iOS Example.release.xcconfig"; sourceTree = "<group>"; };
7669B6F3267891B0317A0167 /* Pods-AFNetworking iOS Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AFNetworking iOS Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AFNetworking iOS Example/Pods-AFNetworking iOS Example.debug.xcconfig"; sourceTree = "<group>"; };
9D87F8FEDE4A4313B0D579A3 /* libPods-AFNetworking iOS Example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AFNetworking iOS Example.a"; sourceTree = BUILT_PRODUCTS_DIR; };
BEA3D3BDD12996573240F05F /* Pods-AFNetworking iOS Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AFNetworking iOS Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-AFNetworking iOS Example/Pods-AFNetworking iOS Example.release.xcconfig"; sourceTree = "<group>"; };
C3B414D5F7FCC5379A284B4E /* Pods-AFNetworking iOS Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AFNetworking iOS Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AFNetworking iOS Example.debug.xcconfig"; sourceTree = "<group>"; };
DB1F7D464FF374F6931E274F /* libPods-AFNetworking iOS Example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AFNetworking iOS Example.a"; sourceTree = BUILT_PRODUCTS_DIR; };
F8129C3815910830009BFE23 /* Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Prefix.pch; sourceTree = SOURCE_ROOT; };
F8129C7215910C37009BFE23 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = SOURCE_ROOT; };
F8129C7315910C37009BFE23 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = SOURCE_ROOT; };
......@@ -83,7 +81,7 @@
F8E469DF13957DD500DB05C8 /* CoreLocation.framework in Frameworks */,
F8D0701B14310F4A00653FD3 /* SystemConfiguration.framework in Frameworks */,
F818101615E6A0C600EF93C2 /* MobileCoreServices.framework in Frameworks */,
E5D2E13908F241ABAC3B554B /* libPods-AFNetworking iOS Example.a in Frameworks */,
9A67BEDAF4D3529C5380A3E2 /* libPods-AFNetworking iOS Example.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......@@ -93,8 +91,6 @@
9CE17E7C344B0E75BC0723EA /* Pods */ = {
isa = PBXGroup;
children = (
C3B414D5F7FCC5379A284B4E /* Pods-AFNetworking iOS Example.debug.xcconfig */,
5628C4E1DE6DDC806B14CF8D /* Pods-AFNetworking iOS Example.release.xcconfig */,
7669B6F3267891B0317A0167 /* Pods-AFNetworking iOS Example.debug.xcconfig */,
BEA3D3BDD12996573240F05F /* Pods-AFNetworking iOS Example.release.xcconfig */,
);
......@@ -169,7 +165,7 @@
F8E469641395739D00DB05C8 /* UIKit.framework */,
F8E469661395739D00DB05C8 /* Foundation.framework */,
F8E469681395739D00DB05C8 /* CoreGraphics.framework */,
9D87F8FEDE4A4313B0D579A3 /* libPods-AFNetworking iOS Example.a */,
DB1F7D464FF374F6931E274F /* libPods-AFNetworking iOS Example.a */,
);
name = Frameworks;
sourceTree = "<group>";
......@@ -383,7 +379,7 @@
GCC_WARN_SIGN_COMPARE = YES;
GCC_WARN_UNUSED_PARAMETER = NO;
INFOPLIST_FILE = "iOS-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 5.0;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
PRODUCT_NAME = "$(TARGET_NAME)";
WARNING_CFLAGS = "";
WRAPPER_EXTENSION = app;
......@@ -404,7 +400,7 @@
GCC_WARN_SIGN_COMPARE = YES;
GCC_WARN_UNUSED_PARAMETER = NO;
INFOPLIST_FILE = "iOS-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 5.0;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
PRODUCT_NAME = "$(TARGET_NAME)";
VALIDATE_PRODUCT = YES;
WARNING_CFLAGS = "";
......
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0500"
LastUpgradeVersion = "0610"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
......
......@@ -25,6 +25,7 @@
#if __IPHONE_OS_VERSION_MIN_REQUIRED
#import "GlobalTimelineViewController.h"
#import <AFNetworking/AFNetworkActivityIndicatorManager.h>
#import "AFNetworkActivityIndicatorManager.h"
@implementation AppDelegate
......
......@@ -2,7 +2,7 @@
xcodeproj "AFNetworking Mac Example.xcodeproj"
####
workspace 'AFNetworking Examples.xcworkspace'
workspace 'Examples.xcworkspace'
target "AFNetworking Example" do
platform :osx, '10.8'
......@@ -11,7 +11,7 @@ target "AFNetworking Example" do
end
target "AFNetworking iOS Example" do
platform :ios, '7.0'
platform :ios, '8.0'
xcodeproj "AFNetworking iOS Example.xcodeproj"
pod "AFNetworking", "1.3.3"
end
Pod::Spec.new do |s|
s.name = 'Alamofire'
s.version = '0.0.1'
s.license = 'MIT'
s.summary = 'Elegant HTTP Networking in Swift'
s.homepage = 'https://github.com/Alamofire/Alamofire'
s.social_media_url = 'http://twitter.com/mattt'
s.authors = { 'Mattt Thompson' => 'm@mattt.me' }
s.source = { :git => 'https://github.com/Alamofire/Alamofire.git', :branch => 'master' }
s.requires_arc = true
s.ios.deployment_target = '8.0'
s.osx.deployment_target = '10.10'
s.source_files = 'Source/*.swift'
end
// AppDelegate.swift
//
// Copyright (c) 2014 Alamofire (http://alamofire.org)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDelegate {
var window: UIWindow?
// MARK: - UIApplicationDelegate
func application(application: UIApplication!, didFinishLaunchingWithOptions launchOptions: NSDictionary!) -> Bool {
let splitViewController = self.window!.rootViewController as UISplitViewController
let navigationController = splitViewController.viewControllers.last as UINavigationController
navigationController.topViewController.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem()
splitViewController.delegate = self
return true
}
// MARK: - UISplitViewControllerDelegate
func splitViewController(splitViewController: UISplitViewController!, collapseSecondaryViewController secondaryViewController:UIViewController!, ontoPrimaryViewController primaryViewController:UIViewController!) -> Bool {
if let secondaryAsNavController = secondaryViewController as? UINavigationController {
if let topAsDetailController = secondaryAsNavController.topViewController as? DetailViewController {
return topAsDetailController.request == nil
}
}
return false
}
}
This diff is collapsed.
// DetailViewController.swift
//
// Copyright (c) 2014 Alamofire (http://alamofire.org)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import UIKit
import Alamofire
class DetailViewController: UITableViewController {
enum Sections: Int {
case Headers, Body
}
var request: Alamofire.Request? {
didSet {
oldValue?.cancel()
self.title = self.request?.description
self.refreshControl?.endRefreshing()
self.headers.removeAll()
self.body = nil
self.elapsedTime = nil
}
}
var headers: [String: String] = [:]
var body: String?
var elapsedTime: NSTimeInterval?
override func awakeFromNib() {
super.awakeFromNib()
self.refreshControl?.addTarget(self, action: "refresh", forControlEvents: .ValueChanged)
}
// MARK: - UIViewController
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.refresh()
}
// MARK: - IBAction
@IBAction func refresh() {
if self.request == nil {
return
}
self.refreshControl?.beginRefreshing()
let start = CACurrentMediaTime()
self.request?.responseString { (request, response, body, error) in
let end = CACurrentMediaTime()
self.elapsedTime = end - start
for (field, value) in response!.allHeaderFields {
self.headers["\(field)"] = "\(value)"
}
self.body = body
self.tableView.reloadData()
self.refreshControl?.endRefreshing()
}
}
// MARK: UITableViewDataSource
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch Sections(rawValue: section)! {
case .Headers:
return self.headers.count
case .Body:
return self.body == nil ? 0 : 1
default:
return 0
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
switch Sections(rawValue: indexPath.section)! {
case .Headers:
let cell = self.tableView.dequeueReusableCellWithIdentifier("Header") as UITableViewCell
let field = self.headers.keys.array.sorted(<)[indexPath.row]
let value = self.headers[field]
cell.textLabel.text = field
cell.detailTextLabel!.text = value
return cell
case .Body:
let cell = self.tableView.dequeueReusableCellWithIdentifier("Body") as UITableViewCell
cell.textLabel.text = self.body
return cell
}
}
// MARK: UITableViewDelegate
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 2
}
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String {
if self.tableView(tableView, numberOfRowsInSection: section) == 0 {
return ""
}
switch Sections(rawValue: section)! {
case .Headers:
return "Headers"
case .Body:
return "Body"
}
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
switch Sections(rawValue: indexPath.section)! {
case .Body:
return 300
default:
return tableView.rowHeight
}
}
override func tableView(tableView: UITableView, titleForFooterInSection section: Int) -> String {
if Sections(rawValue: section)! == .Body && self.elapsedTime != nil {
let numberFormatter = NSNumberFormatter()
numberFormatter.numberStyle = .DecimalStyle
return "Elapsed Time: \(numberFormatter.stringFromNumber(self.elapsedTime!)) sec"
}
return ""
}
}
// MasterViewController.swift
//
// Copyright (c) 2014 Alamofire (http://alamofire.org)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
import Alamofire
enum HTTPBinRoute: URLStringConvertible {
case Method(Alamofire.Method)
case BasicAuth(String, String)
var URLString: String {
let baseURLString = "http://httpbin.org/"
let path: String = {
switch self {
case .Method(let method):
return "/\(method.rawValue.lowercaseString)"
case .BasicAuth(let user, let password):
return "/basic-auth/\(user)/\(password)"
}
}()
return NSURL(string: path, relativeToURL: NSURL(string: baseURLString))!.absoluteString!
}
}
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
{
"images" : [
{
"orientation" : "portrait",
"idiom" : "iphone",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "iphone",
"subtype" : "retina4",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "1x"
},
{
"orientation" : "landscape",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "1x"
},
{
"orientation" : "portrait",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"orientation" : "landscape",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "Logo.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "Logo@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>com.alamofire.$(PRODUCT_NAME:rfc1034identifier)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>Alamofire</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UIStatusBarTintParameters</key>
<dict>
<key>UINavigationBar</key>
<dict>
<key>Style</key>
<string>UIBarStyleDefault</string>
<key>Translucent</key>
<false/>
</dict>
</dict>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
// MasterViewController.swift
//
// Copyright (c) 2014 Alamofire (http://alamofire.org)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import UIKit
import Alamofire
class MasterViewController: UITableViewController {
@IBOutlet weak var titleImageView: UIImageView!
var detailViewController: DetailViewController? = nil
var objects = NSMutableArray()
override func awakeFromNib() {
super.awakeFromNib()
self.navigationItem.titleView = self.titleImageView
}
// MARK: - UIViewController
override func viewDidLoad() {
super.viewDidLoad()
if let split = self.splitViewController {
let controllers = split.viewControllers
self.detailViewController = controllers.last?.topViewController as? DetailViewController
}
}
// MARK: - UIStoryboardSegue
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let detailViewController = segue.destinationViewController.topViewController as? DetailViewController {
func requestForSegue(segue: UIStoryboardSegue) -> Request? {
switch segue.identifier as String! {
case "GET":
return Alamofire.request(.GET, "http://httpbin.org/get")
case "POST":
return Alamofire.request(.POST, "http://httpbin.org/post")
case "PUT":
return Alamofire.request(.PUT, "http://httpbin.org/put")
case "DELETE":
return Alamofire.request(.DELETE, "http://httpbin.org/delete")
default:
return nil
}
}
if let request = requestForSegue(segue) {
detailViewController.request = request
}
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:iOS Example.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>
Copyright (c) 2014 Alamofire (http://alamofire.org/)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
source 'https://github.com/CocoaPods/Specs.git'
workspace 'Examples.xcworkspace'
xcodeproj 'iOS Example.xcodeproj'
target 'iOS Example' do
platform :ios, '8.0'
use_frameworks!
pod 'Alamofire', :path => '.'
end
// Alamofire.h
//
// Copyright (c) 2014 Alamofire (http://alamofire.org)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import <Foundation/Foundation.h>
FOUNDATION_EXPORT double AlamofireVersionNumber;
FOUNDATION_EXPORT const unsigned char AlamofireVersionString[];
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>com.alamofire.$(PRODUCT_NAME:rfc1034identifier)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
......@@ -56,9 +56,13 @@ module Pod
autoload :BridgeSupport, 'cocoapods/generator/bridge_support'
autoload :CopyResourcesScript, 'cocoapods/generator/copy_resources_script'
autoload :DummySource, 'cocoapods/generator/dummy_source'
autoload :EmbedFrameworksScript, 'cocoapods/generator/embed_frameworks_script'
autoload :Header, 'cocoapods/generator/header'
autoload :InfoPlistFile, 'cocoapods/generator/info_plist_file'
autoload :ModuleMap, 'cocoapods/generator/module_map'
autoload :PrefixHeader, 'cocoapods/generator/prefix_header'
autoload :TargetEnvironmentHeader, 'cocoapods/generator/target_environment_header'
autoload :UmbrellaHeader, 'cocoapods/generator/umbrella_header'
autoload :XCConfig, 'cocoapods/generator/xcconfig'
end
......
......@@ -28,7 +28,7 @@ module Pod
self.abstract_command = true
self.command = 'pod'
self.version = VERSION
self.description = 'CocoaPods, the Objective-C library package manager.'
self.description = 'CocoaPods, the Cocoa library package manager.'
self.plugin_prefixes = %w(claide cocoapods)
[Install, Update, Outdated, IPC::Podfile, IPC::Repl].each { |c| c.send(:include, ProjectDirectory) }
......
......@@ -113,6 +113,7 @@ module Pod
['--subspec=NAME', 'Lint validates only the given subspec'],
['--no-subspecs', 'Lint skips validation of subspecs'],
['--no-clean', 'Lint leaves the build directory intact for inspection'],
['--use-frameworks', 'Lint uses frameworks to install the spec'],
['--sources=https://github.com/artsy/Specs', 'The sources from which to pull dependant pods ' \
'(defaults to https://github.com/CocoaPods/Specs.git). '\
'Multiple sources must be comma-delimited.']].concat(super)
......@@ -124,6 +125,7 @@ module Pod
@clean = argv.flag?('clean', true)
@subspecs = argv.flag?('subspecs', true)
@only_subspec = argv.option('subspec')
@use_frameworks = argv.flag?('use-frameworks')
@source_urls = argv.option('sources', 'https://github.com/CocoaPods/Specs.git').split(',')
@podspecs_paths = argv.arguments!
super
......@@ -144,6 +146,7 @@ module Pod
validator.allow_warnings = @allow_warnings
validator.no_subspecs = !@subspecs || @only_subspec
validator.only_subspec = @only_subspec
validator.use_frameworks = @use_frameworks
validator.validate
unless @clean
......
......@@ -68,6 +68,7 @@ module Pod
['--subspec=NAME', 'Lint validates only the given subspec'],
['--no-subspecs', 'Lint skips validation of subspecs'],
['--no-clean', 'Lint leaves the build directory intact for inspection'],
['--use-frameworks', 'Lint uses frameworks to install the spec'],
['--sources=https://github.com/artsy/Specs', 'The sources from which to pull dependant pods ' \
'(defaults to https://github.com/CocoaPods/Specs.git). '\
'Multiple sources must be comma-delimited.']].concat(super)
......@@ -79,6 +80,7 @@ module Pod
@clean = argv.flag?('clean', true)
@subspecs = argv.flag?('subspecs', true)
@only_subspec = argv.option('subspec')
@use_frameworks = argv.flag?('use-frameworks')
@source_urls = argv.option('sources', 'https://github.com/CocoaPods/Specs.git').split(',')
@podspecs_paths = argv.arguments!
super
......@@ -94,6 +96,7 @@ module Pod
validator.allow_warnings = @allow_warnings
validator.no_subspecs = !@subspecs || @only_subspec
validator.only_subspec = @only_subspec
validator.use_frameworks = @use_frameworks
validator.validate
invalid_count += 1 unless validator.validated?
......@@ -580,8 +583,8 @@ Pod::Spec.new do |s|
# ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# CocoaPods is smart about how it includes source code. For source files
# giving a folder will include any h, m, mm, c & cpp files. For header
# files it will include any header in the folder.
# giving a folder will include any swift, h, m, mm, c & cpp files.
# For header files it will include any header in the folder.
# Not including the public_header_files will make all headers public.
#
......
......@@ -264,7 +264,7 @@ module Pod
'CocoaPods.podfile.yaml',
'CocoaPods.podfile',
'Podfile',
]
].freeze
public
......
module Pod
module Generator
class EmbedFrameworksScript
# @return [TargetDefinition] The target definition, whose label will be
# used to locate the target-specific build products.
#
attr_reader :target_definition
# @return [Hash{String, Array{String}] Multiple lists of frameworks per
# configuration.
#
attr_reader :frameworks_by_config
# @param [TargetDefinition] target_definition
# @see #target_definition
#
# @param [Hash{String, Array{String}] frameworks_by_config
# @see #frameworks_by_config
#
def initialize(target_definition, frameworks_by_config)
@target_definition = target_definition
@frameworks_by_config = frameworks_by_config
end
# Saves the resource script to the given pathname.
#
# @param [Pathname] pathname
# The path where the embed frameworks script should be saved.
#
# @return [void]
#
def save_as(pathname)
pathname.open('w') do |file|
file.puts(script)
end
File.chmod(0755, pathname.to_s)
end
private
# @!group Private Helpers
# @return [String] The contents of the embed frameworks script.
#
def script
script = <<-eos.strip_heredoc
#!/bin/sh
set -e
echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}"
install_framework()
{
local source="${BUILT_PRODUCTS_DIR}/#{target_definition.label}/$1"
local destination="${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
if [ -L ${source} ]; then
echo "Symlinked..."
source=$(readlink "${source}")
fi
# use filter instead of exclude so missing patterns dont' throw errors
echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers/\" --filter \"- PrivateHeaders/\" ${source} ${destination}"
rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers/" --filter "- PrivateHeaders/" "${source}" "${destination}"
# Resign the code if required by the build settings to avoid unstable apps
if [ "${CODE_SIGNING_REQUIRED}" == "YES" ]; then
code_sign "${destination}/$1"
fi
# Embed linked Swift runtime libraries
local basename
basename=$(echo $1 | sed -E s/\\\\..+// && exit ${PIPESTATUS[0]})
local swift_runtime_libs
swift_runtime_libs=$(xcrun otool -LX "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/$1/${basename}" | grep @rpath/libswift | sed -E s/@rpath\\\\/\\(.+dylib\\).*/\\\\1/g | uniq -u && exit ${PIPESTATUS[0]})
for lib in $swift_runtime_libs; do
echo "rsync -av \\"${SWIFT_STDLIB_PATH}/${lib}\\" \\"${destination}\\""
rsync -av "${SWIFT_STDLIB_PATH}/${lib}" "${destination}"
done
}
# Signs a framework with the provided identity
code_sign() {
# Use the current code_sign_identitiy
echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements $1"
/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements "$1"
}
eos
script += "\n" unless frameworks_by_config.values.all?(&:empty?)
frameworks_by_config.each do |config, frameworks|
unless frameworks.empty?
script += %(if [[ "$CONFIGURATION" == "#{config}" ]]; then\n)
frameworks.each do |framework|
script += " install_framework '#{framework}'\n"
end
script += "fi\n"
end
end
script
end
end
end
end
......@@ -13,7 +13,11 @@ module Pod
# @return [Array<String>] The list of the headers to import.
#
attr_reader :imports
attr_accessor :imports
# @return [Array<String>] The list of the modules to import.
#
attr_accessor :module_imports
# @param [Symbol] platform
# @see platform
......@@ -21,6 +25,7 @@ module Pod
def initialize(platform)
@platform = platform
@imports = []
@module_imports = []
end
# Generates the contents of the header according to the platform.
......@@ -41,6 +46,13 @@ module Pod
result << %|#import "#{import}"\n|
end
unless module_imports.empty?
module_imports.each do |import|
result << %|\n@import #{import}|
end
result << "\n"
end
result
end
......
module Pod
module Generator
# Generates Info.plist files. A Info.plist file is generated for each
# Pod and for each Pod target definition, that requires to be built as
# framework. It states public attributes.
#
class InfoPlistFile
# @return [Target] the target represented by this Info.plist.
#
attr_reader :target
# @param [Target] target @see target
#
def initialize(target)
@target = target
end
# Generates and saves the Info.plist to the given path.
#
# @param [Pathname] path
# the path where the prefix header should be stored.
#
# @return [void]
#
def save_as(path)
contents = generate
path.open('w') do |f|
f.write(contents)
end
end
# The version associated with the current target
#
# @note Will return 1.0.0 for the AggregateTarget
#
# @return [String]
#
def target_version
if target && target.respond_to?(:root_spec)
target.root_spec.version.to_s
else
'1.0.0'
end
end
# Generates the contents of the Info.plist
#
# @return [String]
#
def generate
FILE_CONTENTS.sub('${CURRENT_PROJECT_VERSION_STRING}', target_version)
end
FILE_CONTENTS = <<-EOS
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>org.cocoapods.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>${CURRENT_PROJECT_VERSION_STRING}</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${CURRENT_PROJECT_VERSION}</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
EOS
end
end
end
module Pod
module Generator
# Generates LLVM module map files. A module map file is generated for each
# Pod and for each Pod target definition that is built as a framework. It
# specifies a different umbrella header than usual to avoid name conflicts
# with existing headers of the podspec.
#
class ModuleMap
# @return [Target] the target represented by this Info.plist.
#
attr_reader :target
# @param [Target] target @see target
#
def initialize(target)
@target = target
end
# Generates and saves the Info.plist to the given path.
#
# @param [Pathname] path
# the path where the prefix header should be stored.
#
# @return [void]
#
def save_as(path)
contents = generate
path.open('w') do |f|
f.write(contents)
end
end
# Generates the contents of the module.modulemap file.
#
# @return [String]
#
def generate
<<-eos.strip_heredoc
framework module #{target.product_module_name} {
umbrella header "#{target.umbrella_header_path.basename}"
export *
module * { export * }
}
eos
end
end
end
end
module Pod
module Generator
# Generates an umbrella header file for clang modules, which are used by
# dynamic frameworks on iOS 8 and OSX 10.10 under the hood.
#
# If the target is a +PodTarget+, then the umbrella header is required
# to make all public headers in a convenient manner available without the
# need to write out header declarations for every library header.
#
class UmbrellaHeader < Header
# @return [Target]
# the target, which provides the product name
attr_reader :target
# @param [Target] target
# @see target
#
def initialize(target)
super(target.target_definition.platform)
@target = target
end
# Generates the contents of the umbrella header according to the included
# pods.
#
# @return [String]
#
def generate
result = super
result << "\n"
result << <<-eos.strip_heredoc
FOUNDATION_EXPORT double #{target.product_module_name}VersionNumber;
FOUNDATION_EXPORT const unsigned char #{target.product_module_name}VersionString[];
eos
result << "\n"
result
end
end
end
end
......@@ -47,34 +47,58 @@ module Pod
# @return [Xcodeproj::Config]
#
def generate
header_search_path_flags = target.sandbox.public_headers.search_paths(target.platform)
@xcconfig = Xcodeproj::Config.new(
'OTHER_LDFLAGS' => XCConfigHelper.default_ld_flags(target),
'OTHER_LIBTOOLFLAGS' => '$(OTHER_LDFLAGS)',
'HEADER_SEARCH_PATHS' => XCConfigHelper.quote(header_search_path_flags),
'PODS_ROOT' => target.relative_pods_root,
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) COCOAPODS=1',
'OTHER_CFLAGS' => '$(inherited) ' + XCConfigHelper.quote(header_search_path_flags, '-isystem')
)
pod_targets = target.pod_targets_for_build_configuration(@configuration_name)
config = {
'OTHER_LDFLAGS' => XCConfigHelper.default_ld_flags(target),
'OTHER_LIBTOOLFLAGS' => '$(OTHER_LDFLAGS)',
'PODS_ROOT' => target.relative_pods_root,
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) COCOAPODS=1',
}
target.pod_targets.each do |pod_target|
next unless pod_target.include_in_build_config?(@configuration_name)
if target.requires_frameworks?
# Framework headers are automatically discoverable by `#import <…>`.
header_search_paths = pod_targets.map { |target| "$PODS_FRAMEWORK_BUILD_PATH/#{target.product_name}/Headers" }
build_settings = {
'PODS_FRAMEWORK_BUILD_PATH' => target.configuration_build_dir,
'FRAMEWORK_SEARCH_PATHS' => '"$PODS_FRAMEWORK_BUILD_PATH"',
# Make headers discoverable by `import "…"`
'OTHER_CFLAGS' => '$(inherited) ' + XCConfigHelper.quote(header_search_paths, '-iquote')
}
config.merge!(build_settings)
else
# Make headers discoverable from $PODS_ROOT/Headers directory
header_search_paths = target.sandbox.public_headers.search_paths(target.platform)
build_settings = {
# by `#import "…"`
'HEADER_SEARCH_PATHS' => XCConfigHelper.quote(header_search_paths),
# by `#import <…>`
'OTHER_CFLAGS' => '$(inherited) ' + XCConfigHelper.quote(header_search_paths, '-isystem')
}
config.merge!(build_settings)
end
pod_target.file_accessors.each do |file_accessor|
XCConfigHelper.add_spec_build_settings_to_xcconfig(file_accessor.spec_consumer, @xcconfig)
file_accessor.vendored_frameworks.each do |vendored_framework|
XCConfigHelper.add_framework_build_settings(vendored_framework, @xcconfig, target.sandbox.root)
end
file_accessor.vendored_libraries.each do |vendored_library|
XCConfigHelper.add_library_build_settings(vendored_library, @xcconfig, target.sandbox.root)
end
end
@xcconfig = Xcodeproj::Config.new(config)
# Add pod static lib to list of libraries that are to be linked with
# the user’s project.
XCConfigHelper.add_target_specific_settings(target, @xcconfig)
next unless pod_target.should_build?
@xcconfig.merge!('OTHER_LDFLAGS' => %(-l "#{pod_target.name}"))
pod_targets.each do |pod_target|
unless pod_target.should_build? && pod_target.requires_frameworks?
# In case of generated pod targets, which require frameworks, the
# vendored frameworks and libraries are already linked statically
# into the framework binary and must not be linked again to the
# user target.
XCConfigHelper.add_settings_for_file_accessors_of_target(pod_target, @xcconfig)
end
# Add pod target to list of frameworks / libraries that are
# linked with the user’s project.
if pod_target.should_build?
if pod_target.requires_frameworks?
@xcconfig.merge!('OTHER_LDFLAGS' => %(-framework "#{pod_target.product_basename}"))
else
@xcconfig.merge!('OTHER_LDFLAGS' => %(-l "#{pod_target.product_basename}"))
end
end
end
# TODO Need to decide how we are going to ensure settings like these
......@@ -83,9 +107,30 @@ module Pod
# See https://github.com/CocoaPods/CocoaPods/issues/1216
@xcconfig.attributes.delete('USE_HEADERMAP')
generate_ld_runpath_search_paths if target.requires_frameworks?
@xcconfig
end
def generate_ld_runpath_search_paths
ld_runpath_search_paths = ['$(inherited)']
if target.platform.symbolic_name == :osx
ld_runpath_search_paths << "'@executable_path/../Frameworks'"
ld_runpath_search_paths << \
if target.native_target.symbol_type == :unit_test_bundle
"'@loader_path/../Frameworks'"
else
"'@loader_path/Frameworks'"
end
else
ld_runpath_search_paths << [
"'@executable_path/Frameworks'",
"'@loader_path/Frameworks'"
]
end
@xcconfig.merge!('LD_RUNPATH_SEARCH_PATHS' => ld_runpath_search_paths.join(' '))
end
#---------------------------------------------------------------------#
end
end
......
......@@ -57,8 +57,20 @@ module Pod
# 'USE_HEADERMAP' => 'NO'
}
if target.requires_frameworks?
# Only quote the FRAMEWORK_SEARCH_PATHS entry, because it’s a setting that takes multiple values.
# In addition, quoting CONFIGURATION_BUILD_DIR would make it be interpreted as a relative path.
build_settings = {
'PODS_FRAMEWORK_BUILD_PATH' => target.configuration_build_dir,
'CONFIGURATION_BUILD_DIR' => '$PODS_FRAMEWORK_BUILD_PATH',
'FRAMEWORK_SEARCH_PATHS' => '"$PODS_FRAMEWORK_BUILD_PATH"',
}
config.merge!(build_settings)
end
xcconfig_hash = add_xcconfig_namespaced_keys(public_xcconfig.to_hash, config, target.xcconfig_prefix)
@xcconfig = Xcodeproj::Config.new(xcconfig_hash)
XCConfigHelper.add_target_specific_settings(target, @xcconfig)
@xcconfig.includes = [target.name]
@xcconfig
end
......
......@@ -40,15 +40,7 @@ module Pod
#
def generate
@xcconfig = Xcodeproj::Config.new
target.file_accessors.each do |file_accessor|
XCConfigHelper.add_spec_build_settings_to_xcconfig(file_accessor.spec_consumer, @xcconfig)
file_accessor.vendored_frameworks.each do |vendored_framework|
XCConfigHelper.add_framework_build_settings(vendored_framework, @xcconfig, target.sandbox.root)
end
file_accessor.vendored_libraries.each do |vendored_library|
XCConfigHelper.add_library_build_settings(vendored_library, @xcconfig, target.sandbox.root)
end
end
XCConfigHelper.add_settings_for_file_accessors_of_target(target, @xcconfig)
@xcconfig
end
......
......@@ -33,6 +33,26 @@ module Pod
ld_flags
end
# Configures the given Xcconfig
#
# @param [PodTarget] pod_target
# The pod target, which holds the list of +Spec::FileAccessor+.
#
# @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit.
#
def self.add_settings_for_file_accessors_of_target(target, xcconfig)
target.file_accessors.each do |file_accessor|
XCConfigHelper.add_spec_build_settings_to_xcconfig(file_accessor.spec_consumer, xcconfig)
file_accessor.vendored_frameworks.each do |vendored_framework|
XCConfigHelper.add_framework_build_settings(vendored_framework, xcconfig, target.sandbox.root)
end
file_accessor.vendored_libraries.each do |vendored_library|
XCConfigHelper.add_library_build_settings(vendored_library, xcconfig, target.sandbox.root)
end
end
end
# Configures the given Xcconfig according to the build settings of the
# given Specification.
#
......@@ -59,6 +79,9 @@ module Pod
# @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit.
#
# @param [Pathname] sandbox_root
# The path retrieved from Sandbox#root.
#
def self.add_framework_build_settings(framework_path, xcconfig, sandbox_root)
name = File.basename(framework_path, '.framework')
dirname = '$(PODS_ROOT)/' + framework_path.dirname.relative_path_from(sandbox_root).to_s
......@@ -70,7 +93,7 @@ module Pod
end
# Configures the given Xcconfig with the the build settings for the given
# framework path.
# library path.
#
# @param [Pathanme] framework_path
# The path of the framework.
......@@ -78,6 +101,9 @@ module Pod
# @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit.
#
# @param [Pathname] sandbox_root
# The path retrieved from Sandbox#root.
#
def self.add_library_build_settings(library_path, xcconfig, sandbox_root)
name = File.basename(library_path, '.a').sub(/\Alib/, '')
dirname = '$(PODS_ROOT)/' + library_path.dirname.relative_path_from(sandbox_root).to_s
......@@ -88,6 +114,58 @@ module Pod
xcconfig.merge!(build_settings)
end
# Add the code signing settings for generated targets to ensure that
# frameworks are correctly signed to be integrated and re-signed when
# building the application and embedding the framework
#
# @param [Target] target
# The target.
#
# @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit.
#
def self.add_code_signing_settings(target, xcconfig)
build_settings = {}
if target.platform.to_sym == :osx
build_settings['CODE_SIGN_IDENTITY'] = ''
end
xcconfig.merge!(build_settings)
end
# Checks if the given target requires specific settings and configures
# the given Xcconfig.
#
# @param [Target] target
# The target.
#
# @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit.
#
def self.add_target_specific_settings(target, xcconfig)
if target.requires_frameworks?
add_code_signing_settings(target, xcconfig)
end
add_language_specific_settings(target, xcconfig)
end
# Checks if the given target requires language specific settings and
# configures the given Xcconfig.
#
# @param [Target] target
# The target.
#
# @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit.
#
def self.add_language_specific_settings(target, xcconfig)
if target.uses_swift?
build_settings = {
'OTHER_SWIFT_FLAGS' => quote(['-D COCOAPODS']),
}
xcconfig.merge!(build_settings)
end
end
# Adds the search paths of the developer frameworks to the specification
# if needed. This is done because the `SenTestingKit` requires them and
# adding them to each specification which requires it is repetitive and
......
......@@ -89,6 +89,7 @@ module Pod
prepare
resolve_dependencies
download_dependencies
determine_dependency_product_types
generate_pods_project
integrate_user_project if config.integrate_targets?
perform_post_install_actions
......@@ -311,6 +312,21 @@ module Pod
@pod_installers.each(&:clean!)
end
# Determines if the dependencies need to be built as dynamic frameworks or
# if they can be built as static libraries by checking for the Swift source
# presence. Therefore it is important that the file accessors of the
# #pod_targets are created.
#
# @return [void]
#
def determine_dependency_product_types
aggregate_targets.each do |aggregate_target|
aggregate_target.pod_targets.each do |pod_target|
pod_target.host_requires_frameworks = aggregate_target.requires_frameworks?
end
end
end
# Performs any post-installation actions
#
# @return [void]
......@@ -444,7 +460,13 @@ module Pod
end
end
# Adds a target dependency for each pod spec to each aggregate target and
# links the pod targets among each other.
#
# @return [void]
#
def set_target_dependencies
frameworks_group = pods_project.frameworks_group
aggregate_targets.each do |aggregate_target|
aggregate_target.pod_targets.each do |pod_target|
unless pod_target.should_build?
......@@ -464,7 +486,15 @@ module Pod
unless pod_dependency_target
puts "[BUG] DEP: #{dep}"
end
next unless pod_dependency_target.should_build?
pod_target.native_target.add_dependency(pod_dependency_target.native_target)
if pod_target.requires_frameworks?
product_ref = frameworks_group.files.find { |f| f.path == pod_dependency_target.product_name } ||
frameworks_group.new_product_ref_for_target(pod_dependency_target.product_basename, pod_dependency_target.product_type)
pod_target.native_target.frameworks_build_phase.add_file_reference(product_ref)
end
end
end
end
......
......@@ -180,47 +180,92 @@ module Pod
def generate_targets
targets = []
result.specs_by_target.each do |target_definition, specs|
target = AggregateTarget.new(target_definition, sandbox)
targets << target
if config.integrate_targets?
project_path = compute_user_project_path(target_definition)
user_project = Xcodeproj::Project.open(project_path)
native_targets = compute_user_project_targets(target_definition, user_project)
target.user_project_path = project_path
target.client_root = project_path.dirname
target.user_target_uuids = native_targets.map(&:uuid)
target.user_build_configurations = compute_user_build_configurations(target_definition, native_targets)
target.archs = @archs_by_target_def[target_definition]
else
target.client_root = config.installation_root
target.user_target_uuids = []
target.user_build_configurations = target_definition.build_configurations || { 'Release' => :release, 'Debug' => :debug }
if target_definition.platform.name == :osx
target.archs = '$(ARCHS_STANDARD_64_BIT)'
end
targets << generate_target(target_definition, specs)
end
targets
end
# Setup the aggregate target for a single user target
#
# @param [TargetDefinition] target_definition
# the target definition for the user target.
#
# @param [Array<Specification>] specs
# the specifications that need to be installed grouped by the
# given target definition.
#
# @return [AggregateTarget]
#
def generate_target(target_definition, specs)
target = AggregateTarget.new(target_definition, sandbox)
target.host_requires_frameworks |= target_definition.uses_frameworks?
if config.integrate_targets?
project_path = compute_user_project_path(target_definition)
user_project = Xcodeproj::Project.open(project_path)
native_targets = compute_user_project_targets(target_definition, user_project)
target.user_project_path = project_path
target.client_root = project_path.dirname
target.user_target_uuids = native_targets.map(&:uuid)
target.user_build_configurations = compute_user_build_configurations(target_definition, native_targets)
target.archs = @archs_by_target_def[target_definition]
else
target.client_root = config.installation_root
target.user_target_uuids = []
target.user_build_configurations = target_definition.build_configurations || { 'Release' => :release, 'Debug' => :debug }
if target_definition.platform.name == :osx
target.archs = '$(ARCHS_STANDARD_64_BIT)'
end
end
grouped_specs = specs.map do |spec|
specs.select { |s| s.root == spec.root }
end.uniq
target.pod_targets = generate_pod_targets(target, specs)
grouped_specs.each do |pod_specs|
pod_target = PodTarget.new(pod_specs, target_definition, sandbox)
if config.integrate_targets?
pod_target.user_build_configurations = target.user_build_configurations
pod_target.archs = @archs_by_target_def[target_definition]
else
pod_target.user_build_configurations = {}
if target_definition.platform.name == :osx
pod_target.archs = '$(ARCHS_STANDARD_64_BIT)'
end
end
target.pod_targets << pod_target
target
end
# Setup the pod targets for an aggregate target. Group specs and subspecs
# by their root to create a {PodTarget} for each spec.
#
# @param [AggregateTarget] target
# the aggregate target
#
# @param [Array<Specification>] specs
# the specifications that need to be installed.
#
# @return [Array<PodTarget>]
#
def generate_pod_targets(target, specs)
grouped_specs = specs.group_by(&:root).values.uniq
grouped_specs.map do |pod_specs|
generate_pod_target(target, pod_specs)
end
end
# Create a target for each spec group and add it to the aggregate target
#
# @param [AggregateTarget] target
# the aggregate target
#
# @param [Array<Specification>] specs
# the specifications of an equal root.
#
# @return [PodTarget]
#
def generate_pod_target(target, pod_specs)
pod_target = PodTarget.new(pod_specs, target.target_definition, sandbox)
if config.integrate_targets?
pod_target.user_build_configurations = target.user_build_configurations
pod_target.archs = @archs_by_target_def[target.target_definition]
else
pod_target.user_build_configurations = {}
if target.platform.name == :osx
pod_target.archs = '$(ARCHS_STANDARD_64_BIT)'
end
end
targets
pod_target
end
# Generates dependencies that require the specific version of the Pods
......@@ -515,6 +560,37 @@ module Pod
end
end
# Checks if any of the targets for the {TargetDefinition} computed before
# by #compute_user_project_targets require to be build as a framework due
# the presence of Swift source code in any of the source build phases.
#
# @param [TargetDefinition] target_definition
# the target definition
#
# @param [Array<PBXNativeTarget>] native_targets
# the targets which are checked for presence of Swift source code
#
# @return [Boolean] Whether the user project targets to integrate into
# uses Swift
#
def compute_user_project_targets_require_framework(target_definition, native_targets)
file_predicate = nil
file_predicate = proc do |file_ref|
if file_ref.respond_to?(:last_known_file_type)
file_ref.last_known_file_type == 'sourcecode.swift'
elsif file_ref.respond_to?(:files)
file_ref.files.any?(&file_predicate)
else
false
end
end
target_definition.platform.supports_dynamic_frameworks? || native_targets.any? do |target|
target.source_build_phase.files.any? do |build_file|
file_predicate.call(build_file.file_ref)
end
end
end
# @return [Hash{String=>Symbol}] A hash representing the user build
# configurations where each key corresponds to the name of a
# configuration and its value to its type (`:debug` or `:release`).
......
......@@ -36,25 +36,47 @@ module Pod
# @return [void]
#
def add_target
product_type = target.product_type
name = target.label
platform = target.platform.name
deployment_target = target.platform.deployment_target.to_s
@native_target = project.new_target(:static_library, name, platform, deployment_target)
@native_target = project.new_target(product_type, name, platform, deployment_target)
product_name = target.product_name
product = @native_target.product_reference
product.name = product_name
product.path = product_name
target.user_build_configurations.each do |bc_name, type|
configuration = @native_target.add_build_configuration(bc_name, type)
end
settings = { 'OTHER_LDFLAGS' => '', 'OTHER_LIBTOOLFLAGS' => '' }
@native_target.build_configurations.each do |configuration|
configuration.build_settings.merge!(custom_build_settings)
end
target.native_target = @native_target
end
# Returns the customized build settings which are overridden in the build
# settings of the user target.
#
# @return [Hash{String => String}]
#
def custom_build_settings
settings = {}
if target.archs
settings['ARCHS'] = target.archs
end
@native_target.build_configurations.each do |configuration|
configuration.build_settings.merge!(settings)
if target.requires_frameworks?
settings['PRODUCT_NAME'] = target.product_module_name
else
settings.merge!('OTHER_LDFLAGS' => '', 'OTHER_LIBTOOLFLAGS' => '')
end
target.native_target = @native_target
settings
end
# Creates the directory where to store the support files of the target.
......@@ -63,6 +85,68 @@ module Pod
target.support_files_dir.mkdir
end
# Creates the Info.plist file which sets public framework attributes
#
# @return [void]
#
def create_info_plist_file
path = target.info_plist_path
UI.message "- Generating Info.plist file at #{UI.path(path)}" do
generator = Generator::InfoPlistFile.new(target)
generator.save_as(path)
add_file_to_support_group(path)
native_target.build_configurations.each do |c|
relative_path = path.relative_path_from(sandbox.root)
c.build_settings['INFOPLIST_FILE'] = relative_path.to_s
end
end
end
# Creates the module map file which ensures that the umbrella header is
# recognized with a customized path
#
# @return [void]
#
def create_module_map
path = target.module_map_path
UI.message "- Generating module map file at #{UI.path(path)}" do
generator = Generator::ModuleMap.new(target)
generator.save_as(path)
add_file_to_support_group(path)
native_target.build_configurations.each do |c|
relative_path = path.relative_path_from(sandbox.root)
c.build_settings['MODULEMAP_FILE'] = relative_path.to_s
end
end
end
# Generates a header which ensures that all header files are exported
# in the module map
#
# @yield_param [Generator::UmbrellaHeader]
# yielded once to configure the imports
#
def create_umbrella_header
path = target.umbrella_header_path
UI.message "- Generating umbrella header at #{UI.path(path)}" do
generator = Generator::UmbrellaHeader.new(target)
yield generator if block_given?
generator.save_as(path)
# Add the file to the support group and the native target,
# so it will been added to the header build phase
file_ref = add_file_to_support_group(path)
native_target.add_file_references([file_ref])
# Make the umbrella header public
build_file = native_target.headers_build_phase.build_file(file_ref)
build_file.settings ||= {}
build_file.settings['ATTRIBUTES'] = ['Public']
end
end
# Generates a dummy source file for each target so libraries that contain
# only categories build.
#
......
......@@ -12,8 +12,14 @@ module Pod
UI.message "- Installing target `#{target.name}` #{target.platform}" do
add_target
create_support_files_dir
create_suport_files_group
create_support_files_group
create_xcconfig_file
if target.requires_frameworks?
create_info_plist_file
create_module_map
create_umbrella_header
create_embed_frameworks_script
end
create_target_environment_header
create_bridge_support_file
create_copy_resources_script
......@@ -26,12 +32,25 @@ module Pod
private
# Ensure that vendored static frameworks and libraries are not linked
# twice to the aggregate target, which shares the xcconfig of the user
# target.
#
def custom_build_settings
settings = {
'OTHER_LDFLAGS' => '',
'OTHER_LIBTOOLFLAGS' => '',
'PODS_ROOT' => '$(SRCROOT)',
}
super.merge(settings)
end
# Creates the group that holds the references to the support files
# generated by this installer.
#
# @return [void]
#
def create_suport_files_group
def create_support_files_group
parent = project.support_files_group
name = target.name
dir = target.support_files_dir
......@@ -92,9 +111,12 @@ module Pod
#
def create_copy_resources_script
path = target.copy_resources_script_path
file_accessors = target.pod_targets.map(&:file_accessors).flatten
resource_paths = file_accessors.map { |accessor| accessor.resources.flatten.map { |res| res.relative_path_from(project.path.dirname) } }.flatten
resource_bundles = file_accessors.map { |accessor| accessor.resource_bundles.keys.map { |name| "${BUILT_PRODUCTS_DIR}/#{name}.bundle" } }.flatten
library_targets = target.pod_targets.reject do |pod_target|
pod_target.should_build? && pod_target.requires_frameworks?
end
file_accessors = library_targets.flat_map(&:file_accessors)
resource_paths = file_accessors.flat_map { |accessor| accessor.resources.flat_map { |res| res.relative_path_from(project.path.dirname) } }
resource_bundles = file_accessors.flat_map { |accessor| accessor.resource_bundles.keys.map { |name| "${BUILT_PRODUCTS_DIR}/#{name}.bundle" } }
resources = []
resources.concat(resource_paths)
resources.concat(resource_bundles)
......@@ -104,6 +126,28 @@ module Pod
add_file_to_support_group(path)
end
# Creates a script that embeds the frameworks to the bundle of the client
# target.
#
# @note We can't use Xcode default copy bundle resource phase, because
# we need to ensure that we only copy the resources, which are
# relevant for the current build configuration.
#
# @return [void]
#
def create_embed_frameworks_script
path = target.embed_frameworks_script_path
frameworks_by_config = {}
target.user_build_configurations.keys.each do |config|
frameworks_by_config[config] = target.pod_targets.select do |pod_target|
pod_target.include_in_build_config?(config) && pod_target.should_build?
end.map(&:product_name)
end
generator = Generator::EmbedFrameworksScript.new(target_definition, frameworks_by_config)
generator.save_as(path)
add_file_to_support_group(path)
end
# Generates the acknowledgement files (markdown and plist) for the target.
#
# @return [void]
......
......@@ -17,9 +17,16 @@ module Pod
UI.message "- Installing target `#{target.name}` #{target.platform}" do
add_target
create_support_files_dir
add_files_to_build_phases
add_resources_bundle_targets
add_files_to_build_phases
create_xcconfig_file
if target.requires_frameworks?
create_info_plist_file
create_module_map
create_umbrella_header do |generator|
generator.imports += target.file_accessors.flat_map(&:public_headers).map(&:basename)
end
end
create_prefix_header
create_dummy_source
end
......@@ -41,20 +48,41 @@ module Pod
target.file_accessors.each do |file_accessor|
consumer = file_accessor.spec_consumer
headers = file_accessor.headers
public_headers = file_accessor.public_headers
other_source_files = file_accessor.source_files.select { |sf| sf.extname == '.d' }
{
true => file_accessor.arc_source_files,
false => file_accessor.non_arc_source_files,
}.each do |arc, files|
files = files - other_source_files
files = files - headers - other_source_files
flags = compiler_flags_for_consumer(consumer, arc)
regular_file_refs = files.map { |sf| project.reference_for_path(sf) }
native_target.add_file_references(regular_file_refs, flags)
end
header_file_refs = headers.map { |sf| project.reference_for_path(sf) }
native_target.add_file_references(header_file_refs) do |build_file|
# Set added headers as public if needed
if target.requires_frameworks?
if public_headers.include?(build_file.file_ref.real_path)
build_file.settings ||= {}
build_file.settings['ATTRIBUTES'] = ['Public']
end
end
end
other_file_refs = other_source_files.map { |sf| project.reference_for_path(sf) }
native_target.add_file_references(other_file_refs, nil)
next unless target.requires_frameworks?
resource_refs = file_accessor.resources.flatten.map do |res|
project.reference_for_path(res)
end
native_target.add_resources(resource_refs)
end
end
......@@ -68,23 +96,34 @@ module Pod
def add_resources_bundle_targets
target.file_accessors.each do |file_accessor|
file_accessor.resource_bundles.each do |bundle_name, paths|
# Add a dependency on an existing Resource Bundle target if possible
bundle_target = project.targets.find { |target| target.name == bundle_name }
unless bundle_target
file_references = paths.map { |sf| project.reference_for_path(sf) }
bundle_target = project.new_resources_bundle(bundle_name, file_accessor.spec_consumer.platform_name)
bundle_target.add_resources(file_references)
file_references = paths.map { |sf| project.reference_for_path(sf) }
label = target.resources_bundle_target_label(bundle_name)
bundle_target = project.new_resources_bundle(label, file_accessor.spec_consumer.platform_name)
bundle_target.product_reference.tap do |bundle_product|
bundle_file_name = "#{bundle_name}.bundle"
bundle_product.name = bundle_file_name
bundle_product.path = bundle_file_name
end
bundle_target.add_resources(file_references)
target.user_build_configurations.each do |bc_name, type|
bundle_target.add_build_configuration(bc_name, type)
end
target.user_build_configurations.each do |bc_name, type|
bundle_target.add_build_configuration(bc_name, type)
end
target.resource_bundle_targets << bundle_target
if target.should_build?
native_target.add_dependency(bundle_target)
if target.requires_frameworks?
native_target.add_resources([bundle_target.product_reference])
end
end
bundle_target.build_configurations.each do |c|
c.build_settings['PRODUCT_NAME'] = bundle_name
if target.requires_frameworks?
c.build_settings['CONFIGURATION_BUILD_DIR'] = target.configuration_build_dir
end
end
end
end
......
......@@ -132,7 +132,8 @@ module Pod
end
end
INHERITED_FLAGS = ['$(inherited)', '${inherited}']
IGNORED_KEYS = %w(CODE_SIGN_IDENTITY).freeze
INHERITED_FLAGS = %w($(inherited) ${inherited}).freeze
# Checks whether the settings of the CocoaPods generated xcconfig are
# overridden by the build configuration of a target and prints a
......@@ -144,7 +145,7 @@ module Pod
user_target.build_configurations.each do |config|
xcconfig = aggregate_target.xcconfigs[config.name]
if xcconfig
xcconfig.to_hash.keys.each do |key|
(xcconfig.to_hash.keys - IGNORED_KEYS).each do |key|
target_values = config.build_settings[key]
if target_values &&
!INHERITED_FLAGS.any? { |flag| target_values.include?(flag) }
......
......@@ -31,8 +31,10 @@ module Pod
project_is_dirty = [
XCConfigIntegrator.integrate(target, native_targets),
update_to_cocoapods_0_34,
remove_embed_frameworks_script_phases,
unless native_targets_to_integrate.empty?
add_pods_library
add_embed_frameworks_script_phase if target.requires_frameworks?
add_copy_resources_script_phase
add_check_manifest_lock_script_phase
true
......@@ -91,9 +93,9 @@ module Pod
changes
end
# Adds spec libraries to the frameworks build phase of the
# Adds spec product reference to the frameworks build phase of the
# {TargetDefinition} integration libraries. Adds a file reference to
# the library of the {TargetDefinition} and adds it to the frameworks
# the frameworks group of the project and adds it to the frameworks
# build phase of the targets.
#
# @return [void]
......@@ -101,12 +103,71 @@ module Pod
def add_pods_library
frameworks = user_project.frameworks_group
native_targets_to_integrate.each do |native_target|
library = frameworks.files.select { |f| f.path == target.product_name }.first ||
frameworks.new_product_ref_for_target(target.name, :static_library)
unless native_target.frameworks_build_phase.files_references.include?(library)
native_target.frameworks_build_phase.add_file_reference(library)
build_phase = native_target.frameworks_build_phase
# Find and delete possible reference for the other product type
old_product_name = target.requires_frameworks? ? target.static_library_name : target.framework_name
old_product_ref = frameworks.files.find { |f| f.path == old_product_name }
if old_product_ref.present?
UI.message("Removing old Pod product reference #{old_product_name} from project.")
build_phase.remove_file_reference(old_product_ref)
frameworks.remove_reference(old_product_ref)
end
# Find or create and add a reference for the current product type
target_basename = target.product_basename
new_product_ref = frameworks.files.find { |f| f.path == target.product_name } ||
frameworks.new_product_ref_for_target(target_basename, target.product_type)
build_file = build_phase.build_file(new_product_ref) ||
build_phase.add_file_reference(new_product_ref)
if target.requires_frameworks?
# Weak link the aggregate target's product, because as it contains
# no symbols, it isn't copied into the app bundle. dyld will so
# never try to find the missing executable at runtime.
build_file.settings ||= {}
build_file.settings['ATTRIBUTES'] = ['Weak']
end
end
end
# Find or create a 'Embed Pods Frameworks' Copy Files Build Phase
#
# @return [void]
#
def add_embed_frameworks_script_phase
phase_name = 'Embed Pods Frameworks'
native_targets_to_integrate.each do |native_target|
embed_build_phase = native_target.shell_script_build_phases.find { |bp| bp.name == phase_name }
unless embed_build_phase.present?
UI.message("Adding Build Phase '#{phase_name}' to project.")
embed_build_phase = native_target.new_shell_script_build_phase(phase_name)
end
script_path = target.embed_frameworks_script_relative_path
embed_build_phase.shell_script = %("#{script_path}"\n)
embed_build_phase.show_env_vars_in_log = '0'
end
end
# Delete 'Embed Pods Frameworks' Build Phases, if they exist
# and are not needed anymore due to not integrating the
# dependencies by frameworks.
#
# @return [Bool] whether any changes to the project were made.
#
def remove_embed_frameworks_script_phases
return false if target.requires_frameworks?
phase_name = 'Embed Pods Frameworks'
result = false
native_targets.each do |native_target|
embed_build_phase = native_target.shell_script_build_phases.find { |bp| bp.name == phase_name }
next unless embed_build_phase.present?
native_target.build_phases.delete(embed_build_phase)
result = true
end
result
end
# Adds a shell script build phase responsible to copy the resources
......
......@@ -12,7 +12,7 @@ module Pod
GLOB_PATTERNS = {
:readme => 'readme{*,.*}'.freeze,
:license => 'licen{c,s}e{*,.*}'.freeze,
:source_files => '*.{h,hpp,hh,m,mm,c,cpp}'.freeze,
:source_files => '*.{h,hpp,hh,m,mm,c,cpp,swift}'.freeze,
:public_header_files => "*{#{HEADER_EXTENSIONS.join(',')}}".freeze,
}.freeze
......
......@@ -26,6 +26,10 @@ module Pod
@search_paths = []
end
# @param [Platform] platform
# the platform for which the header search paths should be
# returned
#
# @return [Array<String>] All the search paths of the header directory in
# xcconfig format. The paths are specified relative to the pods
# root with the `${PODS_ROOT}` variable.
......
......@@ -15,18 +15,65 @@ module Pod
#
attr_reader :sandbox
# @return [Boolean] Whether the target needs to be implemented as a framework.
# Computed by analyzer.
#
attr_accessor :host_requires_frameworks
alias_method :host_requires_frameworks?, :host_requires_frameworks
# @return [String] the name of the library.
#
def name
label
end
# @return [String] the name of the library.
# @return [String] the name of the product.
#
def product_name
if requires_frameworks?
framework_name
else
static_library_name
end
end
# @return [String] the name of the product excluding the file extension or
# a product type specific prefix, depends on #requires_frameworks?
# and #product_module_name or #label.
#
def product_basename
if requires_frameworks?
product_module_name
else
label
end
end
# @return [String] the name of the framework, depends on #label.
#
# @note This may not depend on #requires_frameworks? indirectly as it is
# used for migration.
#
def framework_name
"#{product_module_name}.framework"
end
# @return [String] the name of the library, depends on #label.
#
# @note This may not depend on #requires_frameworks? indirectly as it is
# used for migration.
#
def static_library_name
"lib#{label}.a"
end
# @return [Symbol] either :framework or :static_library, depends on
# #requires_frameworks?.
#
def product_type
requires_frameworks? ? :framework : :static_library
end
# @return [String] the XCConfig namespaced prefix.
#
def xcconfig_prefix
......@@ -41,6 +88,20 @@ module Pod
#-------------------------------------------------------------------------#
# @return [Boolean] whether the generated target needs to be implemented
# as a framework
#
# @note This applies either if Swift was used by the host, which was checked
# eagerly by the analyzer before, or in the given target or its
# dependents, which can only be checked after the specs were been
# fetched.
#
def requires_frameworks?
host_requires_frameworks? || uses_swift?
end
#-------------------------------------------------------------------------#
# @!group Information storage
# @return [Hash{String=>Symbol}] A hash representing the user build
......@@ -95,6 +156,22 @@ module Pod
support_files_dir + "#{label}-Private.xcconfig"
end
# @return [Pathname] the absolute path of the header file which contains
# the exported foundation constants with framework version
# information and all headers, which should been exported in the
# module map.
#
def umbrella_header_path
support_files_dir + "#{label}-umbrella.h"
end
# @return [Pathname] the absolute path of the LLVM module map file that
# defines the module structure for the compiler.
#
def module_map_path
support_files_dir + "#{label}.modulemap"
end
# @return [Pathname] the absolute path of the header file which contains
# the information about the installed pods.
#
......@@ -115,12 +192,51 @@ module Pod
support_files_dir + "#{label}.bridgesupport"
end
# @return [Pathname] the absolute path of the Info.plist file.
#
def info_plist_path
support_files_dir + "Info.plist"
end
# @return [Pathname] the path of the dummy source generated by CocoaPods
#
def dummy_source_path
support_files_dir + "#{label}-dummy.m"
end
# @return [String] The configuration build dir, if the target is integrated
# as framework.
#
# @note Namespace the pod target product with its target definition name.
# Pod target products are named after their specs. The namespacing
# cannot directly happen in the product name itself, because this
# must be equal to the module name and this will be used in source
# code, which should stay agnostic over the dependency manager.
# We need namespacing at all because multiple targets can exist for
# the same podspec and their products should not collide. This
# happens when multiple user targets require the same pod, because
# they could require different sets of subspecs.
#
def configuration_build_dir
"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/#{target_definition.label}"
end
#-------------------------------------------------------------------------#
private
# Transforms the given string into a valid +identifier+ after C99ext
# standard, so that it can be used in source code where escaping of
# ambiguous characters is not applicable.
#
# @param [String] name
# any name, which may contain leading numbers, spaces or invalid
# characters.
#
# @return [String]
#
def c99ext_identifier(name)
name.gsub(/^([0-9])/, '_\1').gsub(/[^a-zA-Z0-9_]/, '_')
end
end
end
......@@ -20,6 +20,14 @@ module Pod
target_definition.label.to_s
end
# @return [String] the name to use for the source code module constructed
# for this target, and which will be used to import the module in
# implementation source files.
#
def product_module_name
c99ext_identifier(label)
end
# @return [Pathname] the folder where the client is stored used for
# computing the relative paths. If integrating it should be the
# folder where the user project is stored, otherwise it should
......@@ -71,21 +79,32 @@ module Pod
#
attr_accessor :pod_targets
# @param [String] build_configuration The build configuration for which the
# the pod targets should be returned.
#
# @return [Array<PodTarget>] the pod targets for the given build
# configuration.
#
def pod_targets_for_build_configuration(build_configuration)
pod_targets.select do |pod_target|
pod_target.include_in_build_config?(build_configuration)
end
end
# @return [Array<Specification>] The specifications used by this aggregate target.
#
def specs
pod_targets.map(&:specs).flatten
end
# @return [Hash{Symbol => Array<PodTarget>}] The pod targets for each
# @return [Hash{Symbol => Array<Specification>}] The pod targets for each
# build configuration.
#
def specs_by_build_configuration
result = {}
user_build_configurations.keys.each do |build_configuration|
result[build_configuration] = pod_targets.select do |pod_target|
pod_target.include_in_build_config?(build_configuration)
end.map(&:specs).flatten
result[build_configuration] = pod_targets_for_build_configuration(build_configuration).
flat_map(&:specs)
end
result
end
......@@ -96,6 +115,16 @@ module Pod
specs.map { |spec| spec.consumer(platform) }
end
# @return [Boolean] Whether the target uses Swift code
#
def uses_swift?
pod_targets.any?(&:uses_swift?)
end
#-------------------------------------------------------------------------#
# @!group Support files
# @return [Pathname] The absolute path of acknowledgements file.
#
# @note The acknowledgements generators add the extension according to
......@@ -111,6 +140,12 @@ module Pod
support_files_dir + "#{label}-resources.sh"
end
# @return [Pathname] The absolute path of the embed frameworks script.
#
def embed_frameworks_script_path
support_files_dir + "#{label}-frameworks.sh"
end
# @return [String] The xcconfig path of the root from the `$(SRCROOT)`
# variable of the user's project.
#
......@@ -133,6 +168,13 @@ module Pod
"${SRCROOT}/#{relative_to_srcroot(copy_resources_script_path)}"
end
# @return [String] The path of the embed frameworks relative to the
# root of the user project.
#
def embed_frameworks_script_relative_path
"${SRCROOT}/#{relative_to_srcroot(embed_frameworks_script_path)}"
end
private
# @!group Private Helpers
......
......@@ -30,6 +30,14 @@ module Pod
"#{target_definition.label}-#{root_spec.name}"
end
# @return [String] The name to use for the source code module constructed
# for this target, and which will be used to import the module in
# implementation source files.
#
def product_module_name
root_spec.module_name
end
# @return [Array<Sandbox::FileAccessor>] the file accessors for the
# specifications of this target.
#
......@@ -54,6 +62,14 @@ module Pod
specs.map { |spec| spec.consumer(platform) }
end
# @return [Boolean] Whether the target uses Swift code
#
def uses_swift?
file_accessors.any? do |file_accessor|
file_accessor.source_files.any? { |sf| sf.extname == ".swift" }
end
end
# @return [Specification] The root specification for the target.
#
def root_spec
......@@ -66,6 +82,15 @@ module Pod
root_spec.name
end
# @param [String] bundle_name
# The name of the bundle product, which is given by the +spec+.
#
# @return [String] The derived name of the resource bundle target.
#
def resources_bundle_target_label(bundle_name)
"#{label}-#{bundle_name}"
end
# @return [Array<String>] The names of the Pods on which this target
# depends.
#
......
......@@ -143,6 +143,10 @@ module Pod
#
attr_accessor :no_subspecs
# @return [Bool] Whether frameworks should be used for the installation.
#
attr_accessor :use_frameworks
#-------------------------------------------------------------------------#
# !@group Lint results
......@@ -299,7 +303,7 @@ module Pod
#
def install_pod
deployment_target = spec.subspec_by_name(subspec_name).deployment_target(consumer.platform_name)
podfile = podfile_from_spec(consumer.platform_name, deployment_target)
podfile = podfile_from_spec(consumer.platform_name, deployment_target, use_frameworks)
sandbox = Sandbox.new(config.sandbox_root)
installer = Installer.new(sandbox, podfile)
installer.install!
......@@ -449,19 +453,31 @@ module Pod
#
attr_reader :source_urls
# @param [String] platform_name
# the name of the platform, which should be declared
# in the Podfile.
#
# @param [String] deployment_target
# the deployment target, which should be declared in
# the Podfile.
#
# @param [Bool] use_frameworks
# whether frameworks should be used for the installation
#
# @return [Podfile] a podfile that requires the specification on the
# current platform.
# current platform.
#
# @note The generated podfile takes into account whether the linter is
# in local mode.
#
def podfile_from_spec(platform_name, deployment_target)
def podfile_from_spec(platform_name, deployment_target, use_frameworks = nil)
name = subspec_name ? subspec_name : spec.name
podspec = file.realpath
local = local?
urls = source_urls
podfile = Pod::Podfile.new do
urls.each { |u| source(u) }
use_frameworks!(use_frameworks) unless use_frameworks.nil?
platform(platform_name, deployment_target)
if local
pod name, :path => podspec.dirname.to_s
......
Subproject commit 3d83baf65d54e6abae10d480bdeb4f00a11e3682
Subproject commit 5ad1e8ba91444988fcc96379fd986f5b8641ded2
Pod::Spec.new do |s|
s.name = "monkey"
s.version = "1.0.2"
s.author = { "Funky Monkey" => "funky@monkey.local" }
s.summary = "🙈🙉🙊"
s.description = "See no evil! Hear no evil! Speak no evil!"
s.homepage = "http://httpbin.org/html"
s.source = { :git => "http://monkey.local/monkey.git", :tag => s.version.to_s }
s.license = 'MIT'
s.vendored_library = 'monkey.a'
end
# OS X
.DS_Store
# Xcode
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
profile
*.moved-aside
DerivedData
*.hmap
*.ipa
# Bundler
.bundle
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
#
# Note: if you ignore the Pods directory, make sure to uncomment
# `pod install` in .travis.yml
#
# Pods/
Copyright (c) 2014 Marius Rackwitz <git@mariusrackwitz.de>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Pod::Spec.new do |s|
s.name = "OrangeFramework"
s.version = "0.1.0"
s.author = { "Swiftest Orang-Utan" => "swiftest@orang.utan.local" }
s.summary = "Fresh juice!"
s.description = "Blends fresh orange juice."
s.homepage = "http://httpbin.org/html"
s.source = { :git => "http://utan.local/orange-framework.git", :tag => s.version.to_s }
s.license = 'MIT'
s.platform = :ios, '8.0'
s.source_files = 'Source/Juicer.swift'
s.frameworks = 'UIKit'
end
This diff is collapsed.
This diff is collapsed.
#import <UIKit/UIKit.h>
//! Project version number for orange-framework.
FOUNDATION_EXPORT double orangeVersionNumber;
//! Project version string for orange-framework.
FOUNDATION_EXPORT const unsigned char orangeVersionString[];
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment