nob_stage2.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. #include <stdbool.h>
  2. #define NOB_IMPLEMENTATION
  3. #define NOB_STRIP_PREFIX
  4. // #define NOB_WARN_DEPRECATED
  5. #include "../thirdparty/nob.h"
  6. #include "../build/config.h"
  7. #include "./configurer.c"
  8. static const char *raylib_modules[] = {
  9. "rcore",
  10. "raudio",
  11. "rglfw",
  12. "rmodels",
  13. "rshapes",
  14. "rtext",
  15. "rtextures",
  16. "utils",
  17. };
  18. // @backcomp
  19. #if defined(MUSIALIZER_TARGET)
  20. #error "We recently replaced a single MUSIALIZER_TARGET macro with a bunch of MUSIALIZER_TARGET_<TARGET> macros instead. Since MUSIALIZER_TARGET is still defined your ./build/ is probably old. Please remove it so ./build/config.h gets regenerated."
  21. #endif // MUSIALIZER_TARGET
  22. #if defined(MUSIALIZER_TARGET_LINUX)
  23. #include "nob_linux.c"
  24. #elif defined(MUSIALIZER_TARGET_MACOS)
  25. #include "nob_macos.c"
  26. #elif defined(MUSIALIZER_TARGET_WIN64_MINGW)
  27. #include "nob_win64_mingw.c"
  28. #elif defined(MUSIALIZER_TARGET_WIN64_MSVC)
  29. #include "nob_win64_msvc.c"
  30. #elif defined(MUSIALIZER_TARGET_OPENBSD)
  31. #include "nob_openbsd.c"
  32. #else
  33. #error "No Musializer Target is defined. Check your ./build/config.h."
  34. #endif // MUSIALIZER_TARGET
  35. #include "../build/config_logger.c"
  36. void log_available_subcommands(const char *program, Nob_Log_Level level)
  37. {
  38. nob_log(level, "Usage: %s [subcommand]", program);
  39. nob_log(level, "Subcommands:");
  40. nob_log(level, " build (default)");
  41. nob_log(level, " dist");
  42. nob_log(level, " svg");
  43. nob_log(level, " help");
  44. }
  45. typedef struct {
  46. const char *file_path;
  47. size_t offset;
  48. size_t size;
  49. } Resource;
  50. Resource resources[] = {
  51. { .file_path = "./resources/logo/logo-256.png" },
  52. { .file_path = "./resources/shaders/glsl330/circle.fs" },
  53. { .file_path = "./resources/shaders/glsl120/circle.fs" },
  54. { .file_path = "./resources/icons/volume.png" },
  55. { .file_path = "./resources/icons/play.png" },
  56. { .file_path = "./resources/icons/render.png" },
  57. { .file_path = "./resources/icons/fullscreen.png" },
  58. { .file_path = "./resources/icons/microphone.png" },
  59. { .file_path = "./resources/fonts/Alegreya-Regular.ttf" },
  60. };
  61. bool generate_resource_bundle(void)
  62. {
  63. bool result = true;
  64. Nob_String_Builder bundle = {0};
  65. Nob_String_Builder content = {0};
  66. FILE *out = NULL;
  67. // bundle = [aaaaaaaaabbbbb]
  68. // ^ ^
  69. // content = []
  70. // 0, 9
  71. for (size_t i = 0; i < NOB_ARRAY_LEN(resources); ++i) {
  72. content.count = 0;
  73. if (!nob_read_entire_file(resources[i].file_path, &content)) nob_return_defer(false);
  74. resources[i].offset = bundle.count;
  75. resources[i].size = content.count;
  76. nob_da_append_many(&bundle, content.items, content.count);
  77. nob_da_append(&bundle, 0);
  78. }
  79. const char *bundle_h_path = "./build/bundle.h";
  80. out = fopen(bundle_h_path, "wb");
  81. if (out == NULL) {
  82. nob_log(NOB_ERROR, "Could not open file %s for writing: %s", bundle_h_path, strerror(errno));
  83. nob_return_defer(false);
  84. }
  85. genf(out, "#ifndef BUNDLE_H_");
  86. genf(out, "#define BUNDLE_H_");
  87. genf(out, "typedef struct {");
  88. genf(out, " const char *file_path;");
  89. genf(out, " size_t offset;");
  90. genf(out, " size_t size;");
  91. genf(out, "} Resource;");
  92. genf(out, "size_t resources_count = %zu;", NOB_ARRAY_LEN(resources));
  93. genf(out, "Resource resources[] = {");
  94. for (size_t i = 0; i < NOB_ARRAY_LEN(resources); ++i) {
  95. genf(out, " {.file_path = \"%s\", .offset = %zu, .size = %zu},",
  96. resources[i].file_path, resources[i].offset, resources[i].size);
  97. }
  98. genf(out, "};");
  99. genf(out, "unsigned char bundle[] = {");
  100. size_t row_size = 20;
  101. for (size_t i = 0; i < bundle.count; ) {
  102. fprintf(out, " ");
  103. for (size_t col = 0; col < row_size && i < bundle.count; ++col, ++i) {
  104. fprintf(out, "0x%02X, ", (unsigned char)bundle.items[i]);
  105. }
  106. genf(out, "");
  107. }
  108. genf(out, "};");
  109. genf(out, "#endif // BUNDLE_H_");
  110. nob_log(NOB_INFO, "Generated %s", bundle_h_path);
  111. defer:
  112. if (out) fclose(out);
  113. free(content.items);
  114. free(bundle.items);
  115. return result;
  116. }
  117. int main(int argc, char **argv)
  118. {
  119. nob_log(NOB_INFO, "--- STAGE 2 ---");
  120. log_config(NOB_INFO);
  121. nob_log(NOB_INFO, "---");
  122. const char *program = nob_shift_args(&argc, &argv);
  123. const char *subcommand = NULL;
  124. if (argc <= 0) {
  125. subcommand = "build";
  126. } else {
  127. subcommand = nob_shift_args(&argc, &argv);
  128. }
  129. if (strcmp(subcommand, "build") == 0) {
  130. if (!build_raylib()) return 1;
  131. #ifndef MUSIALIZER_UNBUNDLE
  132. if (!generate_resource_bundle()) return 1;
  133. #endif // MUSIALIZER_UNBUNDLE
  134. if (!build_musializer()) return 1;
  135. } else if (strcmp(subcommand, "dist") == 0) {
  136. if (!build_dist()) return 1;
  137. } else if (strcmp(subcommand, "config") == 0) {
  138. nob_log(NOB_ERROR, "The `config` command does not exist anymore!");
  139. nob_log(NOB_ERROR, "Edit %s to configure the build!", CONFIG_PATH);
  140. return 1;
  141. } else if (strcmp(subcommand, "svg") == 0) {
  142. Nob_Procs procs = {0};
  143. Nob_Cmd cmd = {0};
  144. typedef struct {
  145. const char *in_path;
  146. const char *out_path;
  147. int resize;
  148. } Svg;
  149. Svg svgs[] = {
  150. {.out_path = "./resources/logo/logo-256.ico", .in_path = "./resources/logo/logo.svg", .resize = 256, },
  151. {.out_path = "./resources/logo/logo-256.png", .in_path = "./resources/logo/logo.svg", .resize = 256, },
  152. {.out_path = "./resources/icons/fullscreen.png", .in_path = "./resources/icons/fullscreen.svg" },
  153. {.out_path = "./resources/icons/volume.png", .in_path = "./resources/icons/volume.svg" },
  154. {.out_path = "./resources/icons/play.png", .in_path = "./resources/icons/play.svg" },
  155. {.out_path = "./resources/icons/render.png", .in_path = "./resources/icons/render.svg" },
  156. {.out_path = "./resources/icons/microphone.png", .in_path = "./resources/icons/microphone.svg" },
  157. };
  158. for (size_t i = 0; i < NOB_ARRAY_LEN(svgs); ++i) {
  159. if (nob_needs_rebuild1(svgs[i].out_path, svgs[i].in_path)) {
  160. cmd.count = 0;
  161. nob_cmd_append(&cmd, "convert");
  162. nob_cmd_append(&cmd, "-background", "None");
  163. nob_cmd_append(&cmd, svgs[i].in_path);
  164. if (svgs[i].resize) {
  165. nob_cmd_append(&cmd, "-resize", nob_temp_sprintf("%d", svgs[i].resize));
  166. }
  167. nob_cmd_append(&cmd, svgs[i].out_path);
  168. if (!nob_cmd_run(&cmd, .async = &procs)) return 1;
  169. } else {
  170. nob_log(NOB_INFO, "%s is up to date", svgs[i].out_path);
  171. }
  172. }
  173. if (!nob_procs_wait(procs)) return 1;
  174. } else if (strcmp(subcommand, "help") == 0) {
  175. log_available_subcommands(program, NOB_INFO);
  176. } else {
  177. nob_log(NOB_ERROR, "Unknown subcommand %s", subcommand);
  178. log_available_subcommands(program, NOB_ERROR);
  179. }
  180. // TODO: it would be nice to check for situations like building TARGET_WIN64_MSVC on Linux and report that it's not possible.
  181. return 0;
  182. }