Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adopt DMD's MSVC toolchain detection #3415

Merged
merged 6 commits into from
May 4, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -932,11 +932,6 @@ if(${BUILD_SHARED})
endif()
install(FILES ${PROJECT_BINARY_DIR}/bin/${LDC_EXE}_install.conf DESTINATION ${CONF_INST_DIR} RENAME ${LDC_EXE}.conf)

if(MSVC)
file(COPY vcbuild/ DESTINATION ${PROJECT_BINARY_DIR}/bin FILES_MATCHING PATTERN "*.bat")
install(DIRECTORY vcbuild/ DESTINATION ${CMAKE_INSTALL_PREFIX}/bin FILES_MATCHING PATTERN "*.bat")
endif()

if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
if(NOT DEFINED BASH_COMPLETION_COMPLETIONSDIR)
find_package(bash-completion QUIET)
5 changes: 2 additions & 3 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
@@ -90,12 +90,11 @@ jobs:
displayName: Generate hello.d
- script: |
echo on
%ARTIFACT_NAME%\bin\ldc2 -v -run hello.d || exit /b
%ARTIFACT_NAME%\bin\ldc2 -v -m32 -run hello.d
%ARTIFACT_NAME%\bin\ldc2 -v -mscrtlib=vcruntime140 -run hello.d || exit /b
%ARTIFACT_NAME%\bin\ldc2 -v -mscrtlib=vcruntime140 -m32 -run hello.d
displayName: Run 32/64-bit hello-world smoke test with internal toolchain
- script: |
echo on
set LDC_VSDIR_FORCE=1
%ARTIFACT_NAME%\bin\ldc2 -v -run hello.d || exit /b
%ARTIFACT_NAME%\bin\ldc2 -v -m32 -run hello.d
displayName: Run 32/64-bit hello-world smoke test with MSVC auto-detection
87 changes: 0 additions & 87 deletions dmd/env.d

This file was deleted.

195 changes: 116 additions & 79 deletions dmd/root/filename.d
Original file line number Diff line number Diff line change
@@ -41,12 +41,12 @@ version (Windows)

version (IN_LLVM)
{
private enum codepage = CP_UTF8;
private enum CodePage = CP_UTF8;
}
else
{
// assume filenames encoded in system default Windows ANSI code page
private enum codepage = CP_ACP;
private enum CodePage = CP_ACP;
}
}

@@ -376,55 +376,67 @@ nothrow:
/// Ditto
extern(D) static const(char)[] combine(const(char)[] path, const(char)[] name)
{
if (!path.length)
return name;
return !path.length ? name : buildPath(path, name);
}

char* f = cast(char*)mem.xmalloc(path.length + 1 + name.length + 1);
memcpy(f, path.ptr, path.length);
bool trailingSlash = false;
version (Posix)
unittest
{
version (Windows)
assert(combine("foo"[], "bar"[]) == "foo\\bar");
else
assert(combine("foo"[], "bar"[]) == "foo/bar");
assert(combine("foo/"[], "bar"[]) == "foo/bar");
}

static const(char)[] buildPath(const(char)[][] fragments...)
{
size_t size;
foreach (f; fragments)
size += f.length ? f.length + 1 : 0;
if (size == 0)
size = 1;

char* p = cast(char*) mem.xmalloc_noscan(size);
size_t length;
foreach (f; fragments)
{
if (path[$ - 1] != '/')
if (!f.length)
continue;

p[length .. length + f.length] = f;
length += f.length;

const last = p[length - 1];
version (Posix)
{
f[path.length] = '/';
trailingSlash = true;
if (last != '/')
p[length++] = '/';
}
}
else version (Windows)
{
if (path[$ - 1] != '\\' && path[$ - 1] != '/' && path[$ - 1] != ':')
else version (Windows)
{
f[path.length] = '\\';
trailingSlash = true;
if (last != '\\' && last != '/' && last != ':')
p[length++] = '\\';
}
else
assert(0);
}
else
{
assert(0);
}
const len = path.length + trailingSlash;
memcpy(f + len, name.ptr, name.length);
// Note: At the moment `const(char)*` are being transitioned to
// `const(char)[]`. To avoid bugs crippling in, we `\0` terminate
// slices, but don't include it in the slice so `.ptr` can be used.
f[len + name.length] = '\0';
return f[0 .. len + name.length];

// overwrite last slash with null terminator
p[length ? --length : 0] = 0;

return p[0 .. length];
}

