mirror of
https://github.com/swisspol/GCDWebServer.git
synced 2026-02-11 00:00:07 +08:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d1e2a1a12f | ||
|
|
54d5abd3a8 | ||
|
|
a9fee8d7e2 | ||
|
|
6b15bdaa4e | ||
|
|
3771cf4e92 | ||
|
|
a5d83abdd0 | ||
|
|
f1e9f1a37c | ||
|
|
00b5ec87ba | ||
|
|
cf94e70a42 | ||
|
|
d47409c776 | ||
|
|
a9db13475b | ||
|
|
17fad0f1b9 | ||
|
|
5493d9e803 | ||
|
|
12b1edb958 | ||
|
|
7544a6dc4e |
@@ -1,19 +1,19 @@
|
|||||||
# http://guides.cocoapods.org/syntax/podspec.html
|
# http://guides.cocoapods.org/syntax/podspec.html
|
||||||
# Verify Podspec with:
|
# http://guides.cocoapods.org/making/getting-setup-with-trunk.html
|
||||||
# sudo gem update cocoapods
|
# $ sudo gem update cocoapods
|
||||||
# pod spec lint GCDWebServer.podspec --verbose
|
# (optional) $ pod trunk register {email} {name} --description={computer}
|
||||||
# Add to source line:
|
# $ pod trunk push
|
||||||
# :tag => s.version.to_s
|
# DELETE THIS SECTION BEFORE PROCEEDING!
|
||||||
|
|
||||||
Pod::Spec.new do |s|
|
Pod::Spec.new do |s|
|
||||||
s.name = 'GCDWebServer'
|
s.name = 'GCDWebServer'
|
||||||
s.version = '2.5'
|
s.version = '2.5.3'
|
||||||
s.author = { 'Pierre-Olivier Latour' => 'info@pol-online.net' }
|
s.author = { 'Pierre-Olivier Latour' => 'info@pol-online.net' }
|
||||||
s.license = { :type => 'BSD', :file => 'LICENSE' }
|
s.license = { :type => 'BSD', :file => 'LICENSE' }
|
||||||
s.homepage = 'https://github.com/swisspol/GCDWebServer'
|
s.homepage = 'https://github.com/swisspol/GCDWebServer'
|
||||||
s.summary = 'Lightweight GCD based HTTP server for OS X & iOS (includes web based uploader & WebDAV server)'
|
s.summary = 'Lightweight GCD based HTTP server for OS X & iOS (includes web based uploader & WebDAV server)'
|
||||||
|
|
||||||
s.source = { :git => 'https://github.com/swisspol/GCDWebServer.git' }
|
s.source = { :git => 'https://github.com/swisspol/GCDWebServer.git', :tag => s.version.to_s }
|
||||||
s.ios.deployment_target = '5.0'
|
s.ios.deployment_target = '5.0'
|
||||||
s.osx.deployment_target = '10.7'
|
s.osx.deployment_target = '10.7'
|
||||||
s.requires_arc = true
|
s.requires_arc = true
|
||||||
|
|||||||
@@ -370,7 +370,7 @@
|
|||||||
08FB7793FE84155DC02AAC07 /* Project object */ = {
|
08FB7793FE84155DC02AAC07 /* Project object */ = {
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastUpgradeCheck = 0510;
|
LastUpgradeCheck = 0600;
|
||||||
};
|
};
|
||||||
buildConfigurationList = 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "GCDWebServer" */;
|
buildConfigurationList = 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "GCDWebServer" */;
|
||||||
compatibilityVersion = "Xcode 3.2";
|
compatibilityVersion = "Xcode 3.2";
|
||||||
@@ -491,7 +491,6 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ARCHS = "$(ARCHS_STANDARD)";
|
ARCHS = "$(ARCHS_STANDARD)";
|
||||||
MACOSX_DEPLOYMENT_TARGET = 10.7;
|
|
||||||
PRODUCT_NAME = GCDWebServer;
|
PRODUCT_NAME = GCDWebServer;
|
||||||
SDKROOT = macosx;
|
SDKROOT = macosx;
|
||||||
};
|
};
|
||||||
@@ -501,7 +500,6 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ARCHS = "$(ARCHS_STANDARD)";
|
ARCHS = "$(ARCHS_STANDARD)";
|
||||||
MACOSX_DEPLOYMENT_TARGET = 10.7;
|
|
||||||
PRODUCT_NAME = GCDWebServer;
|
PRODUCT_NAME = GCDWebServer;
|
||||||
SDKROOT = macosx;
|
SDKROOT = macosx;
|
||||||
};
|
};
|
||||||
@@ -553,7 +551,6 @@
|
|||||||
ARCHS = "$(ARCHS_STANDARD)";
|
ARCHS = "$(ARCHS_STANDARD)";
|
||||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
INFOPLIST_FILE = iOS/Info.plist;
|
INFOPLIST_FILE = iOS/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 5.1.1;
|
|
||||||
PRODUCT_NAME = GCDWebServer;
|
PRODUCT_NAME = GCDWebServer;
|
||||||
PROVISIONING_PROFILE = "";
|
PROVISIONING_PROFILE = "";
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
@@ -567,7 +564,6 @@
|
|||||||
ARCHS = "$(ARCHS_STANDARD)";
|
ARCHS = "$(ARCHS_STANDARD)";
|
||||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
INFOPLIST_FILE = iOS/Info.plist;
|
INFOPLIST_FILE = iOS/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 5.1.1;
|
|
||||||
PRODUCT_NAME = GCDWebServer;
|
PRODUCT_NAME = GCDWebServer;
|
||||||
PROVISIONING_PROFILE = "";
|
PROVISIONING_PROFILE = "";
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
|
|||||||
@@ -77,16 +77,18 @@ typedef GCDWebServerResponse* (^GCDWebServerProcessBlock)(GCDWebServerRequest* r
|
|||||||
extern NSString* const GCDWebServerOption_Port;
|
extern NSString* const GCDWebServerOption_Port;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Bonjour name used by the GCDWebServer (NSString).
|
* The Bonjour name used by the GCDWebServer (NSString). If set to an empty string,
|
||||||
|
* the name will automatically take the value of the GCDWebServerOption_ServerName
|
||||||
|
* option. If this option is set to nil, Bonjour will be disabled.
|
||||||
*
|
*
|
||||||
* The default value is an empty string i.e. use the computer / device name.
|
* The default value is an empty string.
|
||||||
*/
|
*/
|
||||||
extern NSString* const GCDWebServerOption_BonjourName;
|
extern NSString* const GCDWebServerOption_BonjourName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Bonjour service type used by the GCDWebServer (NSString).
|
* The Bonjour service type used by the GCDWebServer (NSString).
|
||||||
*
|
*
|
||||||
* The default value is "_http._tcp", standard HTTP web server.
|
* The default value is "_http._tcp", the service type for HTTP web servers.
|
||||||
*/
|
*/
|
||||||
extern NSString* const GCDWebServerOption_BonjourType;
|
extern NSString* const GCDWebServerOption_BonjourType;
|
||||||
|
|
||||||
@@ -336,12 +338,14 @@ extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess;
|
|||||||
*
|
*
|
||||||
* @warning This property is only valid if the server is running and Bonjour
|
* @warning This property is only valid if the server is running and Bonjour
|
||||||
* registration has successfully completed, which can take up to a few seconds.
|
* registration has successfully completed, which can take up to a few seconds.
|
||||||
|
* Also be aware this property will not automatically update if the Bonjour hostname
|
||||||
|
* has been dynamically changed after the server started running (this should be rare).
|
||||||
*/
|
*/
|
||||||
@property(nonatomic, readonly) NSURL* bonjourServerURL;
|
@property(nonatomic, readonly) NSURL* bonjourServerURL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the server on port 8080 (OS X & iOS Simulator) or port 80 (iOS)
|
* Starts the server on port 8080 (OS X & iOS Simulator) or port 80 (iOS)
|
||||||
* using the computer / device name for as the Bonjour name.
|
* using the default Bonjour name.
|
||||||
*
|
*
|
||||||
* Returns NO if the server failed to start.
|
* Returns NO if the server failed to start.
|
||||||
*/
|
*/
|
||||||
@@ -350,7 +354,7 @@ extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess;
|
|||||||
/**
|
/**
|
||||||
* Starts the server on a given port and with a specific Bonjour name.
|
* Starts the server on a given port and with a specific Bonjour name.
|
||||||
* Pass a nil Bonjour name to disable Bonjour entirely or an empty string to
|
* Pass a nil Bonjour name to disable Bonjour entirely or an empty string to
|
||||||
* use the computer / device name.
|
* use the default name.
|
||||||
*
|
*
|
||||||
* Returns NO if the server failed to start.
|
* Returns NO if the server failed to start.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -147,7 +147,6 @@ static void _ExecuteMainThreadRunLoopSources() {
|
|||||||
NSMutableArray* _handlers;
|
NSMutableArray* _handlers;
|
||||||
NSInteger _activeConnections; // Accessed through _syncQueue only
|
NSInteger _activeConnections; // Accessed through _syncQueue only
|
||||||
BOOL _connected; // Accessed on main thread only
|
BOOL _connected; // Accessed on main thread only
|
||||||
BOOL _disconnecting; // Accessed on main thread only
|
|
||||||
CFRunLoopTimerRef _disconnectTimer; // Accessed on main thread only
|
CFRunLoopTimerRef _disconnectTimer; // Accessed on main thread only
|
||||||
|
|
||||||
NSDictionary* _options;
|
NSDictionary* _options;
|
||||||
@@ -160,7 +159,8 @@ static void _ExecuteMainThreadRunLoopSources() {
|
|||||||
CFTimeInterval _disconnectDelay;
|
CFTimeInterval _disconnectDelay;
|
||||||
NSUInteger _port;
|
NSUInteger _port;
|
||||||
dispatch_source_t _source;
|
dispatch_source_t _source;
|
||||||
CFNetServiceRef _service;
|
CFNetServiceRef _registrationService;
|
||||||
|
CFNetServiceRef _resolutionService;
|
||||||
#if TARGET_OS_IPHONE
|
#if TARGET_OS_IPHONE
|
||||||
BOOL _suspendInBackground;
|
BOOL _suspendInBackground;
|
||||||
UIBackgroundTaskIdentifier _backgroundTask;
|
UIBackgroundTaskIdentifier _backgroundTask;
|
||||||
@@ -192,23 +192,11 @@ static void _ExecuteMainThreadRunLoopSources() {
|
|||||||
GCDWebServerInitializeFunctions();
|
GCDWebServerInitializeFunctions();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _DisconnectTimerCallBack(CFRunLoopTimerRef timer, void* info) {
|
|
||||||
DCHECK([NSThread isMainThread]);
|
|
||||||
GCDWebServer* server = (ARC_BRIDGE GCDWebServer*)info;
|
|
||||||
@autoreleasepool {
|
|
||||||
[server _didDisconnect];
|
|
||||||
}
|
|
||||||
server->_disconnecting = NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (instancetype)init {
|
- (instancetype)init {
|
||||||
if ((self = [super init])) {
|
if ((self = [super init])) {
|
||||||
_syncQueue = dispatch_queue_create([NSStringFromClass([self class]) UTF8String], DISPATCH_QUEUE_SERIAL);
|
_syncQueue = dispatch_queue_create([NSStringFromClass([self class]) UTF8String], DISPATCH_QUEUE_SERIAL);
|
||||||
_sourceSemaphore = dispatch_semaphore_create(0);
|
_sourceSemaphore = dispatch_semaphore_create(0);
|
||||||
_handlers = [[NSMutableArray alloc] init];
|
_handlers = [[NSMutableArray alloc] init];
|
||||||
CFRunLoopTimerContext context = {0, (ARC_BRIDGE void*)self, NULL, NULL, NULL};
|
|
||||||
_disconnectTimer = CFRunLoopTimerCreate(kCFAllocatorDefault, HUGE_VAL, HUGE_VAL, 0, 0, _DisconnectTimerCallBack, &context);
|
|
||||||
CFRunLoopAddTimer(CFRunLoopGetMain(), _disconnectTimer, kCFRunLoopCommonModes);
|
|
||||||
#if TARGET_OS_IPHONE
|
#if TARGET_OS_IPHONE
|
||||||
_backgroundTask = UIBackgroundTaskInvalid;
|
_backgroundTask = UIBackgroundTaskInvalid;
|
||||||
#endif
|
#endif
|
||||||
@@ -220,9 +208,8 @@ static void _DisconnectTimerCallBack(CFRunLoopTimerRef timer, void* info) {
|
|||||||
DCHECK(_connected == NO);
|
DCHECK(_connected == NO);
|
||||||
DCHECK(_activeConnections == 0);
|
DCHECK(_activeConnections == 0);
|
||||||
DCHECK(_options == nil); // The server can never be dealloc'ed while running because of the retain-cycle with the dispatch source
|
DCHECK(_options == nil); // The server can never be dealloc'ed while running because of the retain-cycle with the dispatch source
|
||||||
|
DCHECK(_disconnectTimer == NULL); // The server can never be dealloc'ed while the disconnect timer is pending because of the retain-cycle
|
||||||
|
|
||||||
CFRunLoopTimerInvalidate(_disconnectTimer);
|
|
||||||
CFRelease(_disconnectTimer);
|
|
||||||
ARC_RELEASE(_handlers);
|
ARC_RELEASE(_handlers);
|
||||||
ARC_DISPATCH_RELEASE(_sourceSemaphore);
|
ARC_DISPATCH_RELEASE(_sourceSemaphore);
|
||||||
ARC_DISPATCH_RELEASE(_syncQueue);
|
ARC_DISPATCH_RELEASE(_syncQueue);
|
||||||
@@ -272,9 +259,10 @@ static void _DisconnectTimerCallBack(CFRunLoopTimerRef timer, void* info) {
|
|||||||
DCHECK(_activeConnections >= 0);
|
DCHECK(_activeConnections >= 0);
|
||||||
if (_activeConnections == 0) {
|
if (_activeConnections == 0) {
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
if (_disconnecting) {
|
if (_disconnectTimer) {
|
||||||
CFRunLoopTimerSetNextFireDate(_disconnectTimer, HUGE_VAL);
|
CFRunLoopTimerInvalidate(_disconnectTimer);
|
||||||
_disconnecting = NO;
|
CFRelease(_disconnectTimer);
|
||||||
|
_disconnectTimer = NULL;
|
||||||
}
|
}
|
||||||
if (_connected == NO) {
|
if (_connected == NO) {
|
||||||
[self _didConnect];
|
[self _didConnect];
|
||||||
@@ -328,8 +316,17 @@ static void _DisconnectTimerCallBack(CFRunLoopTimerRef timer, void* info) {
|
|||||||
if (_activeConnections == 0) {
|
if (_activeConnections == 0) {
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
if ((_disconnectDelay > 0.0) && (_source != NULL)) {
|
if ((_disconnectDelay > 0.0) && (_source != NULL)) {
|
||||||
CFRunLoopTimerSetNextFireDate(_disconnectTimer, CFAbsoluteTimeGetCurrent() + _disconnectDelay);
|
if (_disconnectTimer) {
|
||||||
_disconnecting = YES;
|
CFRunLoopTimerInvalidate(_disconnectTimer);
|
||||||
|
CFRelease(_disconnectTimer);
|
||||||
|
}
|
||||||
|
_disconnectTimer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + _disconnectDelay, 0.0, 0, 0, ^(CFRunLoopTimerRef timer) {
|
||||||
|
DCHECK([NSThread isMainThread]);
|
||||||
|
[self _didDisconnect];
|
||||||
|
CFRelease(_disconnectTimer);
|
||||||
|
_disconnectTimer = NULL;
|
||||||
|
});
|
||||||
|
CFRunLoopAddTimer(CFRunLoopGetMain(), _disconnectTimer, kCFRunLoopCommonModes);
|
||||||
} else {
|
} else {
|
||||||
[self _didDisconnect];
|
[self _didDisconnect];
|
||||||
}
|
}
|
||||||
@@ -339,12 +336,12 @@ static void _DisconnectTimerCallBack(CFRunLoopTimerRef timer, void* info) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (NSString*)bonjourName {
|
- (NSString*)bonjourName {
|
||||||
CFStringRef name = _service ? CFNetServiceGetName(_service) : NULL;
|
CFStringRef name = _resolutionService ? CFNetServiceGetName(_resolutionService) : NULL;
|
||||||
return name && CFStringGetLength(name) ? ARC_BRIDGE_RELEASE(CFStringCreateCopy(kCFAllocatorDefault, name)) : nil;
|
return name && CFStringGetLength(name) ? ARC_BRIDGE_RELEASE(CFStringCreateCopy(kCFAllocatorDefault, name)) : nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString*)bonjourType {
|
- (NSString*)bonjourType {
|
||||||
CFStringRef type = _service ? CFNetServiceGetType(_service) : NULL;
|
CFStringRef type = _resolutionService ? CFNetServiceGetType(_resolutionService) : NULL;
|
||||||
return type && CFStringGetLength(type) ? ARC_BRIDGE_RELEASE(CFStringCreateCopy(kCFAllocatorDefault, type)) : nil;
|
return type && CFStringGetLength(type) ? ARC_BRIDGE_RELEASE(CFStringCreateCopy(kCFAllocatorDefault, type)) : nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,11 +357,26 @@ static void _DisconnectTimerCallBack(CFRunLoopTimerRef timer, void* info) {
|
|||||||
[_handlers removeAllObjects];
|
[_handlers removeAllObjects];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _NetServiceClientCallBack(CFNetServiceRef service, CFStreamError* error, void* info) {
|
static void _NetServiceRegisterCallBack(CFNetServiceRef service, CFStreamError* error, void* info) {
|
||||||
DCHECK([NSThread isMainThread]);
|
DCHECK([NSThread isMainThread]);
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
if (error->error) {
|
if (error->error) {
|
||||||
LOG_ERROR(@"Bonjour error %i (domain %i)", (int)error->error, (int)error->domain);
|
LOG_ERROR(@"Bonjour registration error %i (domain %i)", (int)error->error, (int)error->domain);
|
||||||
|
} else {
|
||||||
|
GCDWebServer* server = (ARC_BRIDGE GCDWebServer*)info;
|
||||||
|
LOG_VERBOSE(@"Bonjour registration complete for %@", [server class]);
|
||||||
|
CFNetServiceResolveWithTimeout(server->_resolutionService, 1.0, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _NetServiceResolveCallBack(CFNetServiceRef service, CFStreamError* error, void* info) {
|
||||||
|
DCHECK([NSThread isMainThread]);
|
||||||
|
@autoreleasepool {
|
||||||
|
if (error->error) {
|
||||||
|
if ((error->domain != kCFStreamErrorDomainNetServices) && (error->error != kCFNetServicesErrorTimeout)) {
|
||||||
|
LOG_ERROR(@"Bonjour resolution error %i (domain %i)", (int)error->error, (int)error->domain);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
GCDWebServer* server = (ARC_BRIDGE GCDWebServer*)info;
|
GCDWebServer* server = (ARC_BRIDGE GCDWebServer*)info;
|
||||||
LOG_INFO(@"%@ now reachable at %@", [server class], server.bonjourServerURL);
|
LOG_INFO(@"%@ now reachable at %@", [server class], server.bonjourServerURL);
|
||||||
@@ -392,8 +404,9 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
|||||||
|
|
||||||
- (BOOL)_start:(NSError**)error {
|
- (BOOL)_start:(NSError**)error {
|
||||||
DCHECK(_source == NULL);
|
DCHECK(_source == NULL);
|
||||||
|
|
||||||
NSUInteger port = [_GetOption(_options, GCDWebServerOption_Port, @0) unsignedIntegerValue];
|
NSUInteger port = [_GetOption(_options, GCDWebServerOption_Port, @0) unsignedIntegerValue];
|
||||||
NSString* name = _GetOption(_options, GCDWebServerOption_BonjourName, @"");
|
NSString* bonjourName = _GetOption(_options, GCDWebServerOption_BonjourName, @"");
|
||||||
NSString* bonjourType = _GetOption(_options, GCDWebServerOption_BonjourType, @"_http._tcp");
|
NSString* bonjourType = _GetOption(_options, GCDWebServerOption_BonjourType, @"_http._tcp");
|
||||||
NSUInteger maxPendingConnections = [_GetOption(_options, GCDWebServerOption_MaxPendingConnections, @16) unsignedIntegerValue];
|
NSUInteger maxPendingConnections = [_GetOption(_options, GCDWebServerOption_MaxPendingConnections, @16) unsignedIntegerValue];
|
||||||
int listeningSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
int listeningSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
@@ -491,14 +504,21 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
|||||||
_port = port;
|
_port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name) {
|
if (bonjourName) {
|
||||||
_service = CFNetServiceCreate(kCFAllocatorDefault, CFSTR("local."), (ARC_BRIDGE CFStringRef)bonjourType, (ARC_BRIDGE CFStringRef)name, (SInt32)_port);
|
_registrationService = CFNetServiceCreate(kCFAllocatorDefault, CFSTR("local."), (ARC_BRIDGE CFStringRef)bonjourType, (ARC_BRIDGE CFStringRef)(bonjourName.length ? bonjourName : _serverName), (SInt32)_port);
|
||||||
if (_service) {
|
if (_registrationService) {
|
||||||
CFNetServiceClientContext context = {0, (ARC_BRIDGE void*)self, NULL, NULL, NULL};
|
CFNetServiceClientContext context = {0, (ARC_BRIDGE void*)self, NULL, NULL, NULL};
|
||||||
CFNetServiceSetClient(_service, _NetServiceClientCallBack, &context);
|
|
||||||
CFNetServiceScheduleWithRunLoop(_service, CFRunLoopGetMain(), kCFRunLoopCommonModes);
|
CFNetServiceSetClient(_registrationService, _NetServiceRegisterCallBack, &context);
|
||||||
|
CFNetServiceScheduleWithRunLoop(_registrationService, CFRunLoopGetMain(), kCFRunLoopCommonModes);
|
||||||
CFStreamError streamError = {0};
|
CFStreamError streamError = {0};
|
||||||
CFNetServiceRegisterWithOptions(_service, 0, &streamError);
|
CFNetServiceRegisterWithOptions(_registrationService, 0, &streamError);
|
||||||
|
|
||||||
|
_resolutionService = CFNetServiceCreateCopy(kCFAllocatorDefault, _registrationService);
|
||||||
|
if (_resolutionService) {
|
||||||
|
CFNetServiceSetClient(_resolutionService, _NetServiceResolveCallBack, &context);
|
||||||
|
CFNetServiceScheduleWithRunLoop(_resolutionService, CFRunLoopGetMain(), kCFRunLoopCommonModes);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG_ERROR(@"Failed creating CFNetService");
|
LOG_ERROR(@"Failed creating CFNetService");
|
||||||
}
|
}
|
||||||
@@ -537,11 +557,19 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
|||||||
- (void)_stop {
|
- (void)_stop {
|
||||||
DCHECK(_source != NULL);
|
DCHECK(_source != NULL);
|
||||||
|
|
||||||
if (_service) {
|
if (_registrationService) {
|
||||||
CFNetServiceUnscheduleFromRunLoop(_service, CFRunLoopGetMain(), kCFRunLoopCommonModes);
|
if (_resolutionService) {
|
||||||
CFNetServiceSetClient(_service, NULL, NULL);
|
CFNetServiceUnscheduleFromRunLoop(_resolutionService, CFRunLoopGetMain(), kCFRunLoopCommonModes);
|
||||||
CFRelease(_service);
|
CFNetServiceSetClient(_resolutionService, NULL, NULL);
|
||||||
_service = NULL;
|
CFNetServiceCancel(_resolutionService);
|
||||||
|
CFRelease(_resolutionService);
|
||||||
|
_resolutionService = NULL;
|
||||||
|
}
|
||||||
|
CFNetServiceUnscheduleFromRunLoop(_registrationService, CFRunLoopGetMain(), kCFRunLoopCommonModes);
|
||||||
|
CFNetServiceSetClient(_registrationService, NULL, NULL);
|
||||||
|
CFNetServiceCancel(_registrationService);
|
||||||
|
CFRelease(_registrationService);
|
||||||
|
_registrationService = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch_source_cancel(_source);
|
dispatch_source_cancel(_source);
|
||||||
@@ -560,9 +588,10 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
|||||||
_authenticationDigestAccounts = nil;
|
_authenticationDigestAccounts = nil;
|
||||||
|
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
if (_disconnecting) {
|
if (_disconnectTimer) {
|
||||||
CFRunLoopTimerSetNextFireDate(_disconnectTimer, HUGE_VAL);
|
CFRunLoopTimerInvalidate(_disconnectTimer);
|
||||||
_disconnecting = NO;
|
CFRelease(_disconnectTimer);
|
||||||
|
_disconnectTimer = NULL;
|
||||||
[self _didDisconnect];
|
[self _didDisconnect];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -623,7 +652,7 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)isRunning {
|
- (BOOL)isRunning {
|
||||||
return (_source ? YES : NO);
|
return (_options ? YES : NO);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)stop {
|
- (void)stop {
|
||||||
@@ -663,13 +692,14 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (NSURL*)bonjourServerURL {
|
- (NSURL*)bonjourServerURL {
|
||||||
if (_source && _service) {
|
if (_source && _resolutionService) {
|
||||||
CFStringRef name = CFNetServiceGetName(_service);
|
NSString* name = (ARC_BRIDGE NSString*)CFNetServiceGetTargetHost(_resolutionService);
|
||||||
if (name && CFStringGetLength(name)) {
|
if (name.length) {
|
||||||
|
name = [name substringToIndex:(name.length - 1)]; // Strip trailing period at end of domain
|
||||||
if (_port != 80) {
|
if (_port != 80) {
|
||||||
return [NSURL URLWithString:[NSString stringWithFormat:@"http://%@.local:%i/", name, (int)_port]];
|
return [NSURL URLWithString:[NSString stringWithFormat:@"http://%@:%i/", name, (int)_port]];
|
||||||
} else {
|
} else {
|
||||||
return [NSURL URLWithString:[NSString stringWithFormat:@"http://%@.local/", name]];
|
return [NSURL URLWithString:[NSString stringWithFormat:@"http://%@/", name]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -760,10 +790,23 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
|||||||
if (![requestMethod isEqualToString:method]) {
|
if (![requestMethod isEqualToString:method]) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
if ([expression firstMatchInString:urlPath options:0 range:NSMakeRange(0, urlPath.length)] == nil) {
|
|
||||||
|
NSArray* matches = [expression matchesInString:urlPath options:0 range:NSMakeRange(0, urlPath.length)];
|
||||||
|
if (matches.count == 0) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
return ARC_AUTORELEASE([[aClass alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery]);
|
|
||||||
|
NSMutableArray* captures = [NSMutableArray array];
|
||||||
|
for (NSTextCheckingResult* result in matches) {
|
||||||
|
// Start at 1; index 0 is the whole string
|
||||||
|
for (NSUInteger i = 1; i < result.numberOfRanges; i++) {
|
||||||
|
[captures addObject:[urlPath substringWithRange:[result rangeAtIndex:i]]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GCDWebServerRequest* request = [[aClass alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery];
|
||||||
|
[request setAttribute:captures forKey:GCDWebServerRequestAttribute_RegexCaptures];
|
||||||
|
return ARC_AUTORELEASE(request);
|
||||||
|
|
||||||
} processBlock:block];
|
} processBlock:block];
|
||||||
} else {
|
} else {
|
||||||
@@ -849,17 +892,18 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
|||||||
|
|
||||||
GCDWebServerResponse* response = nil;
|
GCDWebServerResponse* response = nil;
|
||||||
NSString* filePath = [directoryPath stringByAppendingPathComponent:[request.path substringFromIndex:basePath.length]];
|
NSString* filePath = [directoryPath stringByAppendingPathComponent:[request.path substringFromIndex:basePath.length]];
|
||||||
BOOL isDirectory;
|
NSString* fileType = [[[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:NULL] fileType];
|
||||||
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath isDirectory:&isDirectory]) {
|
if (fileType) {
|
||||||
if (isDirectory) {
|
if ([fileType isEqualToString:NSFileTypeDirectory]) {
|
||||||
if (indexFilename) {
|
if (indexFilename) {
|
||||||
NSString* indexPath = [filePath stringByAppendingPathComponent:indexFilename];
|
NSString* indexPath = [filePath stringByAppendingPathComponent:indexFilename];
|
||||||
if ([[NSFileManager defaultManager] fileExistsAtPath:indexPath isDirectory:&isDirectory] && !isDirectory) {
|
NSString* indexType = [[[NSFileManager defaultManager] attributesOfItemAtPath:indexPath error:NULL] fileType];
|
||||||
|
if ([indexType isEqualToString:NSFileTypeRegular]) {
|
||||||
return [GCDWebServerFileResponse responseWithFile:indexPath];
|
return [GCDWebServerFileResponse responseWithFile:indexPath];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
response = [server _responseWithContentsOfDirectory:filePath];
|
response = [server _responseWithContentsOfDirectory:filePath];
|
||||||
} else {
|
} else if ([fileType isEqualToString:NSFileTypeRegular]) {
|
||||||
if (allowRangeRequests) {
|
if (allowRangeRequests) {
|
||||||
response = [GCDWebServerFileResponse responseWithFile:filePath byteRange:request.byteRange];
|
response = [GCDWebServerFileResponse responseWithFile:filePath byteRange:request.byteRange];
|
||||||
[response setValue:@"bytes" forAdditionalHeader:@"Accept-Ranges"];
|
[response setValue:@"bytes" forAdditionalHeader:@"Accept-Ranges"];
|
||||||
|
|||||||
@@ -204,10 +204,13 @@ NSDictionary* GCDWebServerParseURLEncodedForm(NSString* form) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
key = [key stringByReplacingOccurrencesOfString:@"+" withString:@" "];
|
key = [key stringByReplacingOccurrencesOfString:@"+" withString:@" "];
|
||||||
|
NSString* unescapedKey = key ? GCDWebServerUnescapeURLString(key) : nil;
|
||||||
value = [value stringByReplacingOccurrencesOfString:@"+" withString:@" "];
|
value = [value stringByReplacingOccurrencesOfString:@"+" withString:@" "];
|
||||||
if (key && value) {
|
NSString* unescapedValue = value ? GCDWebServerUnescapeURLString(value) : nil;
|
||||||
[parameters setObject:GCDWebServerUnescapeURLString(value) forKey:GCDWebServerUnescapeURLString(key)];
|
if (unescapedKey && unescapedValue) {
|
||||||
|
[parameters setObject:unescapedValue forKey:unescapedKey];
|
||||||
} else {
|
} else {
|
||||||
|
LOG_WARNING(@"Failed parsing URL encoded form for key \"%@\" and value \"%@\"", key, value);
|
||||||
DNOT_REACHED();
|
DNOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,8 +25,7 @@
|
|||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#import <TargetConditionals.h>
|
#import <os/object.h>
|
||||||
#import <AvailabilityMacros.h>
|
|
||||||
|
|
||||||
#if __has_feature(objc_arc)
|
#if __has_feature(objc_arc)
|
||||||
#define ARC_BRIDGE __bridge
|
#define ARC_BRIDGE __bridge
|
||||||
@@ -35,7 +34,7 @@
|
|||||||
#define ARC_RELEASE(__OBJECT__)
|
#define ARC_RELEASE(__OBJECT__)
|
||||||
#define ARC_AUTORELEASE(__OBJECT__) __OBJECT__
|
#define ARC_AUTORELEASE(__OBJECT__) __OBJECT__
|
||||||
#define ARC_DEALLOC(__OBJECT__)
|
#define ARC_DEALLOC(__OBJECT__)
|
||||||
#if (TARGET_OS_IPHONE && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_6_0)) || (!TARGET_OS_IPHONE && (__MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_8))
|
#if OS_OBJECT_USE_OBJC_RETAIN_RELEASE
|
||||||
#define ARC_DISPATCH_RETAIN(__OBJECT__)
|
#define ARC_DISPATCH_RETAIN(__OBJECT__)
|
||||||
#define ARC_DISPATCH_RELEASE(__OBJECT__)
|
#define ARC_DISPATCH_RELEASE(__OBJECT__)
|
||||||
#else
|
#else
|
||||||
@@ -154,6 +153,7 @@ extern NSString* GCDWebServerComputeMD5Digest(NSString* format, ...) NS_FORMAT_F
|
|||||||
- (BOOL)performOpen:(NSError**)error;
|
- (BOOL)performOpen:(NSError**)error;
|
||||||
- (BOOL)performWriteData:(NSData*)data error:(NSError**)error;
|
- (BOOL)performWriteData:(NSData*)data error:(NSError**)error;
|
||||||
- (BOOL)performClose:(NSError**)error;
|
- (BOOL)performClose:(NSError**)error;
|
||||||
|
- (void)setAttribute:(id)attribute forKey:(NSString*)key;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface GCDWebServerResponse ()
|
@interface GCDWebServerResponse ()
|
||||||
|
|||||||
@@ -27,6 +27,15 @@
|
|||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute key to retrieve an NSArray containing NSStrings from a GCDWebServerRequest
|
||||||
|
* with the contents of any regular expression captures done on the request path.
|
||||||
|
*
|
||||||
|
* @warning This attribute will only be set on the request if adding a handler using
|
||||||
|
* -addHandlerForMethod:pathRegex:requestClass:processBlock:.
|
||||||
|
*/
|
||||||
|
extern NSString* const GCDWebServerRequestAttribute_RegexCaptures;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This protocol is used by the GCDWebServerConnection to communicate with
|
* This protocol is used by the GCDWebServerConnection to communicate with
|
||||||
* the GCDWebServerRequest and write the received HTTP body data.
|
* the GCDWebServerRequest and write the received HTTP body data.
|
||||||
@@ -163,4 +172,11 @@
|
|||||||
*/
|
*/
|
||||||
- (BOOL)hasByteRange;
|
- (BOOL)hasByteRange;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves an attribute associated with this request using the given key.
|
||||||
|
*
|
||||||
|
* @return The attribute value for the key.
|
||||||
|
*/
|
||||||
|
- (id)attributeForKey:(NSString*)key;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -29,6 +29,8 @@
|
|||||||
|
|
||||||
#import "GCDWebServerPrivate.h"
|
#import "GCDWebServerPrivate.h"
|
||||||
|
|
||||||
|
NSString* const GCDWebServerRequestAttribute_RegexCaptures = @"GCDWebServerRequestAttribute_RegexCaptures";
|
||||||
|
|
||||||
#define kZlibErrorDomain @"ZlibErrorDomain"
|
#define kZlibErrorDomain @"ZlibErrorDomain"
|
||||||
#define kGZipInitialBufferSize (256 * 1024)
|
#define kGZipInitialBufferSize (256 * 1024)
|
||||||
|
|
||||||
@@ -152,6 +154,7 @@
|
|||||||
|
|
||||||
BOOL _opened;
|
BOOL _opened;
|
||||||
NSMutableArray* _decoders;
|
NSMutableArray* _decoders;
|
||||||
|
NSMutableDictionary* _attributes;
|
||||||
id<GCDWebServerBodyWriter> __unsafe_unretained _writer;
|
id<GCDWebServerBodyWriter> __unsafe_unretained _writer;
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
@@ -238,6 +241,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
_decoders = [[NSMutableArray alloc] init];
|
_decoders = [[NSMutableArray alloc] init];
|
||||||
|
_attributes = [[NSMutableDictionary alloc] init];
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@@ -252,6 +256,7 @@
|
|||||||
ARC_RELEASE(_modifiedSince);
|
ARC_RELEASE(_modifiedSince);
|
||||||
ARC_RELEASE(_noneMatch);
|
ARC_RELEASE(_noneMatch);
|
||||||
ARC_RELEASE(_decoders);
|
ARC_RELEASE(_decoders);
|
||||||
|
ARC_RELEASE(_attributes);
|
||||||
|
|
||||||
ARC_DEALLOC(super);
|
ARC_DEALLOC(super);
|
||||||
}
|
}
|
||||||
@@ -264,6 +269,10 @@
|
|||||||
return GCDWebServerIsValidByteRange(_range);
|
return GCDWebServerIsValidByteRange(_range);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (id)attributeForKey:(NSString*)key {
|
||||||
|
return [_attributes objectForKey:key];
|
||||||
|
}
|
||||||
|
|
||||||
- (BOOL)open:(NSError**)error {
|
- (BOOL)open:(NSError**)error {
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
@@ -307,6 +316,10 @@
|
|||||||
return [_writer close:error];
|
return [_writer close:error];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setAttribute:(id)attribute forKey:(NSString*)key {
|
||||||
|
[_attributes setValue:attribute forKey:key];
|
||||||
|
}
|
||||||
|
|
||||||
- (NSString*)description {
|
- (NSString*)description {
|
||||||
NSMutableString* description = [NSMutableString stringWithFormat:@"%@ %@", _method, _path];
|
NSMutableString* description = [NSMutableString stringWithFormat:@"%@ %@", _method, _path];
|
||||||
for (NSString* argument in [[_query allKeys] sortedArrayUsingSelector:@selector(compare:)]) {
|
for (NSString* argument in [[_query allKeys] sortedArrayUsingSelector:@selector(compare:)]) {
|
||||||
|
|||||||
@@ -322,6 +322,9 @@
|
|||||||
NSString* title = server.title;
|
NSString* title = server.title;
|
||||||
if (title == nil) {
|
if (title == nil) {
|
||||||
title = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
|
title = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
|
||||||
|
if (title == nil) {
|
||||||
|
title = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"];
|
||||||
|
}
|
||||||
#if !TARGET_OS_IPHONE
|
#if !TARGET_OS_IPHONE
|
||||||
if (title == nil) {
|
if (title == nil) {
|
||||||
title = [[NSProcessInfo processInfo] processName];
|
title = [[NSProcessInfo processInfo] processName];
|
||||||
|
|||||||
24
Run-Tests.sh
24
Run-Tests.sh
@@ -32,19 +32,35 @@ function runTests {
|
|||||||
logLevel=2 $1 -mode "$2" -root "$PAYLOAD_DIR/Payload" -tests "$3"
|
logLevel=2 $1 -mode "$2" -root "$PAYLOAD_DIR/Payload" -tests "$3"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Build for iOS in manual memory management mode (TODO: run tests on iOS)
|
# Build for iOS in manual memory management mode and for oldest deployment target (TODO: run tests on iOS)
|
||||||
|
rm -rf "$MRC_BUILD_DIR"
|
||||||
|
xcodebuild -sdk "$IOS_SDK" -target "$IOS_TARGET" -configuration "$CONFIGURATION" build "SYMROOT=$MRC_BUILD_DIR" "CLANG_ENABLE_OBJC_ARC=NO" "IPHONEOS_DEPLOYMENT_TARGET=5.1.1" > /dev/null
|
||||||
|
|
||||||
|
# Build for iOS in manual memory management mode and for default deployment target (TODO: run tests on iOS)
|
||||||
rm -rf "$MRC_BUILD_DIR"
|
rm -rf "$MRC_BUILD_DIR"
|
||||||
xcodebuild -sdk "$IOS_SDK" -target "$IOS_TARGET" -configuration "$CONFIGURATION" build "SYMROOT=$MRC_BUILD_DIR" "CLANG_ENABLE_OBJC_ARC=NO" > /dev/null
|
xcodebuild -sdk "$IOS_SDK" -target "$IOS_TARGET" -configuration "$CONFIGURATION" build "SYMROOT=$MRC_BUILD_DIR" "CLANG_ENABLE_OBJC_ARC=NO" > /dev/null
|
||||||
|
|
||||||
# Build for iOS in ARC mode (TODO: run tests on iOS)
|
# Build for iOS in ARC mode and for oldest deployment target (TODO: run tests on iOS)
|
||||||
|
rm -rf "$ARC_BUILD_DIR"
|
||||||
|
xcodebuild -sdk "$IOS_SDK" -target "$IOS_TARGET" -configuration "$CONFIGURATION" build "SYMROOT=$ARC_BUILD_DIR" "CLANG_ENABLE_OBJC_ARC=YES" "IPHONEOS_DEPLOYMENT_TARGET=5.1.1" > /dev/null
|
||||||
|
|
||||||
|
# Build for iOS in ARC mode and for default deployment target (TODO: run tests on iOS)
|
||||||
rm -rf "$ARC_BUILD_DIR"
|
rm -rf "$ARC_BUILD_DIR"
|
||||||
xcodebuild -sdk "$IOS_SDK" -target "$IOS_TARGET" -configuration "$CONFIGURATION" build "SYMROOT=$ARC_BUILD_DIR" "CLANG_ENABLE_OBJC_ARC=YES" > /dev/null
|
xcodebuild -sdk "$IOS_SDK" -target "$IOS_TARGET" -configuration "$CONFIGURATION" build "SYMROOT=$ARC_BUILD_DIR" "CLANG_ENABLE_OBJC_ARC=YES" > /dev/null
|
||||||
|
|
||||||
# Build for OS X in manual memory management mode
|
# Build for OS X in manual memory management mode and for oldest deployment target
|
||||||
|
rm -rf "$MRC_BUILD_DIR"
|
||||||
|
xcodebuild -sdk "$OSX_SDK" -target "$OSX_TARGET" -configuration "$CONFIGURATION" build "SYMROOT=$MRC_BUILD_DIR" "CLANG_ENABLE_OBJC_ARC=NO" "MACOSX_DEPLOYMENT_TARGET=10.7" > /dev/null
|
||||||
|
|
||||||
|
# Build for OS X in manual memory management mode and for default deployment target
|
||||||
rm -rf "$MRC_BUILD_DIR"
|
rm -rf "$MRC_BUILD_DIR"
|
||||||
xcodebuild -sdk "$OSX_SDK" -target "$OSX_TARGET" -configuration "$CONFIGURATION" build "SYMROOT=$MRC_BUILD_DIR" "CLANG_ENABLE_OBJC_ARC=NO" > /dev/null
|
xcodebuild -sdk "$OSX_SDK" -target "$OSX_TARGET" -configuration "$CONFIGURATION" build "SYMROOT=$MRC_BUILD_DIR" "CLANG_ENABLE_OBJC_ARC=NO" > /dev/null
|
||||||
|
|
||||||
# Build for OS X in ARC mode
|
# Build for OS X in ARC mode and for oldest deployment target
|
||||||
|
rm -rf "$ARC_BUILD_DIR"
|
||||||
|
xcodebuild -sdk "$OSX_SDK" -target "$OSX_TARGET" -configuration "$CONFIGURATION" build "SYMROOT=$ARC_BUILD_DIR" "CLANG_ENABLE_OBJC_ARC=YES" "MACOSX_DEPLOYMENT_TARGET=10.7" > /dev/null
|
||||||
|
|
||||||
|
# Build for OS X in ARC mode and for default deployment target
|
||||||
rm -rf "$ARC_BUILD_DIR"
|
rm -rf "$ARC_BUILD_DIR"
|
||||||
xcodebuild -sdk "$OSX_SDK" -target "$OSX_TARGET" -configuration "$CONFIGURATION" build "SYMROOT=$ARC_BUILD_DIR" "CLANG_ENABLE_OBJC_ARC=YES" > /dev/null
|
xcodebuild -sdk "$OSX_SDK" -target "$OSX_TARGET" -configuration "$CONFIGURATION" build "SYMROOT=$ARC_BUILD_DIR" "CLANG_ENABLE_OBJC_ARC=YES" > /dev/null
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user