--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "vg/vg_log.h"
+
+struct compiler_info
+{
+ char name[64],
+ file[512],
+ link[512],
+ library[512],
+ include[512],
+ build_dir[512],
+ executable[512];
+
+ enum optimization_profile
+ {
+ k_optimization_profile_debug,
+ k_optimization_profile_release
+ }
+ optimization_profile;
+
+ enum target_file
+ {
+ k_target_file_game,
+ k_target_file_server
+ }
+ target_file;
+
+ enum compiler
+ {
+ k_compiler_clang,
+ k_compiler_gcc,
+ k_compiler_mingw
+ }
+ compiler;
+}
+
+static vg_compiler;
+
+void vg_build_syscall(const char *fmt, ...)
+{
+ va_list args;
+ va_start( args, fmt );
+
+ char call[4096];
+ vsnprintf( call, vg_list_size( call ), fmt, args );
+
+ va_end( args );
+
+ puts( call );
+
+ if( system(call) )
+ exit(0);
+}
+
+void vg_build_object( const char *file )
+{
+ strcat( vg_compiler.file, file );
+}
+
+void vg_build_library_dir( const char *ldir )
+{
+ strcat( vg_compiler.library, ldir );
+}
+
+void vg_build_link( const char *link )
+{
+ strcat( vg_compiler.link, link );
+}
+
+void vg_build_include( const char *inc )
+{
+ strcat( vg_compiler.include, inc );
+}
+
+const char *vg_compiler_str(void)
+{
+ return (const char *[]){ "clang", "gcc", "i686-w64-mingw32-gcc" }
+ [vg_compiler.compiler];
+}
+
+void vg_build_start( const char *name, enum compiler compiler )
+{
+ vg_compiler.file[0] = '\0';
+ vg_compiler.link[0] = '\0';
+ vg_compiler.include[0] = '\0';
+ vg_compiler.library[0] = '\0';
+ vg_compiler.compiler = compiler;
+
+ strcpy( vg_compiler.name, name );
+
+ snprintf( vg_compiler.build_dir, 512,
+ "bin/%s-%s",
+ name,
+ vg_compiler_str() );
+
+ vg_build_syscall( "mkdir -p %s", vg_compiler.build_dir );
+ vg_build_include( "-I. -I./vg/src " );
+ vg_build_library_dir( "-L. " );
+}
+
+void vg_build_add_link_for_graphics(void)
+{
+ if( (vg_compiler.compiler == k_compiler_gcc) ||
+ (vg_compiler.compiler == k_compiler_clang ) )
+ {
+ vg_build_link( "-lGL -lglfw3 -lX11 -lXxf86vm -lXrandr -lXi -ldl " );
+ }
+ else
+ {
+ vg_build_link( "-lglfw3dll -lopengl32 -static -mwindows " );
+ }
+
+ vg_build_object( "vg/dep/glad/glad.c " );
+ vg_build_link( "-lm -pthread " );
+ vg_build_library_dir( "-L./vg/dep/glfw " );
+}
+
+void vg_build_add_link_for_game(void)
+{
+ if( (vg_compiler.compiler == k_compiler_gcc) ||
+ (vg_compiler.compiler == k_compiler_clang ) )
+ {
+ vg_build_link( "-lsteam_api " );
+ vg_build_object( "vg/dep/dr_soft/miniaudio." );
+ }
+ else
+ {
+ vg_build_link( "vg/dep/steam/steam_api.dll " );
+ vg_build_object( "vg/dep/dr_soft/miniaudio." );
+ }
+
+ vg_build_object( vg_compiler_str() );
+ vg_build_object( ".o " );
+
+ vg_build_include( "-I./vg/dep " );
+ vg_build_library_dir( "-L./vg/dep/steam " );
+}
+
+void vg_build_bin_dependency_file( const char *src )
+{
+ vg_build_syscall( "cp %s %s", src, vg_compiler.build_dir );
+}
+
+void vg_build_symbolic_link( const char *folder, const char *bin_name )
+{
+ char dest[512];
+ snprintf( dest, 512, "%s/%s", vg_compiler.build_dir, bin_name );
+
+ if( !access( dest, F_OK ) )
+ vg_build_syscall( "unlink %s", dest );
+
+ vg_build_syscall( "ln -srf %s %s", folder, dest );
+}
+
+void vg_build_copy_graphics_dependencies(void)
+{
+ if( vg_compiler.compiler == k_compiler_mingw )
+ {
+ vg_build_bin_dependency_file( "vg/dep/glfw/glfw3.dll" );
+ }
+}
+
+void vg_build_copy_game_dependencies(void)
+{
+ if( (vg_compiler.compiler == k_compiler_gcc) ||
+ (vg_compiler.compiler == k_compiler_clang) )
+ {
+ vg_build_bin_dependency_file( "vg/dep/steam/libsteam_api.so" );
+ }
+ else
+ {
+ vg_build_bin_dependency_file( "vg/dep/steam/steam_api.dll" );
+ }
+}
+
+void vg_build_mode_release(void)
+{
+ vg_compiler.optimization_profile = k_optimization_profile_release;
+}
+
+void vg_build_mode_debug(void)
+{
+ vg_compiler.optimization_profile = k_optimization_profile_debug;
+}
+
+void vg_build_miniaudio(void)
+{
+ vg_build_syscall( "ccache %s -O3\\\n"
+ " -c vg/dep/dr_soft/miniaudio_impl.c\\\n"
+ " -o vg/dep/dr_soft/miniaudio.%s.o",
+ vg_compiler_str(), vg_compiler_str() );
+}
+
+void vg_build(void)
+{
+ char cmd[4096];
+ cmd[0] = '\0';
+
+ /* Compiler */
+ strcat( cmd, "ccache " );
+ strcat( cmd, vg_compiler_str() );
+ strcat( cmd, " -std=gnu99 -D_REENTRANT \\\n" );
+
+ /* Debugging information */
+ if( vg_compiler.optimization_profile == k_optimization_profile_debug )
+ {
+ strcat( cmd, " -O0 -ggdb3 -fno-omit-frame-pointer " );
+
+ if( (vg_compiler.compiler == k_compiler_gcc) ||
+ (vg_compiler.compiler == k_compiler_clang ) )
+ {
+ strcat( cmd, "-rdynamic -fsanitize=address " );
+ }
+
+ strcat( cmd, "\\\n" );
+ }
+ else
+ {
+ strcat( cmd, " -O3 -DVG_RELEASE\\\n" );
+ }
+
+ /* Warnings */
+ strcat( cmd,
+ " -Wall\\\n"
+ " -Wno-unused-function -Wno-unused-variable\\\n"
+ " -Wno-unused-command-line-argument -Wno-unused-but-set-variable\\\n"
+ );
+
+ /* Include */
+ strcat( cmd, " " );
+ strcat( cmd, vg_compiler.include );
+ strcat( cmd, "\\\n" );
+
+ /* Library */
+ strcat( cmd, " " );
+ strcat( cmd, vg_compiler.library );
+ strcat( cmd, "\\\n" );
+
+ /* Targets */
+ strcat( cmd, " " );
+ strcat( cmd, vg_compiler.file );
+ strcat( cmd, "\\\n" );
+
+ /* Output */
+ strcat( cmd, " -o " );
+ vg_compiler.executable[0] = '\0';
+ strcat( vg_compiler.executable, vg_compiler.build_dir );
+ strcat( vg_compiler.executable, "/" );
+ strcat( vg_compiler.executable, vg_compiler.name );
+
+ if( vg_compiler.compiler == k_compiler_mingw )
+ strcat( vg_compiler.executable, ".exe" );
+
+ strcat( cmd, vg_compiler.executable );
+ strcat( cmd, "\\\n" );
+
+ /* Link */
+ strcat( cmd, " " );
+ strcat( cmd, vg_compiler.link );
+ strcat( cmd, "\\\n" );
+
+ strcat( cmd, " -Wl,-rpath=./" );
+
+ vg_build_syscall( cmd );
+}