-
-
Notifications
You must be signed in to change notification settings - Fork 97
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #289 from rainers/build-mingw
Build mingw COFF libraries
- Loading branch information
Showing
9 changed files
with
952 additions
and
21 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 |
---|---|---|
@@ -1,21 +1,3 @@ | ||
language: c | ||
|
||
addons: | ||
apt: | ||
# https://github.com/SimonKagstrom/kcov/blob/master/INSTALL.md#user-content-ubuntu | ||
packages: [shellcheck, binutils-dev, libcurl4-openssl-dev, zlib1g-dev, libdw-dev, libiberty-dev] | ||
|
||
matrix: | ||
include: | ||
- os: linux | ||
install: | ||
- KCOV_VERSION=34 | ||
- curl -fsSL https://github.com/SimonKagstrom/kcov/archive/v"$KCOV_VERSION".tar.gz | tar -C "$HOME" -zxf - | ||
- pushd "$HOME/kcov-$KCOV_VERSION" | ||
- cmake -DCMAKE_INSTALL_PREFIX=$HOME/.local . | ||
- make install -j$(nproc) | ||
- popd | ||
script: kcov --exclude-pattern=travis.sh $PWD/coverage ./travis.sh | ||
after_success: bash <(curl -s https://codecov.io/bash) -s $PWD/coverage | ||
- os: osx | ||
script: ./travis.sh | ||
branches: | ||
except: | ||
- /^build-/ |
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,16 @@ | ||
os: Visual Studio 2017 | ||
|
||
environment: | ||
matrix: | ||
- ARCH: x86 | ||
MINGW_VER: 5.0.2 | ||
D_VERSION: 2.077.1 | ||
|
||
artifacts: | ||
- path: mingw-libs-$(MINGW_VER).zip | ||
name: mingwlibs | ||
|
||
build_script: | ||
- call windows\build_mingw.bat | ||
|
||
test_script: true |
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,46 @@ | ||
@setlocal | ||
|
||
set ROOT=%CD% | ||
|
||
set DMD_URL=http://downloads.dlang.org/releases/2.x/%D_VERSION%/dmd.%D_VERSION%.windows.7z | ||
echo DMD_URL=%DMD_URL% | ||
appveyor DownloadFile %DMD_URL% -FileName dmd2.7z || exit /B 1 | ||
7z x dmd2.7z || exit /B 1 | ||
set PATH=%ROOT%\dmd2\windows\bin;%PATH% | ||
|
||
echo b80b0c9d0158f9125e482b50fe00b70dde11d7a015ee687ca455fe2ea2ec8733 *w32api.src.tar.xz> sha256sums | ||
echo 77233333f5440287840d134804bcecf3144ec3efc7fd7f7c6dce318e4e7146ee *mingwrt.src.tar.xz>> sha256sums | ||
|
||
set MINGW_BASEURL=https://sourceforge.net/projects/mingw/files/MinGW/Base/ | ||
set W32API_URL=%MINGW_BASEURL%/w32api/w32api-%MINGW_VER%/w32api-%MINGW_VER%-mingw32-src.tar.xz | ||
set MINGWRT_URL=%MINGW_BASEURL%/mingwrt/mingwrt-%MINGW_VER%/mingwrt-%MINGW_VER%-mingw32-src.tar.xz | ||
|
||
appveyor DownloadFile %W32API_URL% -FileName w32api.src.tar.xz || exit /B 1 | ||
appveyor DownloadFile %MINGWRT_URL% -FileName mingwrt.src.tar.xz || exit /B 1 | ||
|
||
:: e.g. from git installation | ||
sha256sum -c sha256sums || exit /B 1 | ||
|
||
7z x w32api.src.tar.xz || exit /B 1 | ||
7z x w32api.src.tar || exit /B 1 | ||
|
||
7z x mingwrt.src.tar.xz || exit /B 1 | ||
7z x mingwrt.src.tar || exit /B 1 | ||
|
||
move w32api-%MINGW_VER% w32api | ||
move mingwrt-%MINGW_VER% mingwrt | ||
|
||
cd windows\mingw | ||
set w32api_lib=../../w32api/lib | ||
set msvcrt_def_in=../../mingwrt/msvcrt-xref/msvcrt.def.in | ||
|
||
call "c:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat" | ||
rem CWD might be changed by vcvars64.bat | ||
cd %ROOT%\windows\mingw | ||
dmd -run buildsdk.d x64 %w32api_lib% dmd2\windows\lib64 %msvcrt_def_in% || exit /B 1 | ||
|
||
call "c:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars32.bat" | ||
cd %ROOT%\windows\mingw | ||
dmd -run buildsdk.d x86 %w32api_lib% dmd2\windows\lib32mscoff %msvcrt_def_in% || exit /B 1 | ||
|
||
7z a %ROOT%\mingw-libs-%MINGW_VER%.zip dmd2\windows |
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,192 @@ | ||
// | ||
// Convert MingGW definition files to COFF import librries | ||
// | ||
// Distributed under the Boost Software License, Version 1.0. | ||
// (See accompanying file LICENSE_1_0.txt or copy at | ||
// http://www.boost.org/LICENSE_1_0.txt) | ||
// | ||
// usage: buildsdk [x86|x64] [def-folder] [output-folder] [msvcrt.def.in] | ||
// | ||
// Source files extracted from the MinGW reositories | ||
// | ||
// def-folder: https://sourceforge.net/p/mingw/mingw-org-wsl/ci/5.0-active/tree/w32api/lib/ | ||
// msvcrt.def.in: https://sourceforge.net/p/mingw/mingw-org-wsl/ci/5.0-active/tree/mingwrt/msvcrt-xref/msvcrt.def.in | ||
// | ||
// assumes VC tools cl,link,lib and ml installed and found through path | ||
// and configured to the appropriate architecture | ||
// | ||
|
||
import std.file; | ||
import std.regex; | ||
import std.string; | ||
import std.stdio; | ||
import std.path; | ||
import std.process; | ||
import std.algorithm; | ||
|
||
version = verbose; | ||
|
||
void runShell(string cmd) | ||
{ | ||
version(verbose) | ||
writeln(cmd); | ||
auto rc = executeShell(cmd); | ||
if (rc.status) | ||
{ | ||
writeln("'", cmd, "' failed with status ", rc.status); | ||
writeln(rc.output); | ||
throw new Exception("'" ~ cmd ~ "' failed"); | ||
} | ||
} | ||
|
||
// x86: the exported symbols have stdcall mangling (including trailing @n) | ||
// but the internal names of the platform DLLs have names with @n stripped off | ||
// lib /DEF doesn't support renaming symbols so we have to go through compiling | ||
// a C file with the symbols and building a DLL with renamed exports to get | ||
// the appropriate import library | ||
// | ||
// x64: strip any @ from the symbol names | ||
bool def2implib(bool x64, string f, string dir, string linkopt = null) | ||
{ | ||
static auto re = regex(r"@?([a-zA-Z0-9_]+)(@[0-9]*)"); | ||
char[] content = cast(char[])std.file.read(f); | ||
auto pos = content.indexOf("EXPORTS"); | ||
if (pos < 0) | ||
return false; | ||
|
||
char[] def = content[0..pos]; | ||
char[] csrc; | ||
bool[string] written; | ||
auto lines = content[pos..$].splitLines; | ||
foreach(line; lines) | ||
{ | ||
line = line.strip; | ||
if (line.length == 0 || line[0] == ';') | ||
continue; | ||
const(char)[] sym; | ||
char[] cline; | ||
auto m = matchFirst(line, re); | ||
if (m) | ||
{ | ||
if (x64) | ||
def ~= m[1] ~ "\n"; | ||
else | ||
def ~= m[0] ~ "=" ~ m[1] ~ "\n"; | ||
sym = m[1]; | ||
cline = "void " ~ m[1] ~ "() {}\n"; | ||
} | ||
else | ||
{ | ||
def ~= line ~ "\n"; | ||
if (line.endsWith(" DATA")) | ||
{ | ||
sym = strip(line[0..$-5]); | ||
cline = "int " ~ sym ~ ";\n"; | ||
} | ||
else | ||
{ | ||
auto idx = line.indexOf('='); | ||
if (idx > 0) | ||
sym = line[idx+1 .. $].strip; | ||
else | ||
sym = line; | ||
cline = "void " ~ sym ~ "() {}\n"; | ||
} | ||
} | ||
if(sym.length && sym !in written) | ||
{ | ||
csrc ~= cline; | ||
written[sym.idup] = true; | ||
} | ||
} | ||
string base = stripExtension(baseName(f)); | ||
string dirbase = dir ~ base; | ||
std.file.write(dirbase ~ ".def", def); | ||
std.file.write(dirbase ~ ".c", csrc); | ||
|
||
runShell("cl /c /Fo" ~ dirbase ~ ".obj " ~ dirbase ~ ".c"); | ||
runShell("link /NOD /NOENTRY /DLL " ~ dirbase ~ ".obj /out:" ~ dirbase ~ ".dll /def:" ~ dirbase ~ ".def" ~ linkopt); | ||
|
||
// cleanup | ||
std.file.remove(dirbase ~ ".def"); | ||
std.file.remove(dirbase ~ ".c"); | ||
std.file.remove(dirbase ~ ".obj"); | ||
std.file.remove(dirbase ~ ".dll"); | ||
std.file.remove(dirbase ~ ".exp"); | ||
return true; | ||
} | ||
|
||
void buildLibs(bool x64, string defdir, string dir) | ||
{ | ||
mkdirRecurse(dir); | ||
|
||
//goto LnoDef; | ||
foreach(f; std.file.dirEntries(defdir, SpanMode.shallow)) | ||
if (extension(f).toLower == ".def") | ||
def2implib(x64, f, dir); | ||
foreach(f; std.file.dirEntries(defdir ~ "/directx", SpanMode.shallow)) | ||
if (extension(f).toLower == ".def") | ||
def2implib(x64, f, dir); | ||
|
||
version(DDK) // disable for now | ||
{ | ||
mkdirRecurse(dir ~ ddk); | ||
foreach(f; std.file.dirEntries(defdir ~ "/ddk", SpanMode.shallow)) | ||
if (extension(f).toLower == ".def") | ||
def2implib(x64, f, dir ~ "ddk/"); | ||
} | ||
} | ||
|
||
void buildMsvcrt(bool x64, string dir, string msvcdef) | ||
{ | ||
string arch = x64 ? "x64" : "x86"; | ||
string lib = "lib /MACHINE:" ~ arch ~ " "; | ||
string msvcrtlib = "msvcrt100.lib"; | ||
|
||
// build msvcrt.lib for VS2010 | ||
runShell("cl /EP -D__MSVCRT_VERSION__=0x10000000UL -D__DLLNAME__=msvcr100 " ~ msvcdef ~ " >" ~ dir ~ "msvcrt.def"); | ||
runShell(lib ~ "/OUT:" ~ dir ~ msvcrtlib ~ " /DEF:" ~ dir ~ "msvcrt.def"); // no translation necessary | ||
runShell("cl /c /Zl /Fo" ~ dir ~ "msvcrt_stub0.obj /D_APPTYPE=0 msvcrt_stub.c"); | ||
runShell("cl /c /Zl /Fo" ~ dir ~ "msvcrt_stub1.obj /D_APPTYPE=1 msvcrt_stub.c"); | ||
runShell("cl /c /Zl /Fo" ~ dir ~ "msvcrt_stub2.obj /D_APPTYPE=2 msvcrt_stub.c"); | ||
runShell("cl /c /Zl /Fo" ~ dir ~ "msvcrt_data.obj msvcrt_data.c"); | ||
runShell("cl /c /Zl /Fo" ~ dir ~ "msvcrt_atexit.obj msvcrt_atexit.c"); | ||
auto files = ["msvcrt_stub0.obj", "msvcrt_stub1.obj", "msvcrt_stub2.obj", "msvcrt_data.obj", "msvcrt_atexit.obj" ]; | ||
if (!x64) | ||
{ | ||
runShell("ml /c /Fo" ~ dir ~ "msvcrt_abs.obj msvcrt_abs.asm"); | ||
files ~= "msvcrt_abs.obj"; | ||
} | ||
auto objs = files.map!(a => dir ~ a).join(" "); | ||
runShell(lib ~ dir ~ msvcrtlib ~ " " ~ objs); | ||
|
||
// create oldnames.lib (expected by dmd) | ||
runShell("cl /c /Zl /Fo" ~ dir ~ "oldnames.obj oldnames.c"); | ||
runShell(lib ~ "/OUT:" ~ dir ~ "oldnames.lib " ~ dir ~ "oldnames.obj"); | ||
|
||
// create empty uuid.lib (expected by dmd, but UUIDs already in druntime) | ||
std.file.write(dir ~ "empty.c", ""); | ||
runShell("cl /c /Zl /Fo" ~ dir ~ "uuid.obj " ~ dir ~ "empty.c"); | ||
runShell(lib ~ "/OUT:" ~ dir ~ "uuid.lib " ~ dir ~ "uuid.obj"); | ||
|
||
foreach(f; files) | ||
std.file.remove(dir ~ f); | ||
std.file.remove(dir ~ stripExtension(msvcrtlib) ~ ".exp"); | ||
std.file.remove(dir ~ "msvcrt.def"); | ||
std.file.remove(dir ~ "oldnames.obj"); | ||
std.file.remove(dir ~ "uuid.obj"); | ||
std.file.remove(dir ~ "empty.c"); | ||
} | ||
|
||
void main(string[] args) | ||
{ | ||
bool x64 = (args.length > 1 && args[1] == "x64"); | ||
string defdir = (args.length > 2 ? args[2] : "def"); | ||
string outdir = x64 ? "lib64/" : "lib32mscoff/"; | ||
if (args.length > 3) | ||
outdir = args[3] ~ "/"; | ||
string msvcdef = (args.length > 4 ? args[4] : "msvcrt.def.in"); | ||
|
||
buildLibs(x64, defdir, outdir); | ||
buildMsvcrt(x64, outdir, msvcdef); | ||
} |
Oops, something went wrong.