@@ -72,6 +72,36 @@ fn srcDir(b: *std.Build) []const u8 {
72
72
return std .fs .path .dirname (src_file ) orelse "." ;
73
73
}
74
74
75
+ /// A list of all flags from `src/config.h` that one may override
76
+ const config_h_flags = outer : {
77
+ // Set this value higher if compile errors happen as `src/config.h` gets larger
78
+ @setEvalBranchQuota (1 << 20 );
79
+
80
+ const config_h = @embedFile ("config.h" );
81
+ var flags : [std .mem .count (u8 , config_h , "\n " ) + 1 ][]const u8 = undefined ;
82
+
83
+ var i = 0 ;
84
+ var lines = std .mem .tokenizeScalar (u8 , config_h , '\n ' );
85
+ while (lines .next ()) | line | {
86
+ if (! std .mem .containsAtLeast (u8 , line , 1 , "SUPPORT" )) continue ;
87
+ if (std .mem .startsWith (u8 , line , "//" )) continue ;
88
+ if (std .mem .startsWith (u8 , line , "#if" )) continue ;
89
+
90
+ var flag = std .mem .trimLeft (u8 , line , " \t " ); // Trim whitespace
91
+ flag = flag ["#define " .len - 1 .. ]; // Remove #define
92
+ flag = std .mem .trimLeft (u8 , flag , " \t " ); // Trim whitespace
93
+ flag = flag [0 .. std .mem .indexOf (u8 , flag , " " ) orelse continue ]; // Flag is only one word, so capture till space
94
+ flag = "-D" ++ flag ; // Prepend with -D
95
+
96
+ flags [i ] = flag ;
97
+ i += 1 ;
98
+ }
99
+
100
+ // Uncomment this to check what flags normally get passed
101
+ //@compileLog(flags[0..i].*);
102
+ break :outer flags [0.. i ].* ;
103
+ };
104
+
75
105
fn compileRaylib (b : * std.Build , target : std.Build.ResolvedTarget , optimize : std.builtin.OptimizeMode , options : Options ) ! * std.Build.Step.Compile {
76
106
raylib_flags_arr .clearRetainingCapacity ();
77
107
@@ -86,33 +116,36 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
86
116
"-fno-sanitize=undefined" , // https://github.com/raysan5/raylib/issues/3674
87
117
});
88
118
if (options .config .len > 0 ) {
89
- const file = b .pathJoin (&.{ srcDir (b ), "config.h" });
90
- const content = try std .fs .cwd ().readFileAlloc (b .allocator , file , std .math .maxInt (usize ));
91
- defer b .allocator .free (content );
92
-
93
- var lines = std .mem .splitScalar (u8 , content , '\n ' );
94
- while (lines .next ()) | line | {
95
- if (! std .mem .containsAtLeast (u8 , line , 1 , "SUPPORT" )) continue ;
96
- if (std .mem .startsWith (u8 , line , "//" )) continue ;
97
- if (std .mem .startsWith (u8 , line , "#if" )) continue ;
98
-
99
- var flag = std .mem .trimLeft (u8 , line , " \t " ); // Trim whitespace
100
- flag = flag ["#define " .len - 1 .. ]; // Remove #define
101
- flag = std .mem .trimLeft (u8 , flag , " \t " ); // Trim whitespace
102
- flag = flag [0 .. std .mem .indexOf (u8 , flag , " " ) orelse continue ]; // Flag is only one word, so capture till space
103
- flag = try std .fmt .allocPrint (b .allocator , "-D{s}" , .{flag }); // Prepend with -D
104
-
105
- // If user specifies the flag skip it
106
- if (std .mem .containsAtLeast (u8 , options .config , 1 , flag )) continue ;
107
-
108
- // Append default value from config.h to compile flags
109
- try raylib_flags_arr .append (b .allocator , flag );
110
- }
119
+ // Sets a flag indiciating the use of a custom `config.h`
120
+ try raylib_flags_arr .append (b .allocator , "-DEXTERNAL_CONFIG_FLAGS" );
111
121
112
- // Append config flags supplied by user to compile flags
113
- try raylib_flags_arr .append (b .allocator , options .config );
122
+ // Splits a space-separated list of config flags into multiple flags
123
+ //
124
+ // Note: This means certain flags like `-x c++` won't be processed properly.
125
+ // `-xc++` or similar should be used when possible
126
+ var config_iter = std .mem .tokenizeScalar (u8 , options .config , ' ' );
127
+
128
+ // Apply config flags supplied by the user
129
+ while (config_iter .next ()) | config_flag |
130
+ try raylib_flags_arr .append (b .allocator , config_flag );
131
+
132
+ // Apply all relevant configs from `src/config.h` *except* the user-specified ones
133
+ //
134
+ // Note: Currently using a suboptimal `O(m*n)` time algorithm where:
135
+ // `m` corresponds roughly to the number of lines in `src/config.h`
136
+ // `n` corresponds to the number of user-specified flags
137
+ outer : for (config_h_flags ) | flag | {
138
+ // If a user already specified the flag, skip it
139
+ while (config_iter .next ()) | config_flag | {
140
+ // For a user-specified flag to match, it must share the same prefix and have the
141
+ // same length or be followed by an equals sign
142
+ if (! std .mem .startsWith (u8 , config_flag , flag )) continue ;
143
+ if (config_flag .len == flag .len or config_flag [flag .len ] == '=' ) continue :outer ;
144
+ }
114
145
115
- try raylib_flags_arr .append (b .allocator , "-DEXTERNAL_CONFIG_FLAGS" );
146
+ // Otherwise, append default value from config.h to compile flags
147
+ try raylib_flags_arr .append (b .allocator , flag );
148
+ }
116
149
}
117
150
118
151
if (options .shared ) {
@@ -319,10 +352,28 @@ pub const Options = struct {
319
352
shared : bool = false ,
320
353
linux_display_backend : LinuxDisplayBackend = .Both ,
321
354
opengl_version : OpenglVersion = .auto ,
322
- /// config should be a list of cflags, eg, "-DSUPPORT_CUSTOM_FRAME_CONTROL"
355
+ /// config should be a list of space-separated cflags, eg, "-DSUPPORT_CUSTOM_FRAME_CONTROL"
323
356
config : []const u8 = &.{},
324
357
325
358
raygui_dependency_name : []const u8 = "raygui" ,
359
+
360
+ const defaults = Options {};
361
+
362
+ fn getOptions (b : * std.Build ) Options {
363
+ return .{
364
+ .platform = b .option (PlatformBackend , "platform" , "Choose the platform backedn for desktop target" ) orelse defaults .platform ,
365
+ .raudio = b .option (bool , "raudio" , "Compile with audio support" ) orelse defaults .raudio ,
366
+ .raygui = b .option (bool , "raygui" , "Compile with raygui support" ) orelse defaults .raygui ,
367
+ .rmodels = b .option (bool , "rmodels" , "Compile with models support" ) orelse defaults .rmodels ,
368
+ .rtext = b .option (bool , "rtext" , "Compile with text support" ) orelse defaults .rtext ,
369
+ .rtextures = b .option (bool , "rtextures" , "Compile with textures support" ) orelse defaults .rtextures ,
370
+ .rshapes = b .option (bool , "rshapes" , "Compile with shapes support" ) orelse defaults .rshapes ,
371
+ .shared = b .option (bool , "shared" , "Compile as shared library" ) orelse defaults .shared ,
372
+ .linux_display_backend = b .option (LinuxDisplayBackend , "linux_display_backend" , "Linux display backend to use" ) orelse defaults .linux_display_backend ,
373
+ .opengl_version = b .option (OpenglVersion , "opengl_version" , "OpenGL version to use" ) orelse defaults .opengl_version ,
374
+ .config = b .option ([]const u8 , "config" , "Compile with custom define macros overriding config.h" ) orelse &.{},
375
+ };
376
+ }
326
377
};
327
378
328
379
pub const OpenglVersion = enum {
@@ -371,22 +422,7 @@ pub fn build(b: *std.Build) !void {
371
422
// set a preferred release mode, allowing the user to decide how to optimize.
372
423
const optimize = b .standardOptimizeOption (.{});
373
424
374
- const defaults = Options {};
375
- const options = Options {
376
- .platform = b .option (PlatformBackend , "platform" , "Choose the platform backedn for desktop target" ) orelse defaults .platform ,
377
- .raudio = b .option (bool , "raudio" , "Compile with audio support" ) orelse defaults .raudio ,
378
- .raygui = b .option (bool , "raygui" , "Compile with raygui support" ) orelse defaults .raygui ,
379
- .rmodels = b .option (bool , "rmodels" , "Compile with models support" ) orelse defaults .rmodels ,
380
- .rtext = b .option (bool , "rtext" , "Compile with text support" ) orelse defaults .rtext ,
381
- .rtextures = b .option (bool , "rtextures" , "Compile with textures support" ) orelse defaults .rtextures ,
382
- .rshapes = b .option (bool , "rshapes" , "Compile with shapes support" ) orelse defaults .rshapes ,
383
- .shared = b .option (bool , "shared" , "Compile as shared library" ) orelse defaults .shared ,
384
- .linux_display_backend = b .option (LinuxDisplayBackend , "linux_display_backend" , "Linux display backend to use" ) orelse defaults .linux_display_backend ,
385
- .opengl_version = b .option (OpenglVersion , "opengl_version" , "OpenGL version to use" ) orelse defaults .opengl_version ,
386
- .config = b .option ([]const u8 , "config" , "Compile with custom define macros overriding config.h" ) orelse &.{},
387
- };
388
-
389
- const lib = try compileRaylib (b , target , optimize , options );
425
+ const lib = try compileRaylib (b , target , optimize , Options .getOptions (b ));
390
426
391
427
lib .installHeader (b .path (b .pathJoin (&.{ srcDir (b ), "raylib.h" })), "raylib.h" );
392
428
lib .installHeader (b .path (b .pathJoin (&.{ srcDir (b ), "raymath.h" })), "raymath.h" );
0 commit comments