polybuild.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. #include "polybuild.h"
  2. #include "string.h"
  3. #include "archive.h"
  4. #include "archive_entry.h"
  5. #ifdef _WINDOWS
  6. #include <windows.h>
  7. #include <direct.h>
  8. #else
  9. #include <dirent.h>
  10. #include <sys/types.h>
  11. #include <sys/stat.h>
  12. #endif
  13. #include "physfs.h"
  14. #if defined(__APPLE__) && defined(__MACH__)
  15. #include <mach-o/dyld.h>
  16. #endif
  17. using std::vector;
  18. vector<BuildArg> args;
  19. #define MAXFILENAME (2048)
  20. String getArg(String argName) {
  21. for(int i=0; i < args.size(); i++) {
  22. if(args[i].name == argName) {
  23. return args[i].value;
  24. }
  25. }
  26. return "";
  27. }
  28. #ifdef _WINDOWS
  29. void wtoc(char* Dest, TCHAR* Source, int SourceSize)
  30. {
  31. for(int i = 0; i < SourceSize; ++i)
  32. Dest[i] = (char)Source[i];
  33. }
  34. #endif
  35. void addFileToZip(struct archive *a, String filePath, String pathInZip, bool silent) {
  36. struct archive_entry *entry;
  37. struct stat st;
  38. int len;
  39. FILE *fd;
  40. char buff[8192];
  41. stat(filePath.c_str(), &st);
  42. entry = archive_entry_new();
  43. archive_entry_set_pathname(entry, pathInZip.c_str());
  44. archive_entry_set_size(entry, st.st_size);
  45. archive_entry_set_filetype(entry, AE_IFREG);
  46. archive_entry_set_perm(entry, 0644);
  47. archive_write_header(a, entry);
  48. fd = fopen(filePath.c_str(), "rb");
  49. if(fd) {
  50. len = fread(buff, 1, sizeof(buff), fd);
  51. while ( len > 0 ) {
  52. archive_write_data(a, buff, len);
  53. len = fread(buff, 1, sizeof(buff), fd);
  54. }
  55. fclose(fd);
  56. }
  57. archive_entry_free(entry);
  58. }
  59. void addFolderToZip(struct archive *a, String folderPath, String parentFolder, bool silent) {
  60. std::vector<OSFileEntry> files = OSBasics::parseFolder(folderPath, false);
  61. for(int i=0; i < files.size(); i++) {
  62. if(files[i].type == OSFileEntry::TYPE_FILE) {
  63. String pathInZip;
  64. if(parentFolder == "") {
  65. pathInZip = files[i].name;
  66. } else {
  67. pathInZip = parentFolder + "/" + files[i].name;
  68. }
  69. addFileToZip(a, files[i].fullPath, pathInZip, silent);
  70. } else {
  71. if(parentFolder == "") {
  72. addFolderToZip(a, files[i].fullPath.c_str(), files[i].name, silent);
  73. } else {
  74. addFolderToZip(a, files[i].fullPath.c_str(), parentFolder + "/" + files[i].name, silent);
  75. }
  76. }
  77. }
  78. }
  79. int main(int argc, char **argv) {
  80. PHYSFS_init(argv[0]);
  81. #if defined(__APPLE__) && defined(__MACH__)
  82. uint32_t bufsize = 2048;
  83. char path[bufsize];
  84. _NSGetExecutablePath(path, &bufsize);
  85. String basePath = path;
  86. vector<String> cpts = basePath.split("/");
  87. String installPath = "";
  88. for(int i=0; i < cpts.size() - 2; i++) {
  89. installPath = installPath + cpts[i];
  90. installPath += String("/");
  91. }
  92. #elif defined (_WINDOWS)
  93. char path[2049];
  94. TCHAR tpath[2049];
  95. GetModuleFileName(NULL, (LPWSTR)tpath, 2048);
  96. wtoc(path, tpath, 2048);
  97. String basePath = path;
  98. vector<String> cpts = basePath.split("\\");
  99. String installPath = "";
  100. for(int i=0; i < cpts.size() - 2; i++) {
  101. installPath = installPath + cpts[i];
  102. installPath += String("\\");
  103. }
  104. #else
  105. String basePath = PHYSFS_getBaseDir();
  106. vector<String> cpts = basePath.split("/");
  107. String installPath = "";
  108. for(int i=0; i < cpts.size() - 2; i++) {
  109. installPath = installPath + cpts[i];
  110. installPath += String("/");
  111. }
  112. #endif
  113. printf("Polycode build tool v"POLYCODE_VERSION_STRING"\n");
  114. for(int i=0; i < argc; i++) {
  115. String argString = String(argv[i]);
  116. vector<String> bits = argString.split("=");
  117. if(bits.size() == 2) {
  118. BuildArg arg;
  119. arg.name = bits[0];
  120. arg.value = bits[1];
  121. // printf("arg: %s=%s\n", arg.name.c_str(), arg.value.c_str());
  122. args.push_back(arg);
  123. }
  124. }
  125. if(getArg("--config") == "") {
  126. printf("\n\nInput config XML missing. Use --config=path to specify.\n\n");
  127. return 1;
  128. }
  129. if(getArg("--out") == "") {
  130. printf("\n\nOutput file not specified. Use --out=outfile.polyapp to specify.\n\n");
  131. return 1;
  132. }
  133. char dirPath[4099];
  134. #if defined(__APPLE__) && defined(__MACH__)
  135. getcwd(dirPath, sizeof(dirPath));
  136. #elif defined (_WINDOWS)
  137. TCHAR tdirpath[4099];
  138. GetCurrentDirectory(4098, (LPWSTR)tdirpath);
  139. wtoc(dirPath, tdirpath, 4098);
  140. #else
  141. getcwd(dirPath, sizeof(dirPath));
  142. #endif
  143. String currentPath = String(dirPath);
  144. String configPath = getArg("--config");
  145. String finalPath = configPath;
  146. if(configPath[0] != '/' && configPath[1] !=':') {
  147. #ifdef _WINDOWS
  148. finalPath = currentPath+"\\"+configPath;
  149. #else
  150. finalPath = currentPath+"/"+configPath;
  151. #endif
  152. }
  153. printf("Reading config file from %s\n", finalPath.c_str());
  154. Object configFile;
  155. if(!configFile.loadFromXML(finalPath)) {
  156. printf("Specified config file doesn't exist!\n");
  157. return 1;
  158. }
  159. printf("OK!\n");
  160. // start required params
  161. String entryPoint;
  162. int defaultWidth;
  163. int defaultHeight;
  164. int frameRate = 60;
  165. int antiAliasingLevel = 0;
  166. int anisotropyLevel = 0;
  167. bool vSync = false;
  168. bool fullScreen = false;
  169. float backgroundColorR = 0.2;
  170. float backgroundColorG = 0.2;
  171. float backgroundColorB = 0.2;
  172. String textureFiltering = "linear";
  173. if(configFile.root["entryPoint"]) {
  174. printf("Entry point: %s\n", configFile.root["entryPoint"]->stringVal.c_str());
  175. entryPoint = configFile.root["entryPoint"]->stringVal;
  176. } else {
  177. printf("Required parameter: \"entryPoint\" is missing from config file!\n");
  178. return 1;
  179. }
  180. if(configFile.root["defaultWidth"]) {
  181. printf("Width: %d\n", configFile.root["defaultWidth"]->intVal);
  182. defaultWidth = configFile.root["defaultWidth"]->intVal;
  183. } else {
  184. printf("Required parameter: \"defaultWidth\" is missing from config file!\n");
  185. return 1;
  186. }
  187. if(configFile.root["defaultHeight"]) {
  188. printf("Height: %d\n", configFile.root["defaultHeight"]->intVal);
  189. defaultHeight = configFile.root["defaultHeight"]->intVal;
  190. } else {
  191. printf("Required parameter: \"defaultHeight\" is missing from config file!\n");
  192. return 1;
  193. }
  194. // start optional params
  195. if(configFile.root["frameRate"]) {
  196. printf("Frame rate: %d\n", configFile.root["frameRate"]->intVal);
  197. frameRate = configFile.root["frameRate"]->intVal;
  198. }
  199. if(configFile.root["textureFiltering"]) {
  200. printf("Filtering mode: %s\n", configFile.root["textureFiltering"]->stringVal.c_str());
  201. textureFiltering = configFile.root["textureFiltering"]->stringVal;
  202. }
  203. if(configFile.root["antiAliasingLevel"]) {
  204. printf("Anti-aliasing level: %d\n", configFile.root["antiAliasingLevel"]->intVal);
  205. antiAliasingLevel = configFile.root["antiAliasingLevel"]->intVal;
  206. }
  207. if(configFile.root["anisotropyLevel"]) {
  208. printf("Anisotropy level: %d\n", configFile.root["anisotropyLevel"]->intVal);
  209. anisotropyLevel = configFile.root["anisotropyLevel"]->intVal;
  210. }
  211. if(configFile.root["vSync"]) {
  212. vSync = configFile.root["vSync"]->boolVal;
  213. if(vSync) {
  214. printf("V-Sync: true\n");
  215. } else {
  216. printf("V-Sync: false\n");
  217. }
  218. }
  219. if(configFile.root["fullScreen"]) {
  220. fullScreen = configFile.root["fullScreen"]->boolVal;
  221. if(fullScreen) {
  222. printf("Full-screen: true\n");
  223. } else {
  224. printf("Full-screen: false\n");
  225. }
  226. }
  227. if(configFile.root["backgroundColor"]) {
  228. ObjectEntry *color = configFile.root["backgroundColor"];
  229. if((*color)["red"] && (*color)["green"] && (*color)["blue"]) {
  230. backgroundColorR = (*color)["red"]->NumberVal;
  231. backgroundColorG = (*color)["green"]->NumberVal;
  232. backgroundColorB = (*color)["blue"]->NumberVal;
  233. printf("Background color: %f %f %f\n", backgroundColorR, backgroundColorG, backgroundColorB);
  234. } else {
  235. printf("backgroundColor node specified, but missing all three color attributes (red,green,blue). Ignoring.\n");
  236. }
  237. }
  238. struct archive *a;
  239. a = archive_write_new();
  240. archive_write_set_format_zip(a);
  241. archive_write_open_filename(a, getArg("--out").c_str());
  242. //zipFile z = zipOpen(getArg("--out").c_str(), 0);
  243. Object runInfo;
  244. runInfo.root.name = "PolycodeApp";
  245. runInfo.root.addChild("entryPoint", entryPoint);
  246. runInfo.root.addChild("defaultHeight", defaultHeight);
  247. runInfo.root.addChild("defaultWidth", defaultWidth);
  248. runInfo.root.addChild("frameRate", frameRate);
  249. runInfo.root.addChild("antiAliasingLevel", antiAliasingLevel);
  250. runInfo.root.addChild("anisotropyLevel", anisotropyLevel);
  251. runInfo.root.addChild("vSync", vSync);
  252. runInfo.root.addChild("fullScreen", fullScreen);
  253. runInfo.root.addChild("textureFiltering", String(textureFiltering));
  254. ObjectEntry *color = runInfo.root.addChild("backgroundColor");
  255. color->addChild("red", backgroundColorR);
  256. color->addChild("green", backgroundColorG);
  257. color->addChild("blue", backgroundColorB);
  258. if(configFile.root["fonts"]) {
  259. runInfo.root.addChild(configFile.root["fonts"]);
  260. }
  261. if(configFile.root["modules"]) {
  262. #ifdef _WINDOWS
  263. String modulesPath = installPath + "Modules\\";
  264. #else
  265. String modulesPath = installPath + "Modules/";
  266. #endif
  267. ObjectEntry *modules = configFile.root["modules"];
  268. if(modules) {
  269. for(int i=0; i < modules->length; i++) {
  270. printf("Adding module: %s\n", (*modules)[i]->stringVal.c_str());
  271. String modulePath = modulesPath + (*modules)[i]->stringVal;
  272. #ifdef _WINDOWS
  273. String moduleAPIPath = modulePath + "\\API";
  274. String moduleLibPath = modulePath + "\\Lib";
  275. moduleAPIPath = moduleAPIPath.replace("\\", "/");
  276. moduleAPIPath = moduleAPIPath.substr(2, moduleAPIPath.length() - 2);
  277. moduleLibPath = moduleLibPath.replace("\\", "/");
  278. moduleLibPath = moduleLibPath.substr(2, moduleLibPath.length() - 2);
  279. #else
  280. String moduleAPIPath = modulePath + "/API";
  281. String moduleLibPath = modulePath + "/Lib";
  282. #endif
  283. printf("Path:%s\n", moduleAPIPath.c_str());
  284. addFolderToZip(a, moduleAPIPath, "", false);
  285. addFolderToZip(a, moduleLibPath, "__lib", false);
  286. //String module = configFile.root["entryPoint"]->stringVal;
  287. }
  288. runInfo.root.addChild(configFile.root["modules"]);
  289. }
  290. }
  291. if(configFile.root["packedItems"]) {
  292. ObjectEntry *packed = configFile.root["packedItems"];
  293. if(packed) {
  294. for(int i=0; i < packed->length; i++) {
  295. ObjectEntry *entryPath = (*(*packed)[i])["path"];
  296. ObjectEntry *entryType = (*(*packed)[i])["type"];
  297. ObjectEntry *entrySource = (*(*packed)[i])["source"];
  298. if(entryPath && entryType) {
  299. if (!entrySource) entrySource = entryPath;
  300. if(entryType->stringVal == "folder") {
  301. addFolderToZip(a, entrySource->stringVal, entryPath->stringVal, false);
  302. } else {
  303. addFileToZip(a, entrySource->stringVal, entryPath->stringVal, false);
  304. }
  305. }
  306. }
  307. runInfo.root.addChild(configFile.root["packedItems"]);
  308. }
  309. }
  310. runInfo.saveToXML("runinfo_tmp_zzzz.polyrun");
  311. addFileToZip(a, "runinfo_tmp_zzzz.polyrun", "runinfo.polyrun", true);
  312. archive_write_close(a);
  313. archive_write_free(a);
  314. #ifdef _WINDOWS
  315. char *buffer = _getcwd(NULL, 0);
  316. String workingDir = String(buffer);
  317. free(buffer);
  318. OSBasics::removeItem(workingDir+"/runinfo_tmp_zzzz.polyrun");
  319. #else
  320. OSBasics::removeItem("runinfo_tmp_zzzz.polyrun");
  321. #endif
  322. return 0;
  323. }