Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/run-tests-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:

strategy:
matrix:
compiler: [gcc, clang]
compiler: [clang]

steps:
- name: Checkout code with submodules
Expand All @@ -33,6 +33,7 @@ jobs:
"04-raylib-build"
"05-samurai-source-code"
"06-lua-source-code"
"07-raylib-source-code"
)

for test in "${tests[@]}"; do
Expand Down
109 changes: 109 additions & 0 deletions mate.h
Original file line number Diff line number Diff line change
Expand Up @@ -2377,6 +2377,8 @@ typedef struct {
OptimizationFlag optimization;
} StaticLibOptions;

typedef enum { none = 0, needed, weak } LinkFrameworkOptions;

typedef StringBuilder FlagBuilder;

/* --- Build System --- */
Expand Down Expand Up @@ -2422,6 +2424,31 @@ static void mateAddLibraryPaths(String *targetLibs, StringVector *libs);
} while (0)
static void mateLinkSystemLibraries(String *targetLibs, StringVector *libs);


#define LinkFrameworks(target, ...) \
do { \
StringVector _frameworks = {0}; \
StringVectorPushMany(_frameworks, __VA_ARGS__); \
/* Frameworks are just specialized library bundles. */ \
mateLinkFrameworks(&(target).libs, &_frameworks); \
\
/* Cleanup */ \
VecFree(_frameworks); \
} while (0)
static void mateLinkFrameworks(String *targetLibs, StringVector *frameworks);

#define LinkFrameworksWithOptions(target, options, ...) \
do { \
StringVector _frameworks = {0}; \
StringVectorPushMany(_frameworks, __VA_ARGS__); \
/* Frameworks are just specialized library bundles. */ \
mateLinkFrameworksWithOptions(&(target).libs, options, &_frameworks); \
\
/* Cleanup */ \
VecFree(_frameworks); \
} while (0)
static void mateLinkFrameworksWithOptions(String *targetLibs, LinkFrameworkOptions options, StringVector *frameworks);

#define AddIncludePaths(target, ...) \
do { \
StringVector _includes = {0}; \
Expand All @@ -2433,6 +2460,18 @@ static void mateLinkSystemLibraries(String *targetLibs, StringVector *libs);
} while (0)
static void mateAddIncludePaths(String *targetIncludes, StringVector *vector);

#define AddFrameworkPaths(target, ...) \
do { \
StringVector _frameworks = {0}; \
StringVectorPushMany(_frameworks, __VA_ARGS__); \
/* Frameworks are just specialized library bundles. */ \
mateAddFrameworkPaths(&(target).includes, &_frameworks); \
\
/* Cleanup */ \
VecFree(_frameworks); \
} while (0)
static void mateAddFrameworkPaths(String *targetIncludes, StringVector *includes);

#define AddFile(target, source) mateAddFile(&(target).sources, s(source));
static void mateAddFile(StringVector *sources, String source);

Expand Down Expand Up @@ -6517,6 +6556,51 @@ static void mateLinkSystemLibraries(String *targetLibs, StringVector *libs) {
*targetLibs = builder.buffer;
}

static void mateLinkFrameworks(String *targetLibs, StringVector *frameworks) {
mateLinkFrameworksWithOptions(targetLibs, none, frameworks);
}

static void mateLinkFrameworksWithOptions(String *targetLibs, LinkFrameworkOptions options, StringVector *frameworks) {
Assert(!isGCC(),
"LinkFrameworks: Automatic framework linking is not supported by GCC. "
"Use standard linking functions after adding a framework path instead.");
Assert(isClang(), "LinkFrameworks: This function is only supported for Clang.");

char *frameworkFlag = NULL;
switch (options) {
case none:
frameworkFlag = "-framework";
break;
case needed:
frameworkFlag = "-needed_framework";
break;
case weak:
frameworkFlag = "-weak_framework";
break;
default:
Assert(0, "LinkFrameworks: Invalid framework linking option provided.");
}

StringBuilder builder = StringBuilderCreate(mateState.arena);

if (targetLibs->length) {
StringBuilderAppend(mateState.arena, &builder, targetLibs);
}

for (size_t i = 0; i < frameworks->length; i++) {
String currFW = VecAt((*frameworks), i);
if (i == 0 && builder.buffer.length == 0) {
String buffer = F(mateState.arena, "%s %s", frameworkFlag, currFW.data);
StringBuilderAppend(mateState.arena, &builder, &buffer);
continue;
}
String buffer = F(mateState.arena, " %s %s", frameworkFlag, currFW.data);
StringBuilderAppend(mateState.arena, &builder, &buffer);
}

*targetLibs = builder.buffer;
}

static void mateAddIncludePaths(String *targetIncludes, StringVector *includes) {
StringBuilder builder = StringBuilderCreate(mateState.arena);

Expand Down Expand Up @@ -6554,6 +6638,31 @@ static void mateAddIncludePaths(String *targetIncludes, StringVector *includes)
*targetIncludes = builder.buffer;
}

