Skip to content

Commit

Permalink
Admit defeat, pursue wrapper .exe generation tack
Browse files Browse the repository at this point in the history
  • Loading branch information
staticfloat committed Apr 10, 2020
1 parent 2250b86 commit 02b36be
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 108 deletions.
2 changes: 1 addition & 1 deletion Make.inc
Original file line number Diff line number Diff line change
Expand Up @@ -1210,7 +1210,7 @@ ifeq ($(USE_BINARYBUILDER_LLVM),1)
CLANG_INCDIR = $(Clang_jll_DIR)/include
else
LLVM_CONFIG = $(build_depsbindir)/llvm-config$(EXE)
LLVM_SHLIBDIR = $(build_shlibdir)
LIBLLVM_SHLIBDIR = $(build_shlibdir)
CLANG_EXE = $(build_depsbindir)/clang$(EXE)
CLANG_INCDIR = $(build_includedir)
endif # USE_BINARYBUILDER_LLVM
Expand Down
46 changes: 46 additions & 0 deletions contrib/windows/exe_path_wrapper.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include <windows.h>
#include <tchar.h>
#define ENVVAR_MAXLEN 32760

/* PATH_ENTRIES is our simulated RPATH, usually of the form "../path1;../path2;../path3" */
#ifndef PATH_ENTRIES
#define PATH_ENTRIES TEXT("")
#endif

/* JULIA_EXE_PATH is the relative path to julia.exe */
#ifndef JULIA_EXE_PATH
#define JULIA_EXE_PATH "../libexec/julia.exe"
#endif

int wmain(int argc, char **argv) {
// On windows, we simulate RPATH by pushing onto PATH
LPSTR pathVal = (LPSTR) malloc(ENVVAR_MAXLEN*sizeof(TCHAR));
DWORD dwRet = GetEnvironmentVariable("PATH", pathVal, ENVVAR_MAXLEN);
if (dwRet == 0) {
// If we cannot get PATH, then our job is easy!
pathVal[0] = '\0';
lstrcat(pathVal, TEXT(PATH_ENTRIES));
} else {
// Otherwise, we append, if we have enough space to:
if (ENVVAR_MAXLEN - dwRet < _tcslen(PATH_ENTRIES) ) {
printf("ERROR: Cannot append entries to PATH: not enough space in environment block. Reduce size of PATH!");
exit(1);
}
lstrcat(pathVal, TEXT(";"));
lstrcat(pathVal, TEXT(PATH_ENTRIES));
}
SetEnvironmentVariable("PATH", pathVal);
free(pathVal);

STARTUPINFO info;
PROCESS_INFORMATION processInfo;
DWORD exit_code = 1;
GetStartupInfo(&info);
if (CreateProcess(TEXT(JULIA_EXE_PATH), GetCommandLine(), NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo)) {
WaitForSingleObject(processInfo.hProcess, INFINITE);
GetExitCodeProcess(pi.hProcess, &exit_code);
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
}
return exit_code;
}
48 changes: 18 additions & 30 deletions ui/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,26 +37,11 @@ endif

# Delay-import DLL on Windows, giving us time to insert entries into PATH
ifeq ($(OS),WINNT)
$(build_libdir)/import_libraries:
mkdir -p $@

$(build_libdir)/import_libraries/libjulia.a: $(build_shlibdir)/libjulia.dll $(build_shlibdir)/libjulia.def | $(build_libdir)/import_libraries
$(DLLTOOL) -d $(build_shlibdir)/libjulia.def -D $(build_shlibdir)/libjulia.dll -y $@
$(build_libdir)/import_libraries/libjulia-debug.a: $(build_shlibdir)/libjulia-debug.dll $(build_shlibdir)/libjulia-debug.def | $(build_libdir)/import_libraries
$(DLLTOOL) -d $(build_shlibdir)/libjulia-debug.def -D $(build_shlibdir)/libjulia-debug.dll -y $@

LIBJULIA_LINK := $(build_libdir)/import_libraries/libjulia.a
LIBJULIADEBUG_LINK := $(build_libdir)/import_libraries/libjulia-debug.a
SHIPFLAGS += -DLIBJULIA_NAME="\"libjulia.dll\""
DEBUGFLAGS += -DLIBJULIA_NAME="\"libjulia-debug.dll\""

