1 /*
2  * DSFML - The Simple and Fast Multimedia Library for D
3  *
4  * Copyright (c) 2013 - 2017 Jeremy DeHaan (dehaan.jeremiah@gmail.com)
5  *
6  * This software is provided 'as-is', without any express or implied warranty.
7  * In no event will the authors be held liable for any damages arising from the
8  * 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 claim
15  * that you wrote the original software. If you use this software in a product,
16  * an acknowledgment in the product documentation would be appreciated but is
17  * not required.
18  *
19  * 2. Altered source versions must be plainly marked as such, and must not be
20  * misrepresented as being the original software.
21  *
22  * 3. This notice may not be removed or altered from any source distribution
23  */
24 
25 module build;
26 
27 import std.stdio;
28 import std.file;
29 import std.process;
30 import std.algorithm;
31 import std.array;
32 import std.getopt;
33 
34 static if (__VERSION__ < 2068L)
35 {
36 	static assert(0, "Please upgrade your compiler to v2.068 or later");
37 }
38 
39 version(DigitalMars)
40 {
41     string compiler = "dmd ";
42 }
43 else version(GNU)
44 {
45     string compiler = "gdc ";
46 }
47 else version(LDC)
48 {
49     string compiler = "ldc2 ";
50 }
51 else
52 {
53     static assert(false, "Unknown or unsupported compiler.");
54 }
55 
56 //build settings
57 string prefix;
58 string postfix;
59 string extension;
60 string linkerInclude;
61 string libSwitches;
62 string docSwitches;
63 string interfaceSwitches;
64 string unittestSwitches;
65 
66 //switch settings
67 bool buildingLibs;
68 bool buildingInterfaceFiles;
69 bool buildingDoc;
70 bool buildingWebsiteDocs;
71 bool debugLibs;
72 bool force32Build;
73 bool force64Build;
74 
75 bool buildingUnittests;
76 string unittestLibraryLocation;
77 
78 bool buildingAll;
79 
80 bool hasUnrecognizedSwitch;
81 string unrecognizedSwitch;
82 
83 string makefileType;
84 string makefileProgram;
85 string objExt;
86 string singleFileSwitches;
87 string archSwitch;
88 
89 
90 //Possibly use this to completely automate the process for dmd/ldc users on windows
91 //environment.get("VCINSTALLDIR");
92 //will need to find an alternative for gdc users on windows in regards to mingw
93 
94 version(Windows)
95 {
96 }
97 else version(linux)
98 {
99 }
100 else version(OSX)
101 {
102 }
103 //FreeBSD Support coming soon!
104 else
105 {
106     static assert(false, "DSFML is only supported on OSX, Windows, and Linux.");
107 }
108 
109 
110 string[5] modules = ["system", "audio", "network", "window", "graphics"];
111 string selectedModule;
112 
113 //lists of d files and c++ object files
114 string[][string] fileList;
115 string[string] objectList;
116 
117 
118 /**
119  * Checks for any inconsistencies with the passed switchs.
120  *
121  * Returns: true if no errors were found, false otherwise.
122  */
123 bool checkSwitchErrors()
124 {
125     //can't force both
126     if(force32Build && force64Build)
127     {
128         writeln("Can't use -m32 and -m64 together");
129         return false;
130     }
131 
132     //if other Switchs are used with -all
133     if(buildingAll)
134     {
135         if(buildingLibs || buildingDoc ||
136            buildingInterfaceFiles || buildingUnittests)
137         {
138             writeln("Can't use -all with any other build switches ",
139                     "(-lib, -doc, -import, -unittest)");
140 
141             return false;
142         }
143     }
144 
145     return true;
146 }
147 
148 //initialize all build settings
149 void initialize()
150 {
151     archSwitch = "";
152     postfix = "";
153 
154     if(force32Build)
155     {
156         archSwitch = " -m32";
157     }
158 
159     if(force64Build)
160     {
161         archSwitch = " -m64";
162     }
163 
164     version (Windows)
165     {
166         write("Building for Windows ");
167         prefix = "";
168         extension = ".lib";
169         objExt = ".obj";
170 
171         //Default to 64 bit on windows because why wouldn't we?
172         if(!force64Build || !force32Build)
173         {
174             archSwitch = " -m64";
175         }
176 
177         if(force32Build)
178         {
179             archSwitch = " -m32mscoff";
180         }
181 
182         makefileProgram = "nmake";
183         makefileType = `"NMake Makefiles"`;
184         linkerInclude = "";
185     }
186     else
187     {
188         version(linux)
189             write("Building for Linux ");
190         else
191             write("Building for OSX ");
192 
193         prefix = "lib";
194         extension = ".a";
195         objExt = ".o";
196 
197         makefileProgram = "make";
198         makefileType = `"Unix Makefiles"`;
199     }
200 
201     version(DigitalMars)
202     {
203         writeln("with dmd");
204         initializeDMD();
205     }
206     else version(GNU)
207     {
208         writeln("with gdc");
209         initializeGDC();
210     }
211     else version(LDC)
212     {
213         writeln("with ldc");
214         initializeLDC();
215     }
216 
217     // add links to the SFML files for building the unit tests
218     unittestSwitches ~= lib("sfml-graphics")~lib("sfml-window")~
219                         lib("sfml-audio")~lib("sfml-network")~
220                         lib("sfml-system");
221 
222     //need to link to c++ standard library on these systems
223     version(Posix)
224     {
225         unittestSwitches ~= lib("stdc++");
226     }
227 
228     //Does OSX need to include rpath for unittests?
229 
230     //populate file lists
231     fileList["system"] = ["clock", "config", "err", "inputstream", "lock",
232                           "mutex", "package", "sleep", "string", "thread",
233                           "time", "vector2", "vector3"];
234 
235     fileList["audio"] = ["listener", "music", "package", "sound",
236                          "soundbuffer", "soundbufferrecorder",
237                          "inputsoundfile", "outputsoundfile",
238                          "soundrecorder", "soundsource", "soundstream"];
239 
240     fileList["network"] = ["ftp", "http", "ipaddress", "package",
241                            "packet", "socket", "socketselector",
242                            "tcplistener", "tcpsocket", "udpsocket"];
243 
244     fileList["window"] = ["context", "contextsettings", "event", "joystick",
245                           "keyboard", "mouse", "sensor", "touch", "package",
246                           "videomode", "window", "windowhandle"];
247 
248     fileList["graphics"] = ["blendmode", "circleshape", "color", "convexshape",
249                             "drawable", "font", "glsl", "glyph", "image",
250                             "package", "primitivetype", "rect",
251                             "rectangleshape", "renderstates", "rendertarget",
252                             "rendertexture", "renderwindow", "shader", "shape",
253                             "sprite", "text", "texture", "transform",
254                             "transformable", "vertex", "vertexarray", "view"];
255 
256     //populate C++ object list
257     string dir = "src/DSFMLC/System/CMakeFiles/dsfmlc-system.dir/";
258     objectList["system"] = dir~"Err.cpp"~objExt~" "~
259                            dir~"ErrStream.cpp"~objExt~" "~
260                            dir~"String.cpp"~objExt~" ";
261 
262     dir = "src/DSFMLC/Audio/CMakeFiles/dsfmlc-audio.dir/";
263     objectList["audio"] = dir~"InputSoundFile.cpp"~objExt~" "~
264                           dir~"Listener.cpp"~objExt~" "~
265                           dir~"OutputSoundFile.cpp"~objExt~" "~
266                           dir~"Sound.cpp"~objExt~" "~
267                           dir~"SoundBuffer.cpp"~objExt~" "~
268                           dir~"SoundRecorder.cpp"~objExt~" "~
269                           dir~"SoundStream.cpp"~objExt~" ";
270 
271     dir = "src/DSFMLC/Network/CMakeFiles/dsfmlc-network.dir/";
272     objectList["network"] = dir~"Ftp.cpp"~objExt~" "~
273                             dir~"Http.cpp"~objExt~" "~
274                             dir~"IpAddress.cpp"~objExt~" "~
275                             dir~"Packet.cpp"~objExt~" "~
276                             dir~"SocketSelector.cpp"~objExt~" "~
277                             dir~"TcpListener.cpp"~objExt~" "~
278                             dir~"TcpSocket.cpp"~objExt~" "~
279                             dir~"UdpSocket.cpp"~objExt~" ";
280 
281     dir = "src/DSFMLC/Window/CMakeFiles/dsfmlc-window.dir/";
282     objectList["window"] = dir~"Context.cpp"~objExt~" "~
283                            dir~"Joystick.cpp"~objExt~" "~
284                            dir~"Keyboard.cpp"~objExt~" "~
285                            dir~"Mouse.cpp"~objExt~" "~
286                            dir~"Sensor.cpp"~objExt~" "~
287                            dir~"Touch.cpp"~objExt~" "~
288                            dir~"VideoMode.cpp"~objExt~" "~
289                            dir~"Window.cpp"~objExt~" ";
290 
291     dir = "src/DSFMLC/Graphics/CMakeFiles/dsfmlc-graphics.dir/";
292     objectList["graphics"] = dir~"Font.cpp"~objExt~" "~
293                              dir~"Image.cpp"~objExt~" "~
294                              dir~"RenderTexture.cpp"~objExt~" "~
295                              dir~"RenderWindow.cpp"~objExt~" "~
296                              dir~"Shader.cpp"~objExt~" "~
297                              dir~"Texture.cpp"~objExt~" "~
298                              dir~"Transform.cpp"~objExt~" ";
299 
300     if(debugLibs)
301     {
302         singleFileSwitches = " -g " ~ singleFileSwitches;
303         postfix = "-d";
304     }
305 
306     writeln();
307 }
308 
309 /// Initialize the DMD compiler
310 void initializeDMD()
311 {
312     singleFileSwitches = archSwitch ~ " -c -O -release -inline -Isrc -of";
313     libSwitches = archSwitch ~ " -lib -oflib/"~prefix~"dsfml-";
314     docSwitches = " -c -o- -op -D -Dd../../doc -I../../src";
315     interfaceSwitches = " -c -o- -op -H -Hd../import -I../src";
316 
317     unittestSwitches =
318     archSwitch ~ " -main -unittest -version=DSFML_Unittest_System " ~
319     "-version=DSFML_Unittest_Window -version=DSFML_Unittest_Graphics " ~
320     "-version=DSFML_Unittest_Audio -version=DSFML_Unittest_Network " ~
321     "-ofunittest/unittest";
322 
323     version (Windows)
324     {
325         unittestSwitches ~= ".exe -L/LIBPATH:lib -L/LIBPATH:SFML\\lib ";
326     }
327     else
328     {
329         linkerInclude = "-L-l";
330         unittestSwitches ~= " -L-LSFML/lib ";
331     }
332 }
333 
334 /// Initialize the GDC compiler
335 void initializeGDC()
336 {
337     //need to set up for windows and macOS later
338 
339     singleFileSwitches = archSwitch ~ " -c -O3 -frelease -Isrc -o";
340     libSwitches = "ar rcs ./lib/libdsfml-";
341     docSwitches = " -c -fdoc -I../../src";
342     interfaceSwitches = " -c -fintfc -I../src -o obj.o";
343 
344     unittestSwitches =
345     archSwitch ~ " -funittest -fversion=DSFML_Unittest_System " ~
346     "-fversion=DSFML_Unittest_Window -fversion=DSFML_Unittest_Graphics " ~
347     "-fversion=DSFML_Unittest_Audio -fversion=DSFML_Unittest_Network " ~
348     "-ounittest/unittest";
349 
350     version(linux)
351     {
352         linkerInclude = "-l";
353         unittestSwitches ~= " -LSFML/lib ";
354     }
355 }
356 
357 /// Initialize the LDC compiler
358 void initializeLDC()
359 {
360     string linkToSFMLLibs = "";
361 
362     singleFileSwitches = archSwitch ~ " -c -O -release -oq -I=src -of=";
363     libSwitches = archSwitch ~ " -lib -of=lib/"~prefix~"dsfml-";
364     docSwitches = " -c -o- -op -D -Dd=../../doc -I=../../src";
365     interfaceSwitches = " -c -o- -op -H -Hd=../import -I=../src";
366 
367     unittestSwitches =
368     archSwitch ~ " -main -unittest -d-version=DSFML_Unittest_System " ~
369     "-d-version=DSFML_Unittest_Window -d-version=DSFML_Unittest_Graphics " ~
370     "-d-version=DSFML_Unittest_Audio -d-version=DSFML_Unittest_Network " ~
371     "-of=unittest/unittest";
372 
373     version(Windows)
374     {
375          unittestSwitches ~= ".exe -L=/LIBPATH:lib -L=/LIBPATH:SFML\\lib ";
376     }
377     else
378     {
379         linkerInclude = "-L=-l";
380         unittestSwitches ~= " -L=-LSFML/lib ";
381     }
382 }
383 
384 /**
385  * Build the DSFMLC source files.
386  *
387  * Returns: true on successful build, false otherwise.
388  */
389 bool buildDSFMLC()
390 {
391     chdir("src/DSFMLC/");
392 
393     // generate the cmake files on the first run
394     if(!exists("CMakeCache.txt"))
395     {
396         auto pid = spawnShell("cmake -G"~makefileType~" .");
397         if(wait(pid) != 0)
398         {
399             return false;
400         }
401     }
402 
403     //always try to rebuild c++ files. They will be skipped if nothing to do.
404     auto pid = spawnProcess([makefileProgram]);
405     if(wait(pid) != 0)
406     {
407         return false;
408     }
409 
410     writeln();
411 
412     chdir("../..");
413 
414     return true;
415 }
416 
417 /**
418  * Build the static libraries.
419  *
420  * Returns: true on successful build, false otherwise.
421  */
422 bool buildLibs()
423 {
424     import std.ascii: toUpper;
425 
426     if(!exists("lib/"))
427     {
428         mkdir("lib/");
429     }
430 
431     if(!buildDSFMLC())
432         return false;
433 
434     foreach(theModule;modules)
435     {
436         //+1 to include the library file in the count
437         size_t numberOfFiles = fileList[theModule].length + 1;
438         string files = "";
439 
440         string objLocation = "obj/"~(debugLibs?"debug":"release")~
441             "/dsfml/" ~theModule~"/";
442 
443         if(!exists(objLocation))
444         {
445             mkdirRecurse(objLocation);
446         }
447 
448         foreach (fileNumber, name; fileList[theModule])
449         {
450             string objectFile = objLocation~name~objExt;
451 
452             string dFile = "src/dsfml/" ~theModule~"/"~name~".d";
453             string buildCommand = compiler~dFile~singleFileSwitches~objectFile;
454 
455             if(needToBuild(objectFile, dFile))
456             {
457                 progressOutput(fileNumber, numberOfFiles, dFile);
458 
459                 auto status = executeShell(buildCommand);
460 
461                 if(status.status !=0)
462                 {
463                     writeln(status.output);
464                     return false;
465                 }
466             }
467 
468             files~= objectFile ~ " ";
469         }
470 
471         files ~= objectList[theModule];
472 
473         string buildCommand = compiler ~ files;
474 
475         version(GNU)
476         {
477             //We're using ar here, so we'll completely reset the build command
478             buildCommand = libSwitches~theModule~postfix~extension~" "~files;
479         }
480         else
481         {
482             buildCommand ~= libSwitches~theModule~postfix~extension;
483         }
484 
485         //always rebuilds the lib in case the cpp files were re-built
486         auto status = executeShell(buildCommand);
487 
488         if(status.status !=0)
489         {
490             writeln("Something happened!");
491             writeln(status.output);
492             return false;
493         }
494 
495         writeln("[100%] Built "~prefix~"dsfml-" ~ theModule~extension);
496     }
497 
498     return true;
499 }
500 
501 /**
502  * Build DSFML unit tests.
503  *
504  * Returns: true if unit tests could be built, false if not.
505  */
506 bool buildUnittests()
507 {
508     import std.ascii: toUpper;
509 
510     if(!findSFML())
511         return false;
512 
513     if(!buildDSFMLC())
514         return false;
515 
516     string files = "";
517 
518     foreach(theModule;modules)
519     {
520         foreach(string name; fileList[theModule])
521         {
522             files~= "src/dsfml/" ~theModule~"/"~name~".d ";
523         }
524 
525         files ~= objectList[theModule];
526     }
527 
528     string buildCommand = compiler;
529 
530     version(GNU)
531     {
532         std.file.write("main.d", "void main(){}");
533 
534         buildCommand ~= "main.d ";
535     }
536 
537     buildCommand ~= files~unittestSwitches;
538 
539     write("Building unittest/unitest");
540     version(Windows)
541         writeln(".exe");
542     else
543         writeln();
544 
545     auto status = executeShell(buildCommand);
546 
547     version(GNU)
548     {
549         std.file.remove("main.d");
550     }
551 
552     if(status.status !=0)
553     {
554         writeln(status.output);
555         return false;
556     }
557 
558     return true;
559 }
560 
561 /**
562  * Build DSFML documentation.
563  *
564  * Returns: true if documentation could be built, false if not.
565  */
566 bool buildDocumentation()
567 {
568     if(!exists("doc/"))
569     {
570         mkdir("doc/");
571     }
572 
573     chdir("src/dsfml/");
574 
575     string docExtension;
576     string ddoc;
577     if(buildingWebsiteDocs)
578     {
579         docExtension = ".php";
580 
581         version(GNU)
582             ddoc = "../../doc/website_documentation.ddoc";
583         else
584             ddoc = " ../../doc/website_documentation.ddoc";
585     }
586     else
587     {
588         docExtension = ".html";
589         version(GNU)
590             ddoc = "../../doc/default_ddoc_theme.ddoc";
591         else
592             ddoc = " ../../doc/local_documentation.ddoc";
593     }
594 
595     foreach(theModule;modules)
596     {
597         if(selectedModule != "" && theModule != selectedModule)
598         {
599             continue;
600         }
601 
602         // skipping package.d
603         size_t numberOfFiles = fileList[theModule].length -1 ;
604         foreach (fileNumber, name; fileList[theModule])
605         {
606             if (name == "package")
607                 continue;
608 
609             string docFile = "../../doc/"~theModule~"/"~name~docExtension;
610             string outputFile = name~docExtension;
611             string dFile = theModule~"/"~name~".d";
612 
613             string buildCommand;
614 
615             version(GNU)
616             {
617                 buildCommand = compiler~dFile~" -fdoc-inc="~ddoc~
618                 " -fdoc-dir=../../doc/dsfml/"~theModule~
619                 docSwitches~" -o obj.o";
620             }
621             else
622                 buildCommand = compiler~dFile~ddoc~docSwitches;
623 
624             if(needToBuild(docFile, dFile))
625             {
626                 progressOutput(fileNumber, numberOfFiles, outputFile);
627 
628                 auto status = executeShell(buildCommand);
629                 if(status.status !=0)
630                 {
631                     writeln(status.output);
632                     return false;
633                 }
634 
635                 if(docExtension!=".html")
636                     rename("../../doc/"~theModule~"/"~name~".html",
637                            "../../doc/"~theModule~"/"~name~docExtension);
638             }
639         }
640     }
641 
642     version(GNU)
643         core.stdc.stdio.remove("obj.o");
644 
645     chdir("../..");
646 
647     return true;
648 }
649 
650 /**
651  * Build DSFML interface files.
652  *
653  * Returns: true if documentation could be built, false if not.
654  */
655 bool buildInterfaceFiles()
656 {
657     if(!exists("import/"))
658     {
659         mkdir("import/");
660     }
661 
662     chdir("src/");
663 
664     foreach(theModule;modules)
665     {
666         size_t numberOfFiles = fileList[theModule].length;
667 
668         foreach (fileNumber, name; fileList[theModule])
669         {
670             string dFile = "dsfml/"~theModule~"/"~name~".d";
671             string outputFile = "../import/dsfml/"~theModule~"/"~name~".di";
672             if(name == "package")
673                 outputFile.length = outputFile.length - 1;
674 
675             version(GNU)
676             {
677                 interfaceSwitches ~= " -fintfc-dir=../import/dsfml/"~theModule;
678             }
679 
680             string buildCommand = compiler~dFile~interfaceSwitches;
681 
682             if(needToBuild(outputFile, dFile))
683             {
684                 progressOutput(fileNumber, numberOfFiles, outputFile[3 .. $]);
685 
686                 auto status = executeShell(buildCommand);
687                 if(status.status !=0)
688                 {
689                     writeln(status.output);
690                     return false;
691                 }
692             }
693         }
694 
695         if(exists("../import/dsfml/"~theModule~"/package.di"))
696         {
697             rename("../import/dsfml/"~theModule~"/package.di",
698                    "../import/dsfml/"~theModule~"/package.d");
699         }
700     }
701 
702     version(GNU)
703         core.stdc.stdio.remove("obj.o");
704 
705     chdir("../..");
706 
707     return true;
708 }
709 
710 /**
711  * Display the progress as a percentage given the current file is next.
712  *
713  * Display example:
714  * [ 20%] Building dsfml/src/system/clock.d
715  */
716 void progressOutput(size_t currentFile, size_t totalFiles, string fileName)
717 {
718     size_t percentage = ((currentFile+1)*100)/totalFiles;
719 
720     writefln("[%3u%%] Building %s", percentage, fileName);
721 }
722 
723 /**
724  * Checks the timestamps on the object file and its associated source file.
725  *
726  * If the source file has been more recently updated than the object file was
727  * built, or if the object file doesn't yet exist, this will return true.
728  */
729 bool needToBuild(string objLocation, string srcLocation)
730 {
731     import std.file: exists, timeStamp = timeLastModified;
732 
733     return exists(objLocation)?timeStamp(objLocation) < timeStamp(srcLocation):
734                                true;
735 }
736 
737 /**
738  * Search for SFML shared libraries in the submodule directory.
739  *
740  * Returns: true if SFML shared libraries can be found, false otherwise.
741  */
742 bool findSFML()
743 {
744     version(Windows)
745     {
746         //technically, we also need .lib files because Windows is stupid, but
747         //the build script will only look for the .dll's.
748         string dynamicExtension = "-2.dll";
749     }
750     else version(linux)
751     {
752         string dynamicExtension = ".so";
753     }
754     else
755     {
756         string dynamicExtension = ".dylib";
757     }
758 
759     //check to make sure ALL SFML libs were built
760     foreach(theModule; modules)
761     {
762         if(!exists("SFML/lib/"~prefix~"sfml-"~theModule~dynamicExtension))
763         {
764             writeln("SFML/lib/"~prefix~"sfml-"~theModule~dynamicExtension,
765                     " not found.");
766             writeln("Building unit tests requires SFML libs in ",
767                     "dsfml/SFML/lib/ directory.");
768             return false;
769         }
770     }
771 
772     return true;
773 }
774 
775 /**
776  * Builds a string consisting of the linker flags, library name, and extention.
777  *
778  * This is to simplify building the list of libraries needed when building unit
779  * tests.
780  *
781  */
782 string lib(string library)
783 {
784     version(Windows)
785         return linkerInclude~library~extension~" ";
786     else
787         return linkerInclude~library~" ";
788 }
789 
790 int main(string[] args)
791 {
792     GetoptResult optInfo;
793     try
794     {
795         optInfo = getopt(args,
796         "lib", "Build static libraries.", &buildingLibs,
797         "m32", "Force 32 bit building.", &force32Build,
798         "m64", "Force 64 bit building.", &force64Build,
799         "unittest", "Build DSFML unit test executable.", &buildingUnittests,
800         "doc", "Build DSFML documentation.", &buildingDoc,
801         "webdoc", "Build the DSFML website documentation.", &buildingWebsiteDocs,
802         "import", "Generate D interface files.", &buildingInterfaceFiles,
803         "debug", "Build debug libraries (ignored when not building libraries).", &debugLibs
804         );
805     }
806     catch(GetOptException e)
807     {
808         writeln(e.msg);
809         return -1;
810     }
811 
812     if(optInfo.helpWanted)
813     {
814         defaultGetoptPrinter("Switch Information\n"
815         ~"Default (no switches passed) will be to build static libraries with the compiler that built this.",
816         optInfo.options);
817         return 0;
818     }
819 
820     //default to building libs
821     if(!buildingLibs && !buildingDoc && !buildingInterfaceFiles &&
822        !buildingWebsiteDocs && !buildingUnittests && !buildingAll)
823     {
824         buildingLibs = true;
825     }
826 
827     if(!checkSwitchErrors())
828     {
829         return -1;
830     }
831 
832     writeln();
833     initialize();
834 
835     if(buildingLibs)
836     {
837         if(!buildLibs())
838             return -1;
839     }
840     if(buildingUnittests)
841     {
842         if(!buildUnittests())
843             return -1;
844     }
845     if(buildingDoc || buildingWebsiteDocs)
846     {
847         if(!buildDocumentation())
848             return -1;
849     }
850     if(buildingInterfaceFiles)
851     {
852         if(!buildInterfaceFiles())
853             return -1;
854     }
855 
856     return 0;
857 }