unittest
{
assert(buildPath() == "");
assert(buildPath("foo") == "foo");
assert(buildPath("foo", null) == "foo");
assert(buildPath(null, "foo") == "foo");
version (Windows)
assert(combine("foo"[], "bar"[]) == "foo\\bar");
assert(buildPath("C:", r"a\", "bb/", "ccc", "d") == r"C:a\bb/ccc\d");
else
assert(combine("foo"[], "bar"[]) == "foo/bar");
assert(combine("foo/"[], "bar"[]) == "foo/bar");
}

static const(char)* buildPath(const(char)* path, const(char)*[] names...)
{
foreach (const(char)* name; names)
path = combine(path, name);
return path;
assert(buildPath("a/", "bb", "ccc") == "a/bb/ccc");
}

// Split a path into an Array of paths
@@ -827,7 +839,7 @@ nothrow:
}
else version (Windows)
{
return name.toCStringThen!((cstr) => cstr.toWStringzThen!((wname)
return name.toWStringzThen!((wname)
{
const dw = GetFileAttributesW(&wname[0]);
if (dw == -1)
@@ -836,7 +848,7 @@ nothrow:
return 2;
else
return 1;
}));
});
}
else
{
@@ -1009,26 +1021,15 @@ nothrow:
// First find out how long the buffer has to be.
const fullPathLength = GetFullPathNameW(&wname[0], 0, null, null);
if (!fullPathLength) return null;
auto fullPath = new wchar[fullPathLength];
auto fullPath = (cast(wchar*) mem.xmalloc_noscan((fullPathLength + 1) * wchar.sizeof))[0 .. fullPathLength + 1];
scope(exit) mem.xfree(fullPath.ptr);

// Actually get the full path name
const fullPathLengthNoTerminator = GetFullPathNameW(
&wname[0], fullPathLength, &fullPath[0], null /*filePart*/);
// Unfortunately, when the buffer is large enough the return value is the number of characters
// _not_ counting the null terminator, so fullPathLengthNoTerminator should be smaller
assert(fullPathLength > fullPathLengthNoTerminator);

// Find out size of the converted string
const retLength = WideCharToMultiByte(
codepage, 0 /*flags*/, &fullPath[0], fullPathLength, null, 0, null, null);
auto ret = new char[retLength];

// Actually convert to char
const retLength2 = WideCharToMultiByte(
codepage, 0 /*flags*/, &fullPath[0], fullPathLength, &ret[0], retLength, null, null);
assert(retLength == retLength2);

return ret;
const length = GetFullPathNameW(
&wname[0], cast(DWORD) fullPath.length, &fullPath[0], null /*filePart*/);
assert(length == fullPathLength);

return toNarrowStringz(fullPath[0 .. length]);
});
}
else
@@ -1176,6 +1177,60 @@ version(Windows)
});
}

/**********************************
* Converts a UTF-16 string to a (null-terminated) narrow string.
* Returns:
* If `buffer` is specified and the result fits, a slice of that buffer,
* otherwise a new buffer which can be released via `mem.xfree()`.
* Nulls are propagated, i.e., if `wide` is null, the returned slice is
* null too.
*/
char[] toNarrowStringz(const(wchar)[] wide, char[] buffer = null) nothrow
{
if (wide is null)
return null;

const requiredLength = WideCharToMultiByte(CodePage, 0, wide.ptr, cast(int) wide.length, buffer.ptr, cast(int) buffer.length, null, null);
if (requiredLength < buffer.length)
{
buffer[requiredLength] = 0;
return buffer[0 .. requiredLength];
}

char* newBuffer = cast(char*) mem.xmalloc_noscan(requiredLength + 1);
const length = WideCharToMultiByte(CodePage, 0, wide.ptr, cast(int) wide.length, newBuffer, requiredLength, null, null);
assert(length == requiredLength);
newBuffer[length] = 0;
return newBuffer[0 .. length];
}

/**********************************
* Converts a narrow string to a (null-terminated) UTF-16 string.
* Returns:
* If `buffer` is specified and the result fits, a slice of that buffer,
* otherwise a new buffer which can be released via `mem.xfree()`.
* Nulls are propagated, i.e., if `narrow` is null, the returned slice is
* null too.
*/
wchar[] toWStringz(const(char)[] narrow, wchar[] buffer = null) nothrow
{
if (narrow is null)
return null;

const requiredLength = MultiByteToWideChar(CodePage, 0, narrow.ptr, cast(int) narrow.length, buffer.ptr, cast(int) buffer.length);
if (requiredLength < buffer.length)
{
buffer[requiredLength] = 0;
return buffer[0 .. requiredLength];
}

wchar* newBuffer = cast(wchar*) mem.xmalloc_noscan((requiredLength + 1) * wchar.sizeof);
const length = MultiByteToWideChar(CodePage, 0, narrow.ptr, cast(int) narrow.length, newBuffer, requiredLength);
assert(length == requiredLength);
newBuffer[length] = 0;
return newBuffer[0 .. length];
}

/**********************************
* Converts a slice of UTF-8 characters to an array of wchar that's null
* terminated so it can be passed to Win32 APIs then calls the supplied
@@ -1191,28 +1246,10 @@ version(Windows)
{
if (!str.length) return F(""w.ptr);

import core.stdc.stdlib: malloc, free;
wchar[1024] buf = void;
wchar[] wide = toWStringz(str, buf);
scope(exit) wide.ptr != buf.ptr && mem.xfree(wide.ptr);

// first find out how long the buffer must be to store the result
const length = MultiByteToWideChar(codepage, 0 /*flags*/, &str[0], cast(int)str.length, null, 0);
if (!length) return F(""w);

wchar[] ret = length >= buf.length
? (cast(wchar*)malloc((length + 1) * wchar.sizeof))[0 .. length + 1]
: buf[0 .. length + 1];
scope (exit)
{
if (&ret[0] != &buf[0])
free(&ret[0]);
}
// actually do the conversion
const length2 = MultiByteToWideChar(
codepage, 0 /*flags*/, &str[0], cast(int)str.length, &ret[0], length);
assert(length == length2); // should always be true according to the API
// Add terminating `\0`
ret[$ - 1] = '\0';

return F(ret[0 .. $ - 1]);
return F(wide);
}
}
Loading