JLDFLAGS += -municode -static-libgcc
CPPFLAGS_PATH = -DPATH_ENTRIES="\"$$(echo "$(call cygpath_w,$(CSL_SHLIBDIR));$(call cygpath_w,$(LLVM_SHLIBDIR))" | sed -e 's_\\_\\\\_g')\""
JLDFLAGS += -municode

$(build_bindir)/julia$(EXE): $(LIBJULIA_LINK)
$(build_bindir)/julia-debug$(EXE): $(LIBJULIADEBUG_LINK)
else
LIBJULIA_LINK := -ljulia
els-ljulia:= -ljulia
LIBJULIADEBUG_LINK := -ljulia-debug
endif

Expand All @@ -65,9 +50,9 @@ all: release debug
release debug : % : julia-%

$(BUILDDIR)/%.o: $(SRCDIR)/%.c $(HEADERS)
@$(call PRINT_CC, $(CC) $(CPPFLAGS) $(CPPFLAGS_PATH) $(CFLAGS) $(SHIPFLAGS) -c $< -o $@)
@$(call PRINT_CC, $(CC) $(CPPFLAGS) $(CFLAGS) $(SHIPFLAGS) -c $< -o $@)
$(BUILDDIR)/%.dbg.obj: $(SRCDIR)/%.c $(HEADERS)
@$(call PRINT_CC, $(CC) $(CPPFLAGS) $(CPPFLAGS_PATH) $(CFLAGS) $(DEBUGFLAGS) -c $< -o $@)
@$(call PRINT_CC, $(CC) $(CPPFLAGS) $(CFLAGS) $(DEBUGFLAGS) -c $< -o $@)

ifeq ($(OS),WINNT)
ifneq ($(USEMSVC), 1)
Expand Down Expand Up @@ -107,24 +92,27 @@ else
CXXLD := $(LD)
endif

# Add `.cmd` wrapper generation to properly setup `PATH` on windows
# Add `.exe` wrapper generation to properly setup `PATH` on windows to simulate `RPATH`
ifeq ($(OS),WINNT)
$(build_bindir)/%.cmd:
@echo "@echo off" > $@
@echo "set PATH=%PATH%;%~dp0\\$(call binrel_path,$(CSL_SHLIBDIR));%~dp0\\$(call binrel_path,$(LLVM_SHLIBDIR))" >> $@
@echo "\"%~dp0\"\\$*.exe %*" >> $@
@chmod a+x $@

julia-release: $(build_bindir)/julia.cmd
julia-debug: $(build_bindir)/julia-debug.cmd
CPPFLAGS_PATH = -DPATH_ENTRIES="\"$$(echo "$(call cygpath_w,$(CSL_SHLIBDIR));$(call cygpath_w,$(LLVM_SHLIBDIR))" | sed -e 's_\\_\\\\_g')\""
define gen_wrapper_exe
-mv $(build_bindir)/$(1) $(build_libexecdir)/$(1)
$(call PRINT_CC, $(CXX) $(CXXFLAGS) $(SHIPFLAGS) -DJULIA_EXE_PATH=$(libexecdir_rel)/$(1) $(CPPFLAGS_PATH) $(JULIAHOME)/contrib/windows/exe_path_wrapper.c -o $(build_bindir)/$(1))
endef
endif


$(build_bindir)/julia$(EXE): $(OBJS)
@$(call PRINT_LINK, $(CXXLD) $(CXXFLAGS) $(CXXLDFLAGS) $(LINK_FLAGS) $(SHIPFLAGS) $(OBJS) -o $@ -L$(build_private_libdir) -L$(build_libdir) -L$(build_shlibdir) $(LIBJULIA_LINK) $(JLDFLAGS) $(CXXLDFLAGS))
@$(call PRINT_LINK, $(CXXLD) $(CXXFLAGS) $(CXXLDFLAGS) $(LINK_FLAGS) $(SHIPFLAGS) $(OBJS) -o $@ -L$(build_private_libdir) -L$(build_libdir) -L$(build_shlibdir) -ljulia $(JLDFLAGS) $(CXXLDFLAGS))
ifeq ($(OS),WINNT)
@$(call gen_wrapper_exe,julia$(EXE))
endif

