Browse Source

Added MacOS frameworks as a feature in the build system.

David Piuva 8 months ago
parent
commit
3a2444c5c8

+ 6 - 10
Source/DFPSR/DFPSR.DsrHead

@@ -1,4 +1,4 @@
-# A project header for using the DFPSR library.
+# A project header for using the DFPSR library.
 #   Backends:
 #   Backends:
 #     * Give the Graphics flag if the application should be able to create a window.
 #     * Give the Graphics flag if the application should be able to create a window.
 #     * Give the Sound flag if the application should be able to generate sounds.
 #     * Give the Sound flag if the application should be able to generate sounds.
@@ -32,7 +32,7 @@ Link "pthread"
 #   so we use .. to leave the Source/DFPSR folder and then go into the windowManagers folder.
 #   so we use .. to leave the Source/DFPSR folder and then go into the windowManagers folder.
 WindowManager = "../windowManagers/NoWindow.cpp"
 WindowManager = "../windowManagers/NoWindow.cpp"
 if Graphics
 if Graphics
-	Message "Building with graphics enabled"
+	Message "Building with graphics enabled\n"
 	if Linux
 	if Linux
 		Message "  Using X11\n"
 		Message "  Using X11\n"
 		Link "X11"
 		Link "X11"
@@ -57,20 +57,16 @@ Crawl WindowManager
 
 
 SoundManager = "../soundManagers/NoSound.cpp"
 SoundManager = "../soundManagers/NoSound.cpp"
 if Sound
 if Sound
-	Message "Building with sound enabled"
+	Message "Building with sound enabled\n"
 	if Linux
 	if Linux
 		Message "  Using Alsa\n"
 		Message "  Using Alsa\n"
 		Link "asound"
 		Link "asound"
 		SoundManager = "../soundManagers/AlsaSound.cpp"
 		SoundManager = "../soundManagers/AlsaSound.cpp"
 	end if
 	end if
 	if MacOS
 	if MacOS
-		Message "  Using CoreAudio\n"
-		# -framework and CoreAudio must be sent as individual arguments to Clang.
-		#TODO: Modify the build system to allow sending multiple arguments as groups to the compiler.
-		#LinkerFlag "-framework"
-		#  LinkerFlag "CoreAudio"
-		LinkerFlag "-framework"
-		  LinkerFlag "AudioUnit"
+		Message "  Using CoreAudio\n"
+		#Linking to AudioUnit, which is a part of CoreAudio.
+		Framework "AudioUnit"
 		SoundManager = "../soundManagers/CoreAudioSound.cpp"
 		SoundManager = "../soundManagers/CoreAudioSound.cpp"
 	end if
 	end if
 	if Windows
 	if Windows

+ 25 - 8
Source/tools/builder/code/Machine.cpp

@@ -42,6 +42,9 @@ void printSettings(const Machine &settings) {
 	for (int64_t i = 0; i < settings.linkerFlags.length(); i++) {
 	for (int64_t i = 0; i < settings.linkerFlags.length(); i++) {
 		printText(U"    Linker flag ", settings.linkerFlags[i], U"\n");
 		printText(U"    Linker flag ", settings.linkerFlags[i], U"\n");
 	}
 	}
+	for (int64_t i = 0; i < settings.frameworks.length(); i++) {
+		printText(U"    Framework ", settings.frameworks[i], U"\n");
+	}
 	for (int64_t i = 0; i < settings.variables.length(); i++) {
 	for (int64_t i = 0; i < settings.variables.length(); i++) {
 		printText(U"    Variable ", settings.variables[i].key, U" = ", settings.variables[i].value, U"\n");
 		printText(U"    Variable ", settings.variables[i].key, U" = ", settings.variables[i].value, U"\n");
 	}
 	}
@@ -58,6 +61,11 @@ void validateSettings(const Machine &settings, const dsr::ReadableString &eventD
 		printSettings(settings);
 		printSettings(settings);
 		throwError(U"Found duplicate linker flags ", eventDescription, U"!\n");
 		throwError(U"Found duplicate linker flags ", eventDescription, U"!\n");
 	};
 	};
