added support for FreeBSD. Closes #4.

This commit is contained in:
Gregory Pakosz 2016-02-11 13:30:39 +00:00
parent 8ad3792af0
commit 73c56ffacc
3 changed files with 121 additions and 1 deletions

View File

@ -11,6 +11,7 @@ Supported platforms:
- iOS
- Android
- QNX Neutrino
- FreeBSD
Just drop `whereami.h` and `whereami.c` into your build and get started. (see
also [customizing compilation])

View File

@ -24,6 +24,10 @@ ifeq ($(platform),)
override CC := gcc
endif
endif
ifeq ($(__uname_s),freebsd)
override platform := freebsd
override architecture := $(__uname_m)
endif
endif
ifeq ($(architecture),)
override architecture := unknown-architecture
@ -41,13 +45,17 @@ CFLAGS := -O2 -g -Wall -pedantic -Werror -std=c99
CXXFLAGS := -O2 -g -Wall -pedantic -Werror
ifeq ($(platform),linux)
override LDFLAGS := $(LDFLAGS) -ldl
LDFLAGS += -ldl
CFLAGS += -D_XOPEN_SOURCE=500 -fpic
CXXFLAGS += -fpic
endif
ifeq ($(platform),mac)
CFLAGS += -D_DARWIN_C_SOURCE
endif
ifeq ($(platform),freebsd)
CFLAGS += -fpic
CXXFLAGS += -fpic
endif
ifeq ($(platform),mac)
libsuffix := .dylib
@ -58,6 +66,9 @@ endif
ifeq ($(platform),windows)
libsuffix := .dll
endif
ifeq ($(platform),freebsd)
libsuffix := .so
endif
.PHONY: build-executable
build: build-executable

View File

@ -545,6 +545,114 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
return length;
}
#elif defined(__FreeBSD__)
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <dlfcn.h>
WAI_FUNCSPEC
int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
{
char buffer1[PATH_MAX];
char buffer2[PATH_MAX];
char* path = buffer1;
char* resolved = NULL;
int length = -1;
for (;;)
{
int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
size_t size = sizeof(buffer1);
if (sysctl(mib, (u_int)(sizeof(mib) / sizeof(mib[0])), path, &size, NULL, 0) != 0)
break;
resolved = realpath(path, buffer2);
if (!resolved)
break;
length = (int)strlen(resolved);
if (length <= capacity)
{
memcpy(out, resolved, length);
if (dirname_length)
{
int i;
for (i = length - 1; i >= 0; --i)
{
if (out[i] == '/')
{
*dirname_length = i;
break;
}
}
}
}
break;
}
if (path != buffer1)
WAI_FREE(path);
return length;
}
WAI_NOINLINE
WAI_FUNCSPEC
int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
{
char buffer[PATH_MAX];
char* resolved = NULL;
int length = -1;
for(;;)
{
Dl_info info;
if (dladdr(WAI_RETURN_ADDRESS(), &info))
{
resolved = realpath(info.dli_fname, buffer);
if (!resolved)
break;
length = (int)strlen(resolved);
if (length <= capacity)
{
memcpy(out, resolved, length);
if (dirname_length)
{
int i;
for (i = length - 1; i >= 0; --i)
{
if (out[i] == '/')
{
*dirname_length = i;
break;
}
}
}
}
}
break;
}
return length;
}
#else
#error unsupported platform
#endif
#ifdef __cplusplus