The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

222 lines
7.5KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2022 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 7 End-User License
  8. Agreement and JUCE Privacy Policy.
  9. End User License Agreement: www.juce.com/juce-7-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. /*
  19. ==============================================================================
  20. Utility to turn a bunch of binary files into a .cpp file and .h file full of
  21. data so they can be built directly into an executable.
  22. Use this code at your own risk! It carries no warranty!
  23. ==============================================================================
  24. */
  25. #include <JuceHeader.h>
  26. //==============================================================================
  27. static int addFile (const File& file,
  28. const String& classname,
  29. OutputStream& headerStream,
  30. OutputStream& cppStream)
  31. {
  32. MemoryBlock mb;
  33. file.loadFileAsData (mb);
  34. const String name (file.getFileName()
  35. .replaceCharacter (' ', '_')
  36. .replaceCharacter ('.', '_')
  37. .retainCharacters ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789"));
  38. std::cout << "Adding " << name << ": "
  39. << (int) mb.getSize() << " bytes" << std::endl;
  40. headerStream << " extern const char* " << name << ";\r\n"
  41. " const int " << name << "Size = "
  42. << (int) mb.getSize() << ";\r\n\r\n";
  43. static int tempNum = 0;
  44. cppStream << "static const unsigned char temp" << ++tempNum << "[] = {";
  45. size_t i = 0;
  46. const uint8* const data = (const uint8*) mb.getData();
  47. while (i < mb.getSize() - 1)
  48. {
  49. if ((i % 40) != 39)
  50. cppStream << (int) data[i] << ",";
  51. else
  52. cppStream << (int) data[i] << ",\r\n ";
  53. ++i;
  54. }
  55. cppStream << (int) data[i] << ",0,0};\r\n";
  56. cppStream << "const char* " << classname << "::" << name
  57. << " = (const char*) temp" << tempNum << ";\r\n\r\n";
  58. return (int) mb.getSize();
  59. }
  60. static bool isHiddenFile (const File& f, const File& root)
  61. {
  62. return f.getFileName().endsWithIgnoreCase (".scc")
  63. || f.getFileName() == ".svn"
  64. || f.getFileName().startsWithChar ('.')
  65. || (f.getSize() == 0 && ! f.isDirectory())
  66. || (f.getParentDirectory() != root && isHiddenFile (f.getParentDirectory(), root));
  67. }
  68. //==============================================================================
  69. int main (int argc, char* argv[])
  70. {
  71. std::cout << std::endl << " BinaryBuilder! Visit www.juce.com for more info." << std::endl;
  72. if (argc < 4 || argc > 5)
  73. {
  74. std::cout << " Usage: BinaryBuilder sourcedirectory targetdirectory targetclassname [optional wildcard pattern]\n\n"
  75. " BinaryBuilder will find all files in the source directory, and encode them\n"
  76. " into two files called (targetclassname).cpp and (targetclassname).h, which it\n"
  77. " will write into the target directory supplied.\n\n"
  78. " Any files in sub-directories of the source directory will be put into the\n"
  79. " resultant class, but #ifdef'ed out using the name of the sub-directory (hard to\n"
  80. " explain, but obvious when you try it...)\n";
  81. return 0;
  82. }
  83. const File sourceDirectory (File::getCurrentWorkingDirectory()
  84. .getChildFile (String (argv[1]).unquoted()));
  85. if (! sourceDirectory.isDirectory())
  86. {
  87. std::cout << "Source directory doesn't exist: "
  88. << sourceDirectory.getFullPathName()
  89. << std::endl << std::endl;
  90. return 0;
  91. }
  92. const File destDirectory (File::getCurrentWorkingDirectory()
  93. .getChildFile (String (argv[2]).unquoted()));
  94. if (! destDirectory.isDirectory())
  95. {
  96. std::cout << "Destination directory doesn't exist: "
  97. << destDirectory.getFullPathName() << std::endl << std::endl;
  98. return 0;
  99. }
  100. String className (argv[3]);
  101. className = className.trim();
  102. const File headerFile (destDirectory.getChildFile (className).withFileExtension (".h"));
  103. const File cppFile (destDirectory.getChildFile (className).withFileExtension (".cpp"));
  104. std::cout << "Creating " << headerFile.getFullPathName()
  105. << " and " << cppFile.getFullPathName()
  106. << " from files in " << sourceDirectory.getFullPathName()
  107. << "..." << std::endl << std::endl;
  108. auto files = sourceDirectory.findChildFiles (File::findFiles, true,
  109. (argc > 4) ? argv[4] : "*");
  110. if (files.isEmpty())
  111. {
  112. std::cout << "Didn't find any source files in: "
  113. << sourceDirectory.getFullPathName() << std::endl << std::endl;
  114. return 0;
  115. }
  116. headerFile.deleteFile();
  117. cppFile.deleteFile();
  118. std::unique_ptr<OutputStream> header (headerFile.createOutputStream());
  119. if (header == nullptr)
  120. {
  121. std::cout << "Couldn't open "
  122. << headerFile.getFullPathName() << " for writing" << std::endl << std::endl;
  123. return 0;
  124. }
  125. std::unique_ptr<OutputStream> cpp (cppFile.createOutputStream());
  126. if (cpp == nullptr)
  127. {
  128. std::cout << "Couldn't open "
  129. << cppFile.getFullPathName() << " for writing" << std::endl << std::endl;
  130. return 0;
  131. }
  132. *header << "/* (Auto-generated binary data file). */\r\n\r\n"
  133. "#pragma once\r\n\r\n"
  134. "namespace " << className << "\r\n"
  135. "{\r\n";
  136. *cpp << "/* (Auto-generated binary data file). */\r\n\r\n"
  137. "#include \"" << className << ".h\"\r\n\r\n";
  138. int totalBytes = 0;
  139. for (int i = 0; i < files.size(); ++i)
  140. {
  141. const File file (files[i]);
  142. // (avoid source control files and hidden files..)
  143. if (! isHiddenFile (file, sourceDirectory))
  144. {
  145. if (file.getParentDirectory() != sourceDirectory)
  146. {
  147. *header << " #ifdef " << file.getParentDirectory().getFileName().toUpperCase() << "\r\n";
  148. *cpp << "#ifdef " << file.getParentDirectory().getFileName().toUpperCase() << "\r\n";
  149. totalBytes += addFile (file, className, *header, *cpp);
  150. *header << " #endif\r\n";
  151. *cpp << "#endif\r\n";
  152. }
  153. else
  154. {
  155. totalBytes += addFile (file, className, *header, *cpp);
  156. }
  157. }
  158. }
  159. *header << "}\r\n";
  160. header = nullptr;
  161. cpp = nullptr;
  162. std::cout << std::endl << " Total size of binary data: " << totalBytes << " bytes" << std::endl;
  163. return 0;
  164. }