+	if (!isUnique(settings.frameworks)) {
+		printText(U"Duplicate frameworks:\n");
+		printSettings(settings);
+		throwError(U"Found duplicate frameworks ", eventDescription, U"!\n");
+	};
 	if (!isUnique(settings.variables)) {
 	if (!isUnique(settings.variables)) {
 		printText(U"Duplicate variables:\n");
 		printText(U"Duplicate variables:\n");
 		printSettings(settings);
 		printSettings(settings);
@@ -130,14 +138,17 @@ void cloneMachine(Machine &child, const Machine &parent) {
 	for (int64_t v = 0; v < parent.variables.length(); v++) {
 	for (int64_t v = 0; v < parent.variables.length(); v++) {
 		child.variables.push(parent.variables[v]);
 		child.variables.push(parent.variables[v]);
 	}
 	}
-	for (int64_t v = 0; v < parent.compilerFlags.length(); v++) {
-		child.compilerFlags.push(parent.compilerFlags[v]);
+	for (int64_t c = 0; c < parent.compilerFlags.length(); c++) {
+		child.compilerFlags.push(parent.compilerFlags[c]);
 	}
 	}
-	for (int64_t v = 0; v < parent.linkerFlags.length(); v++) {
-		child.linkerFlags.push(parent.linkerFlags[v]);
+	for (int64_t l = 0; l < parent.linkerFlags.length(); l++) {
+		child.linkerFlags.push(parent.linkerFlags[l]);
 	}
 	}
-	for (int64_t v = 0; v < parent.crawlOrigins.length(); v++) {
-		child.crawlOrigins.push(parent.crawlOrigins[v]);
+	for (int64_t f = 0; f < parent.frameworks.length(); f++) {
+		child.linkerFlags.push(parent.frameworks[f]);
+	}
+	for (int64_t o = 0; o < parent.crawlOrigins.length(); o++) {
+		child.crawlOrigins.push(parent.crawlOrigins[o]);
 	}
 	}
 }
 }
 
 
@@ -317,15 +328,21 @@ static void interpretLine(Machine &target, const List<String> &tokens, int64_t s
 				// Only the library name itself is needed, because the -l prefix can be added automatically.
 				// Only the library name itself is needed, because the -l prefix can be added automatically.
 				String libraryName = STRING_EXPR(startTokenIndex + 1, endTokenIndex);
 				String libraryName = STRING_EXPR(startTokenIndex + 1, endTokenIndex);
 				if (libraryName[0] == U'-' && (libraryName[1] == U'l' || libraryName[1] == U'L')) {
 				if (libraryName[0] == U'-' && (libraryName[1] == U'l' || libraryName[1] == U'L')) {
+					// Avoid duplicating -l when it has already been included by accident.
 					target.linkerFlags.push(libraryName);
 					target.linkerFlags.push(libraryName);
 				} else {
 				} else {
+					// Insert the library name after -l when used correctly.
 					target.linkerFlags.push(string_combine(U"-l", libraryName));
 					target.linkerFlags.push(string_combine(U"-l", libraryName));
 				}
 				}
-				validateSettings(target, U"in target after adding a linker flag\n");
+				validateSettings(target, U"in target after adding a library\n");
 			} else if (string_caseInsensitiveMatch(first, U"linkerflag")) {
 			} else if (string_caseInsensitiveMatch(first, U"linkerflag")) {
-				// For linker flags that are not used to
+				// For linker flags that are not used to link with a library.
 				target.linkerFlags.push(STRING_EXPR(startTokenIndex + 1, endTokenIndex));
 				target.linkerFlags.push(STRING_EXPR(startTokenIndex + 1, endTokenIndex));
 				validateSettings(target, U"in target after adding a linker flag\n");
 				validateSettings(target, U"in target after adding a linker flag\n");
+			} else if (string_caseInsensitiveMatch(first, U"framework")) {
+				// For linking with a framework. (MacOS feature in Clang where the name follows a separate -framework argument)
+				target.frameworks.push(STRING_EXPR(startTokenIndex + 1, endTokenIndex));
+				validateSettings(target, U"in target after adding a framework\n");
 			} else if (string_caseInsensitiveMatch(first, U"compilerflag")) {
 			} else if (string_caseInsensitiveMatch(first, U"compilerflag")) {
 				target.compilerFlags.push(STRING_EXPR(startTokenIndex + 1, endTokenIndex));
 				target.compilerFlags.push(STRING_EXPR(startTokenIndex + 1, endTokenIndex));
 				validateSettings(target, U"in target after adding a compiler flag\n");
 				validateSettings(target, U"in target after adding a compiler flag\n");

+ 10 - 4
Source/tools/builder/code/analyzer.cpp

@@ -341,17 +341,23 @@ void gatherBuildInstructions(SessionContext &output, ProjectContext &context, Ma
 	//       This would allow calling the compiler directly when given a folder path for temporary files instead of a script path.
 	//       This would allow calling the compiler directly when given a folder path for temporary files instead of a script path.
 	String generatedCompilerFlags;
 	String generatedCompilerFlags;
 	for (int64_t i = 0; i < settings.compilerFlags.length(); i++) {
 	for (int64_t i = 0; i < settings.compilerFlags.length(); i++) {
-		printText(U"Build script gave compiler flag:", settings.compilerFlags[i], U"\n");
+		printText(U"Build script gave compiler flag: ", settings.compilerFlags[i], U"\n");
 		string_append(generatedCompilerFlags, U" ", settings.compilerFlags[i]);
 		string_append(generatedCompilerFlags, U" ", settings.compilerFlags[i]);
 	}
 	}
 	String linkerFlags;
 	String linkerFlags;
 	for (int64_t i = 0; i < settings.linkerFlags.length(); i++) {
 	for (int64_t i = 0; i < settings.linkerFlags.length(); i++) {
-		printText(U"Build script gave linker flag:", settings.linkerFlags[i], U"\n");
-		string_append(linkerFlags, settings.linkerFlags[i]);
+		printText(U"Build script gave linker flag: ", settings.linkerFlags[i], U"\n");
+		string_append(linkerFlags, U" ", settings.linkerFlags[i]);
+	}
+	String frameworks;
+	for (int64_t i = 0; i < settings.frameworks.length(); i++) {
+		printText(U"Build script gave framework: ", settings.frameworks[i], U"\n");
+		string_append(frameworks, U" ", settings.frameworks[i]);
 	}
 	}
 	printText(U"Generating build instructions for ", programPath, U" using settings:\n");
 	printText(U"Generating build instructions for ", programPath, U" using settings:\n");
 	printText(U"  Compiler flags:", generatedCompilerFlags, U"\n");
 	printText(U"  Compiler flags:", generatedCompilerFlags, U"\n");
 	printText(U"  Linker flags:", linkerFlags, U"\n");
 	printText(U"  Linker flags:", linkerFlags, U"\n");
+	printText(U"  Frameworks:", frameworks, U"\n");
 	for (int64_t v = 0; v < settings.variables.length(); v++) {
 	for (int64_t v = 0; v < settings.variables.length(); v++) {
 		printText(U"  * ", settings.variables[v].key, U" = ", settings.variables[v].value);
 		printText(U"  * ", settings.variables[v].key, U" = ", settings.variables[v].value);
 		if (settings.variables[v].inherited) {
 		if (settings.variables[v].inherited) {
@@ -388,7 +394,7 @@ void gatherBuildInstructions(SessionContext &output, ProjectContext &context, Ma
 	if (hasSourceCode) {
 	if (hasSourceCode) {
 		printText(U"Listing target executable ", programPath, U" in the current session.\n");
 		printText(U"Listing target executable ", programPath, U" in the current session.\n");
 		bool executeResult = getFlagAsInteger(settings, U"Supressed") == 0;
 		bool executeResult = getFlagAsInteger(settings, U"Supressed") == 0;
-		output.linkerSteps.pushConstruct(compilerName, compileFrom, programPath, settings.linkerFlags, sourceObjectIndices, executeResult);
+		output.linkerSteps.pushConstruct(compilerName, compileFrom, programPath, settings.linkerFlags, settings.frameworks, sourceObjectIndices, executeResult);
 	} else {
 	} else {
 		printText(U"Failed to find any source code to compile when building ", programPath, U".\n");
 		printText(U"Failed to find any source code to compile when building ", programPath, U".\n");
 	}
 	}

+ 6 - 3
Source/tools/builder/code/builderTypes.h

@@ -24,6 +24,8 @@ struct Machine {
 	List<String> compilerFlags;
 	List<String> compilerFlags;
 	// The flags to give the linker.
 	// The flags to give the linker.
 	List<String> linkerFlags;
 	List<String> linkerFlags;
+	// The frameworks to give the linker.
+	List<String> frameworks;
 	// A list of implementation files to start crawling from, usually main.cpp or a disconnected backend implementation.
 	// A list of implementation files to start crawling from, usually main.cpp or a disconnected backend implementation.
 	List<String> crawlOrigins;
 	List<String> crawlOrigins;
 	// Paths to look for other projects in.
 	// Paths to look for other projects in.
@@ -90,11 +92,12 @@ struct SourceObject {
 
 
 struct LinkingStep {
 struct LinkingStep {
 	String compilerName, compileFrom, binaryName;
 	String compilerName, compileFrom, binaryName;
-	List<String> linkerFlags;
+	List<String> linkerFlags; // Linker flags are given as separate arguments to the linker.
+	List<String> frameworks; // Frameworks are like static libraries to link with, but uses -framework as a separate argument to the compiler before the framework's name.
 	List<int64_t> sourceObjectIndices;
 	List<int64_t> sourceObjectIndices;
 	bool executeResult;
 	bool executeResult;
-	LinkingStep(const ReadableString &compilerName, const ReadableString &compileFrom, const ReadableString &binaryName, const List<String> &linkerFlags, const List<int64_t> &sourceObjectIndices, bool executeResult)
-	: compilerName(compilerName), compileFrom(compileFrom), binaryName(binaryName), linkerFlags(linkerFlags), sourceObjectIndices(sourceObjectIndices), executeResult(executeResult) {}
+	LinkingStep(const ReadableString &compilerName, const ReadableString &compileFrom, const ReadableString &binaryName, const List<String> &linkerFlags, const List<String> &frameworks, const List<int64_t> &sourceObjectIndices, bool executeResult)
+	: compilerName(compilerName), compileFrom(compileFrom), binaryName(binaryName), linkerFlags(linkerFlags), frameworks(frameworks), sourceObjectIndices(sourceObjectIndices), executeResult(executeResult) {}
 };
 };
 
 
 struct SessionContext {
 struct SessionContext {

+ 8 - 1
Source/tools/builder/code/generator.cpp

@@ -194,7 +194,14 @@ void produce(SessionContext &input, const ReadableString &scriptPath, ScriptLang
 			String linkerFlag = linkingStep->linkerFlags[l];
 			String linkerFlag = linkingStep->linkerFlags[l];
 			string_append(linkerFlags, U" ", linkerFlag);
 			string_append(linkerFlags, U" ", linkerFlag);
 			linkerArguments.push(linkerFlag);
 			linkerArguments.push(linkerFlag);
-			printText(U"\t\t* ", linkerFlag, U" library\n");
+			printText(U"\t\t* ", linkerFlag, U"\n");
+		}
+		for (int64_t f = 0; f < linkingStep->frameworks.length(); f++) {
+			String framework = linkingStep->frameworks[f];
+			string_append(linkerFlags, U" -framework ", framework);
+			linkerArguments.push(U"-framework");
+			linkerArguments.push(framework);
+			printText(U"\t\t* -framework ", framework, U"\n");
 		}
 		}
 		linkerArguments.push(U"-o");
 		linkerArguments.push(U"-o");
 		linkerArguments.push(programPath);
 		linkerArguments.push(programPath);

+ 4 - 2
Source/tools/builder/code/main.cpp

@@ -49,9 +49,11 @@ Project files:
 				CompilerFlag -DMACRO
 				CompilerFlag -DMACRO
 		Settings for linking:
 		Settings for linking:
 			* Add a linker flag as is for direct control
 			* Add a linker flag as is for direct control
-				LinkerFlag -lLibrary
+				LinkerFlag -lsomeLibrary
 			* Add a linker flag with automatic prefix for future proofing
 			* Add a linker flag with automatic prefix for future proofing
-				Link Library
+				Link someLibrary
+			* Add a MacOS framework
+				Framework someFramework
 		Building other projects at the same time:
 		Building other projects at the same time:
 			* Build all projects in myFolder with the SkipIfBinaryExists flag in arbitrary order before continuing with compilation
 			* Build all projects in myFolder with the SkipIfBinaryExists flag in arbitrary order before continuing with compilation
 				Build "../myFolder" SkipIfBinaryExists
 				Build "../myFolder" SkipIfBinaryExists