1 /** 2 Copyright: Copyright (c) 2015-2016 Andrey Penechko. 3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 4 Authors: Andrey Penechko. 5 */ 6 module packager; 7 8 import std.file; 9 import std.string; 10 import std.digest.crc; 11 import std.stdio; 12 import std.zip; 13 import std.path; 14 import std.process; 15 import std.datetime; 16 17 enum ROOT_PATH = "../.."; 18 19 void main(string[] args) 20 { 21 string semver = "0.6.1"; 22 23 StopWatch sw; 24 sw.start(); 25 completeBuild(Arch.x32, semver); 26 completeBuild(Arch.x64, semver); 27 sw.stop(); 28 writefln("Finished in %.1fs", sw.peek().to!("seconds", real)); 29 } 30 31 void completeBuild(Arch arch, string semver) 32 { 33 string dub_arch = arch == Arch.x32 ? "x86" : "x86_64"; 34 string launcher_arch = arch == Arch.x32 ? "32" : "64"; 35 string dubCom(Arch arch) { 36 return format(`dub run --root="tools/launcher" -q --build=release --arch=%s --nodeps -- --release=%s`, 37 dub_arch, launcher_arch); 38 } 39 40 string com = dubCom(arch); 41 writefln("Executing '%s'", com); stdout.flush(); 42 auto dub = executeShell(com, null, Config.none, size_t.max, ROOT_PATH); 43 if (dub.status != 0) 44 writeln("Failed to run launcher"); 45 else dub.output.write; 46 writefln("Packing %sbit", launcher_arch); stdout.flush(); 47 pack(semver, arch, Platform.windows); 48 } 49 50 struct ReleasePackage 51 { 52 string semver; 53 Arch arch; 54 Platform platform; 55 ZipArchive zip; 56 string fileRoot; 57 string archRoot; 58 } 59 60 void pack(string semver, Arch arch, Platform pl) 61 { 62 ReleasePackage pack = ReleasePackage( 63 semver, 64 arch, 65 pl, 66 new ZipArchive, 67 ROOT_PATH); 68 string archName = archName(&pack, "voxelman"); 69 pack.archRoot = archName; 70 71 makePackage(&pack); 72 writePackage(&pack, buildNormalizedPath(ROOT_PATH, archName) ~ ".zip"); 73 } 74 75 //enum allowedExt = ["exe", "d", "txt", "dll"]; 76 //enum dirs = ["builds/default", "config", "lib", "pluginpacks", "plugins", "source"]; 77 enum Arch { x64, x32 } 78 enum Platform { windows, linux, macos } 79 string[Platform] platformToString; 80 string[Arch] archToString; 81 static this() 82 { 83 platformToString = [Platform.windows : "win", Platform.linux : "linux", Platform.macos : "mac"]; 84 archToString = [Arch.x64 : "64", Arch.x32 : "32"]; 85 } 86 87 void makePackage(ReleasePackage* pack) 88 { 89 pack.addFiles("builds/default", "*.exe"); 90 pack.addFiles("config", "*.sdl"); 91 pack.addFiles("lib/"~archToString[pack.arch], "*.dll"); 92 pack.addFile("README.md"); 93 pack.addFile("CHANGELOG.md"); 94 pack.addFile("LICENSE.md"); 95 pack.addFile("pluginpacks/default.txt"); 96 pack.addFile("launcher.exe"); 97 } 98 99 void writePackage(ReleasePackage* pack, string path) 100 { 101 std.file.write(path, pack.zip.build()); 102 } 103 104 string archName(R)(ReleasePackage* pack, R baseName) 105 { 106 string arch = archToString[pack.arch]; 107 string platform = platformToString[pack.platform]; 108 return format("%s-v%s-%s%s", baseName, pack.semver, platform, arch); 109 } 110 111 alias normPath = buildNormalizedPath; 112 alias absPath = absolutePath; 113 void addFiles(ReleasePackage* pack, string path, string pattern) 114 { 115 import std.file : dirEntries, SpanMode; 116 117 string absRoot = pack.fileRoot.absPath.normPath; 118 foreach (entry; dirEntries(buildPath(pack.fileRoot, path), pattern, SpanMode.depth)) 119 if (entry.isFile) { 120 string absPath = entry.name.absPath.normPath; 121 addFile(pack, absPath, relativePath(absPath, absRoot)); 122 } 123 } 124 125 void addFile(ReleasePackage* pack, string arch_name) 126 { 127 addFile(pack.zip, buildPath(pack.fileRoot, arch_name).absPath.normPath, buildPath(pack.archRoot, arch_name)); 128 } 129 130 void addFile(ReleasePackage* pack, string fs_name, string arch_name) 131 { 132 addFile(pack.zip, fs_name.absPath.normPath, buildPath(pack.archRoot, arch_name)); 133 } 134 135 void addFile(ZipArchive arch, string fs_name, string arch_name) 136 { 137 string norm = arch_name.normPath; 138 writefln("Add %s as %s", fs_name, norm); 139 void[] data = std.file.read(fs_name); 140 ArchiveMember am = new ArchiveMember(); 141 am.name = norm; 142 am.compressionMethod = CompressionMethod.deflate; 143 am.expandedData(cast(ubyte[])data); 144 arch.addMember(am); 145 }