static void mateAddFrameworkPaths(String *targetIncludes, StringVector *includes) {
Assert(isClang() || isGCC(), "AddFrameworkPaths: This function is only supported for GCC/Clang.");

StringBuilder builder = StringBuilderCreate(mateState.arena);

if (targetIncludes->length) {
StringBuilderAppend(mateState.arena, &builder, targetIncludes);
StringBuilderAppend(mateState.arena, &builder, &S(" "));
}

// GCC/Clang format: -F"path"
for (size_t i = 0; i < includes->length; i++) {
String currInclude = VecAt((*includes), i);
if (i == 0 && builder.buffer.length == 0) {
String buffer = F(mateState.arena, "-F\"%s\"", currInclude.data);
StringBuilderAppend(mateState.arena, &builder, &buffer);
continue;
}
String buffer = F(mateState.arena, " -F\"%s\"", currInclude.data);
StringBuilderAppend(mateState.arena, &builder, &buffer);
}

*targetIncludes = builder.buffer;
}

void EndBuild(void) {
LogInfo("Build took: " FMT_I64 "ms", mateState.totalTime);
ArenaFree(mateState.arena);
Expand Down
2 changes: 1 addition & 1 deletion scripts/run-tests-macos.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ tests=(
"04-raylib-build"
"05-samurai-source-code"
"06-lua-source-code"
# "07-raylib-source-code" # Requires framework linking on macOS, which isnt implemented yet
"07-raylib-source-code"
)

echo "NOTE: Skipping 07-raylib-source-code test due to missing framework linking support"
Expand Down
70 changes: 70 additions & 0 deletions src/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -1104,6 +1104,51 @@ static void mateLinkSystemLibraries(String *targetLibs, StringVector *libs) {
*targetLibs = builder.buffer;
}

static void mateLinkFrameworks(String *targetLibs, StringVector *frameworks) {
mateLinkFrameworksWithOptions(targetLibs, none, frameworks);
}

static void mateLinkFrameworksWithOptions(String *targetLibs, LinkFrameworkOptions options, StringVector *frameworks) {
Assert(!isGCC(),
"LinkFrameworks: Automatic framework linking is not supported by GCC. "
"Use standard linking functions after adding a framework path instead.");
Assert(isClang(), "LinkFrameworks: This function is only supported for Clang.");

char *frameworkFlag = NULL;
switch (options) {
case none:
frameworkFlag = "-framework";
break;
case needed:
frameworkFlag = "-needed_framework";
break;
case weak:
frameworkFlag = "-weak_framework";
break;
default:
Assert(0, "LinkFrameworks: Invalid framework linking option provided.");
}

StringBuilder builder = StringBuilderCreate(mateState.arena);

if (targetLibs->length) {
StringBuilderAppend(mateState.arena, &builder, targetLibs);
}

for (size_t i = 0; i < frameworks->length; i++) {
String currFW = VecAt((*frameworks), i);
if (i == 0 && builder.buffer.length == 0) {
String buffer = F(mateState.arena, "%s %s", frameworkFlag, currFW.data);
StringBuilderAppend(mateState.arena, &builder, &buffer);
continue;
}
String buffer = F(mateState.arena, " %s %s", frameworkFlag, currFW.data);
StringBuilderAppend(mateState.arena, &builder, &buffer);
}

*targetLibs = builder.buffer;
}

static void mateAddIncludePaths(String *targetIncludes, StringVector *includes) {
StringBuilder builder = StringBuilderCreate(mateState.arena);

Expand Down Expand Up @@ -1141,6 +1186,31 @@ static void mateAddIncludePaths(String *targetIncludes, StringVector *includes)
*targetIncludes = builder.buffer;
}

static void mateAddFrameworkPaths(String *targetIncludes, StringVector *includes) {
Assert(isClang() || isGCC(), "AddFrameworkPaths: This function is only supported for GCC/Clang.");

StringBuilder builder = StringBuilderCreate(mateState.arena);

if (targetIncludes->length) {
StringBuilderAppend(mateState.arena, &builder, targetIncludes);
StringBuilderAppend(mateState.arena, &builder, &S(" "));
}

// GCC/Clang format: -F"path"
for (size_t i = 0; i < includes->length; i++) {
String currInclude = VecAt((*includes), i);
if (i == 0 && builder.buffer.length == 0) {
String buffer = F(mateState.arena, "-F\"%s\"", currInclude.data);
StringBuilderAppend(mateState.arena, &builder, &buffer);
continue;
}
String buffer = F(mateState.arena, " -F\"%s\"", currInclude.data);
StringBuilderAppend(mateState.arena, &builder, &buffer);
}

*targetIncludes = builder.buffer;
}

void EndBuild(void) {
LogInfo("Build took: " FMT_I64 "ms", mateState.totalTime);
ArenaFree(mateState.arena);
Expand Down
39 changes: 39 additions & 0 deletions src/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ typedef struct {
OptimizationFlag optimization;
} StaticLibOptions;

typedef enum { none = 0, needed, weak } LinkFrameworkOptions;

typedef StringBuilder FlagBuilder;

/* --- Build System --- */
Expand Down Expand Up @@ -185,6 +187,31 @@ static void mateAddLibraryPaths(String *targetLibs, StringVector *libs);
} while (0)
static void mateLinkSystemLibraries(String *targetLibs, StringVector *libs);


#define LinkFrameworks(target, ...) \
do { \
StringVector _frameworks = {0}; \
StringVectorPushMany(_frameworks, __VA_ARGS__); \
/* Frameworks are just specialized library bundles. */ \
mateLinkFrameworks(&(target).libs, &_frameworks); \
\
/* Cleanup */ \
VecFree(_frameworks); \
} while (0)
static void mateLinkFrameworks(String *targetLibs, StringVector *frameworks);

#define LinkFrameworksWithOptions(target, options, ...) \
do { \
StringVector _frameworks = {0}; \
StringVectorPushMany(_frameworks, __VA_ARGS__); \
/* Frameworks are just specialized library bundles. */ \
mateLinkFrameworksWithOptions(&(target).libs, options, &_frameworks); \
\
/* Cleanup */ \
VecFree(_frameworks); \
} while (0)
static void mateLinkFrameworksWithOptions(String *targetLibs, LinkFrameworkOptions options, StringVector *frameworks);

#define AddIncludePaths(target, ...) \
do { \
StringVector _includes = {0}; \
Expand All @@ -196,6 +223,18 @@ static void mateLinkSystemLibraries(String *targetLibs, StringVector *libs);
} while (0)
static void mateAddIncludePaths(String *targetIncludes, StringVector *vector);

#define AddFrameworkPaths(target, ...) \
do { \
StringVector _frameworks = {0}; \
StringVectorPushMany(_frameworks, __VA_ARGS__); \
/* Frameworks are just specialized library bundles. */ \
mateAddFrameworkPaths(&(target).includes, &_frameworks); \
\
/* Cleanup */ \
VecFree(_frameworks); \
} while (0)
static void mateAddFrameworkPaths(String *targetIncludes, StringVector *includes);

#define AddFile(target, source) mateAddFile(&(target).sources, s(source));
static void mateAddFile(StringVector *sources, String source);

Expand Down
23 changes: 21 additions & 2 deletions tests/07-raylib-source-code/mate.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ static char *GetCFlags(void) {
if (isLinux()) {
FlagBuilderAdd(&flagsBuilder, "DPLATFORM_DESKTOP_GLFW", "D_GLFW_X11");
}

if (isMacOs()) {
FlagBuilderAdd(&flagsBuilder, "DPLATFORM_DESKTOP_GLFW", "D_GL_SILENCE_DEPRECATION=1");
// Required due to raylib's use of Objective-C types on macOS.
FlagBuilderAdd(&flagsBuilder, "x objective-c");
}
if (isWindows()) {
FlagBuilderAdd(&flagsBuilder, "DPLATFORM_DESKTOP_GLFW");
}
Expand All @@ -27,7 +31,10 @@ i32 main(void) {
StartBuild();
{
{ // Compile static lib
StaticLib staticLib = CreateStaticLib((StaticLibOptions){.output = "libraylib", .flags = GetCFlags()});
StaticLib staticLib = CreateStaticLib((StaticLibOptions){
.output = "libraylib",
.flags = GetCFlags(),
});

AddFile(staticLib, "./src/rcore.c");
AddFile(staticLib, "./src/utils.c");
Expand All @@ -45,6 +52,12 @@ i32 main(void) {
if (isLinux()) {
LinkSystemLibraries(staticLib, "GL", "rt", "dl", "m", "X11", "Xcursor", "Xext", "Xfixes", "Xi", "Xinerama", "Xrandr", "Xrender");
}
if (isMacOs()) {
// Link regular system libraries.
LinkSystemLibraries(staticLib, "m");
// Link macOS system frameworks.
LinkFrameworks(staticLib, "Foundation", "AppKit", "IOKit", "OpenGL", "CoreVideo");
}
if (isWindows()) {
LinkSystemLibraries(staticLib, "winmm", "gdi32", "opengl32");
}
Expand All @@ -67,6 +80,12 @@ i32 main(void) {
if (isLinux()) {
LinkSystemLibraries(executable, "raylib", "GL", "rt", "dl", "m", "X11");
}
if (isMacOs()) {
// Link regular system libraries.
LinkSystemLibraries(executable, "raylib", "m");
// Link macOS system frameworks.
LinkFrameworks(executable, "CoreVideo", "IOKit", "Cocoa", "GLUT", "OpenGL");
}
if (isWindows()) {
LinkSystemLibraries(executable, "raylib", "winmm", "gdi32", "opengl32");
}
Expand Down