nob.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. #define NOB_IMPLEMENTATION
  2. #define NOB_STRIP_PREFIX
  3. #define NOB_EXPERIMENTAL_DELETE_OLD
  4. #define NOB_WARN_DEPRECATED
  5. #include "./dev-deps/nob.h"
  6. #define COMMON_CFLAGS "-Wall", "-Wextra", "-pedantic", "-ggdb", "-I.", "-I./build/", "-I./dev-deps/"
  7. bool build_tools(Cmd *cmd, Procs *procs)
  8. {
  9. if (!mkdir_if_not_exists("build")) return false;
  10. if (!mkdir_if_not_exists("build/tools")) return false;
  11. cmd_append(cmd, "clang", COMMON_CFLAGS, "-o", "./build/tools/png2c", "./tools/png2c.c", "-lm");
  12. if (!cmd_run(cmd, .async = procs)) return false;
  13. cmd_append(cmd, "clang", COMMON_CFLAGS, "-o", "./build/tools/obj2c", "./tools/obj2c.c", "-lm");
  14. if (!cmd_run(cmd, .async = procs)) return false;
  15. return true;
  16. }
  17. bool build_assets(Cmd *cmd, Procs *procs)
  18. {
  19. if (!mkdir_if_not_exists("build")) return false;
  20. if (!mkdir_if_not_exists("build/assets")) return false;
  21. cmd_append(cmd, "./build/tools/png2c", "-n", "tsodinPog", "-o", "./build/assets/tsodinPog.c", "./assets/tsodinPog.png");
  22. if (!cmd_run(cmd, .async = procs)) return false;
  23. cmd_append(cmd, "./build/tools/png2c", "-n", "tsodinCup", "-o", "./build/assets/tsodinCup.c", "./assets/tsodinCup.png");
  24. if (!cmd_run(cmd, .async = procs)) return false;
  25. cmd_append(cmd, "./build/tools/png2c", "-n", "oldstone", "-o", "./build/assets/oldstone.c", "./assets/oldstone.png");
  26. if (!cmd_run(cmd, .async = procs)) return false;
  27. cmd_append(cmd, "./build/tools/png2c", "-n", "lavastone", "-o", "./build/assets/lavastone.c", "./assets/lavastone.png");
  28. if (!cmd_run(cmd, .async = procs)) return false;
  29. cmd_append(cmd, "./build/tools/obj2c", "-o", "./build/assets/tsodinCupLowPoly.c", "./assets/tsodinCupLowPoly.obj");
  30. if (!cmd_run(cmd, .async = procs)) return false;
  31. cmd_append(cmd, "./build/tools/obj2c", "-s", "0.40", "-o", "./build/assets/utahTeapot.c", "./assets/utahTeapot.obj");
  32. if (!cmd_run(cmd, .async = procs)) return false;
  33. cmd_append(cmd, "./build/tools/obj2c", "-s", "1.5", "-o", "./build/assets/penger.c", "./assets/penger_obj/penger.obj");
  34. if (!cmd_run(cmd, .async = procs)) return false;
  35. return true;
  36. }
  37. bool build_tests(Cmd *cmd, Procs *procs)
  38. {
  39. cmd_append(cmd, "clang", COMMON_CFLAGS, "-fsanitize=memory", "-o", "./build/test", "test.c", "-lm");
  40. if (!cmd_run(cmd, .async = procs)) return false;
  41. return true;
  42. }
  43. bool build_wasm_demo(Cmd *cmd, Procs *procs, const char *name)
  44. {
  45. cmd_append(cmd, "clang", COMMON_CFLAGS, "-O2", "-fno-builtin", "--target=wasm32", "--no-standard-libraries", "-Wl,--no-entry", "-Wl,--export=vc_render", "-Wl,--export=__heap_base", "-Wl,--allow-undefined", "-o", temp_sprintf("./build/demos/%s.wasm", name), "-DVC_PLATFORM=VC_WASM_PLATFORM", temp_sprintf("./demos/%s.c", name));
  46. return cmd_run(cmd, .async = procs);
  47. }
  48. bool build_term_demo(Cmd *cmd, Procs *procs, const char *name)
  49. {
  50. cmd_append(cmd, "clang", COMMON_CFLAGS, "-O2", "-o", temp_sprintf("./build/demos/%s.term", name), "-DVC_PLATFORM=VC_TERM_PLATFORM", "-D_XOPEN_SOURCE=600", temp_sprintf("./demos/%s.c", name), "-lm");
  51. return cmd_run(cmd, .async = procs);
  52. }
  53. bool build_sdl_demo(Cmd *cmd, Procs *procs, const char *name)
  54. {
  55. cmd_append(cmd, "clang", COMMON_CFLAGS, "-O2", "-o", temp_sprintf("./build/demos/%s.sdl", name), "-DVC_PLATFORM=VC_SDL_PLATFORM", temp_sprintf("./demos/%s.c", name), "-lm", "-lSDL2", NULL);
  56. return cmd_run(cmd, .async = procs);
  57. }
  58. bool build_vc_demo(Cmd *cmd, Procs *procs, const char *name)
  59. {
  60. if (!build_wasm_demo(cmd, procs, name)) return false;
  61. if (!build_term_demo(cmd, procs, name)) return false;
  62. if (!build_sdl_demo(cmd, procs, name)) return false;
  63. return true;
  64. }
  65. const char *vc_demo_names[] = {
  66. "triangle",
  67. "dots3d",
  68. "squish",
  69. "triangle3d",
  70. "triangleTex",
  71. "triangle3dTex",
  72. "cup3d",
  73. "teapot3d",
  74. "penger3d",
  75. };
  76. bool copy_all_vc_demos_to_build(void)
  77. {
  78. for (size_t i = 0; i < ARRAY_LEN(vc_demo_names); ++i) {
  79. const char *src_path = temp_sprintf("./build/demos/%s.wasm", vc_demo_names[i]);
  80. const char *dst_path = temp_sprintf("./wasm/%s.wasm", vc_demo_names[i]);
  81. if (!copy_file(src_path, dst_path)) return false;
  82. }
  83. return true;
  84. }
  85. bool build_all_vc_demos(Cmd *cmd, Procs *procs)
  86. {
  87. if (!mkdir_if_not_exists("build")) return false;
  88. if (!mkdir_if_not_exists("build/demos")) return false;
  89. for (size_t i = 0; i < ARRAY_LEN(vc_demo_names); ++i) {
  90. if (!build_vc_demo(cmd, procs, vc_demo_names[i])) return false;
  91. }
  92. return true;
  93. }
  94. void usage(const char *program)
  95. {
  96. nob_log(INFO, "Usage: %s [<subcommand>]", program);
  97. nob_log(INFO, "Subcommands:");
  98. nob_log(INFO, " tools");
  99. nob_log(INFO, " Build all the tools. Things like png2c, obj2c, etc.");
  100. nob_log(INFO, " assets");
  101. nob_log(INFO, " Build the assets in the assets/ folder.");
  102. nob_log(INFO, " Basically convert their data to C code so we can bake them in demos.");
  103. nob_log(INFO, " test[s] [<args>]");
  104. nob_log(INFO, " Build and run test.c");
  105. nob_log(INFO, " If <args> are provided the test utility is run with them.");
  106. nob_log(INFO, " demos [<platform>] [run]");
  107. nob_log(INFO, " Build demos.");
  108. nob_log(INFO, " Available platforms are: sdl, term, or wasm.");
  109. nob_log(INFO, " Optional [run] runs the demo after the build.");
  110. nob_log(INFO, " [run] is not available for wasm platform.");
  111. nob_log(INFO, " help");
  112. nob_log(INFO, " Print this message");
  113. }
  114. int main(int argc, char **argv)
  115. {
  116. NOB_GO_REBUILD_URSELF(argc, argv);
  117. Cmd cmd = {0};
  118. Procs procs = {0};
  119. const char *program = shift_args(&argc, &argv);
  120. if (argc > 0) {
  121. const char *subcmd = shift_args(&argc, &argv);
  122. if (strcmp(subcmd, "tools") == 0) {
  123. if (!build_tools(&cmd, &procs)) return 1;
  124. if (!procs_flush(&procs)) return 1;
  125. } else if (strcmp(subcmd, "assets") == 0) {
  126. if (!build_assets(&cmd, &procs)) return 1;
  127. if (!procs_flush(&procs)) return 1;
  128. } else if (strcmp(subcmd, "tests") == 0 || strcmp(subcmd, "test") == 0) {
  129. if (!build_tests(&cmd, &procs)) return 1;
  130. if (!procs_flush(&procs)) return 1;
  131. if (argc > 0) {
  132. cmd_append(&cmd, "./build/test");
  133. da_append_many(&cmd, argv, argc);
  134. if (!cmd_run(&cmd)) return 1;
  135. }
  136. } else if (strcmp(subcmd, "demos") == 0) {
  137. if (argc <= 0) {
  138. if (!build_all_vc_demos(&cmd, &procs)) return 1;
  139. if (!procs_flush(&procs));
  140. return 0;
  141. }
  142. const char *name = shift(argv, argc);
  143. if (argc <= 0) {
  144. if (build_vc_demo(&cmd, &procs, name)) return 1;
  145. if (!procs_flush(&procs)) return 1;
  146. const char *src_path = temp_sprintf("./build/demos/%s.wasm", name);
  147. const char *dst_path = temp_sprintf("./wasm/%s.wasm", name);
  148. if (!copy_file(src_path, dst_path)) return 1;
  149. return 0;
  150. }
  151. const char *platform = shift(argv, argc);
  152. if (strcmp(platform, "sdl") == 0) {
  153. if (!build_sdl_demo(&cmd, &procs, name)) return 1;
  154. if (!procs_flush(&procs)) return 1;
  155. if (argc <= 0) return 0;
  156. const char *run = shift(argv, argc);
  157. if (strcmp(run, "run") != 0) {
  158. usage(program);
  159. nob_log(ERROR, "unknown action `%s` for SDL demo: %s", run, name);
  160. return 1;
  161. }
  162. cmd_append(&cmd, temp_sprintf("./build/demos/%s.sdl", name));
  163. if (!cmd_run(&cmd)) return 1;
  164. return 0;
  165. } else if (strcmp(platform, "term") == 0) {
  166. if (!build_term_demo(&cmd, &procs, name)) return 1;
  167. if (!procs_flush(&procs)) return 1;
  168. if (argc <= 0) return 0;
  169. const char *run = shift(argv, argc);
  170. if (strcmp(run, "run") != 0) {
  171. usage(program);
  172. nob_log(ERROR, "unknown action `%s` for Terminal demo: %s", run, name);
  173. return 1;
  174. }
  175. cmd_append(&cmd, temp_sprintf("./build/demos/%s.term", name));
  176. if (!cmd_run(&cmd)) return 1;
  177. return 0;
  178. } else if (strcmp(platform, "wasm") == 0) {
  179. if (!build_wasm_demo(&cmd, &procs, name)) return 1;
  180. if (!procs_flush(&procs)) return 1;
  181. const char *src_path = temp_sprintf("./build/demos/%s.wasm", name);
  182. const char *dst_path = temp_sprintf("./wasm/%s.wasm", name);
  183. if (!copy_file(src_path, dst_path)) return 1;
  184. } else {
  185. usage(program);
  186. nob_log(ERROR, "unknown demo platform %s", platform);
  187. return 1;
  188. }
  189. } else if(strcmp(subcmd, "help") == 0) {
  190. usage(program);
  191. } else {
  192. usage(program);
  193. nob_log(ERROR, "Unknown command `%s`", subcmd);
  194. return 1;
  195. }
  196. } else {
  197. if (!build_tools(&cmd, &procs)) return 1;
  198. if (!procs_flush(&procs)) return 1;
  199. if (!build_assets(&cmd, &procs)) return 1;
  200. if (!procs_flush(&procs)) return 1;
  201. if (!build_tests(&cmd, &procs)) return 1;
  202. if (!procs_flush(&procs)) return 1;
  203. if (!build_all_vc_demos(&cmd, &procs)) return 1;
  204. if (!procs_flush(&procs)) return 1;
  205. if (!copy_all_vc_demos_to_build()) return 1;
  206. }
  207. return 0;
  208. }