Skip to content

Commit

Permalink
PonyC can now be built with VS2017 as well as use the VS2017 linker. (p…
Browse files Browse the repository at this point in the history
  • Loading branch information
chalcolith authored and sylvanc committed Mar 29, 2017
1 parent c701436 commit 44b2d56
Show file tree
Hide file tree
Showing 6 changed files with 154 additions and 73 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ waf-*
waf3-*
.lock-waf*
tmp.eof
src/.vs
tmp.longline
.vs/
CppProperties.json
build/
work/
Expand Down
3 changes: 3 additions & 0 deletions src/common/pony/detail/atomics.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ namespace ponyint_atomics

#ifdef PONY_WANT_ATOMIC_DEFS
# ifdef _MSC_VER
# pragma warning(disable:4164)
# pragma intrinsic(_InterlockedCompareExchange128)

namespace ponyint_atomics
Expand Down Expand Up @@ -143,6 +144,8 @@ namespace ponyint_atomics
# define bigatomic_compare_exchange_weak_explicit(PTR, EXP, DES, SUCC, FAIL) \
_InterlockedCompareExchange128((LONGLONG*)PTR, (LONGLONG)((DES).counter), \
(LONGLONG)((DES).object), (LONGLONG*)EXP)

# pragma warning(default:4164)
# else
# define bigatomic_load_explicit(PTR, MO) \
(__typeof__(*(PTR)))__atomic_load_n(&(PTR)->raw, MO)
Expand Down
2 changes: 1 addition & 1 deletion src/libponyc/codegen/genexe.c
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ static bool link_exe(compile_t* c, ast_t* program,

while (true)
{
int num_written = snprintf(ld_cmd, ld_len,
size_t num_written = snprintf(ld_cmd, ld_len,
"cmd /C \"\"%s\" /DEBUG /NOLOGO /MACHINE:X64 "
"/OUT:%s "
"%s %s "
Expand Down
178 changes: 128 additions & 50 deletions src/libponyc/platform/vcvars.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#define REG_SDK_INSTALL_PATH \
TEXT("SOFTWARE\\WOW6432Node\\Microsoft\\Microsoft SDKs\\Windows\\")
#define REG_VS_INSTALL_PATH \
TEXT("SOFTWARE\\WOW6432Node\\Microsoft\\VisualStudio\\")
TEXT("SOFTWARE\\WOW6432Node\\Microsoft\\VisualStudio\\SxS\\VS7")

#define MAX_VER_LEN 20

Expand Down Expand Up @@ -97,12 +97,58 @@ static bool find_registry_key(char* path, query_callback_fn query,
return success;
}

static void pick_vc_tools(HKEY key, char* name, search_t* p)
static bool find_registry_value(char *path, char *name, search_t* p)
{
DWORD size = MAX_PATH;
bool success = false;
HKEY key;

// Try global installations then user-only.
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, 0,
(KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE), &key) == ERROR_SUCCESS ||
RegOpenKeyEx(HKEY_CURRENT_USER, path, 0,
(KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE), &key) == ERROR_SUCCESS)
{
DWORD size = MAX_PATH;
success = RegGetValue(key, NULL, name, RRF_RT_REG_SZ,
NULL, p->path, &size) == ERROR_SUCCESS;
}

RegGetValue(key, NULL, "ProductDir", RRF_RT_REG_SZ,
NULL, p->path, &size);
RegCloseKey(key);
return success;
}

static uint64_t get_version(const char* str)
{
char tokens[MAX_VER_LEN + 1];
strncpy(tokens, str, MAX_VER_LEN);
uint64_t version = 0;
char *token = tokens;

while (*token != NULL && !isdigit(*token))
token++;

if (*token != NULL)
{
char *dot;
int place = 3;
while (place >= 0)
{
if ((dot = strchr(token, '.')) != NULL)
*dot = '\0';
uint64_t num = atol(token);
if (num > 0xffff) num = 0xffff;
version += (num << (place * 16));

place--;

if (dot != NULL)
token = dot + 1;
else
break;
}
}

return version;
}

static void pick_newest_sdk(HKEY key, char* name, search_t* p)
Expand All @@ -115,39 +161,13 @@ static void pick_newest_sdk(HKEY key, char* name, search_t* p)
DWORD version_len = MAX_VER_LEN;
char new_path[MAX_PATH];
char new_version[MAX_VER_LEN];
char version_tokens[MAX_VER_LEN];

if(RegGetValue(key, NULL, "InstallationFolder", RRF_RT_REG_SZ, NULL,
new_path, &path_len) == ERROR_SUCCESS &&
RegGetValue(key, NULL, "ProductVersion", RRF_RT_REG_SZ, NULL, new_version,
&version_len) == ERROR_SUCCESS)
{
strcpy(version_tokens, new_version);
uint64_t new_ver = 0;

char *token = version_tokens;
while (*token != NULL && !isdigit(*token))
token++;
if (*token != NULL)
{
char *dot;
int place = 3;
while (place >= 0)
{
if ((dot = strchr(token, '.')) != NULL)
*dot = '\0';
uint64_t num = atol(token);
if (num > 0xffff) num = 0xffff;
new_ver += (num << (place * 16));

place--;

if (dot != NULL)
token = dot + 1;
else
break;
}
}
uint64_t new_ver = get_version(new_version);

if((strlen(p->version) == 0) || (new_ver > p->latest_ver))
{
Expand Down Expand Up @@ -217,21 +237,61 @@ static bool find_kernel32(vcvars_t* vcvars, errors_t* errors)
return true;
}

static bool find_executable(const char* path, const char* name, char* dest,
errors_t* errors)
static bool find_executable(const char* path, const char* name,
char* dest, bool recurse, errors_t* errors)
{
TCHAR exe[MAX_PATH + 1];
strcpy(exe, path);
strcat(exe, name);
TCHAR full_path[MAX_PATH + 1];
TCHAR best_path[MAX_PATH + 1];
strcpy(full_path, path);
strcat(full_path, name);

if((GetFileAttributes(exe) == INVALID_FILE_ATTRIBUTES))
if((GetFileAttributes(full_path) != INVALID_FILE_ATTRIBUTES))
{
errorf(errors, NULL, "unable to locate %s", name);
return false;
strcpy(dest, full_path);
return true;
}

strcpy(dest, exe);
return true;
if (recurse)
{
PONY_ERRNO err;
PONY_DIR* dir = pony_opendir(path, &err);
if (dir != NULL)
{
uint64_t best_version = 0;

// look for directories with versions
PONY_DIRINFO* result;
while ((result = pony_dir_entry_next(dir)) != NULL)
{
char *entry = pony_dir_info_name(result);
if (entry == NULL || entry[0] == NULL || entry[0] == '.')
continue;

strcpy(full_path, path);
strcat(full_path, entry);
if ((GetFileAttributes(full_path) != FILE_ATTRIBUTE_DIRECTORY))
continue;

uint64_t ver = get_version(entry);
if (ver == 0)
continue;

if (ver > best_version)
{
best_version = ver;
strcpy(best_path, full_path);
strcat(best_path, "\\");
}
}

pony_closedir(dir);

if (best_version > 0)
return find_executable(best_path, name, dest, true, errors);
}
}

return false;
}

static bool find_msvcrt_and_linker(vcvars_t* vcvars, errors_t* errors)
Expand All @@ -243,21 +303,39 @@ static bool find_msvcrt_and_linker(vcvars_t* vcvars, errors_t* errors)
PLATFORM_TOOLS_VERSION % 10);

TCHAR reg_vs_install_path[MAX_PATH+1];
snprintf(reg_vs_install_path, MAX_PATH, "%s%s\\Setup\\VC", REG_VS_INSTALL_PATH, vs.version);
snprintf(reg_vs_install_path, MAX_PATH, "%s", REG_VS_INSTALL_PATH);

if(!find_registry_key(reg_vs_install_path, pick_vc_tools, false, &vs))
if(!find_registry_value(reg_vs_install_path, vs.version, &vs))
{
errorf(errors, NULL, "unable to locate Visual Studio %s", vs.version);
return false;
}

strcpy(vcvars->msvcrt, vs.path);
strcat(vcvars->msvcrt, "lib\\amd64");
// Find the linker and lib archiver relative to vs.path (for VS2015 and earlier)
if (find_executable(vs.path, "VC\\bin\\amd64\\link.exe", vcvars->link, false, errors) &&
find_executable(vs.path, "VC\\bin\\amd64\\lib.exe", vcvars->ar, false, errors))
{
strcpy(vcvars->msvcrt, vs.path);
strcat(vcvars->msvcrt, "VC\\lib\\amd64");
return true;
}

// Find the linker and lib archiver for VS2017
strcat(vs.path, "VC\\Tools\\MSVC\\");
if (find_executable(vs.path, "bin\\HostX64\\x64\\link.exe", vcvars->link, true, errors))
{
strcpy(vs.path, vcvars->link);
vs.path[strlen(vcvars->link)-24] = 0;
if (find_executable(vs.path, "bin\\HostX64\\x64\\lib.exe", vcvars->ar, false, errors))
{
strcpy(vcvars->msvcrt, vs.path);
strcat(vcvars->msvcrt, "lib\\x64");
return true;
}
}

// Find the linker and lib archiver relative to vs.path.
return
find_executable(vs.path, "bin\\link.exe", vcvars->link, errors) &&
find_executable(vs.path, "bin\\lib.exe", vcvars->ar, errors);
errorf(errors, NULL, "unable to locate Visual Studio %s link.exe", vs.version);
return false;
}

bool vcvars_get(vcvars_t* vcvars, errors_t* errors)
Expand Down
19 changes: 9 additions & 10 deletions waf

Large diffs are not rendered by default.

22 changes: 11 additions & 11 deletions wscript
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ CONFIGS = [
'release'
]

MSVC_VERSION = '14'
MSVC_VERSIONS = [ '15', '14' ]

# keep these in sync with the list in .appveyor.yml
LLVM_VERSIONS = [
Expand Down Expand Up @@ -78,19 +78,19 @@ def configure(ctx):
'dbghelp'
]

ctx.env.MSVC_VERSIONS = ['msvc ' + MSVC_VERSION + '.0']
ctx.env.MSVC_TARGETS = ['x64']
base_env = ctx.env
base_env.MSVC_VERSIONS = [ 'msvc ' + v + '.0' for v in MSVC_VERSIONS ]
base_env.MSVC_TARGETS = [ 'x64' ]
ctx.load('msvc')
ctx.env.CC_SRC_F = '/Tp' # force C++ for all files
ctx.env.CXX_SRC_F = '/Tp'
ctx.env.append_value('DEFINES', [

base_env.CC_SRC_F = '/Tp' # force C++ for all files
base_env.CXX_SRC_F = '/Tp'
base_env.append_value('DEFINES', [
'_CRT_SECURE_NO_WARNINGS', '_MBCS',
'PLATFORM_TOOLS_VERSION=' + MSVC_VERSION + '0',
'BUILD_COMPILER="msvc-' + MSVC_VERSION + '-x64"'
'PLATFORM_TOOLS_VERSION=%d0' % base_env.MSVC_VERSION,
'BUILD_COMPILER="msvc-%d-x64"' % base_env.MSVC_VERSION
])
ctx.env.append_value('LIBPATH', [ ctx.env.LLVM_DIR ])

base_env = ctx.env.derive()
base_env.append_value('LIBPATH', [ base_env.LLVM_DIR ])

for llvm_version in LLVM_VERSIONS:
bld_env = base_env.derive()
Expand Down

0 comments on commit 44b2d56

Please sign in to comment.