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 }