SDL
222 строки · 6.9 Кб
1#!/usr/bin/perl -w
2
3# Simple DirectMedia Layer
4# Copyright (C) 1997-2024 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 {
37die("USAGE: $0 <project_name> <emsdk_dir> <compiler_output_directory> <cmake_flags> <html_output_directory>\n\n");
38}
39
40sub do_system {
41my $cmd = shift;
42$cmd = "exec /bin/bash -c \"$cmd\"";
43print("$cmd\n");
44return system($cmd);
45}
46
47sub do_mkdir {
48my $d = shift;
49if ( ! -d $d ) {
50print("mkdir '$d'\n");
51mkdir($d) or die("Couldn't mkdir('$d'): $!\n");
52}
53}
54
55sub do_copy {
56my $src = shift;
57my $dst = shift;
58print("cp '$src' '$dst'\n");
59copy($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.
64print("Building latest version of $project ...\n");
65if (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.
67print("\n\nBuilding latest version of $project FROM SCRATCH ...\n");
68if (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) {
69die("Failed to build latest version of $project!\n"); # oh well.
70}
71}
72}
73
74sub handle_example_dir {
75my $category = shift;
76my $example = shift;
77
78my @files = ();
79my $files_str = '';
80opendir(my $dh, "$examples_dir/$category/$example") or die("Couldn't opendir '$examples_dir/$category/$example': $!\n");
81my $spc = '';
82while (readdir($dh)) {
83my $path = "$examples_dir/$category/$example/$_";
84next if not -f $path; # only care about files.
85push @files, $path if /\.[ch]\Z/; # add .c and .h files to source code.
86if (/\.c\Z/) { # only care about .c files for compiling.
87$files_str .= "$spc$path";
88$spc = ' ';
89}
90}
91closedir($dh);
92
93my $dst = "$output_dir/$category/$example";
94
95print("Building $category/$example ...\n");
96
97my $basefname = "$example";
98$basefname =~ s/\A\d+\-//;
99$basefname = "$category-$basefname";
100my $jsfname = "$basefname.js";
101my $wasmfname = "$basefname.wasm";
102my $jssrc = "$compile_dir/examples/$jsfname";
103my $wasmsrc = "$compile_dir/examples/$wasmfname";
104my $jsdst = "$dst/$jsfname";
105my $wasmdst = "$dst/$wasmfname";
106
107my $description = '';
108if (open(my $readmetxth, '<', "$examples_dir/$category/$example/README.txt")) {
109while (<$readmetxth>) {
110chomp;
111s/\A\s+//;
112s/\s+\Z//;
113$description .= "$_<br/>";
114}
115close($readmetxth);
116}
117
118do_mkdir($dst);
119do_copy($jssrc, $jsdst);
120do_copy($wasmsrc, $wasmdst);
121
122my $highlight_cmd = "highlight '--outdir=$dst' --style-outfile=highlight.css --fragment --enclose-pre --stdout --syntax=c '--plug-in=$examples_dir/highlight-plugin.lua'";
123print("$highlight_cmd\n");
124my $pid = open2(my $child_out, my $child_in, $highlight_cmd);
125
126my $htmlified_source_code = '';
127foreach (sort(@files)) {
128my $path = $_;
129open my $srccode, '<', $path or die("Couldn't open '$path': $!\n");
130my $fname = "$path";
131$fname =~ s/\A.*\///;
132print $child_in "/* $fname ... */\n\n";
133while (<$srccode>) {
134print $child_in $_;
135}
136print $child_in "\n\n\n";
137close($srccode);
138}
139
140close($child_in);
141
142while (<$child_out>) {
143$htmlified_source_code .= $_;
144}
145close($child_out);
146
147waitpid($pid, 0);
148
149
150my $html = '';
151open my $htmltemplate, '<', "$examples_dir/template.html" or die("Couldn't open '$examples_dir/template.html': $!\n");
152while (<$htmltemplate>) {
153s/\@project_name\@/$project/g;
154s/\@category_name\@/$category/g;
155s/\@example_name\@/$example/g;
156s/\@javascript_file\@/$jsfname/g;
157s/\@htmlified_source_code\@/$htmlified_source_code/g;
158s/\@description\@/$description/g;
159$html .= $_;
160}
161close($htmltemplate);
162
163open my $htmloutput, '>', "$dst/index.html" or die("Couldn't open '$dst/index.html': $!\n");
164print $htmloutput $html;
165close($htmloutput);
166}
167
168sub handle_category_dir {
169my $category = shift;
170
171print("Category $category ...\n");
172
173do_mkdir("$output_dir/$category");
174
175opendir(my $dh, "$examples_dir/$category") or die("Couldn't opendir '$examples_dir/$category': $!\n");
176
177while (readdir($dh)) {
178next if ($_ eq '.') || ($_ eq '..'); # obviously skip current and parent entries.
179next if not -d "$examples_dir/$category/$_"; # only care about subdirectories.
180handle_example_dir($category, $_);
181}
182
183closedir($dh);
184}
185
186
187# Mainline!
188
189foreach (@ARGV) {
190$project = $_, next if not defined $project;
191$emsdk_dir = $_, next if not defined $emsdk_dir;
192$compile_dir = $_, next if not defined $compile_dir;
193$cmake_flags = $_, next if not defined $cmake_flags;
194$output_dir = $_, next if not defined $output_dir;
195usage(); # too many arguments.
196}
197
198usage() if not defined $output_dir;
199
200print("Examples dir: $examples_dir\n");
201print("emsdk dir: $emsdk_dir\n");
202print("Compile dir: $compile_dir\n");
203print("CMake flags: $cmake_flags\n");
204print("Output dir: $output_dir\n");
205
206do_system("rm -rf '$output_dir'");
207do_mkdir($output_dir);
208
209build_latest();
210
211opendir(my $dh, $examples_dir) or die("Couldn't opendir '$examples_dir': $!\n");
212
213while (readdir($dh)) {
214next if ($_ eq '.') || ($_ eq '..'); # obviously skip current and parent entries.
215next if not -d "$examples_dir/$_"; # only care about subdirectories.
216handle_category_dir($_);
217}
218
219closedir($dh);
220
221print("All examples built successfully!\n");
222exit(0); # success!
223
224