From 7ef6e7695d2b4b9de479a4683280b1fdf88ecaa8 Mon Sep 17 00:00:00 2001 From: Lars Kanis Date: Sun, 4 Feb 2018 23:07:14 +0100 Subject: [PATCH] MJIT: Determine path of mjit header and libruby at runtime The current MJIT implementation uses the install prefix at build time as part of the include and library paths for gcc/clang at runtime. If ruby is distributed as pre-compiled binary, these paths usually differ between build and runtime. This patch determines the paths based on the ruby top directory and compiles only relative paths into the binary. Makefile.in: Use relative paths for MJIT and remove now unused. win32/Makefile.sub: ditto. ruby.c: Move mjit_init() after retrival of runtime loadpaths. mjit.c: Replace constant header and library paths by variable paths determined at runtime. --- Makefile.in | 2 +- mjit.c | 32 ++++++++++++++++++++++++++++---- ruby.c | 7 ++++--- win32/Makefile.sub | 2 +- 4 files changed, 34 insertions(+), 9 deletions(-) diff --git a/Makefile.in b/Makefile.in index 840e804310..49b0eaef21 100644 --- a/Makefile.in +++ b/Makefile.in @@ -69,7 +69,7 @@ debugflags = @debugflags@ warnflags = @warnflags@ @strict_warnflags@ cppflags = @cppflags@ XCFLAGS = @XCFLAGS@ -CPPFLAGS = @CPPFLAGS@ $(INCFLAGS) -DMJIT_HEADER_BUILD_DIR=\""$(EXTOUT)/include/$(arch)"\" -DLIBRUBYARG_SHARED=\""$(LIBRUBYARG_SHARED)"\" -DLIBRUBY_LIBDIR=\""$(prefix)/lib"\" -DMJIT_HEADER_INSTALL_DIR=\""$(prefix)/include/$(RUBY_BASE_NAME)-$(ruby_version)/$(arch)"\" +CPPFLAGS = @CPPFLAGS@ $(INCFLAGS) -DMJIT_HEADER_BUILD_DIR=\""$(EXTOUT)/include/$(arch)"\" -DLIBRUBYARG_SHARED=\""$(LIBRUBYARG_SHARED)"\" -DMJIT_HEADER_INSTALL_DIR=\""include/$(RUBY_BASE_NAME)-$(ruby_version)/$(arch)"\" MJIT_HEADER_FLAGS = @MJIT_HEADER_FLAGS@ LDFLAGS = @STATIC@ $(CFLAGS) @LDFLAGS@ EXTLDFLAGS = @EXTLDFLAGS@ diff --git a/mjit.c b/mjit.c index 28ad5ca917..dc8c527b9d 100644 --- a/mjit.c +++ b/mjit.c @@ -193,6 +193,10 @@ static int in_jit; /* Defined in the client thread before starting MJIT threads: */ /* Used C compiler path. */ static const char *cc_path; +/* Linker option to enable libruby in the build directory. */ +static char *libruby_build; +/* Linker option to enable libruby in the directory after install. */ +static char *libruby_installed; /* Name of the header file. */ static char *header_file; /* Name of the precompiled header file. */ @@ -632,10 +636,12 @@ compile_c_to_so(const char *c_file, const char *so_file) int exit_code; static const char *input[] = {NULL, NULL}; static const char *output[] = {"-o", NULL, NULL}; - static const char *libs[] = { + const char *libs[] = { #ifdef _WIN32 + /* Look for ruby.dll.a in build and install directories. */ + libruby_installed, + libruby_build, /* Link to ruby.dll.a, because Windows DLLs don't allow unresolved symbols. */ - "-L" LIBRUBY_LIBDIR, LIBRUBYARG_SHARED, "-lmsvcrt", # ifdef __GNUC__ @@ -1054,6 +1060,12 @@ static void init_header_filename(void) { FILE *f; + /* Root path of the running ruby process. Equal to RbConfig::TOPDIR. */ + VALUE basedir_val; + char *basedir; + + basedir_val = rb_const_get(rb_cObject, rb_intern_const("TMP_RUBY_PREFIX")); + basedir = StringValueCStr(basedir_val); header_file = xmalloc(strlen(MJIT_HEADER_BUILD_DIR) + 2 + strlen(RUBY_MJIT_HEADER_FILE)); if (header_file == NULL) @@ -1064,10 +1076,12 @@ init_header_filename(void) if ((f = fopen(header_file, "r")) == NULL) { xfree(header_file); - header_file = xmalloc(strlen(MJIT_HEADER_INSTALL_DIR) + 2 + strlen(RUBY_MJIT_HEADER_FILE)); + header_file = xmalloc(strlen(basedir) + 1 + strlen(MJIT_HEADER_INSTALL_DIR) + 1 + strlen(RUBY_MJIT_HEADER_FILE) + 1); if (header_file == NULL) return; - strcpy(header_file, MJIT_HEADER_INSTALL_DIR); + strcpy(header_file, basedir); + strcat(header_file, "/"); + strcat(header_file, MJIT_HEADER_INSTALL_DIR); strcat(header_file, "/"); strcat(header_file, RUBY_MJIT_HEADER_FILE); if ((f = fopen(header_file, "r")) == NULL) { @@ -1077,6 +1091,16 @@ init_header_filename(void) } } fclose(f); + +#ifdef _WIN32 + libruby_build = xmalloc(2 + strlen(basedir) + 1); + strcpy(libruby_build, "-L"); + strcat(libruby_build, basedir); + libruby_installed = xmalloc(2 + strlen(basedir) + 4 + 1); + strcpy(libruby_installed, "-L"); + strcat(libruby_installed, basedir); + strcat(libruby_installed, "/lib"); +#endif } /* This is called after each fork in the child in to switch off MJIT diff --git a/ruby.c b/ruby.c index 925e4cd956..6bc858f2c7 100644 --- a/ruby.c +++ b/ruby.c @@ -1551,9 +1551,6 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) opt->intern.enc.name = int_enc_name; } - if (opt->mjit.on) - mjit_init(&opt->mjit); - if (opt->src.enc.name) rb_warning("-K is specified; it is for 1.8 compatibility and may cause odd behavior"); @@ -1609,6 +1606,10 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) ruby_gc_set_params(opt->safe_level); ruby_init_loadpath_safe(opt->safe_level); + + if (opt->mjit.on) + mjit_init(&opt->mjit); + Init_enc(); lenc = rb_locale_encoding(); rb_enc_associate(rb_progname, lenc); diff --git a/win32/Makefile.sub b/win32/Makefile.sub index e94b0c98ae..f45eadd5be 100644 --- a/win32/Makefile.sub +++ b/win32/Makefile.sub @@ -285,7 +285,7 @@ LDSHARED_0 = @if exist $(@).manifest $(MINIRUBY) -run -e wait_writable -- -n 10 LDSHARED_1 = @if exist $(@).manifest $(MANIFESTTOOL) -manifest $(@).manifest -outputresource:$(@);2 LDSHARED_2 = @if exist $(@).manifest @$(RM) $(@:/=\).manifest !endif -CPPFLAGS = $(DEFS) $(ARCHDEFS) $(CPPFLAGS) -DMJIT_HEADER_BUILD_DIR=\""$(EXTOUT)/include/$(arch)"\" -DLIBRUBYARG_SHARED=\""$(LIBRUBYARG_SHARED)"\" -DLIBRUBY_LIBDIR=\""$(prefix)/lib"\" -DMJIT_HEADER_INSTALL_DIR=\""$(prefix)/include/$(RUBY_BASE_NAME)-$(ruby_version)/$(arch)"\" +CPPFLAGS = $(DEFS) $(ARCHDEFS) $(CPPFLAGS) -DMJIT_HEADER_BUILD_DIR=\""$(EXTOUT)/include/$(arch)"\" -DLIBRUBYARG_SHARED=\""$(LIBRUBYARG_SHARED)"\" -DMJIT_HEADER_INSTALL_DIR=\""include/$(RUBY_BASE_NAME)-$(ruby_version)/$(arch)"\" MJIT_HEADER_FLAGS = -P DLDFLAGS = $(LDFLAGS) -dll -- 2.12.2.windows.2