$(build_bindir)/julia-debug$(EXE): $(DOBJS)
@$(call PRINT_LINK, $(CXXLD) $(CXXFLAGS) $(CXXLDFLAGS) $(LINK_FLAGS) $(DEBUGFLAGS) $(DOBJS) -o $@ -L$(build_private_libdir) -L$(build_libdir) -L$(build_shlibdir) $(LIBJULIADEBUG_LINK) $(JLDFLAGS) $(CXXLDFLAGS))
@$(call PRINT_LINK, $(CXXLD) $(CXXFLAGS) $(CXXLDFLAGS) $(LINK_FLAGS) $(DEBUGFLAGS) $(DOBJS) -o $@ -L$(build_private_libdir) -L$(build_libdir) -L$(build_shlibdir) -ljulia-debug $(JLDFLAGS) $(CXXLDFLAGS))
ifeq ($(OS),WINNT)
@$(call gen_wrapper_exe,julia-debug$(EXE))
endif

clean: | $(CLEAN_TARGETS)
rm -f *.o *.dbg.obj
Expand Down
96 changes: 19 additions & 77 deletions ui/repl.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,66 +29,33 @@ JULIA_DEFINE_FAST_TLS()
extern "C" {
#endif

// Because windows now uses a delay-load library for RPATH emulation, we cannot directly access
// global variables within libjulia from here, we must instead manually import them via LoadLibrary
// and GetProcAddress within `main()` below. Read more about the ramifications of delay-loading here:
// https://docs.microsoft.com/en-us/cpp/build/reference/constraints-of-delay-loading-dlls
#ifdef _OS_WINDOWS_
HMODULE hLibJulia = NULL;
jl_module_t * get_jl_main_module() {
return *((jl_module_t **)GetProcAddress(hLibJulia, "jl_main_module"));
}
jl_module_t * get_jl_base_module() {
return *((jl_module_t **)GetProcAddress(hLibJulia, "jl_base_module"));
}
JL_STREAM * get_jl_stdout() {
return *((JL_STREAM **)GetProcAddress(hLibJulia, "jl_uv_stdout"));
}
JL_STREAM * get_jl_stderr() {
return *((JL_STREAM **)GetProcAddress(hLibJulia, "jl_uv_stderr"));
}
#else
jl_module_t * get_jl_main_module() {
return jl_main_module;
}
jl_module_t * get_jl_base_module() {
return jl_base_module;
}
JL_STREAM * get_jl_stdout() {
return JL_STDOUT;
}
JL_STREAM * get_jl_stderr() {
return JL_STDERR;
}
#endif

static int exec_program(char *program)
{
JL_TRY {
jl_load(get_jl_main_module(), program);
jl_load(jl_main_module, program);
}
JL_CATCH {
jl_value_t *errs = jl_stderr_obj();
volatile int shown_err = 0;
jl_printf(get_jl_stderr(), "error during bootstrap:\n");
jl_printf(JL_STDERR, "error during bootstrap:\n");
JL_TRY {
if (errs) {
jl_value_t *showf = jl_get_function(get_jl_base_module(), "show");
jl_value_t *showf = jl_get_function(jl_base_module, "show");
if (showf != NULL) {
jl_call2(showf, errs, jl_current_exception());
jl_printf(get_jl_stderr(), "\n");
jl_printf(JL_STDERR, "\n");
shown_err = 1;
}
}
}
JL_CATCH {
}
if (!shown_err) {
jl_static_show(get_jl_stderr(), jl_current_exception());
jl_printf(get_jl_stderr(), "\n");
jl_static_show(JL_STDERR, jl_current_exception());
jl_printf(JL_STDERR, "\n");
}
jlbacktrace();
jl_printf(get_jl_stderr(), "\n");
jl_printf(JL_STDERR, "\n");
return 1;
}
return 0;
Expand All @@ -100,13 +67,13 @@ void jl_lisp_prompt();
static void print_profile(void)
{
size_t i;
void **table = get_jl_base_module()->bindings.table;
for(i=1; i < get_jl_base_module()->bindings.size; i+=2) {
void **table = jl_base_module->bindings.table;
for(i=1; i < jl_base_module->bindings.size; i+=2) {
if (table[i] != HT_NOTFOUND) {
jl_binding_t *b = (jl_binding_t*)table[i];
if (b->value != NULL && jl_is_function(b->value) &&
jl_is_gf(b->value)) {
jl_printf(get_jl_stderr(), "%d\t%s\n",
jl_printf(JL_STDERR, "%d\t%s\n",
jl_gf_mtable(b->value)->ncalls,
jl_gf_name(b->value)->name);
}
Expand All @@ -119,9 +86,8 @@ static NOINLINE int true_main(int argc, char *argv[])
{
jl_set_ARGS(argc, argv);

jl_module_t * base_module = get_jl_base_module();
jl_function_t *start_client = base_module ?
(jl_function_t*)jl_get_global(base_module, jl_symbol("_start")) : NULL;
jl_function_t *start_client = jl_base_module ?
(jl_function_t*)jl_get_global(jl_base_module, jl_symbol("_start")) : NULL;

if (start_client) {
JL_TRY {
Expand Down Expand Up @@ -155,14 +121,14 @@ static NOINLINE int true_main(int argc, char *argv[])
line = ios_readline(ios_stdin);
jl_value_t *val = (jl_value_t*)jl_eval_string(line);
if (jl_exception_occurred()) {
jl_printf(get_jl_stderr(), "error during run:\n");
jl_static_show(get_jl_stderr(), jl_exception_occurred());
jl_printf(JL_STDERR, "error during run:\n");
jl_static_show(JL_STDERR, jl_exception_occurred());
jl_exception_clear();
}
else if (val) {
jl_static_show(get_jl_stdout(), val);
jl_static_show(JL_STDOUT, val);
}
jl_printf(get_jl_stdout(), "\n");
jl_printf(JL_STDOUT, "\n");
free(line);
line = NULL;
uv_run(jl_global_event_loop(),UV_RUN_NOWAIT);
Expand All @@ -172,9 +138,9 @@ static NOINLINE int true_main(int argc, char *argv[])
free(line);
line = NULL;
}
jl_printf(get_jl_stderr(), "\nparser error:\n");
jl_static_show(get_jl_stderr(), jl_current_exception());
jl_printf(get_jl_stderr(), "\n");
jl_printf(JL_STDERR, "\nparser error:\n");
jl_static_show(JL_STDERR, jl_current_exception());
jl_printf(JL_STDERR, "\n");
jlbacktrace();
}
}
Expand All @@ -187,8 +153,6 @@ int main(int argc, char *argv[])
uv_setup_args(argc, argv); // no-op on Windows
#else

#include <tchar.h>
#define ENVVAR_MAXLEN 32760
static void lock_low32() {
#if defined(_P64) && defined(JL_DEBUG_BUILD)
// Wine currently has a that causes it to answer VirtualQuery incorrectly.
Expand Down Expand Up @@ -226,28 +190,6 @@ static void lock_low32() {
}
int wmain(int argc, wchar_t *argv[], wchar_t *envp[])
{
// On windows, we simulate RPATH by pushing onto PATH
LPSTR pathVal = (LPSTR) malloc(ENVVAR_MAXLEN*sizeof(TCHAR));
DWORD dwRet = GetEnvironmentVariable("PATH", pathVal, ENVVAR_MAXLEN);
if (dwRet == 0) {
// If we cannot get PATH, then our job is easy!
pathVal[0] = '\0';
lstrcat(pathVal, TEXT(PATH_ENTRIES));
} else {
// Otherwise, we append, if we have enough space to:
if (ENVVAR_MAXLEN - dwRet < _tcslen(PATH_ENTRIES) ) {
printf("ERROR: Cannot append entries to PATH: not enough space in environment block. Reduce size of PATH!");
exit(1);
}
lstrcat(pathVal, TEXT(";"));
lstrcat(pathVal, TEXT(PATH_ENTRIES));
}
SetEnvironmentVariable("PATH", pathVal);
free(pathVal);

// Once we've set up our PATH, explicitly load libjulia.dll for global symbol lookups later.
hLibJulia = LoadLibrary(TEXT(LIBJULIA_NAME));

int i;
lock_low32();
for (i=0; i<argc; i++) { // write the command line to UTF8
Expand Down

0 comments on commit 02b36be

Please sign in to comment.