b40ecd3c23545040484f0ed8bb560f085ce3f7a9
1 /* zig cc scripting tools */
11 #include "vg_string.h"
12 #include "vg_build_font.h"
14 /* we dont free dynamic vg_strs in this program. so, we dont care.. */
15 const char *__asan_default_options() { return "detect_leaks=0"; }
26 k_platform_anyplatform
,
34 k_architecture_anyarch
,
36 k_architecture_x86_64
,
50 k_libc_version_native
,
56 struct vg_env vg_test_env
= {
57 .arch
= k_architecture_x86_64
,
58 .compiler
= k_compiler_clang
,
59 .libc
= k_libc_version_native
,
62 .platform
= k_platform_linux
,
66 struct vg_env vg_release_env
= {
67 .arch
= k_architecture_x86_64
,
68 .compiler
= k_compiler_zigcc
,
69 .libc
= k_libc_version_2_23
,
72 .platform
= k_platform_anyplatform
,
80 vg_str include
, /* -I<path> */
81 library
, /* -L<path> */
83 sources
, /* file.c obj.o */
84 uid
, /* env/project identifier */
85 target
, /* result object name */
88 compiled_objects
; /* space seperated paths to compiled objects */
101 * -------------------------------------------------------------------------- */
103 static const char *platform_names
[] =
105 [k_platform_anyplatform
] = "anyplatform",
106 [k_platform_windows
] = "windows",
107 [k_platform_linux
] = "linux"
110 static const char *architecture_names
[] =
112 [k_architecture_anyarch
] = "anyarch",
113 [k_architecture_i386
] = "i386",
114 [k_architecture_x86_64
] = "x86_64"
117 static const char *compiler_names
[] =
119 [k_compiler_blob
] = "blob",
120 [k_compiler_clang
] = "clang",
121 [k_compiler_zigcc
] = "zig-cc"
124 static const char *compiler_paths
[] =
126 [k_compiler_blob
] = NULL
,
127 [k_compiler_clang
] = "clang",
128 [k_compiler_zigcc
] = "zig cc"
131 static const char *libc_names
[] =
133 [k_libc_version_native
] = "",
134 [k_libc_version_2_23
] = ".2.23"
138 * source specification
139 * -------------------------------------------------------------------------- */
141 void vg_add_source( struct vg_project
*proj
, const char *source
)
143 if( proj
->type
== k_obj_type_none
)
144 vg_fatal_error( "Cannot add source code without setting binary type\n" );
146 vg_strcat( &proj
->sources
, source
);
147 vg_strcat( &proj
->sources
, " " );
150 void vg_include_dir( struct vg_project
*proj
, const char *dir
)
152 if( proj
->type
== k_obj_type_none
)
153 vg_fatal_error( "Cannot add include dir without setting binary type\n" );
155 vg_strcat( &proj
->include
, dir
);
156 vg_strcat( &proj
->include
, " " );
159 void vg_library_dir( struct vg_project
*proj
, const char *dir
)
161 if( proj
->type
== k_obj_type_none
)
162 vg_fatal_error( "Cannot add library dir without setting binary type\n" );
164 vg_strcat( &proj
->library
, dir
);
165 vg_strcat( &proj
->library
, " " );
168 void vg_link( struct vg_project
*proj
, const char *lib
)
170 if( proj
->type
== k_obj_type_none
)
171 vg_fatal_error( "Cannot link library without setting binary type\n" );
173 vg_strcat( &proj
->link
, lib
);
178 * -------------------------------------------------------------------------- */
180 void vg_syscall( const char *fmt
, ... )
183 va_start( args
, fmt
);
186 vsnprintf( call
, sizeof(call
), fmt
, args
);
189 vg_low( "%s\n", call
);
194 void vg_add_blob( struct vg_project
*proj
, const char *blob
, const char *dest
)
196 vg_syscall( "cp %s bin/%s/%s", blob
, proj
->uid
.buffer
, dest
);
199 void vg_symlink( struct vg_project
*proj
,
200 const char *folder
, const char *bin_name
)
203 snprintf( dest
, 512, "bin/%s/%s", proj
->uid
.buffer
, bin_name
);
204 if( !access( dest
, F_OK
) )
205 vg_syscall( "unlink %s", dest
);
206 vg_syscall( "ln -srf %s %s", folder
, dest
);
209 void vg_tarball_project( struct vg_project
*proj
)
211 vg_syscall( "tar -chzvf dist/%s-%u.tar.gz bin/%s/",
212 proj
->uid
.buffer
, time(NULL
), proj
->uid
.buffer
);
216 * The project configurator and compiler.
217 * -------------------------------------------------------------------------- */
219 void vg_project_new_target( struct vg_project
*proj
, const char *name
,
224 vg_strnull( &proj
->include
, NULL
, -1 );
225 vg_strnull( &proj
->library
, NULL
, -1 );
226 vg_strnull( &proj
->link
, NULL
, -1 );
227 vg_strnull( &proj
->sources
, NULL
, -1 );
228 vg_strnull( &proj
->target
, NULL
, -1 );
231 * Setup target with appropriate extension
233 vg_strcat( &proj
->target
, name
);
235 if( proj
->env
->platform
== k_platform_windows
)
237 if( type
== k_obj_type_exe
)
238 vg_strcat( &proj
->target
, ".exe" );
239 else if( type
== k_obj_type_shared
)
240 vg_strcat( &proj
->target
, ".dll" );
241 else if( type
== k_obj_type_obj
)
242 vg_strcat( &proj
->target
, ".obj" );
246 if( proj
->env
->platform
== k_platform_linux
)
248 if( type
== k_obj_type_shared
)
249 vg_strcat( &proj
->target
, ".so" );
250 else if( type
== k_obj_type_obj
)
251 vg_strcat( &proj
->target
, ".o" );
255 * Add some regular includes / library dirs
257 if( type
!= k_obj_type_none
)
259 vg_include_dir( proj
, "-I." );
260 vg_include_dir( proj
, "-I./vg" );
261 vg_library_dir( proj
, "-L." );
262 vg_library_dir( proj
, "-L/usr/lib" );
265 vg_info( " New target: %s\n", name
);
268 void vg_project_init( struct vg_project
*proj
,
270 const char *identifier
)
273 proj
->type
= k_obj_type_none
;
275 vg_strnull( &proj
->uid
, NULL
, -1 );
276 vg_strnull( &proj
->compiled_objects
, NULL
, -1 );
278 /* check for problems in configuration */
279 if( env
->libc
!= k_libc_version_native
){
280 if( env
->compiler
!= k_compiler_zigcc
){
282 "Cannot specify libc version using the '%s' compiler.\n",
283 compiler_names
[ env
->compiler
] );
287 if( env
->compiler
== k_compiler_clang
){
288 if( env
->platform
!= k_platform_linux
){
289 vg_fatal_error( "Cannot compile for '%s' using the '%s' compiler;" );
293 vg_strcat( &proj
->uid
, identifier
);
294 vg_strcatch( &proj
->uid
, '-' );
295 vg_strcat( &proj
->uid
, platform_names
[ env
->platform
] );
296 vg_strcatch( &proj
->uid
, '-' );
297 vg_strcat( &proj
->uid
, architecture_names
[ env
->arch
] );
298 vg_strcatch( &proj
->uid
, '-' );
299 vg_strcat( &proj
->uid
, compiler_names
[ env
->compiler
] );
301 if( proj
->uid
.i
< 3 )
302 vg_fatal_error( "failed to create project UID\n" );
304 vg_info( "project_init: %s (%s, %s, compiler: %s, opt:%u, fresh: %s)\n",
306 platform_names
[env
->platform
],
307 architecture_names
[env
->arch
],
308 compiler_names
[env
->compiler
],
310 env
->fresh
? "yes":"no");
313 vg_syscall( "rm -rf bin/%s", proj
->uid
.buffer
);
314 vg_syscall( "mkdir -p bin/%s", proj
->uid
.buffer
);
317 void vg_compile_project( struct vg_project
*proj
)
320 vg_strnull( &cmd
, NULL
, -1 );
322 /* compiler specification */
323 vg_strcat( &cmd
, "ccache " );
324 vg_strcat( &cmd
, compiler_paths
[ proj
->env
->compiler
] );
325 vg_strcat( &cmd
, " -std=gnu99 -D_REENTRANT \\\n" );
327 if( proj
->env
->optimization
)
329 vg_strcat( &cmd
, " -O" );
330 vg_strcati32( &cmd
, proj
->env
->optimization
);
331 vg_strcat( &cmd
, " -flto \\\n" );
335 /* add debugger / asan information */
336 vg_strcat( &cmd
, " -O0 -ggdb3 -fno-omit-frame-pointer " );
338 if( (proj
->env
->compiler
== k_compiler_clang
) && proj
->env
->debug_asan
)
340 vg_strcat( &cmd
, " -rdynamic -fsanitize=address -fPIE "
341 "-fstack-protector-strong " );
344 vg_strcat( &cmd
, "\\\n" );
347 /* want a lot of warnings but not useless ones */
348 vg_strcat( &cmd
, " -Wall -ferror-limit=8\\\n"
349 " -Wno-unused-function -Wno-unused-variable\\\n"
350 " -Wno-unused-command-line-argument -Wno-unused-but-set-variable\\\n"
353 if( proj
->env
->compiler
!= k_compiler_clang
)
354 vg_strcat( &cmd
, " -Wno-format-truncation\\\n" );
357 vg_strcat( &cmd
, " " );
358 vg_strcat( &cmd
, proj
->include
.buffer
);
359 vg_strcat( &cmd
, "\\\n" );
362 vg_strcat( &cmd
, " " );
363 vg_strcat( &cmd
, proj
->library
.buffer
);
364 vg_strcat( &cmd
, "\\\n" );
367 vg_strcat( &cmd
, " " );
369 if( proj
->type
== k_obj_type_obj
)
370 vg_strcat( &cmd
, "-c " );
372 if( proj
->type
== k_obj_type_shared
)
373 vg_strcat( &cmd
, "-shared -fPIC " );
375 vg_strcat( &cmd
, proj
->sources
.buffer
);
376 vg_strcat( &cmd
, "\\\n" );
379 vg_strcat( &cmd
, " -o bin/" );
380 vg_strcat( &cmd
, proj
->uid
.buffer
);
381 vg_strcat( &cmd
, "/" );
382 vg_strcat( &cmd
, proj
->target
.buffer
);
383 vg_strcat( &cmd
, "\\\n" );
386 vg_strcat( &cmd
, " " );
387 vg_strcat( &cmd
, proj
->link
.buffer
);
388 vg_strcat( &cmd
, "\\\n" );
390 if( proj
->type
== k_obj_type_exe
)
392 vg_strcat( &cmd
, " -Wl,-rpath=./\\\n" );
395 /* target platform specification (zig-cc only) */
396 if( proj
->env
->compiler
== k_compiler_zigcc
){
397 vg_strcat( &cmd
, " -target " );
398 vg_strcat( &cmd
, architecture_names
[proj
->env
->arch
] );
399 vg_strcat( &cmd
, "-" );
400 vg_strcat( &cmd
, platform_names
[proj
->env
->platform
] );
402 if( proj
->env
->platform
== k_platform_linux
){
403 vg_strcat( &cmd
, "-gnu" );
404 vg_strcat( &cmd
, libc_names
[proj
->env
->libc
] );
407 if( proj
->env
->platform
== k_platform_windows
)
409 /* we currently dont want pdb pretty much ever. goodbye! */
411 if( proj
->type
== k_obj_type_exe
)
413 vg_strcat( &cmd
, " /pdb:/dev/null" );
414 vg_strcat( &cmd
, " /SUBSYSTEM:windows" );
419 vg_syscall( cmd
.buffer
);
422 vg_strcat( &proj
->compiled_objects
, "bin/" );
423 vg_strcat( &proj
->compiled_objects
, proj
->uid
.buffer
);
424 vg_strcat( &proj
->compiled_objects
, "/" );
425 vg_strcat( &proj
->compiled_objects
, proj
->target
.buffer
);
426 vg_strcat( &proj
->compiled_objects
, " \\\n " );
430 * Standard VG includes & libraries which we use for games/graphics
431 * -------------------------------------------------------------------------- */
433 struct vg_engine_config
435 bool use_3d
, legacy_support_vg_msg1
, log_source_info
, steam_api
,
436 custom_game_settings
,
440 vg_engine_default_config
= {
442 .fixed_update_hz
= 60,
443 .legacy_support_vg_msg1
= 0,
444 .log_source_info
= 1,
446 .custom_game_settings
= 0,
450 void vg_add_engine( struct vg_project
*proj
, struct vg_engine_config
*config
)
452 /* building assets */
453 vg_build_default_font();
455 if( !config
) config
= &vg_engine_default_config
;
456 vg_str config_string
;
457 vg_strnull( &config_string
, NULL
, -1 );
458 vg_strcat( &config_string
, config
->use_3d
? "-DVG_3D \\\n": "-DVG_2D \\\n" );
459 vg_strcat( &config_string
, "-DVG_TIMESTEP_FIXED=\"(1.0/" );
460 vg_strcati32( &config_string
, config
->fixed_update_hz
);
461 vg_strcat( &config_string
, ".0)\" \\\n" );
462 if( config
->legacy_support_vg_msg1
)
463 vg_strcat( &config_string
, "-DVG_MSG_V1_SUPPORT \\\n" );
464 if( config
->log_source_info
)
465 vg_strcat( &config_string
, "-DVG_LOG_SOURCE_INFO \\\n" );
466 if( config
->custom_game_settings
)
467 vg_strcat( &config_string
, "-DVG_GAME_SETTINGS \\\n" );
468 if( config
->custom_shaders
)
469 vg_strcat( &config_string
, "-DVG_CUSTOM_SHADERS \\\n" );
471 vg_strcat( &config_string
, "\\\n" );
473 /* compile heavy dependencies seperately */
474 struct vg_project dep_proj
;
475 struct vg_env env
= *proj
->env
;
476 env
.optimization
= 3;
479 vg_project_init( &dep_proj
, proj
->env
, "vg" );
481 /* external dependencies */
482 vg_project_new_target( &dep_proj
, "vg_deps", k_obj_type_obj
);
483 vg_add_source( &dep_proj
, "vg/vg_depencies.c" );
484 vg_compile_project( &dep_proj
);
487 vg_project_new_target( &dep_proj
, "vg_glad", k_obj_type_obj
);
488 vg_add_source( &dep_proj
, "vg/dep/glad/glad.c" );
489 vg_include_dir( &dep_proj
, "-I./vg/dep " );
490 vg_compile_project( &dep_proj
);
493 vg_project_new_target( &dep_proj
, "vg_engine_core", k_obj_type_obj
);
494 vg_add_source( &dep_proj
, config_string
.buffer
);
495 vg_add_source( &dep_proj
, "vg/vg_engine.c" );
496 vg_include_dir( &dep_proj
, "-I./vg/dep " );
497 vg_compile_project( &dep_proj
);
500 if( config
->steam_api
)
502 vg_project_new_target( &dep_proj
, "vg_steam", k_obj_type_obj
);
503 vg_add_source( &dep_proj
, "vg/vg_steam.c" );
504 vg_compile_project( &dep_proj
);
506 if( proj
->env
->platform
== k_platform_linux
)
508 vg_add_blob( proj
, "vg/dep/steam/libsteam_api.so", "" );
509 vg_link( proj
, "-lsteam_api " );
511 else if( proj
->env
->platform
== k_platform_windows
)
513 vg_add_blob( proj
, "vg/dep/steam/steam_api64.dll", "" );
514 vg_link( proj
, "vg/dep/steam/steam_api64.dll " );
517 vg_library_dir( proj
, "-L./vg/dep/steam " );
518 vg_include_dir( proj
, "-I./vg/dep " );
521 /* precipitate to the client project */
523 vg_link( proj
, "-lm " );
524 if( proj
->env
->platform
== k_platform_linux
)
526 vg_link( proj
, "-lSDL2 -lGL -lX11 -lXxf86vm "
527 "-lXrandr -lXi -ldl -pthread " );
529 else if( proj
->env
->platform
== k_platform_windows
)
531 vg_link( proj
, "-lSDL2main -lSDL2 -lopengl32 \\\n" );
532 vg_link( proj
, "vg/dep/sdl/SDL2.dll " );
533 vg_add_blob( proj
, "vg/dep/sdl/SDL2.dll ", "" );
534 vg_library_dir( proj
, "-L./vg/dep/sdl " );
537 vg_add_source( proj
, config_string
.buffer
);
538 vg_add_source( proj
, dep_proj
.compiled_objects
.buffer
);
539 vg_add_source( proj
, "\\\n" );
540 vg_include_dir( proj
, "-I./vg/dep " );
541 vg_link( proj
, "-lm " );
544 void vg_add_controller_database( struct vg_project
*proj
)
547 "vg/submodules/SDL_GameControllerDB/gamecontrollerdb.txt", "" );