-
-
Notifications
You must be signed in to change notification settings - Fork 143
/
get_dlibcurl32.d
executable file
·262 lines (216 loc) · 7.01 KB
/
get_dlibcurl32.d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
#!/usr/bin/env rdmd
/++
This Windows-only tool automatically downloads Win32 libcurl binaries and
generates a libcurl.lib compatible with Win32 DMD (which is needed by
std.net.curl and certain official DMD tools).
There are no prerequisites other than an active internet connection and a
working D compiler to compile this tool.
This tool is provided because, unlike Posix and Win64, the standard libcurl
binaries aren't compatible with the DMD linker used on Win32. Instead, "implib"
needs to be used to generate a compatible import library from libcurl.dll,
which this tool handles automatically.
+/
import std.algorithm;
import std.array;
import std.file;
import std.path;
import std.process;
import std.stdio;
import std.string;
version(Windows) {} else
{
static assert(false,
"This tool is only for Windows. On other systems, simply install "~
"libcurl through your OS's usual package manager.");
}
auto outputDir = "dlibcurl32";
immutable unzipUrl = "http://semitwist.com/download/app/unz600xn.exe";
immutable basicUtilsUrl = "http://ftp.digitalmars.com/bup.zip";
auto curlUrl = "http://curl.haxx.se/gknw.net/$(CURL_VERSION)/dist-w32/curl-$(CURL_VERSION)-rtmp-ssh2-ssl-sspi-zlib-idn-static-bin-w32.zip";
auto curlZipBase = "curl-$(CURL_VERSION)-rtmp-ssh2-ssl-sspi-zlib-idn-static-bin-w32";
immutable unzipArchiveName = "unzip-sfx.exe";
immutable basicUtilsArchiveName = "bup.zip";
immutable curlArchiveName = "curl.zip";
immutable workDirName = "get_dlibcurl32";
immutable dloadToolFilename = "download.vbs";
immutable dloadToolContent =
`Option Explicit
Dim args, http, fileSystem, adoStream, url, target, status
Set args = Wscript.Arguments
Set http = CreateObject("WinHttp.WinHttpRequest.5.1")
url = args(0)
target = args(1)
http.Open "GET", url, False
http.Send
status = http.Status
If status <> 200 Then
WScript.Echo "FAILED to download: HTTP Status " & status
WScript.Quit 1
End If
Set adoStream = CreateObject("ADODB.Stream")
adoStream.Open
adoStream.Type = 1
adoStream.Write http.ResponseBody
adoStream.Position = 0
Set fileSystem = CreateObject("Scripting.FileSystemObject")
If fileSystem.FileExists(target) Then fileSystem.DeleteFile target
adoStream.SaveToFile target
adoStream.Close
`;
string workDir;
string dloadToolPath;
bool hasImplib;
void showHelp()
{
stderr.writeln("Usage: get_dlibcurl32 LIBCURL_VERSION");
stderr.writeln("Ex: get_dlibcurl32 7.32.0");
}
int main(string[] args)
{
if(args.length != 2)
{
showHelp();
return 1;
}
if(args[1] == "--help")
{
showHelp();
return 0;
}
// Setup paths
auto curlVersion = args[1];
curlUrl = curlUrl .replace("$(CURL_VERSION)", curlVersion);
curlZipBase = curlZipBase.replace("$(CURL_VERSION)", curlVersion);
outputDir ~= "-" ~ curlVersion;
workDir = buildPath(tempDir(), workDirName);
checkImplib();
// Clear temporary work dir
writeln("Clearing temporary work dir: ", workDir);
removeDir(workDir);
makeDir(workDir);
// Archive paths
auto unzipArchivePath = buildPath(workDir, "unzip", unzipArchiveName);
auto basicUtilsArchivePath = buildPath(workDir, "bup", basicUtilsArchiveName);
auto curlArchivePath = buildPath(workDir, curlArchiveName);
makeDir(dirName(unzipArchivePath));
makeDir(dirName(basicUtilsArchivePath));
// Download
initDownloader();
download(unzipUrl, unzipArchivePath);
if(!hasImplib)
download(basicUtilsUrl, basicUtilsArchivePath);
download(curlUrl, curlArchivePath);
// Extract
{
auto saveDir = getcwd();
scope(exit) chdir(saveDir);
chdir(dirName(unzipArchivePath));
run(unzipArchiveName); // Self-extracting archive
if(!hasImplib)
{
chdir(dirName(basicUtilsArchivePath));
unzip(basicUtilsArchiveName);
}
chdir(workDir);
unzip(curlArchivePath);
}
// Generate import lib
auto curlDir = buildPath(workDir, curlZipBase);
implib(buildPath(curlDir, "libcurl"));
// Copy results out of temp dir
writeln("Copying results to '", outputDir, "'");
removeDir(outputDir);
copyDir(curlDir, outputDir);
writeln("Done.");
writeln("Your OPTLINK-compatable libcurl.lib, along with the rest of libcurl,");
writeln("is in the directory: ", outputDir);
return 0;
}
string quote(string str)
{
return `"` ~ str ~ `"`;
}
/// Recursively copy contents of 'src' directory into 'dest' directory.
/// Directory 'dest' will be created if it doesn't exist.
void copyDir(string src, string dest)
{
// Needed to generate 'relativePath' correctly.
if(!src.endsWith(dirSeparator))
src ~= dirSeparator;
makeDir(dest);
foreach(DirEntry entry; dirEntries(src, SpanMode.breadth))
{
auto relativePath = entry.name.chompPrefix(src);
auto destPath = buildPath(dest, relativePath);
if(entry.isDir)
makeDir(destPath);
else
{
makeDir(dirName(destPath));
copy(buildPath(src, relativePath), destPath);
}
}
}
/// Remove entire directory tree. If it doesn't exist, do nothing.
void removeDir(string path)
{
if(exists(path))
{
auto failMsg =
"Failed to remove directory: "~path~"\n"~
" A process may still holding an open handle within the directory.\n"~
" Either delete the directory manually or try again later.";
try
system("rmdir /S /Q "~quote(path));
catch(Exception e)
throw new Exception(failMsg);
if(exists(path))
throw new Exception(failMsg);
}
}
/// Like mkdirRecurse, but no error if directory already exists.
void makeDir(string path)
{
if(!exists(path))
mkdirRecurse(path);
}
void initDownloader()
{
dloadToolPath = buildPath(workDir, dloadToolFilename);
std.file.write(dloadToolPath, dloadToolContent);
}
void checkImplib()
{
try
hasImplib = executeShell("implib /h").output.startsWith("Digital Mars Import Library Manager");
catch(Exception e)
hasImplib = false;
}
void run(string cmd)
{
auto errlevel = system(cmd);
if(errlevel != 0)
throw new Exception("Command failed: "~cmd~"\n Ran from dir: "~getcwd());
}
void download(string url, string target)
{
writeln("Downloading: ", url);
run("cscript //Nologo "~quote(dloadToolPath)~" "~quote(url)~" "~quote(target));
}
void unzip(string path)
{
writeln("Unzipping: ", path);
auto unzipTool = buildPath(workDir, `unzip\unzip.exe`);
run(unzipTool~" -q "~quote(path));
}
/// 'libName' includes path, but NOT extension
void implib(string libName)
{
writeln("Generating Import Lib: ", libName);
auto saveDir = getcwd();
scope(exit) chdir(saveDir);
chdir(dirName(libName));
auto implibTool = hasImplib? "implib" : buildPath(workDir, `bup\dm\bin\implib.exe`);
auto libBaseName = baseName(libName);
run(implibTool~" /s "~quote(libBaseName~".lib")~" "~quote(libBaseName~".dll"));
}