diff --git a/makefile b/makefile index c484ae52d4..e78fb8a5e0 100644 --- a/makefile +++ b/makefile @@ -46,6 +46,18 @@ endif ifdef gnu options := $(options)-gnu gnu-sources = $(src)/gnu.cpp + gnu-libraries = \ + $(gnu)/lib/classpath/libjavaio.a \ + $(gnu)/lib/classpath/libjavalang.a \ + $(gnu)/lib/classpath/libjavalangreflect.a \ + $(gnu)/lib/classpath/libjavamath.a \ + $(gnu)/lib/classpath/libjavanet.a \ + $(gnu)/lib/classpath/libjavanio.a \ + $(gnu)/lib/classpath/libjavautil.a + gnu-object-dep = $(build)/gnu-object.dep + gnu-cflags = -DBOOT_BUILTINS=\"javaio,javalang,javalangreflect,javamath,javanet,javanio,javautil\" + gnu-lflags = -lgmp + gnu-objects = $(shell find $(build)/gnu-objects -name "*.o") endif root = $(shell (cd .. && pwd)) @@ -93,13 +105,14 @@ warnings = -Wall -Wextra -Werror -Wunused-parameter -Winit-self \ common-cflags = $(warnings) -fno-rtti -fno-exceptions -fno-omit-frame-pointer \ "-I$(JAVA_HOME)/include" -idirafter $(src) -I$(native-build) \ -D__STDC_LIMIT_MACROS -D_JNI_IMPLEMENTATION_ -DAVIAN_VERSION=\"$(version)\" \ + $(gnu-cflags) build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \ "-I$(JAVA_HOME)/include/linux" -I$(src) -pthread cflags = $(build-cflags) -common-lflags = -lm -lz +common-lflags = -lm -lz $(gnu-lflags) build-lflags = @@ -534,10 +547,11 @@ $(generator-objects): $(native-build)/%.o: $(src)/%.cpp $(jni-objects): $(native-build)/%.o: $(classpath)/%.cpp $(compile-object) +$(static-library): $(gnu-object-dep) $(static-library): $(vm-objects) $(jni-objects) $(vm-heapwalk-objects) @echo "creating $(@)" rm -rf $(@) - $(ar) cru $(@) $(^) + $(ar) cru $(@) $(^) $(call gnu-objects) $(ranlib) $(@) $(bootimage-bin): $(bootimage-generator) @@ -557,16 +571,24 @@ else "$${wd}/$(@)") endif +$(gnu-object-dep): $(gnu-libraries) + @mkdir -p $(build)/gnu-objects + (cd $(build)/gnu-objects && \ + for x in $(gnu-libraries); do ar x $${x}; done) + @touch $(@) + +$(executable): $(gnu-object-dep) $(executable): \ $(vm-objects) $(jni-objects) $(driver-object) $(vm-heapwalk-objects) \ $(boot-object) $(vm-classpath-object) @echo "linking $(@)" ifeq ($(platform),windows) - $(dlltool) -z $(@).def $(^) + $(dlltool) -z $(@).def $(^) $(call gnu-objects) $(dlltool) -d $(@).def -e $(@).exp - $(cc) $(@).exp $(^) $(lflags) -o $(@) + $(cc) $(@).exp $(^) $(call gnu-objects) $(lflags) -o $(@) else - $(cc) $(^) $(rdynamic) $(lflags) $(bootimage-lflags) -o $(@) + $(cc) $(^) $(call gnu-objects) $(rdynamic) $(lflags) $(bootimage-lflags) \ + -o $(@) endif $(strip) $(strip-all) $(@) @@ -597,7 +619,7 @@ endif $(dynamic-library): \ $(vm-objects) $(dynamic-object) $(jni-objects) $(vm-heapwalk-objects) \ - $(boot-object) $(vm-classpath-object) + $(boot-object) $(vm-classpath-object) $(gnu-libraries) @echo "linking $(@)" $(cc) $(^) $(shared) $(lflags) $(bootimage-lflags) -o $(@) $(strip) $(strip-all) $(@) diff --git a/src/gnu.cpp b/src/gnu.cpp index 36d666de23..89dc03822a 100644 --- a/src/gnu.cpp +++ b/src/gnu.cpp @@ -57,9 +57,17 @@ Avian_gnu_classpath_VMSystemProperties_preInit setProperty(t, method, properties, "file.encoding", "ASCII"); -#ifdef WIN32 + // specify a bogus library path so we can do our own search in + // VMRuntime.nativeLoad: +#define LIBRARY_PATH_SENTINAL "*" + setProperty(t, method, properties, "java.library.path", + LIBRARY_PATH_SENTINAL); + +#ifdef WIN32 +# define FILE_SEPARATOR "\\" + setProperty(t, method, properties, "line.separator", "\r\n"); - setProperty(t, method, properties, "file.separator", "\\"); + setProperty(t, method, properties, "file.separator", FILE_SEPARATOR); setProperty(t, method, properties, "path.separator", ";"); setProperty(t, method, properties, "os.name", "Windows"); @@ -69,21 +77,16 @@ Avian_gnu_classpath_VMSystemProperties_preInit setProperty(t, method, properties, "user.home", _wgetenv(L"USERPROFILE"), "%ls"); - - setProperty(t, method, properties, "java.library.path", - _wgetenv(L"PATH"), "%ls"); #else +# define FILE_SEPARATOR "/" + setProperty(t, method, properties, "line.separator", "\n"); - setProperty(t, method, properties, "file.separator", "/"); + setProperty(t, method, properties, "file.separator", FILE_SEPARATOR); setProperty(t, method, properties, "path.separator", ":"); # ifdef __APPLE__ setProperty(t, method, properties, "os.name", "Mac OS X"); - setProperty(t, method, properties, "java.library.path", - getenv("DYLD_LIBRARY_PATH")); # else setProperty(t, method, properties, "os.name", "Linux"); - setProperty(t, method, properties, "java.library.path", - getenv("LD_LIBRARY_PATH")); # endif setProperty(t, method, properties, "java.io.tmpdir", "/tmp"); setProperty(t, method, properties, "user.home", getenv("HOME")); @@ -153,17 +156,17 @@ Avian_java_lang_VMRuntime_mapLibraryName object name = reinterpret_cast(arguments[0]); PROTECT(t, name); - const unsigned prefixLength = sizeof(SO_PREFIX) - 1; + const unsigned soPrefixLength = sizeof(SO_PREFIX) - 1; const unsigned nameLength = stringLength(t, name); - const unsigned suffixLength = sizeof(SO_SUFFIX) - 1; - const unsigned total = prefixLength + nameLength + suffixLength; + const unsigned soSuffixLength = sizeof(SO_SUFFIX) - 1; + const unsigned total = soPrefixLength + nameLength + soSuffixLength; object s = makeByteArray(t, total + 1); char* p = reinterpret_cast(&byteArrayBody(t, s, 0)); - memcpy(p, SO_PREFIX, prefixLength); - stringChars(t, name, p + prefixLength); - memcpy(p + prefixLength + nameLength, SO_SUFFIX, suffixLength); + memcpy(p, SO_PREFIX, soPrefixLength); + stringChars(t, name, p + soPrefixLength); + memcpy(p + soPrefixLength + nameLength, SO_SUFFIX, soSuffixLength); p[total] = 0; return reinterpret_cast(makeString(t, s, 0, total, 0)); @@ -188,7 +191,38 @@ extern "C" JNIEXPORT int64_t JNICALL Avian_java_lang_VMRuntime_nativeLoad (Thread* t, object, uintptr_t* arguments) { - uintptr_t args[] = { arguments[0], 0 }; + object name = reinterpret_cast(arguments[0]); + + // given that we set java.library.path to LIBRARY_PATH_SENTINAL, we + // can determine which names are filenames and which are library + // names by looking for the prefix LIBRARY_PATH_SENTINAL + // FILE_SEPARATOR + + unsigned length = stringLength(t, name); + char n[length + 1]; + stringChars(t, name, n); + + const unsigned pathPrefixLength + = sizeof(LIBRARY_PATH_SENTINAL) - 1 + + sizeof(FILE_SEPARATOR) - 1; + + bool mapName = (strncmp(n, LIBRARY_PATH_SENTINAL FILE_SEPARATOR, + pathPrefixLength) == 0); + if (mapName) { + // strip the path prefix, SO prefix, and SO suffix before passing + // the name to Runtime.load + + const unsigned soPrefixLength = sizeof(SO_PREFIX) - 1; + const unsigned soSuffixLength = sizeof(SO_SUFFIX) - 1; + const unsigned newOffset + = stringOffset(t, name) + pathPrefixLength + soPrefixLength; + const unsigned newLength + = length - pathPrefixLength - soPrefixLength - soSuffixLength; + + name = makeString(t, stringData(t, name), newOffset, newLength, 0); + } + + uintptr_t args[] = { reinterpret_cast(name), mapName }; Avian_java_lang_Runtime_load(t, 0, args); diff --git a/src/main.cpp b/src/main.cpp index 5e412c0bae..074297016d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -83,6 +83,10 @@ main(int ac, const char** av) ++ vmArgs.nOptions; #endif +#ifdef BOOT_BUILTINS + ++ vmArgs.nOptions; +#endif + JavaVMOption options[vmArgs.nOptions]; vmArgs.options = options; @@ -103,6 +107,11 @@ main(int ac, const char** av) = const_cast("-Davian.bootstrap=" BOOT_LIBRARY); #endif +#ifdef BOOT_BUILTINS + options[optionIndex++].optionString + = const_cast("-Davian.builtins=" BOOT_BUILTINS); +#endif + #define CLASSPATH_PROPERTY "-Djava.class.path=" unsigned classpathSize = strlen(classpath);