darwin: remove CoreFoundation dependency
Load the required symbols at run-time rather than linking against the CoreFoundation (and CoreServices and ApplicationServices) frameworks at build time. Should make integration easier for people that bundle libuv with their own projects because they no longer have to replicate magic -framework incantations in their top-level build system.
This commit is contained in:
parent
12933f43c9
commit
d48168afd0
@ -197,9 +197,6 @@ libuv_la_SOURCES += src/unix/darwin.c \
|
||||
src/unix/fsevents.c \
|
||||
src/unix/kqueue.c \
|
||||
src/unix/proctitle.c
|
||||
libuv_la_LDFLAGS += -framework ApplicationServices \
|
||||
-framework CoreServices \
|
||||
-framework Foundation
|
||||
endif
|
||||
|
||||
if FREEBSD
|
||||
|
||||
@ -55,62 +55,111 @@ int uv__set_process_title(const char* title) {
|
||||
#if TARGET_OS_IPHONE
|
||||
return uv__pthread_setname_np(title);
|
||||
#else
|
||||
typedef CFTypeRef (*LSGetCurrentApplicationASNType)(void);
|
||||
typedef OSStatus (*LSSetApplicationInformationItemType)(int,
|
||||
CFTypeRef,
|
||||
CFStringRef,
|
||||
CFStringRef,
|
||||
CFDictionaryRef*);
|
||||
CFStringRef (*pCFStringCreateWithCString)(CFAllocatorRef,
|
||||
const char*,
|
||||
CFStringEncoding);
|
||||
CFBundleRef (*pCFBundleGetBundleWithIdentifier)(CFStringRef);
|
||||
void *(*pCFBundleGetDataPointerForName)(CFBundleRef, CFStringRef);
|
||||
void *(*pCFBundleGetFunctionPointerForName)(CFBundleRef, CFStringRef);
|
||||
OSErr (*pGetCurrentProcess)(ProcessSerialNumber*);
|
||||
CFTypeRef (*pLSGetCurrentApplicationASN)(void);
|
||||
OSStatus (*pLSSetApplicationInformationItem)(int,
|
||||
CFTypeRef,
|
||||
CFStringRef,
|
||||
CFStringRef,
|
||||
CFDictionaryRef*);
|
||||
void* application_services_handle;
|
||||
void* core_foundation_handle;
|
||||
CFBundleRef launch_services_bundle;
|
||||
LSGetCurrentApplicationASNType ls_get_current_application_asn;
|
||||
LSSetApplicationInformationItemType ls_set_application_information_item;
|
||||
CFStringRef* display_name_key;
|
||||
ProcessSerialNumber psn;
|
||||
CFTypeRef asn;
|
||||
CFStringRef display_name;
|
||||
OSStatus err;
|
||||
int err;
|
||||
|
||||
err = -ENOENT;
|
||||
application_services_handle = dlopen("/System/Library/Frameworks/"
|
||||
"ApplicationServices.framework/"
|
||||
"Versions/A/ApplicationServices",
|
||||
RTLD_LAZY | RTLD_LOCAL);
|
||||
core_foundation_handle = dlopen("/System/Library/Frameworks/"
|
||||
"CoreFoundation.framework/"
|
||||
"Versions/A/CoreFoundation",
|
||||
RTLD_LAZY | RTLD_LOCAL);
|
||||
|
||||
if (application_services_handle == NULL || core_foundation_handle == NULL)
|
||||
goto out;
|
||||
|
||||
pGetCurrentProcess =
|
||||
dlsym(application_services_handle, "GetCurrentProcess");
|
||||
pCFStringCreateWithCString =
|
||||
dlsym(core_foundation_handle, "CFStringCreateWithCString");
|
||||
pCFBundleGetBundleWithIdentifier =
|
||||
dlsym(core_foundation_handle, "CFBundleGetBundleWithIdentifier");
|
||||
pCFBundleGetDataPointerForName =
|
||||
dlsym(core_foundation_handle, "CFBundleGetDataPointerForName");
|
||||
pCFBundleGetFunctionPointerForName =
|
||||
dlsym(core_foundation_handle, "CFBundleGetFunctionPointerForName");
|
||||
|
||||
if (pGetCurrentProcess == NULL ||
|
||||
pCFStringCreateWithCString == NULL ||
|
||||
pCFBundleGetBundleWithIdentifier == NULL ||
|
||||
pCFBundleGetDataPointerForName == NULL ||
|
||||
pCFBundleGetFunctionPointerForName == NULL) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
#define S(s) pCFStringCreateWithCString(NULL, (s), kCFStringEncodingUTF8)
|
||||
|
||||
launch_services_bundle =
|
||||
CFBundleGetBundleWithIdentifier(CFSTR("com.apple.LaunchServices"));
|
||||
pCFBundleGetBundleWithIdentifier(S("com.apple.LaunchServices"));
|
||||
|
||||
if (launch_services_bundle == NULL)
|
||||
return -ENOENT;
|
||||
goto out;
|
||||
|
||||
ls_get_current_application_asn = (LSGetCurrentApplicationASNType)
|
||||
CFBundleGetFunctionPointerForName(launch_services_bundle,
|
||||
CFSTR("_LSGetCurrentApplicationASN"));
|
||||
pLSGetCurrentApplicationASN =
|
||||
pCFBundleGetFunctionPointerForName(launch_services_bundle,
|
||||
S("_LSGetCurrentApplicationASN"));
|
||||
|
||||
if (ls_get_current_application_asn == NULL)
|
||||
return -ENOENT;
|
||||
if (pLSGetCurrentApplicationASN == NULL)
|
||||
goto out;
|
||||
|
||||
ls_set_application_information_item = (LSSetApplicationInformationItemType)
|
||||
CFBundleGetFunctionPointerForName(launch_services_bundle,
|
||||
CFSTR("_LSSetApplicationInformationItem"));
|
||||
pLSSetApplicationInformationItem =
|
||||
pCFBundleGetFunctionPointerForName(launch_services_bundle,
|
||||
S("_LSSetApplicationInformationItem"));
|
||||
|
||||
if (ls_set_application_information_item == NULL)
|
||||
return -ENOENT;
|
||||
if (pLSSetApplicationInformationItem == NULL)
|
||||
goto out;
|
||||
|
||||
display_name_key = CFBundleGetDataPointerForName(launch_services_bundle,
|
||||
CFSTR("_kLSDisplayNameKey"));
|
||||
display_name_key = pCFBundleGetDataPointerForName(launch_services_bundle,
|
||||
S("_kLSDisplayNameKey"));
|
||||
|
||||
if (display_name_key == NULL || *display_name_key == NULL)
|
||||
return -ENOENT;
|
||||
goto out;
|
||||
|
||||
/* Force the process manager to initialize. */
|
||||
GetCurrentProcess(&psn);
|
||||
pGetCurrentProcess(&psn);
|
||||
|
||||
display_name = CFStringCreateWithCString(NULL, title, kCFStringEncodingUTF8);
|
||||
asn = ls_get_current_application_asn();
|
||||
err = ls_set_application_information_item(-2, /* Magic value. */
|
||||
asn,
|
||||
*display_name_key,
|
||||
display_name,
|
||||
NULL);
|
||||
if (err != noErr)
|
||||
return -ENOENT;
|
||||
asn = pLSGetCurrentApplicationASN();
|
||||
|
||||
err = -EINVAL;
|
||||
if (pLSSetApplicationInformationItem(-2, /* Magic value. */
|
||||
asn,
|
||||
*display_name_key,
|
||||
S(title),
|
||||
NULL) != noErr) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
uv__pthread_setname_np(title); /* Don't care if it fails. */
|
||||
err = 0;
|
||||
|
||||
return 0;
|
||||
out:
|
||||
if (core_foundation_handle != NULL)
|
||||
dlclose(core_foundation_handle);
|
||||
|
||||
if (application_services_handle != NULL)
|
||||
dlclose(application_services_handle);
|
||||
|
||||
return err;
|
||||
#endif /* !TARGET_OS_IPHONE */
|
||||
}
|
||||
|
||||
@ -40,6 +40,7 @@ void uv__fsevents_loop_delete(uv_loop_t* loop) {
|
||||
|
||||
#else /* TARGET_OS_IPHONE */
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
@ -94,6 +95,47 @@ static void uv__cf_loop_cb(void* arg);
|
||||
static void* uv__cf_loop_runner(void* arg);
|
||||
static int uv__cf_loop_signal(uv_loop_t* loop, uv_fs_event_t* handle);
|
||||
|
||||
/* Lazy-loaded by uv__fsevents_global_init(). */
|
||||
static CFArrayRef (*pCFArrayCreate)(CFAllocatorRef,
|
||||
const void**,
|
||||
CFIndex,
|
||||
const CFArrayCallBacks*);
|
||||
static void (*pCFRelease)(CFTypeRef);
|
||||
static void (*pCFRunLoopAddSource)(CFRunLoopRef,
|
||||
CFRunLoopSourceRef,
|
||||
CFStringRef);
|
||||
static CFRunLoopRef (*pCFRunLoopGetCurrent)(void);
|
||||
static void (*pCFRunLoopRemoveSource)(CFRunLoopRef,
|
||||
CFRunLoopSourceRef,
|
||||
CFStringRef);
|
||||
static void (*pCFRunLoopRun)(void);
|
||||
static CFRunLoopSourceRef (*pCFRunLoopSourceCreate)(CFAllocatorRef,
|
||||
CFIndex,
|
||||
CFRunLoopSourceContext*);
|
||||
static void (*pCFRunLoopSourceSignal)(CFRunLoopSourceRef);
|
||||
static void (*pCFRunLoopStop)(CFRunLoopRef);
|
||||
static void (*pCFRunLoopWakeUp)(CFRunLoopRef);
|
||||
static CFStringRef (*pCFStringCreateWithCString)(CFAllocatorRef,
|
||||
const char*,
|
||||
CFStringEncoding);
|
||||
static CFStringEncoding (*pCFStringGetSystemEncoding)(void);
|
||||
static CFStringRef (*pkCFRunLoopDefaultMode);
|
||||
static FSEventStreamRef (*pFSEventStreamCreate)(CFAllocatorRef,
|
||||
FSEventStreamCallback,
|
||||
FSEventStreamContext*,
|
||||
CFArrayRef,
|
||||
FSEventStreamEventId,
|
||||
CFTimeInterval,
|
||||
FSEventStreamCreateFlags);
|
||||
static void (*pFSEventStreamFlushSync)(FSEventStreamRef);
|
||||
static void (*pFSEventStreamInvalidate)(FSEventStreamRef);
|
||||
static void (*pFSEventStreamRelease)(FSEventStreamRef);
|
||||
static void (*pFSEventStreamScheduleWithRunLoop)(FSEventStreamRef,
|
||||
CFRunLoopRef,
|
||||
CFStringRef);
|
||||
static Boolean (*pFSEventStreamStart)(FSEventStreamRef);
|
||||
static void (*pFSEventStreamStop)(FSEventStreamRef);
|
||||
|
||||
#define UV__FSEVENTS_PROCESS(handle, block) \
|
||||
do { \
|
||||
uv__fsevents_event_t* event; \
|
||||
@ -256,20 +298,20 @@ static void uv__fsevents_create_stream(uv_loop_t* loop, CFArrayRef paths) {
|
||||
* that is being watched now. Which will cause FSEventStream API to report
|
||||
* changes to files from the past.
|
||||
*/
|
||||
ref = FSEventStreamCreate(NULL,
|
||||
&uv__fsevents_event_cb,
|
||||
&ctx,
|
||||
paths,
|
||||
kFSEventStreamEventIdSinceNow,
|
||||
latency,
|
||||
flags);
|
||||
ref = pFSEventStreamCreate(NULL,
|
||||
&uv__fsevents_event_cb,
|
||||
&ctx,
|
||||
paths,
|
||||
kFSEventStreamEventIdSinceNow,
|
||||
latency,
|
||||
flags);
|
||||
assert(ref != NULL);
|
||||
|
||||
state = loop->cf_state;
|
||||
FSEventStreamScheduleWithRunLoop(ref,
|
||||
state->loop,
|
||||
kCFRunLoopDefaultMode);
|
||||
if (!FSEventStreamStart(ref))
|
||||
pFSEventStreamScheduleWithRunLoop(ref,
|
||||
state->loop,
|
||||
*pkCFRunLoopDefaultMode);
|
||||
if (!pFSEventStreamStart(ref))
|
||||
abort();
|
||||
|
||||
state->fsevent_stream = ref;
|
||||
@ -286,14 +328,14 @@ static void uv__fsevents_destroy_stream(uv_loop_t* loop) {
|
||||
return;
|
||||
|
||||
/* Flush all accumulated events */
|
||||
FSEventStreamFlushSync(state->fsevent_stream);
|
||||
pFSEventStreamFlushSync(state->fsevent_stream);
|
||||
|
||||
/* Stop emitting events */
|
||||
FSEventStreamStop(state->fsevent_stream);
|
||||
pFSEventStreamStop(state->fsevent_stream);
|
||||
|
||||
/* Release stream */
|
||||
FSEventStreamInvalidate(state->fsevent_stream);
|
||||
FSEventStreamRelease(state->fsevent_stream);
|
||||
pFSEventStreamInvalidate(state->fsevent_stream);
|
||||
pFSEventStreamRelease(state->fsevent_stream);
|
||||
state->fsevent_stream = NULL;
|
||||
}
|
||||
|
||||
@ -335,9 +377,9 @@ static void uv__fsevents_reschedule(uv_fs_event_t* handle) {
|
||||
curr = QUEUE_DATA(q, uv_fs_event_t, cf_member);
|
||||
|
||||
assert(curr->realpath != NULL);
|
||||
paths[i] = CFStringCreateWithCString(NULL,
|
||||
curr->realpath,
|
||||
CFStringGetSystemEncoding());
|
||||
paths[i] = pCFStringCreateWithCString(NULL,
|
||||
curr->realpath,
|
||||
pCFStringGetSystemEncoding());
|
||||
if (paths[i] == NULL)
|
||||
abort();
|
||||
}
|
||||
@ -346,7 +388,7 @@ static void uv__fsevents_reschedule(uv_fs_event_t* handle) {
|
||||
|
||||
if (path_count != 0) {
|
||||
/* Create new FSEventStream */
|
||||
cf_paths = CFArrayCreate(NULL, (const void**) paths, path_count, NULL);
|
||||
cf_paths = pCFArrayCreate(NULL, (const void**) paths, path_count, NULL);
|
||||
if (cf_paths == NULL)
|
||||
abort();
|
||||
uv__fsevents_create_stream(handle->loop, cf_paths);
|
||||
@ -363,6 +405,84 @@ static void uv__fsevents_reschedule(uv_fs_event_t* handle) {
|
||||
}
|
||||
|
||||
|
||||
static int uv__fsevents_global_init(void) {
|
||||
static pthread_mutex_t global_init_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static void* core_foundation_handle;
|
||||
static void* core_services_handle;
|
||||
int err;
|
||||
|
||||
err = 0;
|
||||
pthread_mutex_lock(&global_init_mutex);
|
||||
if (core_foundation_handle != NULL)
|
||||
goto out;
|
||||
|
||||
/* The libraries are never unloaded because we currently don't have a good
|
||||
* mechanism for keeping a reference count. It's unlikely to be an issue
|
||||
* but if it ever becomes one, we can turn the dynamic library handles into
|
||||
* per-event loop properties and have the dynamic linker keep track for us.
|
||||
*/
|
||||
err = -ENOSYS;
|
||||
core_foundation_handle = dlopen("/System/Library/Frameworks/"
|
||||
"CoreFoundation.framework/"
|
||||
"Versions/A/CoreFoundation",
|
||||
RTLD_LAZY | RTLD_LOCAL);
|
||||
if (core_foundation_handle == NULL)
|
||||
goto out;
|
||||
|
||||
core_services_handle = dlopen("/System/Library/Frameworks/"
|
||||
"CoreServices.framework/"
|
||||
"Versions/A/CoreServices",
|
||||
RTLD_LAZY | RTLD_LOCAL);
|
||||
if (core_services_handle == NULL)
|
||||
goto out;
|
||||
|
||||
err = -ENOENT;
|
||||
#define V(handle, symbol) \
|
||||
do { \
|
||||
p ## symbol = dlsym((handle), #symbol); \
|
||||
if (p ## symbol == NULL) \
|
||||
goto out; \
|
||||
} \
|
||||
while (0)
|
||||
V(core_foundation_handle, CFArrayCreate);
|
||||
V(core_foundation_handle, CFRelease);
|
||||
V(core_foundation_handle, CFRunLoopAddSource);
|
||||
V(core_foundation_handle, CFRunLoopGetCurrent);
|
||||
V(core_foundation_handle, CFRunLoopRemoveSource);
|
||||
V(core_foundation_handle, CFRunLoopRun);
|
||||
V(core_foundation_handle, CFRunLoopSourceCreate);
|
||||
V(core_foundation_handle, CFRunLoopSourceSignal);
|
||||
V(core_foundation_handle, CFRunLoopStop);
|
||||
V(core_foundation_handle, CFRunLoopWakeUp);
|
||||
V(core_foundation_handle, CFStringCreateWithCString);
|
||||
V(core_foundation_handle, CFStringGetSystemEncoding);
|
||||
V(core_foundation_handle, kCFRunLoopDefaultMode);
|
||||
V(core_services_handle, FSEventStreamCreate);
|
||||
V(core_services_handle, FSEventStreamFlushSync);
|
||||
V(core_services_handle, FSEventStreamInvalidate);
|
||||
V(core_services_handle, FSEventStreamRelease);
|
||||
V(core_services_handle, FSEventStreamScheduleWithRunLoop);
|
||||
V(core_services_handle, FSEventStreamStart);
|
||||
V(core_services_handle, FSEventStreamStop);
|
||||
#undef V
|
||||
err = 0;
|
||||
|
||||
out:
|
||||
if (err && core_services_handle != NULL) {
|
||||
dlclose(core_services_handle);
|
||||
core_services_handle = NULL;
|
||||
}
|
||||
|
||||
if (err && core_foundation_handle != NULL) {
|
||||
dlclose(core_foundation_handle);
|
||||
core_foundation_handle = NULL;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&global_init_mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Runs in UV loop */
|
||||
static int uv__fsevents_loop_init(uv_loop_t* loop) {
|
||||
CFRunLoopSourceContext ctx;
|
||||
@ -374,6 +494,10 @@ static int uv__fsevents_loop_init(uv_loop_t* loop) {
|
||||
if (loop->cf_state != NULL)
|
||||
return 0;
|
||||
|
||||
err = uv__fsevents_global_init();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
state = calloc(1, sizeof(*state));
|
||||
if (state == NULL)
|
||||
return -ENOMEM;
|
||||
@ -403,7 +527,7 @@ static int uv__fsevents_loop_init(uv_loop_t* loop) {
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
ctx.info = loop;
|
||||
ctx.perform = uv__cf_loop_cb;
|
||||
state->signal_source = CFRunLoopSourceCreate(NULL, 0, &ctx);
|
||||
state->signal_source = pCFRunLoopSourceCreate(NULL, 0, &ctx);
|
||||
if (state->signal_source == NULL) {
|
||||
err = -ENOMEM;
|
||||
goto fail_signal_source_create;
|
||||
@ -483,7 +607,7 @@ void uv__fsevents_loop_delete(uv_loop_t* loop) {
|
||||
state = loop->cf_state;
|
||||
uv_sem_destroy(&state->fsevent_sem);
|
||||
uv_mutex_destroy(&state->fsevent_mutex);
|
||||
CFRelease(state->signal_source);
|
||||
pCFRelease(state->signal_source);
|
||||
free(state);
|
||||
loop->cf_state = NULL;
|
||||
}
|
||||
@ -496,18 +620,18 @@ static void* uv__cf_loop_runner(void* arg) {
|
||||
|
||||
loop = arg;
|
||||
state = loop->cf_state;
|
||||
state->loop = CFRunLoopGetCurrent();
|
||||
state->loop = pCFRunLoopGetCurrent();
|
||||
|
||||
CFRunLoopAddSource(state->loop,
|
||||
state->signal_source,
|
||||
kCFRunLoopDefaultMode);
|
||||
pCFRunLoopAddSource(state->loop,
|
||||
state->signal_source,
|
||||
*pkCFRunLoopDefaultMode);
|
||||
|
||||
uv_sem_post(&loop->cf_sem);
|
||||
|
||||
CFRunLoopRun();
|
||||
CFRunLoopRemoveSource(state->loop,
|
||||
state->signal_source,
|
||||
kCFRunLoopDefaultMode);
|
||||
pCFRunLoopRun();
|
||||
pCFRunLoopRemoveSource(state->loop,
|
||||
state->signal_source,
|
||||
*pkCFRunLoopDefaultMode);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -539,7 +663,7 @@ static void uv__cf_loop_cb(void* arg) {
|
||||
|
||||
/* This was a termination signal */
|
||||
if (s->handle == NULL)
|
||||
CFRunLoopStop(state->loop);
|
||||
pCFRunLoopStop(state->loop);
|
||||
else
|
||||
uv__fsevents_reschedule(s->handle);
|
||||
|
||||
@ -566,8 +690,8 @@ int uv__cf_loop_signal(uv_loop_t* loop, uv_fs_event_t* handle) {
|
||||
|
||||
state = loop->cf_state;
|
||||
assert(state != NULL);
|
||||
CFRunLoopSourceSignal(state->signal_source);
|
||||
CFRunLoopWakeUp(state->loop);
|
||||
pCFRunLoopSourceSignal(state->signal_source);
|
||||
pCFRunLoopWakeUp(state->loop);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
7
uv.gyp
7
uv.gyp
@ -186,13 +186,6 @@
|
||||
'src/unix/fsevents.c',
|
||||
'src/unix/darwin-proctitle.c',
|
||||
],
|
||||
'link_settings': {
|
||||
'libraries': [
|
||||
'$(SDKROOT)/System/Library/Frameworks/Foundation.framework',
|
||||
'$(SDKROOT)/System/Library/Frameworks/CoreServices.framework',
|
||||
'$(SDKROOT)/System/Library/Frameworks/ApplicationServices.framework',
|
||||
],
|
||||
},
|
||||
'defines': [
|
||||
'_DARWIN_USE_64_BIT_INODE=1',
|
||||
]
|
||||
|
||||
Loading…
Reference in New Issue
Block a user