+/* zig cc scripting tools */
+
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
+#include <time.h>
+#include <stdarg.h>
+#include "vg_opt.h"
#include "vg_log.h"
+#include "vg_string.h"
+#include "vg_build_font.h"
+
+/* we dont free dynamic vg_strs in this program. so, we dont care.. */
+const char *__asan_default_options() { return "detect_leaks=0"; }
-struct compiler_info
+struct vg_env
{
- char name[64],
- file[512],
- link[512],
- library[512],
- include[512],
- build_dir[512],
- executable[512];
-
- enum optimization_profile
+ u32 optimization;
+
+ bool fresh,
+ debug_asan;
+
+ enum platform
{
- k_optimization_profile_debug,
- k_optimization_profile_release
+ k_platform_anyplatform,
+ k_platform_windows,
+ k_platform_linux
}
- optimization_profile;
+ platform;
- enum target_file
+ enum architecture
{
- k_target_file_game,
- k_target_file_server
+ k_architecture_anyarch,
+ k_architecture_i386,
+ k_architecture_x86_64,
}
- target_file;
-
- enum compiler
+ arch;
+
+ enum compiler
{
+ k_compiler_blob,
k_compiler_clang,
- k_compiler_gcc,
- k_compiler_mingw
+ k_compiler_zigcc
}
compiler;
-}
-static vg_compiler;
-
-void vg_build_syscall(const char *fmt, ...)
+ enum libc_version
+ {
+ k_libc_version_native,
+ k_libc_version_2_23,
+ }
+ libc;
+};
+
+struct vg_env vg_test_env = {
+ .arch = k_architecture_x86_64,
+ .compiler = k_compiler_clang,
+ .libc = k_libc_version_native,
+ .debug_asan = 1,
+ .fresh = 0,
+ .platform = k_platform_linux,
+ .optimization = 0
+};
+
+struct vg_env vg_release_env = {
+ .arch = k_architecture_x86_64,
+ .compiler = k_compiler_zigcc,
+ .libc = k_libc_version_2_23,
+ .fresh = 1,
+ .optimization = 3,
+ .platform = k_platform_anyplatform,
+ .debug_asan = 0
+};
+
+struct vg_project
{
- va_list args;
- va_start( args, fmt );
-
- char call[4096];
- vsnprintf( call, vg_list_size( call ), fmt, args );
+ struct vg_env *env;
+
+ vg_str include, /* -I<path> */
+ library, /* -L<path> */
+ link, /* -llibrary */
+ sources, /* file.c obj.o */
+ uid, /* env/project identifier */
+ target, /* result object name */
+
+ /* generated */
+ compiled_objects; /* space seperated paths to compiled objects */
+
+ enum obj_type {
+ k_obj_type_none,
+ k_obj_type_exe,
+ k_obj_type_obj,
+ k_obj_type_shared,
+ }
+ type;
+};
- va_end( args );
+/*
+ * string tables
+ * -------------------------------------------------------------------------- */
- puts( call );
+static const char *platform_names[] =
+{
+ [k_platform_anyplatform] = "anyplatform",
+ [k_platform_windows] = "windows",
+ [k_platform_linux] = "linux"
+};
- if( system(call) )
- exit(0);
-}
+static const char *architecture_names[] =
+{
+ [k_architecture_anyarch] = "anyarch",
+ [k_architecture_i386] = "i386",
+ [k_architecture_x86_64] = "x86_64"
+};
-void vg_build_object( const char *file )
+static const char *compiler_names[] =
{
- strcat( vg_compiler.file, file );
-}
+ [k_compiler_blob] = "blob",
+ [k_compiler_clang] = "clang",
+ [k_compiler_zigcc] = "zig-cc"
+};
-void vg_build_library_dir( const char *ldir )
+static const char *compiler_paths[] =
{
- strcat( vg_compiler.library, ldir );
-}
+ [k_compiler_blob] = NULL,
+ [k_compiler_clang] = "clang",
+ [k_compiler_zigcc] = "zig cc"
+};
-void vg_build_link( const char *link )
+static const char *libc_names[] =
{
- strcat( vg_compiler.link, link );
-}
+ [k_libc_version_native] = "",
+ [k_libc_version_2_23] = ".2.23"
+};
+
+/*
+ * source specification
+ * -------------------------------------------------------------------------- */
-void vg_build_include( const char *inc )
+void vg_add_source( struct vg_project *proj, const char *source )
{
- strcat( vg_compiler.include, inc );
+ if( proj->type == k_obj_type_none )
+ vg_fatal_error( "Cannot add source code without setting binary type\n" );
+
+ vg_strcat( &proj->sources, source );
+ vg_strcat( &proj->sources, " " );
}
-const char *vg_compiler_str(void)
+void vg_include_dir( struct vg_project *proj, const char *dir )
{
- return (const char *[]){ "clang", "gcc", "i686-w64-mingw32-gcc" }
- [vg_compiler.compiler];
+ if( proj->type == k_obj_type_none )
+ vg_fatal_error( "Cannot add include dir without setting binary type\n" );
+
+ vg_strcat( &proj->include, dir );
+ vg_strcat( &proj->include, " " );
}
-void vg_build_start( const char *name, enum compiler compiler )
+void vg_library_dir( struct vg_project *proj, const char *dir )
{
- 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 " );
- vg_build_library_dir( "-L. " );
+ if( proj->type == k_obj_type_none )
+ vg_fatal_error( "Cannot add library dir without setting binary type\n" );
+
+ vg_strcat( &proj->library, dir );
+ vg_strcat( &proj->library, " " );
}
-void vg_build_add_link_for_graphics(void)
+void vg_link( struct vg_project *proj, const char *lib )
{
- if( (vg_compiler.compiler == k_compiler_gcc) ||
- (vg_compiler.compiler == k_compiler_clang ) )
- {
- vg_build_link( "-lSDL2 -lGL -lX11 -lXxf86vm -lXrandr -lXi -ldl " );
- }
- else
- {
- vg_build_link( "-lmingw32 -lSDL2main -lSDL2 -lopengl32 -mwindows \\\n" );
- vg_build_link( " -Wl,--dynamicbase -Wl,--nxcompat \\\n" );
-
- /* + 26.05.23: Suddenly something is pulling in winpthread.
- * cant work out whats doing it or why. */
- vg_build_link( " -Wl,-Bstatic,--whole-archive \\\n" );
- vg_build_link( " -lwinpthread \\\n" );
- vg_build_link( " -Wl,--no-whole-archive " );
- }
-
- vg_build_object( "vg/dep/glad/glad.c " );
+ if( proj->type == k_obj_type_none )
+ vg_fatal_error( "Cannot link library without setting binary type\n" );
- vg_build_link( "-lm " );
- if( vg_compiler.compiler == k_compiler_mingw ){
- //vg_build_link( "-mthreads " );
- //vg_build_link( "-static-libgcc " );
- }
- else{
- vg_build_link( "-pthread " );
- }
+ vg_strcat( &proj->link, lib );
}
-void vg_build_add_link_for_game(void)
+/*
+ * OS & file tools
+ * -------------------------------------------------------------------------- */
+
+void vg_syscall( const char *fmt, ... )
{
- if( (vg_compiler.compiler == k_compiler_gcc) ||
- (vg_compiler.compiler == k_compiler_clang ) )
- {
- vg_build_link( "-lsteam_api " );
- }
- else
- {
- vg_build_library_dir( "-L./vg/dep/sdl " );
- vg_build_link( "vg/dep/steam/steam_api.dll " );
- }
+ va_list args;
+ va_start( args, fmt );
- vg_build_include( "-I./vg/dep " );
- vg_build_library_dir( "-L./vg/dep/steam " );
+ char call[4096];
+ vsnprintf( call, sizeof(call), fmt, args );
+
+ va_end( args );
+ vg_low( "%s\n", call );
+ if( system(call) )
+ exit(1);
}
-void vg_build_bin_dependency_file( const char *src )
+void vg_add_blob( struct vg_project *proj, const char *blob, const char *dest )
{
- vg_build_syscall( "cp %s %s", src, vg_compiler.build_dir );
+ vg_syscall( "cp %s bin/%s/%s", blob, proj->uid.buffer, dest );
}
-void vg_build_symbolic_link( const char *folder, const char *bin_name )
+void vg_symlink( struct vg_project *proj,
+ const char *folder, const char *bin_name )
{
char dest[512];
- snprintf( dest, 512, "%s/%s", vg_compiler.build_dir, bin_name );
-
+ snprintf( dest, 512, "bin/%s/%s", proj->uid.buffer, bin_name );
if( !access( dest, F_OK ) )
- vg_build_syscall( "unlink %s", dest );
+ vg_syscall( "unlink %s", dest );
+ vg_syscall( "ln -srf %s %s", folder, dest );
+}
- vg_build_syscall( "ln -srf %s %s", folder, dest );
+void vg_tarball_project( struct vg_project *proj )
+{
+ vg_syscall( "tar -chzvf dist/%s-%u.tar.gz bin/%s/",
+ proj->uid.buffer, time(NULL), proj->uid.buffer );
}
-void vg_build_copy_graphics_dependencies(void)
+/*
+ * The project configurator and compiler.
+ * -------------------------------------------------------------------------- */
+
+void vg_project_new_target( struct vg_project *proj, const char *name,
+ enum obj_type type )
{
- if( vg_compiler.compiler == k_compiler_mingw )
+ proj->type = type;
+
+ vg_strnull( &proj->include, NULL, -1 );
+ vg_strnull( &proj->library, NULL, -1 );
+ vg_strnull( &proj->link, NULL, -1 );
+ vg_strnull( &proj->sources, NULL, -1 );
+ vg_strnull( &proj->target, NULL, -1 );
+
+ /*
+ * Setup target with appropriate extension
+ */
+ vg_strcat( &proj->target, name );
+
+ if( proj->env->platform == k_platform_windows )
{
- vg_build_bin_dependency_file( "vg/dep/sdl/SDL2.dll" );
+ if( type == k_obj_type_exe )
+ vg_strcat( &proj->target, ".exe" );
+ else if( type == k_obj_type_shared )
+ vg_strcat( &proj->target, ".dll" );
+ else if( type == k_obj_type_obj )
+ vg_strcat( &proj->target, ".obj" );
}
-}
-void vg_build_copy_game_dependencies(void)
-{
- vg_build_bin_dependency_file(
- "vg/submodules/SDL_GameControllerDB/gamecontrollerdb.txt" );
- if( (vg_compiler.compiler == k_compiler_gcc) ||
- (vg_compiler.compiler == k_compiler_clang) )
+ if( proj->env->platform == k_platform_linux )
{
- vg_build_bin_dependency_file( "vg/dep/steam/libsteam_api.so" );
+ if( type == k_obj_type_shared )
+ vg_strcat( &proj->target, ".so" );
+ else if( type == k_obj_type_obj )
+ vg_strcat( &proj->target, ".o" );
}
- else
+
+ /*
+ * Add some regular includes / library dirs
+ */
+ if( type != k_obj_type_none )
{
- vg_build_bin_dependency_file( "vg/dep/steam/steam_api.dll" );
+ vg_include_dir( proj, "-I." );
+ vg_include_dir( proj, "-I./vg" );
+ vg_library_dir( proj, "-L." );
+ vg_library_dir( proj, "-L/usr/lib" );
}
-}
-void vg_build_mode_release(void)
-{
- vg_compiler.optimization_profile = k_optimization_profile_release;
+ vg_info( " New target: %s\n", name );
}
-void vg_build_mode_debug(void)
+void vg_project_init( struct vg_project *proj,
+ struct vg_env *env,
+ const char *identifier )
{
- vg_compiler.optimization_profile = k_optimization_profile_debug;
+ proj->env = env;
+ proj->type = k_obj_type_none;
+
+ vg_strnull( &proj->uid, NULL, -1 );
+ vg_strnull( &proj->compiled_objects, NULL, -1 );
+
+ /* check for problems in configuration */
+ if( env->libc != k_libc_version_native ){
+ if( env->compiler != k_compiler_zigcc ){
+ vg_fatal_error(
+ "Cannot specify libc version using the '%s' compiler.\n",
+ compiler_names[ env->compiler ] );
+ }
+ }
+
+ if( env->compiler == k_compiler_clang ){
+ if( env->platform != k_platform_linux ){
+ vg_fatal_error( "Cannot compile for '%s' using the '%s' compiler;" );
+ }
+ }
+
+ vg_strcat( &proj->uid, identifier );
+ vg_strcatch( &proj->uid, '-' );
+ vg_strcat( &proj->uid, platform_names[ env->platform ] );
+ vg_strcatch( &proj->uid, '-' );
+ vg_strcat( &proj->uid, architecture_names[ env->arch ] );
+ vg_strcatch( &proj->uid, '-' );
+ vg_strcat( &proj->uid, compiler_names[ env->compiler ] );
+
+ if( proj->uid.i < 3 )
+ vg_fatal_error( "failed to create project UID\n" );
+
+ vg_info( "project_init: %s (%s, %s, compiler: %s, opt:%u, fresh: %s)\n",
+ identifier,
+ platform_names[env->platform],
+ architecture_names[env->arch],
+ compiler_names[env->compiler],
+ env->optimization,
+ env->fresh? "yes":"no");
+
+ if( env->fresh )
+ vg_syscall( "rm -rf bin/%s", proj->uid.buffer );
+ vg_syscall( "mkdir -p bin/%s", proj->uid.buffer );
}
-void vg_build(void)
+void vg_compile_project( struct vg_project *proj )
{
- char cmd[8192];
- cmd[0] = '\0';
+ vg_str cmd;
+ vg_strnull( &cmd, NULL, -1 );
- /* Compiler */
- strcat( cmd, "ccache " );
- strcat( cmd, vg_compiler_str() );
- strcat( cmd, " -std=gnu99 -D_REENTRANT \\\n" );
+ /* compiler specification */
+ vg_strcat( &cmd, "ccache " );
+ vg_strcat( &cmd, compiler_paths[ proj->env->compiler ] );
+ vg_strcat( &cmd, " -std=gnu99 -D_REENTRANT \\\n" );
- /* Debugging information */
- if( vg_compiler.optimization_profile == k_optimization_profile_debug )
+ if( proj->env->optimization )
+ {
+ vg_strcat( &cmd, " -O" );
+ vg_strcati32( &cmd, proj->env->optimization );
+ vg_strcat( &cmd, " -flto \\\n" );
+ }
+ else
{
- strcat( cmd, " -O0 -ggdb3 -fno-omit-frame-pointer " );
+ /* add debugger / asan information */
+ vg_strcat( &cmd, " -O0 -ggdb3 -fno-omit-frame-pointer " );
- if( (vg_compiler.compiler == k_compiler_gcc) ||
- (vg_compiler.compiler == k_compiler_clang ) )
+ if( (proj->env->compiler == k_compiler_clang) && proj->env->debug_asan )
{
- strcat( cmd, "-rdynamic -fsanitize=address "
- "-fPIE -fstack-protector-strong " );
+ vg_strcat( &cmd, " -rdynamic -fsanitize=address -fPIE "
+ "-fstack-protector-strong " );
}
- strcat( cmd, "\\\n" );
- }
- else
- {
- strcat( cmd, " -O3 -DVG_RELEASE\\\n" );
+ vg_strcat( &cmd, "\\\n" );
}
- /* Warnings */
- strcat( cmd,
- " -Wall\\\n"
- " -Wno-unused-function -Wno-unused-variable -Wno-format-truncation\\\n"
+ /* want a lot of warnings but not useless ones */
+ vg_strcat( &cmd, " -Wall -ferror-limit=8\\\n"
+ " -Wno-unused-function -Wno-unused-variable\\\n"
" -Wno-unused-command-line-argument -Wno-unused-but-set-variable\\\n"
);
- if( vg_compiler.compiler == k_compiler_clang ){
- strcat( cmd,
- " -ferror-limit=5\\\n" );
+ if( proj->env->compiler != k_compiler_clang )
+ vg_strcat( &cmd, " -Wno-format-truncation\\\n" );
+
+ /* include paths */
+ vg_strcat( &cmd, " " );
+ vg_strcat( &cmd, proj->include.buffer );
+ vg_strcat( &cmd, "\\\n" );
+
+ /* library paths */
+ vg_strcat( &cmd, " " );
+ vg_strcat( &cmd, proj->library.buffer );
+ vg_strcat( &cmd, "\\\n" );
+
+ /* sources */
+ vg_strcat( &cmd, " " );
+
+ if( proj->type == k_obj_type_obj )
+ vg_strcat( &cmd, "-c " );
+
+ if( proj->type == k_obj_type_shared )
+ vg_strcat( &cmd, "-shared -fPIC " );
+
+ vg_strcat( &cmd, proj->sources.buffer );
+ vg_strcat( &cmd, "\\\n" );
+
+ /* output */
+ vg_strcat( &cmd, " -o bin/" );
+ vg_strcat( &cmd, proj->uid.buffer );
+ vg_strcat( &cmd, "/" );
+ vg_strcat( &cmd, proj->target.buffer );
+ vg_strcat( &cmd, "\\\n" );
+
+ /* link */
+ vg_strcat( &cmd, " " );
+ vg_strcat( &cmd, proj->link.buffer );
+ vg_strcat( &cmd, "\\\n" );
+
+ if( proj->type == k_obj_type_exe )
+ {
+ vg_strcat( &cmd, " -Wl,-rpath=./\\\n" );
+ }
+
+ /* target platform specification (zig-cc only) */
+ if( proj->env->compiler == k_compiler_zigcc ){
+ vg_strcat( &cmd, " -target " );
+ vg_strcat( &cmd, architecture_names[proj->env->arch] );
+ vg_strcat( &cmd, "-" );
+ vg_strcat( &cmd, platform_names[proj->env->platform] );
+
+ if( proj->env->platform == k_platform_linux ){
+ vg_strcat( &cmd, "-gnu" );
+ vg_strcat( &cmd, libc_names[proj->env->libc] );
+ }
+
+ if( proj->env->platform == k_platform_windows )
+ {
+ /* we currently dont want pdb pretty much ever. goodbye! */
+
+ if( proj->type == k_obj_type_exe )
+ {
+ vg_strcat( &cmd, " /pdb:/dev/null" );
+ vg_strcat( &cmd, " /SUBSYSTEM:windows" );
+ }
+ }
}
- /* Include */
- strcat( cmd, " " );
- strcat( cmd, vg_compiler.include );
- strcat( cmd, "\\\n" );
+ vg_syscall( cmd.buffer );
- /* Library */
- strcat( cmd, " " );
- strcat( cmd, vg_compiler.library );
- strcat( cmd, "\\\n" );
+ /* add to results */
+ vg_strcat( &proj->compiled_objects, "bin/" );
+ vg_strcat( &proj->compiled_objects, proj->uid.buffer );
+ vg_strcat( &proj->compiled_objects, "/" );
+ vg_strcat( &proj->compiled_objects, proj->target.buffer );
+ vg_strcat( &proj->compiled_objects, " \\\n " );
+}
- /* Targets */
- strcat( cmd, " " );
- strcat( cmd, vg_compiler.file );
- strcat( cmd, "\\\n" );
+/*
+ * Standard VG includes & libraries which we use for games/graphics
+ * -------------------------------------------------------------------------- */
- /* 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 );
+struct vg_engine_config
+{
+ bool use_3d, legacy_support_vg_msg1, log_source_info, steam_api,
+ custom_game_settings,
+ custom_shaders;
+ i32 fixed_update_hz;
+}
+vg_engine_default_config = {
+ .use_3d = 1,
+ .fixed_update_hz = 60,
+ .legacy_support_vg_msg1 = 0,
+ .log_source_info = 1,
+ .steam_api = 0,
+ .custom_game_settings = 0,
+ .custom_shaders = 0
+};
+
+void vg_add_engine( struct vg_project *proj, struct vg_engine_config *config )
+{
+ /* building assets */
+ vg_build_default_font();
+
+ if( !config ) config = &vg_engine_default_config;
+ vg_str config_string;
+ vg_strnull( &config_string, NULL, -1 );
+ vg_strcat( &config_string, config->use_3d? "-DVG_3D \\\n": "-DVG_2D \\\n" );
+ vg_strcat( &config_string, "-DVG_TIMESTEP_FIXED=\"(1.0/" );
+ vg_strcati32( &config_string, config->fixed_update_hz );
+ vg_strcat( &config_string, ".0)\" \\\n" );
+ if( config->legacy_support_vg_msg1 )
+ vg_strcat( &config_string, "-DVG_MSG_V1_SUPPORT \\\n" );
+ if( config->log_source_info )
+ vg_strcat( &config_string, "-DVG_LOG_SOURCE_INFO \\\n" );
+ if( config->custom_game_settings )
+ vg_strcat( &config_string, "-DVG_GAME_SETTINGS \\\n" );
+ if( config->custom_shaders )
+ vg_strcat( &config_string, "-DVG_CUSTOM_SHADERS \\\n" );
+
+ vg_strcat( &config_string, "\\\n" );
+
+ /* compile heavy dependencies seperately */
+ struct vg_project dep_proj;
+ struct vg_env env = *proj->env;
+ env.optimization = 3;
+ env.debug_asan = 0;
+
+ vg_project_init( &dep_proj, proj->env, "vg" );
+
+ /* external dependencies */
+ vg_project_new_target( &dep_proj, "vg_deps", k_obj_type_obj );
+ vg_add_source( &dep_proj, "vg/vg_depencies.c" );
+ vg_compile_project( &dep_proj );
+
+ /* glad */
+ vg_project_new_target( &dep_proj, "vg_glad", k_obj_type_obj );
+ vg_add_source( &dep_proj, "vg/dep/glad/glad.c" );
+ vg_include_dir( &dep_proj, "-I./vg/dep " );
+ vg_compile_project( &dep_proj );
+
+ /* core engine */
+ vg_project_new_target( &dep_proj, "vg_engine_core", k_obj_type_obj );
+ vg_add_source( &dep_proj, config_string.buffer );
+ vg_add_source( &dep_proj, "vg/vg_engine.c" );
+ vg_include_dir( &dep_proj, "-I./vg/dep " );
+ vg_compile_project( &dep_proj );
+
+ /* steamworks */
+ if( config->steam_api )
+ {
+ vg_project_new_target( &dep_proj, "vg_steam", k_obj_type_obj );
+ vg_add_source( &dep_proj, "vg/vg_steam.c" );
+ vg_compile_project( &dep_proj );
- if( vg_compiler.compiler == k_compiler_mingw )
- strcat( vg_compiler.executable, ".exe" );
+ if( proj->env->platform == k_platform_linux )
+ {
+ vg_add_blob( proj, "vg/dep/steam/libsteam_api.so", "" );
+ vg_link( proj, "-lsteam_api " );
+ }
+ else if( proj->env->platform == k_platform_windows )
+ {
+ vg_add_blob( proj, "vg/dep/steam/steam_api64.dll", "" );
+ vg_link( proj, "vg/dep/steam/steam_api64.dll " );
+ }
- strcat( cmd, vg_compiler.executable );
- strcat( cmd, "\\\n" );
+ vg_library_dir( proj, "-L./vg/dep/steam " );
+ vg_include_dir( proj, "-I./vg/dep " );
+ }
- /* Link */
- strcat( cmd, " " );
- strcat( cmd, vg_compiler.link );
- strcat( cmd, "\\\n" );
+ /* precipitate to the client project */
- strcat( cmd, " -Wl,-rpath=./" );
+ vg_link( proj, "-lm " );
+ if( proj->env->platform == k_platform_linux )
+ {
+ vg_link( proj, "-lSDL2 -lGL -lX11 -lXxf86vm "
+ "-lXrandr -lXi -ldl -pthread " );
+ }
+ else if( proj->env->platform == k_platform_windows )
+ {
+ vg_link( proj, "-lSDL2main -lSDL2 -lopengl32 \\\n" );
+ vg_link( proj, "vg/dep/sdl/SDL2.dll " );
+ vg_add_blob( proj, "vg/dep/sdl/SDL2.dll ", "" );
+ vg_library_dir( proj, "-L./vg/dep/sdl " );
+ }
- vg_build_syscall( cmd );
+ vg_add_source( proj, config_string.buffer );
+ vg_add_source( proj, dep_proj.compiled_objects.buffer );
+ vg_add_source( proj, "\\\n" );
+ vg_include_dir( proj, "-I./vg/dep " );
+ vg_link( proj, "-lm " );
+}
+
+void vg_add_controller_database( struct vg_project *proj )
+{
+ vg_add_blob( proj,
+ "vg/submodules/SDL_GameControllerDB/gamecontrollerdb.txt", "" );
}