-
-
Notifications
You must be signed in to change notification settings - Fork 147
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add script 'get_dlibcurl32', to auto-create Win32 libcurl import lib.
- Loading branch information
Abscissa
committed
Aug 17, 2013
1 parent
f3b4edd
commit 4e67ce1
Showing
2 changed files
with
244 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
@echo off | ||
rdmd -gc get_dlibcurl32.d %* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,242 @@ | ||
/++ | ||
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; | ||
|
||
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); | ||
|
||
// 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); | ||
download(basicUtilsUrl, basicUtilsArchivePath); | ||
download(curlUrl, curlArchivePath); | ||
|
||
// Extract | ||
{ | ||
auto saveDir = getcwd(); | ||
scope(exit) chdir(saveDir); | ||
|
||
chdir(dirName(unzipArchivePath)); | ||
run(unzipArchiveName); // Self-extracting archive | ||
|
||
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); | ||
|
||
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 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 = buildPath(workDir, `bup\dm\bin\implib.exe`); | ||
auto libBaseName = baseName(libName); | ||
run(implibTool~" /s "~quote(libBaseName~".lib")~" "~quote(libBaseName~".dll")); | ||
} |