9e5d9a7dcab17db3bead2b3a63c5834db6cd3b71
1 /* zig cc scripting tools */
11 #include "vg_string.h"
13 /* we dont free dynamic vg_strs in this program. so, we dont care.. */
14 const char *__asan_default_options() { return "detect_leaks=0"; }
25 k_platform_anyplatform
,
33 k_architecture_anyarch
,
35 k_architecture_x86_64
,
49 k_libc_version_native
,
55 struct vg_env vg_test_env
= {
56 .arch
= k_architecture_x86_64
,
57 .compiler
= k_compiler_clang
,
58 .libc
= k_libc_version_native
,
61 .platform
= k_platform_linux
,
65 struct vg_env vg_release_env
= {
66 .arch
= k_architecture_x86_64
,
67 .compiler
= k_compiler_zigcc
,
68 .libc
= k_libc_version_2_23
,
71 .platform
= k_platform_anyplatform
,
79 vg_str include
, /* -I<path> */
80 library
, /* -L<path> */
82 sources
, /* file.c obj.o */
83 uid
, /* env/project identifier */
84 target
, /* result object name */
87 compiled_objects
; /* space seperated paths to compiled objects */
100 * -------------------------------------------------------------------------- */
102 static const char *platform_names
[] =
104 [k_platform_anyplatform
] = "anyplatform",
105 [k_platform_windows
] = "windows",
106 [k_platform_linux
] = "linux"
109 static const char *architecture_names
[] =
111 [k_architecture_anyarch
] = "anyarch",
112 [k_architecture_i386
] = "i386",
113 [k_architecture_x86_64
] = "x86_64"
116 static const char *compiler_names
[] =
118 [k_compiler_blob
] = "blob",
119 [k_compiler_clang
] = "clang",
120 [k_compiler_zigcc
] = "zig-cc"
123 static const char *compiler_paths
[] =
125 [k_compiler_blob
] = NULL
,
126 [k_compiler_clang
] = "clang",
127 [k_compiler_zigcc
] = "zig cc"
130 static const char *libc_names
[] =
132 [k_libc_version_native
] = "",
133 [k_libc_version_2_23
] = ".2.23"
137 * source specification
138 * -------------------------------------------------------------------------- */
140 void vg_add_source( struct vg_project
*proj
, const char *source
)
142 if( proj
->type
== k_obj_type_none
)
143 vg_fatal_error( "Cannot add source code without setting binary type\n" );
145 vg_strcat( &proj
->sources
, source
);
146 vg_strcat( &proj
->sources
, " " );
149 void vg_include_dir( struct vg_project
*proj
, const char *dir
)
151 if( proj
->type
== k_obj_type_none
)
152 vg_fatal_error( "Cannot add include dir without setting binary type\n" );
154 vg_strcat( &proj
->include
, dir
);
155 vg_strcat( &proj
->include
, " " );
158 void vg_library_dir( struct vg_project
*proj
, const char *dir
)
160 if( proj
->type
== k_obj_type_none
)
161 vg_fatal_error( "Cannot add library dir without setting binary type\n" );
163 vg_strcat( &proj
->library
, dir
);
164 vg_strcat( &proj
->library
, " " );
167 void vg_link( struct vg_project
*proj
, const char *lib
)
169 if( proj
->type
== k_obj_type_none
)
170 vg_fatal_error( "Cannot link library without setting binary type\n" );
172 vg_strcat( &proj
->link
, lib
);
177 * -------------------------------------------------------------------------- */
179 void vg_syscall( const char *fmt
, ... )
182 va_start( args
, fmt
);
185 vsnprintf( call
, sizeof(call
), fmt
, args
);
188 vg_low( "%s\n", call
);
193 void vg_add_blob( struct vg_project
*proj
, const char *blob
, const char *dest
)
195 vg_syscall( "cp %s bin/%s/%s", blob
, proj
->uid
.buffer
, dest
);
198 void vg_symlink( struct vg_project
*proj
,
199 const char *folder
, const char *bin_name
)
202 snprintf( dest
, 512, "bin/%s/%s", proj
->uid
.buffer
, bin_name
);
203 if( !access( dest
, F_OK
) )
204 vg_syscall( "unlink %s", dest
);
205 vg_syscall( "ln -srf %s %s", folder
, dest
);
208 void vg_tarball_project( struct vg_project
*proj
)
210 vg_syscall( "tar -chzvf dist/%s-%u.tar.gz bin/%s/",
211 proj
->uid
.buffer
, time(NULL
), proj
->uid
.buffer
);
215 * The project configurator and compiler.
216 * -------------------------------------------------------------------------- */
218 void vg_project_new_target( struct vg_project
*proj
, const char *name
,
223 vg_strnull( &proj
->include
, NULL
, -1 );
224 vg_strnull( &proj
->library
, NULL
, -1 );
225 vg_strnull( &proj
->link
, NULL
, -1 );
226 vg_strnull( &proj
->sources
, NULL
, -1 );
227 vg_strnull( &proj
->target
, NULL
, -1 );
230 * Setup target with appropriate extension
232 vg_strcat( &proj
->target
, name
);
234 if( proj
->env
->platform
== k_platform_windows
)
236 if( type
== k_obj_type_exe
)
237 vg_strcat( &proj
->target
, ".exe" );
238 else if( type
== k_obj_type_shared
)
239 vg_strcat( &proj
->target
, ".dll" );
240 else if( type
== k_obj_type_obj
)
241 vg_strcat( &proj
->target
, ".obj" );
245 if( proj
->env
->platform
== k_platform_linux
)
247 if( type
== k_obj_type_shared
)
248 vg_strcat( &proj
->target
, ".so" );
249 else if( type
== k_obj_type_obj
)
250 vg_strcat( &proj
->target
, ".o" );
254 * Add some regular includes / library dirs
256 if( type
!= k_obj_type_none
)
258 vg_include_dir( proj
, "-I." );
259 vg_include_dir( proj
, "-I./vg" );
260 vg_library_dir( proj
, "-L." );
261 vg_library_dir( proj
, "-L/usr/lib" );
264 vg_info( " New target: %s\n", name
);
267 void vg_project_init( struct vg_project
*proj
,
269 const char *identifier
)
272 proj
->type
= k_obj_type_none
;
274 vg_strnull( &proj
->uid
, NULL
, -1 );
275 vg_strnull( &proj
->compiled_objects
, NULL
, -1 );
277 /* check for problems in configuration */
278 if( env
->libc
!= k_libc_version_native
){
279 if( env
->compiler
!= k_compiler_zigcc
){
281 "Cannot specify libc version using the '%s' compiler.\n",
282 compiler_names
[ env
->compiler
] );
286 if( env
->compiler
== k_compiler_clang
){
287 if( env
->platform
!= k_platform_linux
){
288 vg_fatal_error( "Cannot compile for '%s' using the '%s' compiler;" );
292 vg_strcat( &proj
->uid
, identifier
);
293 vg_strcatch( &proj
->uid
, '-' );
294 vg_strcat( &proj
->uid
, platform_names
[ env
->platform
] );
295 vg_strcatch( &proj
->uid
, '-' );
296 vg_strcat( &proj
->uid
, architecture_names
[ env
->arch
] );
297 vg_strcatch( &proj
->uid
, '-' );
298 vg_strcat( &proj
->uid
, compiler_names
[ env
->compiler
] );
300 if( proj
->uid
.i
< 3 )
301 vg_fatal_error( "failed to create project UID\n" );
303 vg_info( "project_init: %s (%s, %s, compiler: %s, opt:%u, fresh: %s)\n",
305 platform_names
[env
->platform
],
306 architecture_names
[env
->arch
],
307 compiler_names
[env
->compiler
],
309 env
->fresh
? "yes":"no");
312 vg_syscall( "rm -rf bin/%s", proj
->uid
.buffer
);
313 vg_syscall( "mkdir -p bin/%s", proj
->uid
.buffer
);
316 void vg_compile_project( struct vg_project
*proj
)
319 vg_strnull( &cmd
, NULL
, -1 );
321 /* compiler specification */
322 vg_strcat( &cmd
, "ccache " );
323 vg_strcat( &cmd
, compiler_paths
[ proj
->env
->compiler
] );
324 vg_strcat( &cmd
, " -std=gnu99 -D_REENTRANT \\\n" );
326 if( proj
->env
->optimization
)
328 vg_strcat( &cmd
, " -O" );
329 vg_strcati32( &cmd
, proj
->env
->optimization
);
330 vg_strcat( &cmd
, " -flto \\\n" );
334 /* add debugger / asan information */
335 vg_strcat( &cmd
, " -O0 -ggdb3 -fno-omit-frame-pointer " );
337 if( (proj
->env
->compiler
== k_compiler_clang
) && proj
->env
->debug_asan
)
339 vg_strcat( &cmd
, " -rdynamic -fsanitize=address -fPIE "
340 "-fstack-protector-strong " );
343 vg_strcat( &cmd
, "\\\n" );
346 /* want a lot of warnings but not useless ones */
347 vg_strcat( &cmd
, " -Wall -ferror-limit=8\\\n"
348 " -Wno-unused-function -Wno-unused-variable\\\n"
349 " -Wno-unused-command-line-argument -Wno-unused-but-set-variable\\\n"
352 if( proj
->env
->compiler
!= k_compiler_clang
)
353 vg_strcat( &cmd
, " -Wno-format-truncation\\\n" );
356 vg_strcat( &cmd
, " " );
357 vg_strcat( &cmd
, proj
->include
.buffer
);
358 vg_strcat( &cmd
, "\\\n" );
361 vg_strcat( &cmd
, " " );
362 vg_strcat( &cmd
, proj
->library
.buffer
);
363 vg_strcat( &cmd
, "\\\n" );
366 vg_strcat( &cmd
, " " );
368 if( proj
->type
== k_obj_type_obj
)
369 vg_strcat( &cmd
, "-c " );
371 if( proj
->type
== k_obj_type_shared
)
372 vg_strcat( &cmd
, "-shared -fPIC " );
374 vg_strcat( &cmd
, proj
->sources
.buffer
);
375 vg_strcat( &cmd
, "\\\n" );
378 vg_strcat( &cmd
, " -o bin/" );
379 vg_strcat( &cmd
, proj
->uid
.buffer
);
380 vg_strcat( &cmd
, "/" );
381 vg_strcat( &cmd
, proj
->target
.buffer
);
382 vg_strcat( &cmd
, "\\\n" );
385 vg_strcat( &cmd
, " " );
386 vg_strcat( &cmd
, proj
->link
.buffer
);
387 vg_strcat( &cmd
, "\\\n" );
389 if( proj
->type
== k_obj_type_exe
)
391 vg_strcat( &cmd
, " -Wl,-rpath=./\\\n" );
394 /* target platform specification (zig-cc only) */
395 if( proj
->env
->compiler
== k_compiler_zigcc
){
396 vg_strcat( &cmd
, " -target " );
397 vg_strcat( &cmd
, architecture_names
[proj
->env
->arch
] );
398 vg_strcat( &cmd
, "-" );
399 vg_strcat( &cmd
, platform_names
[proj
->env
->platform
] );
401 if( proj
->env
->platform
== k_platform_linux
){
402 vg_strcat( &cmd
, "-gnu" );
403 vg_strcat( &cmd
, libc_names
[proj
->env
->libc
] );
406 if( proj
->env
->platform
== k_platform_windows
)
408 /* we currently dont want pdb pretty much ever. goodbye! */
410 if( proj
->type
== k_obj_type_exe
)
412 vg_strcat( &cmd
, " /pdb:/dev/null" );
413 vg_strcat( &cmd
, " /SUBSYSTEM:windows" );
418 vg_syscall( cmd
.buffer
);
421 vg_strcat( &proj
->compiled_objects
, "bin/" );
422 vg_strcat( &proj
->compiled_objects
, proj
->uid
.buffer
);
423 vg_strcat( &proj
->compiled_objects
, "/" );
424 vg_strcat( &proj
->compiled_objects
, proj
->target
.buffer
);
425 vg_strcat( &proj
->compiled_objects
, " \\\n " );
429 * Standard VG includes & libraries which we use for games/graphics
430 * -------------------------------------------------------------------------- */
432 struct vg_engine_config
434 bool use_3d
, legacy_support_vg_msg1
, log_source_info
, steam_api
,
435 custom_game_settings
,
439 vg_engine_default_config
= {
441 .fixed_update_hz
= 60,
442 .legacy_support_vg_msg1
= 0,
443 .log_source_info
= 1,
445 .custom_game_settings
= 0,
449 void vg_add_engine( struct vg_project
*proj
, struct vg_engine_config
*config
)
451 if( !config
) config
= &vg_engine_default_config
;
452 vg_str config_string
;
453 vg_strnull( &config_string
, NULL
, -1 );
454 vg_strcat( &config_string
, config
->use_3d
? "-DVG_3D \\\n": "-DVG_2D \\\n" );
455 vg_strcat( &config_string
, "-DVG_TIMESTEP_FIXED=\"(1.0/" );
456 vg_strcati32( &config_string
, config
->fixed_update_hz
);
457 vg_strcat( &config_string
, ".0)\" \\\n" );
458 if( config
->legacy_support_vg_msg1
)
459 vg_strcat( &config_string
, "-DVG_MSG_V1_SUPPORT \\\n" );
460 if( config
->log_source_info
)
461 vg_strcat( &config_string
, "-DVG_LOG_SOURCE_INFO \\\n" );
462 if( config
->custom_game_settings
)
463 vg_strcat( &config_string
, "-DVG_GAME_SETTINGS \\\n" );
464 if( config
->custom_game_settings
)
465 vg_strcat( &config_string
, "-DVG_RELEASE \\\n" );
467 vg_strcat( &config_string
, "\\\n" );
469 /* compile heavy dependencies seperately */
470 struct vg_project dep_proj
;
471 struct vg_env env
= *proj
->env
;
472 env
.optimization
= 3;
475 vg_project_init( &dep_proj
, proj
->env
, "vg" );
477 /* external dependencies */
478 vg_project_new_target( &dep_proj
, "vg_deps", k_obj_type_obj
);
479 vg_add_source( &dep_proj
, "vg/vg_depencies.c" );
480 vg_compile_project( &dep_proj
);
483 vg_project_new_target( &dep_proj
, "vg_glad", k_obj_type_obj
);
484 vg_add_source( &dep_proj
, "vg/dep/glad/glad.c" );
485 vg_include_dir( &dep_proj
, "-I./vg/dep " );
486 vg_compile_project( &dep_proj
);
489 vg_project_new_target( &dep_proj
, "vg_engine_core", k_obj_type_obj
);
490 vg_add_source( &dep_proj
, config_string
.buffer
);
491 vg_add_source( &dep_proj
, "vg/vg_engine.c" );
492 vg_include_dir( &dep_proj
, "-I./vg/dep " );
493 vg_compile_project( &dep_proj
);
496 if( config
->steam_api
)
498 vg_project_new_target( &dep_proj
, "vg_steam", k_obj_type_obj
);
499 vg_add_source( &dep_proj
, "vg/vg_steam.c" );
500 vg_compile_project( &dep_proj
);
502 if( proj
->env
->platform
== k_platform_linux
)
504 vg_add_blob( proj
, "vg/dep/steam/libsteam_api.so", "" );
505 vg_link( proj
, "-lsteam_api " );
507 else if( proj
->env
->platform
== k_platform_windows
)
509 vg_add_blob( proj
, "vg/dep/steam/steam_api64.dll", "" );
510 vg_link( proj
, "vg/dep/steam/steam_api64.dll " );
513 vg_library_dir( proj
, "-L./vg/dep/steam " );
514 vg_include_dir( proj
, "-I./vg/dep " );
517 /* precipitate to the client project */
519 vg_link( proj
, "-lm " );
520 if( proj
->env
->platform
== k_platform_linux
)
522 vg_link( proj
, "-lSDL2 -lGL -lX11 -lXxf86vm "
523 "-lXrandr -lXi -ldl -pthread " );
525 else if( proj
->env
->platform
== k_platform_windows
)
527 vg_link( proj
, "-lSDL2main -lSDL2 -lopengl32 \\\n" );
528 vg_link( proj
, "vg/dep/sdl/SDL2.dll " );
529 vg_add_blob( proj
, "vg/dep/sdl/SDL2.dll ", "" );
530 vg_library_dir( proj
, "-L./vg/dep/sdl " );
533 vg_add_source( proj
, config_string
.buffer
);
534 vg_add_source( proj
, dep_proj
.compiled_objects
.buffer
);
535 vg_add_source( proj
, "\\\n" );
536 vg_include_dir( proj
, "-I./vg/dep " );
537 vg_link( proj
, "-lm " );
540 void vg_add_controller_database( struct vg_project
*proj
)
543 "vg/submodules/SDL_GameControllerDB/gamecontrollerdb.txt", "" );