+/* zig cc scripting tools */
+
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
+#include <time.h>
#include "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
+/* we dont free dynamic vg_strs in this program. so, we dont care.. */
+const char *__asan_default_options() { return "detect_leaks=0"; }
+
+struct {
+ vg_str include,
+ library,
+ link,
+ sources,
+ dest,
+ project_name;
+
+ u32 optimization,
+ warnings;
+ bool fresh,
+ debug_asan;
+
+ enum platform {
+ k_platform_anyplatform,
+ k_platform_windows,
+ k_platform_linux
}
- optimization_profile;
+ platform;
- enum target_file
- {
- k_target_file_game,
- k_target_file_server
+ enum architecture {
+ 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,
- k_compiler_none
+ k_compiler_zigcc
}
compiler;
- int clean;
+ enum libc_version {
+ k_libc_version_native,
+ k_libc_version_2_23,
+ }
+ libc;
+}
+static vg_build = { .debug_asan = 1 };
+
+/*
+ * string tables
+ * -------------------------------------------------------------------------- */
+
+static const char *platform_names[] = {
+ [k_platform_anyplatform] = "anyplatform",
+ [k_platform_windows] = "windows",
+ [k_platform_linux] = "linux"
+};
+
+static const char *architecture_names[] = {
+ [k_architecture_anyarch] = "anyarch",
+ [k_architecture_i386] = "i386",
+ [k_architecture_x86_64] = "x86_64"
+};
+
+static const char *compiler_names[] = {
+ [k_compiler_blob] = "blob",
+ [k_compiler_clang] = "clang",
+ [k_compiler_zigcc] = "zig-cc"
+};
+
+static const char *compiler_paths[] = {
+ [k_compiler_blob] = NULL,
+ [k_compiler_clang] = "clang",
+ [k_compiler_zigcc] = "zig cc"
+};
+
+static const char *libc_names[] = {
+ [k_libc_version_native] = "",
+ [k_libc_version_2_23] = ".2.23"
+};
+
+/*
+ * source specification
+ * -------------------------------------------------------------------------- */
+
+void vg_add_source( const char *source ){
+ vg_strcat( &vg_build.sources, source );
+ vg_strcat( &vg_build.sources, " " );
+}
+
+void vg_include_dir( const char *dir ){
+ vg_strcat( &vg_build.include, dir );
+ vg_strcat( &vg_build.include, " " );
}
-static vg_compiler;
+void vg_library_dir( const char *dir ){
+ vg_strcat( &vg_build.library, dir );
+ vg_strcat( &vg_build.library, " " );
+}
-void vg_build_syscall(const char *fmt, ...)
-{
+void vg_link( const char *lib ){
+ vg_strcat( &vg_build.link, lib );
+}
+
+/*
+ * OS & file tools
+ * -------------------------------------------------------------------------- */
+
+void vg_syscall( const char *fmt, ... ){
va_list args;
va_start( args, fmt );
char call[4096];
- vsnprintf( call, vg_list_size( call ), fmt, args );
+ vsnprintf( call, sizeof(call), fmt, args );
va_end( args );
-
- puts( call );
-
+ vg_low( "%s\n", call );
if( system(call) )
- exit(0);
+ exit(1);
}
-void vg_build_object( const char *file )
-{
- strcat( vg_compiler.file, file );
+void vg_add_blob( const char *blob, const char *dest ){
+ vg_syscall( "cp %s bin/%s/%s", blob, vg_build.project_name.buffer, dest );
}
-void vg_build_library_dir( const char *ldir )
-{
- strcat( vg_compiler.library, ldir );
+void vg_symlink( const char *folder, const char *bin_name ){
+ char dest[512];
+ snprintf( dest, 512, "bin/%s/%s", vg_build.project_name.buffer, bin_name );
+ if( !access( dest, F_OK ) )
+ vg_syscall( "unlink %s", dest );
+ vg_syscall( "ln -srf %s %s", folder, dest );
}
-void vg_build_link( const char *link )
-{
- strcat( vg_compiler.link, link );
+void vg_tarball_last_project(void){
+ vg_syscall( "tar -chzvf dist/%s-%u.tar.gz bin/%s/",
+ vg_build.project_name.buffer, time(NULL),
+ vg_build.project_name.buffer );
}
-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", "zig", "none" }
- [vg_compiler.compiler];
-}
+/*
+ * Standard VG includes & libraries which we use for games/graphics
+ * -------------------------------------------------------------------------- */
-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() );
-
- if( vg_compiler.clean ){
- vg_build_syscall( "rm -rf %s", vg_compiler.build_dir );
- }
+void vg_add_graphics(void){
+ vg_add_source( "vg/dep/glad/glad.c" );
- vg_build_syscall( "mkdir -p %s", vg_compiler.build_dir );
- vg_build_include( "-I. -I./vg " );
- vg_build_library_dir( "-L. " );
+ if( vg_build.platform == k_platform_windows )
+ vg_add_blob( "vg/dep/sdl/SDL2.dll", "" );
- if( vg_compiler.compiler == k_compiler_zigcc )
- vg_build_library_dir( "-L/usr/lib " );
-}
+ vg_link( "-lm " );
-void vg_build_add_link_for_graphics(void)
-{
- if( (vg_compiler.compiler == k_compiler_gcc) ||
- (vg_compiler.compiler == k_compiler_clang ) ||
- (vg_compiler.compiler == k_compiler_zigcc) )
- {
- vg_build_link( "-lSDL2 -lGL -lX11 -lXxf86vm -lXrandr -lXi -ldl " );
- }
+ if( vg_build.platform == k_platform_linux )
+ vg_link( "-lSDL2 -lGL -lX11 -lXxf86vm -lXrandr -lXi -ldl -pthread " );
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 " );
-
- 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_link( "-lmingw32 -lSDL2main -lSDL2 -lopengl32 \\\n" );
}
-void vg_build_add_link_for_game(void)
-{
- if( (vg_compiler.compiler == k_compiler_gcc) ||
- (vg_compiler.compiler == k_compiler_clang ) ||
- (vg_compiler.compiler == k_compiler_zigcc) )
- {
- vg_build_link( "-lsteam_api " );
+void vg_add_game_stuff(void){
+ vg_add_blob( "vg/submodules/SDL_GameControllerDB/gamecontrollerdb.txt", "" );
+
+ if( vg_build.platform == k_platform_linux ){
+ vg_add_blob( "vg/dep/steam/libsteam_api.so", "" );
+ vg_link( "-lsteam_api " );
}
- else
- {
- vg_build_library_dir( "-L./vg/dep/sdl " );
- vg_build_link( "vg/dep/steam/steam_api.dll " );
+ else if( vg_build.platform == k_platform_windows ){
+ vg_add_blob( "vg/dep/steam/steam_api64.dll", "" );
+ vg_link( "vg/dep/steam/steam_api64.dll " );
+ vg_link( "vg/dep/sdl/SDL2.dll " );
+ vg_library_dir( "-L./vg/dep/sdl " );
}
- 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 );
+ vg_include_dir( "-I./vg/dep " );
+ vg_library_dir( "-L./vg/dep/steam " );
}
-void vg_build_copy_graphics_dependencies(void)
-{
- if( vg_compiler.compiler == k_compiler_mingw )
- {
- vg_build_bin_dependency_file( "vg/dep/sdl/SDL2.dll" );
+/*
+ * The project configurator and compiler.
+ * -------------------------------------------------------------------------- */
+
+void vg_build_new( const char *name ){
+ vg_strnull( &vg_build.include, NULL, -1 );
+ vg_strnull( &vg_build.library, NULL, -1 );
+ vg_strnull( &vg_build.link, NULL, -1 );
+ vg_strnull( &vg_build.sources, NULL, -1 );
+ vg_strnull( &vg_build.dest, NULL, -1 );
+ vg_strnull( &vg_build.project_name, NULL, -1 );
+
+ /* check for problems in configuration */
+ if( vg_build.libc != k_libc_version_native ){
+ if( vg_build.compiler != k_compiler_zigcc ){
+ vg_build.warnings ++;
+ vg_warn( "Cannot specify libc version using the '%s' compiler.\n",
+ compiler_names[ vg_build.compiler ] );
+ }
}
-}
-
-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) ||
- (vg_compiler.compiler == k_compiler_zigcc) )
- {
- vg_build_bin_dependency_file( "vg/dep/steam/libsteam_api.so" );
- }
- else
- {
- vg_build_bin_dependency_file( "vg/dep/steam/steam_api.dll" );
+ if( vg_build.compiler == k_compiler_clang ){
+ if( vg_build.platform != k_platform_linux ){
+ vg_build.warnings ++;
+ vg_warn( "Cannot compile for '%s' using the '%s' compiler;" );
+ }
}
-}
-void vg_build_mode_release(void)
-{
- vg_compiler.optimization_profile = k_optimization_profile_release;
+ vg_str *proj = &vg_build.project_name;
+
+ vg_strcat( proj, name );
+ vg_strcatch( proj, '-' );
+ vg_strcat( proj, platform_names[ vg_build.platform ] );
+ vg_strcatch( proj, '-' );
+ vg_strcat( proj, architecture_names[ vg_build.arch ] );
+ vg_strcatch( proj, '-' );
+ vg_strcat( proj, compiler_names[ vg_build.compiler ] );
+
+ vg_info( "project: %s (%s, %s, compiler: %s, opt:%u, fresh: %s)\n",
+ name,
+ platform_names[vg_build.platform],
+ architecture_names[vg_build.arch],
+ compiler_names[vg_build.compiler],
+ vg_build.optimization,
+ vg_build.fresh? "yes":"no");
+
+ if( proj->i < 3 )
+ vg_fatal_error( "failed to create output directory\n" );
+
+ if( vg_build.fresh )
+ vg_syscall( "rm -rf bin/%s", proj->buffer );
+ vg_syscall( "mkdir -p bin/%s", proj->buffer );
+
+ vg_include_dir( "-I." );
+ vg_include_dir( "-I./vg" );
+ vg_library_dir( "-L." );
+ vg_library_dir( "-L/usr/lib" );
}
-void vg_build_mode_debug(void)
-{
- vg_compiler.optimization_profile = k_optimization_profile_debug;
-}
+void vg_compile( const char *name ){
+ vg_str cmd;
+ vg_strnull( &cmd, NULL, -1 );
-void vg_build_clean(void){
- vg_compiler.clean = 1;
-}
+ /* compiler specification */
+ vg_strcat( &cmd, "ccache " );
+ vg_strcat( &cmd, compiler_paths[ vg_build.compiler ] );
+ vg_strcat( &cmd, " -std=gnu99 -D_REENTRANT \\\n" );
-void vg_build(void)
-{
- char cmd[8192];
- cmd[0] = '\0';
-
- /* Compiler */
- strcat( cmd, "ccache " );
- strcat( cmd, vg_compiler_str() );
- strcat( cmd, " cc" );
- 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 ) ||
- (vg_compiler.compiler == k_compiler_zigcc) )
- {
- strcat( cmd, "-rdynamic -fsanitize=address "
- "-fPIE -fstack-protector-strong " );
+ if( vg_build.optimization ){
+ vg_strcat( &cmd, " -O" );
+ vg_strcati32( &cmd, vg_build.optimization );
+ vg_strcat( &cmd, " -DVG_RELEASE\\\n" );
+ }
+ else {
+ /* add debugger / asan information */
+ vg_strcat( &cmd, " -O0 -ggdb3 -fno-omit-frame-pointer " );
+
+ if( (vg_build.compiler == k_compiler_clang) && vg_build.debug_asan ){
+ 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"
+ /* want a lot of warnings but not useless ones */
+ vg_strcat( &cmd, " -Wall -ferror-limit=8\\\n"
" -Wno-unused-function -Wno-unused-variable -Wno-format-truncation\\\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" );
- }
-
- /* 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=./" );
+ /* include paths */
+ vg_strcat( &cmd, " " );
+ vg_strcat( &cmd, vg_build.include.buffer );
+ vg_strcat( &cmd, "\\\n" );
+
+ /* library paths */
+ vg_strcat( &cmd, " " );
+ vg_strcat( &cmd, vg_build.library.buffer );
+ vg_strcat( &cmd, "\\\n" );
+
+ /* sources */
+ vg_strcat( &cmd, " " );
+ vg_strcat( &cmd, vg_build.sources.buffer );
+ vg_strcat( &cmd, "\\\n" );
+
+ /* output */
+ vg_strcat( &cmd, " -o bin/" );
+ vg_strcat( &cmd, vg_build.project_name.buffer );
+ vg_strcat( &cmd, "/" );
+ vg_strcat( &cmd, name );
+ if( vg_build.platform == k_platform_windows )
+ vg_strcat( &cmd, ".exe" );
+ vg_strcat( &cmd, "\\\n" );
+
+ /* link */
+ vg_strcat( &cmd, " " );
+ vg_strcat( &cmd, vg_build.link.buffer );
+ vg_strcat( &cmd, "\\\n" );
+
+ /* dont remember what this does */
+ vg_strcat( &cmd, " -Wl,-rpath=./\\\n" );
+
+ /* target platform specification (zig-cc only) */
+ if( vg_build.compiler == k_compiler_zigcc ){
+ vg_strcat( &cmd, " -target " );
+ vg_strcat( &cmd, architecture_names[vg_build.arch] );
+ vg_strcat( &cmd, "-" );
+ vg_strcat( &cmd, platform_names[vg_build.platform] );
+
+ if( vg_build.platform == k_platform_linux ){
+ vg_strcat( &cmd, "-gnu" );
+ vg_strcat( &cmd, libc_names[vg_build.libc] );
+ }
- if( vg_compiler.compiler == k_compiler_zigcc ){
- strcat( cmd, " -target native-native-gnu.2.23" );
+ if( vg_build.platform == k_platform_windows ){
+ /* we currently dont want pdb pretty much ever. goodbye! */
+ vg_strcat( &cmd, " /SUBSYSTEM:windows /pdb:/dev/null" );
+ }
}
- vg_build_syscall( cmd );
+ vg_syscall( cmd.buffer );
}