-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Windows: add wrapper .exe
to work around lack of RPATH
#35629
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
#include <windows.h> | ||
#include <tchar.h> | ||
#include <stdio.h> | ||
#include <shlwapi.h> | ||
|
||
/* The maximum path length we allow the environment to impose upon us */ | ||
#define MAX_PATH_LEN 1920 | ||
|
||
/* PATH_ENTRIES is our simulated RPATH, usually of the form 'TEXT("../path1"), TEXT("../path2"), ...' */ | ||
#ifndef PATH_ENTRIES | ||
#define PATH_ENTRIES TEXT("") | ||
#endif | ||
|
||
LPWSTR pathEntries[] = { | ||
PATH_ENTRIES | ||
}; | ||
|
||
/* JULIA_EXE_PATH is the relative path to julia.exe, usually of the form "../path/to/julia.exe" */ | ||
#ifndef JULIA_EXE_PATH | ||
#define JULIA_EXE_PATH "../libexec/julia.exe" | ||
#endif | ||
|
||
int wmain(int argc, wchar_t *argv[], wchar_t *envp[]) { | ||
// Determine absolute path to true julia.exe sitting in `libexec/` | ||
WCHAR currFileDir[MAX_PATH_LEN]; | ||
WCHAR juliaPath[MAX_PATH_LEN]; | ||
if (!GetModuleFileName(NULL, currFileDir, MAX_PATH_LEN)) { | ||
fprintf(stderr, "ERROR: GetModuleFileName() failed with code %lu\n", GetLastError()); | ||
exit(1); | ||
} | ||
PathRemoveFileSpec(currFileDir); | ||
PathCombine(juliaPath, currFileDir, TEXT(JULIA_EXE_PATH)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. PathCombine is not recommended from Microsoft:
https://docs.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-pathcombinew |
||
|
||
// On windows, we simulate RPATH by generating a new PATH, and hiding the original | ||
// PATH into a sidechannel variable, JULIA_ORIGINAL_PATH, which will be restored | ||
// within the callee. | ||
LPWSTR pathVal = (LPWSTR) malloc(MAX_PATH_LEN*sizeof(WCHAR)); | ||
DWORD dwRet = GetEnvironmentVariable(TEXT("PATH"), pathVal, MAX_PATH_LEN); | ||
if (dwRet > 0 && dwRet < MAX_PATH_LEN) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this should be However looking at the documentation for |
||
SetEnvironmentVariable(TEXT("JULIA_ORIGINAL_PATH"), pathVal); | ||
} else { | ||
staticfloat marked this conversation as resolved.
Show resolved
Hide resolved
|
||
SetEnvironmentVariable(TEXT("JULIA_ORIGINAL_PATH"), TEXT("")); | ||
} | ||
|
||
// We also set JULIA_BINDIR to the directory holding this file, as otherwise it | ||
// auto picks up `libexec` instead of `bin`, but only if it is not already set. | ||
if (GetEnvironmentVariable(TEXT("JULIA_BINDIR"), pathVal, MAX_PATH_LEN) == 0) | ||
SetEnvironmentVariable(TEXT("JULIA_BINDIR"), currFileDir); | ||
|
||
// Next, we construct a new PATH variable specifically for launching the inner `julia.exe` | ||
DWORD numPathEntries = sizeof(pathEntries)/sizeof(pathEntries[0]); | ||
pathVal[0] = '\0'; | ||
// We always add the current directory (e.g. `bin/`) to PATH so that we can find e.g. libjulia.dll | ||
staticfloat marked this conversation as resolved.
Show resolved
Hide resolved
|
||
lstrcat(pathVal, currFileDir); | ||
|
||
// For each entry in PATH_ENTRIES, tack it on to the end, relative to the current directory: | ||
int env_idx; | ||
for (env_idx = 0; env_idx < numPathEntries; ++env_idx) { | ||
lstrcat(pathVal, TEXT(";")); | ||
lstrcat(pathVal, currFileDir); | ||
lstrcat(pathVal, TEXT("\\")); | ||
lstrcat(pathVal, pathEntries[env_idx]); | ||
} | ||
SetEnvironmentVariable(TEXT("PATH"), pathVal); | ||
free(pathVal); | ||
|
||
STARTUPINFO info; | ||
PROCESS_INFORMATION processInfo; | ||
DWORD exit_code = 1; | ||
GetStartupInfo(&info); | ||
if (CreateProcess(juliaPath, GetCommandLine(), NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo)) { | ||
WaitForSingleObject(processInfo.hProcess, INFINITE); | ||
GetExitCodeProcess(processInfo.hProcess, &exit_code); | ||
CloseHandle(processInfo.hProcess); | ||
CloseHandle(processInfo.hThread); | ||
} | ||
return exit_code; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be
MAX_PATH
and same for the variable below if usingPathCombine
https://docs.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-pathcombinew