summaryrefslogtreecommitdiff
path: root/src/contrib/SDL-3.2.20/build-scripts/build-web-examples.pl
diff options
context:
space:
mode:
Diffstat (limited to 'src/contrib/SDL-3.2.20/build-scripts/build-web-examples.pl')
-rwxr-xr-xsrc/contrib/SDL-3.2.20/build-scripts/build-web-examples.pl420
1 files changed, 420 insertions, 0 deletions
diff --git a/src/contrib/SDL-3.2.20/build-scripts/build-web-examples.pl b/src/contrib/SDL-3.2.20/build-scripts/build-web-examples.pl
new file mode 100755
index 0000000..c255ea3
--- /dev/null
+++ b/src/contrib/SDL-3.2.20/build-scripts/build-web-examples.pl
@@ -0,0 +1,420 @@
1#!/usr/bin/perl -w
2
3# Simple DirectMedia Layer
4# Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
5#
6# This software is provided 'as-is', without any express or implied
7# warranty. In no event will the authors be held liable for any damages
8# arising from the use of this software.
9#
10# Permission is granted to anyone to use this software for any purpose,
11# including commercial applications, and to alter it and redistribute it
12# freely, subject to the following restrictions:
13#
14# 1. The origin of this software must not be misrepresented; you must not
15# claim that you wrote the original software. If you use this software
16# in a product, an acknowledgment in the product documentation would be
17# appreciated but is not required.
18# 2. Altered source versions must be plainly marked as such, and must not be
19# misrepresented as being the original software.
20# 3. This notice may not be removed or altered from any source distribution.
21
22use warnings;
23use strict;
24use File::Basename;
25use File::Copy;
26use Cwd qw(abs_path);
27use IPC::Open2;
28
29my $examples_dir = abs_path(dirname(__FILE__) . "/../examples");
30my $project = undef;
31my $emsdk_dir = undef;
32my $compile_dir = undef;
33my $cmake_flags = undef;
34my $output_dir = undef;
35
36sub usage {
37 die("USAGE: $0 <project_name> <emsdk_dir> <compiler_output_directory> <cmake_flags> <html_output_directory>\n\n");
38}
39
40sub do_system {
41 my $cmd = shift;
42 $cmd = "exec /bin/bash -c \"$cmd\"";
43 print("$cmd\n");
44 return system($cmd);
45}
46
47sub do_mkdir {
48 my $d = shift;
49 if ( ! -d $d ) {
50 print("mkdir '$d'\n");
51 mkdir($d) or die("Couldn't mkdir('$d'): $!\n");
52 }
53}
54
55sub do_copy {
56 my $src = shift;
57 my $dst = shift;
58 print("cp '$src' '$dst'\n");
59 copy($src, $dst) or die("Failed to copy '$src' to '$dst': $!\n");
60}
61
62sub build_latest {
63 # Try to build just the latest without re-running cmake, since that is SLOW.
64 print("Building latest version of $project ...\n");
65 if (do_system("EMSDK_QUIET=1 source '$emsdk_dir/emsdk_env.sh' && cd '$compile_dir' && ninja") != 0) {
66 # Build failed? Try nuking the build dir and running CMake from scratch.
67 print("\n\nBuilding latest version of $project FROM SCRATCH ...\n");
68 if (do_system("EMSDK_QUIET=1 source '$emsdk_dir/emsdk_env.sh' && rm -rf '$compile_dir' && mkdir '$compile_dir' && cd '$compile_dir' && emcmake cmake -G Ninja -DCMAKE_BUILD_TYPE=MinSizeRel $cmake_flags '$examples_dir/..' && ninja") != 0) {
69 die("Failed to build latest version of $project!\n"); # oh well.
70 }
71 }
72}
73
74sub get_category_description {
75 my $category = shift;
76 my $retval = ucfirst($category);
77
78 if (open(my $fh, '<', "$examples_dir/$category/description.txt")) {
79 $retval = <$fh>;
80 chomp($retval);
81 close($fh);
82 }
83
84 return $retval;
85}
86
87sub get_categories {
88 my @categories = ();
89
90 if (open(my $fh, '<', "$examples_dir/categories.txt")) {
91 while (<$fh>) {
92 chomp;
93 s/\A\s+//;
94 s/\s+\Z//;
95 next if $_ eq '';
96 next if /\A\#/;
97 push @categories, $_;
98 }
99 close($fh);
100 } else {
101 opendir(my $dh, $examples_dir) or die("Couldn't opendir '$examples_dir': $!\n");
102 foreach my $dir (sort readdir $dh) {
103 next if ($dir eq '.') || ($dir eq '..'); # obviously skip current and parent entries.
104 next if not -d "$examples_dir/$dir"; # only care about subdirectories.
105 push @categories, $dir;
106 }
107 closedir($dh);
108 }
109
110 return @categories;
111}
112
113sub get_examples_for_category {
114 my $category = shift;
115
116 my @examples = ();
117
118 opendir(my $dh, "$examples_dir/$category") or die("Couldn't opendir '$examples_dir/$category': $!\n");
119 foreach my $dir (sort readdir $dh) {
120 next if ($dir eq '.') || ($dir eq '..'); # obviously skip current and parent entries.
121 next if not -d "$examples_dir/$category/$dir"; # only care about subdirectories.
122
123 push @examples, $dir;
124 }
125 closedir($dh);
126
127 return @examples;
128}
129
130sub handle_example_dir {
131 my $category = shift;
132 my $example = shift;
133
134 my @files = ();
135 my $files_str = '';
136 opendir(my $dh, "$examples_dir/$category/$example") or die("Couldn't opendir '$examples_dir/$category/$example': $!\n");
137 my $spc = '';
138 while (readdir($dh)) {
139 my $path = "$examples_dir/$category/$example/$_";
140 next if not -f $path; # only care about files.
141 push @files, $path if /\.[ch]\Z/; # add .c and .h files to source code.
142 if (/\.c\Z/) { # only care about .c files for compiling.
143 $files_str .= "$spc$path";
144 $spc = ' ';
145 }
146 }
147 closedir($dh);
148
149 my $dst = "$output_dir/$category/$example";
150
151 print("Building $category/$example ...\n");
152
153 my $basefname = "$example";
154 $basefname =~ s/\A\d+\-//;
155 $basefname = "$category-$basefname";
156 my $jsfname = "$basefname.js";
157 my $wasmfname = "$basefname.wasm";
158 my $thumbnailfname = 'thumbnail.png';
159 my $onmouseoverfname = 'onmouseover.webp';
160 my $jssrc = "$compile_dir/examples/$jsfname";
161 my $wasmsrc = "$compile_dir/examples/$wasmfname";
162 my $thumbnailsrc = "$examples_dir/$category/$example/$thumbnailfname";
163 my $onmouseoversrc = "$examples_dir/$category/$example/$onmouseoverfname";
164 my $jsdst = "$dst/$jsfname";
165 my $wasmdst = "$dst/$wasmfname";
166 my $thumbnaildst = "$dst/$thumbnailfname";
167 my $onmouseoverdst = "$dst/$onmouseoverfname";
168
169 my $description = '';
170 my $has_paragraph = 0;
171 if (open(my $readmetxth, '<', "$examples_dir/$category/$example/README.txt")) {
172 while (<$readmetxth>) {
173 chomp;
174 s/\A\s+//;
175 s/\s+\Z//;
176 if (($_ eq '') && ($description ne '')) {
177 $has_paragraph = 1;
178 } else {
179 if ($has_paragraph) {
180 $description .= "\n<br/>\n<br/>\n";
181 $has_paragraph = 0;
182 }
183 $description .= "$_ ";
184 }
185 }
186 close($readmetxth);
187 $description =~ s/\s+\Z//;
188 }
189
190 do_mkdir($dst);
191 do_copy($jssrc, $jsdst);
192 do_copy($wasmsrc, $wasmdst);
193 do_copy($thumbnailsrc, $thumbnaildst) if ( -f $thumbnailsrc );
194 do_copy($onmouseoversrc, $onmouseoverdst) if ( -f $onmouseoversrc );
195
196 my $highlight_cmd = "highlight '--outdir=$dst' --style-outfile=highlight.css --fragment --enclose-pre --stdout --syntax=c '--plug-in=$examples_dir/highlight-plugin.lua'";
197 print("$highlight_cmd\n");
198 my $pid = open2(my $child_out, my $child_in, $highlight_cmd);
199
200 my $htmlified_source_code = '';
201 foreach (sort(@files)) {
202 my $path = $_;
203 open my $srccode, '<', $path or die("Couldn't open '$path': $!\n");
204 my $fname = "$path";
205 $fname =~ s/\A.*\///;
206 print $child_in "/* $fname ... */\n\n";
207 while (<$srccode>) {
208 print $child_in $_;
209 }
210 print $child_in "\n\n\n";
211 close($srccode);
212 }
213
214 close($child_in);
215
216 while (<$child_out>) {
217 $htmlified_source_code .= $_;
218 }
219 close($child_out);
220
221 waitpid($pid, 0);
222
223 my $other_examples_html = "<ul>";
224 foreach my $example (get_examples_for_category($category)) {
225 $other_examples_html .= "<li><a href='/$project/$category/$example'>$category/$example</a></li>";
226 }
227 $other_examples_html .= "</ul>";
228
229 my $category_description = get_category_description($category);
230 my $preview_image = get_example_thumbnail($project, $category, $example);
231
232 my $html = '';
233 open my $htmltemplate, '<', "$examples_dir/template.html" or die("Couldn't open '$examples_dir/template.html': $!\n");
234 while (<$htmltemplate>) {
235 s/\@project_name\@/$project/g;
236 s/\@category_name\@/$category/g;
237 s/\@category_description\@/$category_description/g;
238 s/\@example_name\@/$example/g;
239 s/\@javascript_file\@/$jsfname/g;
240 s/\@htmlified_source_code\@/$htmlified_source_code/g;
241 s/\@description\@/$description/g;
242 s/\@preview_image\@/$preview_image/g;
243 s/\@other_examples_html\@/$other_examples_html/g;
244 $html .= $_;
245 }
246 close($htmltemplate);
247
248 open my $htmloutput, '>', "$dst/index.html" or die("Couldn't open '$dst/index.html': $!\n");
249 print $htmloutput $html;
250 close($htmloutput);
251}
252
253sub get_example_thumbnail {
254 my $project = shift;
255 my $category = shift;
256 my $example = shift;
257
258 if ( -f "$examples_dir/$category/$example/thumbnail.png" ) {
259 return "/$project/$category/$example/thumbnail.png";
260 } elsif ( -f "$examples_dir/$category/thumbnail.png" ) {
261 return "/$project/$category/thumbnail.png";
262 }
263
264 return "/$project/thumbnail.png";
265}
266
267sub generate_example_thumbnail {
268 my $project = shift;
269 my $category = shift;
270 my $example = shift;
271
272 my $example_no_num = "$example";
273 $example_no_num =~ s/\A\d+\-//;
274
275 my $example_image_url = get_example_thumbnail($project, $category, $example);
276
277 my $example_mouseover_html = '';
278 if ( -f "$examples_dir/$category/$example/onmouseover.webp" ) {
279 $example_mouseover_html = "onmouseover=\"this.src='/$project/$category/$example/onmouseover.webp'\" onmouseout=\"this.src='$example_image_url';\"";
280 } elsif ( -f "$examples_dir/$category/onmouseover.webp" ) {
281 $example_mouseover_html = "onmouseover=\"this.src='/$project/$category/onmouseover.webp'\" onmouseout=\"this.src='$example_image_url';\"";
282 }
283
284 return "
285 <a href='/$project/$category/$example'>
286 <div>
287 <img src='$example_image_url' $example_mouseover_html />
288 <div>$example_no_num</div>
289 </div>
290 </a>"
291 ;
292}
293
294sub generate_example_thumbnails_for_category {
295 my $project = shift;
296 my $category = shift;
297 my @examples = get_examples_for_category($category);
298 my $retval = '';
299 foreach my $example (@examples) {
300 $retval .= generate_example_thumbnail($project, $category, $example);
301 }
302 return $retval;
303}
304
305sub handle_category_dir {
306 my $category = shift;
307
308 print("Category $category ...\n");
309
310 do_mkdir("$output_dir/$category");
311
312 opendir(my $dh, "$examples_dir/$category") or die("Couldn't opendir '$examples_dir/$category': $!\n");
313
314 while (readdir($dh)) {
315 next if ($_ eq '.') || ($_ eq '..'); # obviously skip current and parent entries.
316 next if not -d "$examples_dir/$category/$_"; # only care about subdirectories.
317 handle_example_dir($category, $_);
318 }
319
320 closedir($dh);
321
322 my $examples_list_html = generate_example_thumbnails_for_category($project, $category);
323
324 my $dst = "$output_dir/$category";
325
326 do_copy("$examples_dir/$category/thumbnail.png", "$dst/thumbnail.png") if ( -f "$examples_dir/$category/thumbnail.png" );
327 do_copy("$examples_dir/$category/onmouseover.webp", "$dst/onmouseover.webp") if ( -f "$examples_dir/$category/onmouseover.webp" );
328
329 my $category_description = get_category_description($category);
330 my $preview_image = "/$project/thumbnail.png";
331 if ( -f "$examples_dir/$category/thumbnail.png" ) {
332 $preview_image = "/$project/$category/thumbnail.png";
333 }
334
335 # write category page
336 my $html = '';
337 open my $htmltemplate, '<', "$examples_dir/template-category.html" or die("Couldn't open '$examples_dir/template-category.html': $!\n");
338 while (<$htmltemplate>) {
339 s/\@project_name\@/$project/g;
340 s/\@category_name\@/$category/g;
341 s/\@category_description\@/$category_description/g;
342 s/\@examples_list_html\@/$examples_list_html/g;
343 s/\@preview_image\@/$preview_image/g;
344 $html .= $_;
345 }
346 close($htmltemplate);
347
348 open my $htmloutput, '>', "$dst/index.html" or die("Couldn't open '$dst/index.html': $!\n");
349 print $htmloutput $html;
350 close($htmloutput);
351}
352
353
354# Mainline!
355
356foreach (@ARGV) {
357 $project = $_, next if not defined $project;
358 $emsdk_dir = $_, next if not defined $emsdk_dir;
359 $compile_dir = $_, next if not defined $compile_dir;
360 $cmake_flags = $_, next if not defined $cmake_flags;
361 $output_dir = $_, next if not defined $output_dir;
362 usage(); # too many arguments.
363}
364
365usage() if not defined $output_dir;
366
367print("Examples dir: $examples_dir\n");
368print("emsdk dir: $emsdk_dir\n");
369print("Compile dir: $compile_dir\n");
370print("CMake flags: $cmake_flags\n");
371print("Output dir: $output_dir\n");
372
373do_system("rm -rf '$output_dir'");
374do_mkdir($output_dir);
375
376build_latest();
377
378do_copy("$examples_dir/template.css", "$output_dir/examples.css");
379do_copy("$examples_dir/template-placeholder.png", "$output_dir/thumbnail.png");
380
381opendir(my $dh, $examples_dir) or die("Couldn't opendir '$examples_dir': $!\n");
382
383while (readdir($dh)) {
384 next if ($_ eq '.') || ($_ eq '..'); # obviously skip current and parent entries.
385 next if not -d "$examples_dir/$_"; # only care about subdirectories.
386 # !!! FIXME: this needs to generate a preview page for all the categories.
387 handle_category_dir($_);
388}
389
390closedir($dh);
391
392# write homepage
393my $homepage_list_html = "";
394foreach my $category (get_categories()) {
395 my $category_description = get_category_description($category);
396 $homepage_list_html .= "<h2>$category_description</h2>";
397 $homepage_list_html .= "<div class='list'>";
398 $homepage_list_html .= generate_example_thumbnails_for_category($project, $category);
399 $homepage_list_html .= "</div>";
400}
401
402my $preview_image = "/$project/thumbnail.png";
403
404my $dst = "$output_dir/";
405my $html = '';
406open my $htmltemplate, '<', "$examples_dir/template-homepage.html" or die("Couldn't open '$examples_dir/template-category.html': $!\n");
407while (<$htmltemplate>) {
408 s/\@project_name\@/$project/g;
409 s/\@homepage_list_html\@/$homepage_list_html/g;
410 s/\@preview_image\@/$preview_image/g;
411 $html .= $_;
412}
413close($htmltemplate);
414
415open my $htmloutput, '>', "$dst/index.html" or die("Couldn't open '$dst/index.html': $!\n");
416print $htmloutput $html;
417close($htmloutput);
418
419print("All examples built successfully!\n");
420exit(0); # success!