1 /**
2  * DigitalMars C++ installer
3  *
4  * License:
5  *   This Source Code Form is subject to the terms of
6  *   the Mozilla Public License, v. 2.0. If a copy of
7  *   the MPL was not distributed with this file, You
8  *   can obtain one at http://mozilla.org/MPL/2.0/.
9  *
10  * Authors:
11  *   Vladimir Panteleev <ae@cy.md>
12  */
13 
14 module ae.sys.install.dmc;
15 
16 version(Windows):
17 
18 import std.array;
19 import std.exception;
20 import std.file;
21 import std.path;
22 
23 import ae.sys.archive;
24 import ae.sys.file;
25 import ae.utils.meta : singleton, I;
26 
27 public import ae.sys.install.common;
28 
29 /// Installs old versions of DMC.
30 class LegacyDMCInstaller : Installer
31 {
32 	protected @property override string name() { return "DigitalMars C++" ~ (ver ? " v" ~ ver[0] ~ "." ~ ver[1..$] : null); }
33 	protected @property override string subdirectory() { return "dm" ~ ver; }
34 
35 	protected @property override string[] requiredExecutables() { return ["dmc", "link"]; }
36 	protected @property override string[] binPaths() { return ["bin"]; }
37 
38 	string ver;    /// Version to install
39 	string dmcURL; /// URL to DigitalMars C
40 
41 	this(string ver)
42 	{
43 		ver = ver.replace(".", "");
44 		this.ver = ver;
45 		if (ver >= "855")
46 			dmcURL = "http://downloads.dlang.org/other/dm" ~ ver ~ "c.zip";
47 		else
48 			dmcURL = "http://ftp.digitalmars.com/Digital_Mars_C++/Patch/dm" ~ ver ~ "c.zip";
49 	} ///
50 
51 	static this()
52 	{
53 		urlDigests["http://ftp.digitalmars.com/Digital_Mars_C++/Patch/dm850c.zip"] = "de1d27c337f028f4d001aec903474b85275c7118";
54 		urlDigests["http://downloads.dlang.org/other/dm855c.zip"				 ] = "5a177e50495f0062f107cba0c9231f780ebc56e1";
55 		urlDigests["http://downloads.dlang.org/other/dm856c.zip"				 ] = "c46302e645f9ce649fe8b80c0dec513f1622ccc0";
56 		urlDigests["http://downloads.dlang.org/other/dm857c.zip"				 ] = "c6bbaf8b872bfb1c82e611ef5e249dd19eab5272";
57 	}
58 
59 	protected override void installImpl(string target)
60 	{
61 		auto dmcDir =
62 			dmcURL
63 			.I!save()
64 			.I!unpack();
65 		scope(success) removeRecurse(dmcDir);
66 
67 		enforce(buildPath(dmcDir, "dm", "bin", "dmc.exe").exists);
68 		rename(buildPath(dmcDir, "dm"), target);
69 	}
70 }
71 
72 /// Installs DMC and updates it with the latest OPTLINK and snn.lib.
73 class DMCInstaller : LegacyDMCInstaller
74 {
75 	//string optlinkURL = "http://downloads.dlang.org/other/optlink-8.00.15.zip";
76 	string optlinkURL = null; /// URL to OPTLINK .zip file to install on top of the DMC one
77 	string dmdURL = "http://downloads.dlang.org/releases/2.x/2.074.0/dmd.2.074.0.windows.7z"; /// URL to DMD .zip file with latest snn.lib
78 
79 	protected @property override string subdirectory() { return super.subdirectory ~ "-snn2074-optlink80017"; }
80 
81 	this()
82 	{
83 		super("857");
84 	} ///
85 
86 	static this()
87 	{
88 		urlDigests["http://downloads.dlang.org/other/optlink-8.00.15.zip"                  ] = "f5a161029d795063e57523824be7408282cbdb81";
89 		urlDigests["http://downloads.dlang.org/releases/2.x/2.071.0/dmd.2.071.0.windows.7z"] = "c1bc880e54ff25ba8ee938abb2a1436ff6a9dec8";
90 		urlDigests["http://downloads.dlang.org/releases/2.x/2.074.0/dmd.2.074.0.windows.7z"] = "b2f491a448a674c0c3854ffa6b38b2da638c0ea0";
91 	}
92 
93 	protected override void installImpl(string target)
94 	{
95 		super.installImpl(target);
96 
97 		// Get latest OPTLINK
98 
99 		if (optlinkURL)
100 		{
101 			auto optlinkDir =
102 				optlinkURL
103 				.I!save()
104 				.I!unpack();
105 			scope(success) rmdirRecurse(optlinkDir);
106 
107 			rename(buildPath(optlinkDir, "link.exe"), buildPath(target, "bin", "link.exe"));
108 			hardLink(buildPath(target, "bin", "link.exe"), buildPath(target, "bin", "optlink.exe"));
109 		}
110 
111 		// Get latest snn.lib
112 
113 		if (dmdURL)
114 		{
115 			auto dmdDir =
116 				dmdURL
117 				.I!save()
118 				.I!unpack();
119 			scope(success) rmdirRecurse(dmdDir);
120 
121 			rename(buildPath(dmdDir, "dmd2", "windows", "lib", "snn.lib"), buildPath(target, "lib", "snn.lib"));
122 			if (!optlinkURL)
123 			{
124 				rename(buildPath(dmdDir, "dmd2", "windows", "bin", "link.exe"), buildPath(target, "bin", "link.exe"));
125 				hardLink(buildPath(target, "bin", "link.exe"), buildPath(target, "bin", "optlink.exe"));
126 			}
127 		}
128 	}
129 }
130 
131 alias dmcInstaller = singleton!DMCInstaller; /// ditto