mirror of
https://github.com/corda/corda.git
synced 2025-01-30 08:04:16 +00:00
Added new embed utility for Windows
This commit is contained in:
parent
53b1a2423a
commit
571cc6a85e
47
makefile
47
makefile
@ -496,6 +496,10 @@ ifeq ($(platform),windows)
|
|||||||
else
|
else
|
||||||
shared += -Wl,--add-stdcall-alias
|
shared += -Wl,--add-stdcall-alias
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
embed = $(build-embed)/embed.exe
|
||||||
|
embed-loader = $(build-embed-loader)/embed-loader.exe
|
||||||
|
embed-loader-o = $(build-embed)/embed-loader.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(mode),debug)
|
ifeq ($(mode),debug)
|
||||||
@ -640,6 +644,15 @@ vm-asm-sources = $(src)/$(asm).S
|
|||||||
|
|
||||||
target-asm = $(asm)
|
target-asm = $(asm)
|
||||||
|
|
||||||
|
build-embed = $(build)/embed
|
||||||
|
build-embed-loader = $(build)/embed-loader
|
||||||
|
|
||||||
|
embed-loader-sources = $(src)/embedded-loader.cpp
|
||||||
|
embed-loader-objects = $(call cpp-objects,$(embed-loader-sources),$(src),$(build-embed-loader))
|
||||||
|
|
||||||
|
embed-sources = $(src)/embed.cpp
|
||||||
|
embed-objects = $(call cpp-objects,$(embed-sources),$(src),$(build-embed))
|
||||||
|
|
||||||
ifeq ($(process),compile)
|
ifeq ($(process),compile)
|
||||||
vm-sources += \
|
vm-sources += \
|
||||||
$(src)/compiler.cpp \
|
$(src)/compiler.cpp \
|
||||||
@ -890,7 +903,7 @@ test-args = $(test-flags) $(input)
|
|||||||
.PHONY: build
|
.PHONY: build
|
||||||
build: $(static-library) $(executable) $(dynamic-library) $(lzma-loader) \
|
build: $(static-library) $(executable) $(dynamic-library) $(lzma-loader) \
|
||||||
$(lzma-encoder) $(executable-dynamic) $(classpath-dep) $(test-dep) \
|
$(lzma-encoder) $(executable-dynamic) $(classpath-dep) $(test-dep) \
|
||||||
$(test-extra-dep)
|
$(test-extra-dep) $(embed)
|
||||||
|
|
||||||
$(test-dep): $(classpath-dep)
|
$(test-dep): $(classpath-dep)
|
||||||
|
|
||||||
@ -1005,6 +1018,38 @@ else
|
|||||||
$(ld) $(^) $(shared) $(lflags) -o $(@)
|
$(ld) $(^) $(shared) $(lflags) -o $(@)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifdef embed
|
||||||
|
$(embed): $(embed-objects) $(embed-loader-o)
|
||||||
|
@echo "building $(embed)"
|
||||||
|
$(build-cxx) $(^) -mwindows -mconsole -static -o $(@)
|
||||||
|
|
||||||
|
$(build-embed)/%.o: $(src)/%.cpp
|
||||||
|
@echo "compiling $(@)"
|
||||||
|
@mkdir -p $(dir $(@))
|
||||||
|
$(build-cxx) -D_UNICODE -DUNICODE -c $(<) -o $(@)
|
||||||
|
|
||||||
|
$(embed-loader-o): $(embed-loader) $(converter)
|
||||||
|
@mkdir -p $(dir $(@))
|
||||||
|
$(converter) $(<) $(@) _binary_loader_start \
|
||||||
|
_binary_loader_end $(target-format) $(arch)
|
||||||
|
|
||||||
|
$(embed-loader): $(embed-loader-objects) $(static-library)
|
||||||
|
@mkdir -p $(dir $(@))
|
||||||
|
cd $(dir $(@)) && $(ar) x ../../../$(static-library)
|
||||||
|
$(dlltool) -z $(addsuffix .def,$(basename $(@))) $(dir $(@))/*.o
|
||||||
|
$(dlltool) -d $(addsuffix .def,$(basename $(@))) -e $(addsuffix .exp,$(basename $(@)))
|
||||||
|
$(cxx) $(addsuffix .exp,$(basename $(@))) $(dir $(@))/*.o -L../win32/lib -lmingwthrd -lm -lz -lws2_32 -liphlpapi \
|
||||||
|
-mwindows -mconsole -static -o $(@)
|
||||||
|
strip --strip-all $(@)
|
||||||
|
|
||||||
|
$(build-embed-loader)/%.o: $(src)/%.cpp
|
||||||
|
@echo "compiling $(@)"
|
||||||
|
@mkdir -p $(dir $(@))
|
||||||
|
$(cxx) -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/win32 \
|
||||||
|
-D_JNI_IMPLEMENTATION_ -c $(<) -o $(@)
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
$(build)/%.o: $(lzma)/C/%.c
|
$(build)/%.o: $(lzma)/C/%.c
|
||||||
@echo "compiling $(@)"
|
@echo "compiling $(@)"
|
||||||
@mkdir -p $(dir $(@))
|
@mkdir -p $(dir $(@))
|
||||||
|
125
src/embed.cpp
Normal file
125
src/embed.cpp
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
/* Copyright (c) 2008-2012, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "embed.h"
|
||||||
|
|
||||||
|
extern "C" const uint8_t binary_loader_start[];
|
||||||
|
extern "C" const uint8_t binary_loader_end[];
|
||||||
|
|
||||||
|
__declspec(noreturn)
|
||||||
|
void printUsage(const wchar_t* executableName)
|
||||||
|
{
|
||||||
|
wprintf(L"Usage: %s destination.exe classes.jar package.Main\n", executableName);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeDestinationFile(const wchar_t* filename)
|
||||||
|
{
|
||||||
|
if(FILE* file = _wfopen(filename, L"wb"))
|
||||||
|
{
|
||||||
|
size_t count = binary_loader_end - binary_loader_start;
|
||||||
|
if(count == fwrite(binary_loader_start, sizeof(binary_loader_start[0]), count, file))
|
||||||
|
{
|
||||||
|
fclose(file);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Unable to write to destination file\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void readFile(std::vector<char>* jarFile, const wchar_t* fileName)
|
||||||
|
{
|
||||||
|
if(FILE* file = _wfopen(fileName, L"rb"))
|
||||||
|
{
|
||||||
|
fseek(file, 0, SEEK_END);
|
||||||
|
jarFile->resize(ftell(file));
|
||||||
|
fseek(file, 0, SEEK_SET);
|
||||||
|
fread(&jarFile->at(0), 1, jarFile->size(), file);
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mkStringSection(std::vector<wchar_t>* stringSection, const std::vector<std::wstring>& strings, int first, int last)
|
||||||
|
{
|
||||||
|
stringSection->clear();
|
||||||
|
for(int i = first; i <= last; ++i)
|
||||||
|
{
|
||||||
|
const std::wstring& s = strings.at(i);
|
||||||
|
stringSection->push_back(s.size());
|
||||||
|
stringSection->insert(stringSection->end(), s.begin(), s.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
// pad to 16 entries
|
||||||
|
for(int i = last - first; i < 15; ++i)
|
||||||
|
stringSection->push_back(0);
|
||||||
|
|
||||||
|
return stringSection->size() > 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeStringResources(HANDLE hDest, const std::vector<std::wstring>& strings)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < strings.size(); i += 16)
|
||||||
|
{
|
||||||
|
std::vector<wchar_t> stringSection;
|
||||||
|
|
||||||
|
if(mkStringSection(&stringSection, strings, i, std::min<int>(i + 15, strings.size() - 1)))
|
||||||
|
UpdateResourceW(hDest, RT_STRING, MAKEINTRESOURCE((i >> 4) + 1), LANG_NEUTRAL, &stringSection.at(0), sizeof(wchar_t) * stringSection.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int wmain(int argc, wchar_t* argv[])
|
||||||
|
{
|
||||||
|
if(argc != 4)
|
||||||
|
printUsage(argv[0]);
|
||||||
|
|
||||||
|
const wchar_t* destinationName = argv[1];
|
||||||
|
const wchar_t* classesName = argv[2];
|
||||||
|
const wchar_t* mainClassName = argv[3];
|
||||||
|
|
||||||
|
writeDestinationFile(destinationName);
|
||||||
|
|
||||||
|
if(HANDLE hDest = BeginUpdateResourceW(destinationName, TRUE))
|
||||||
|
{
|
||||||
|
std::vector<std::wstring> strings;
|
||||||
|
strings.resize(RESID_MAIN_CLASS + 1);
|
||||||
|
strings.at(RESID_MAIN_CLASS) = mainClassName;
|
||||||
|
|
||||||
|
writeStringResources(hDest, strings);
|
||||||
|
|
||||||
|
std::vector<char> jarFile;
|
||||||
|
readFile(&jarFile, classesName);
|
||||||
|
UpdateResourceW(hDest, RT_RCDATA, _T(RESID_BOOT_JAR), LANG_NEUTRAL, &jarFile.at(0), jarFile.size());
|
||||||
|
|
||||||
|
EndUpdateResource(hDest, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int _CRT_glob;
|
||||||
|
extern "C" void __wgetmainargs(int*, wchar_t***, wchar_t***, int, int*);
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
wchar_t **enpv, **argv;
|
||||||
|
int argc, si = 0;
|
||||||
|
__wgetmainargs(&argc, &argv, &enpv, _CRT_glob, &si);
|
||||||
|
return wmain(argc, argv);
|
||||||
|
}
|
17
src/embed.h
Normal file
17
src/embed.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/* Copyright (c) 2008-2012, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
#ifndef EMBED_H
|
||||||
|
#define EMBED_H
|
||||||
|
|
||||||
|
#define RESID_MAIN_CLASS 100
|
||||||
|
#define RESID_BOOT_JAR "BOOT.JAR"
|
||||||
|
|
||||||
|
#endif
|
105
src/embedded-loader.cpp
Normal file
105
src/embedded-loader.cpp
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
/* Copyright (c) 2008-2012, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "embed.h"
|
||||||
|
#include "jni.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if (defined __MINGW32__) || (defined _MSC_VER)
|
||||||
|
# define EXPORT __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
# define EXPORT __attribute__ ((visibility("default"))) \
|
||||||
|
__attribute__ ((used))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
EXPORT const uint8_t*
|
||||||
|
bootJar(unsigned* size)
|
||||||
|
{
|
||||||
|
if(HRSRC hResInfo = FindResource(NULL, _T(RESID_BOOT_JAR), RT_RCDATA))
|
||||||
|
{
|
||||||
|
if(HGLOBAL hRes = LoadResource(NULL, hResInfo))
|
||||||
|
{
|
||||||
|
*size = SizeofResource(NULL, hResInfo);
|
||||||
|
return (const uint8_t*)LockResource(hRes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "boot.jar resource not found\n");
|
||||||
|
|
||||||
|
*size = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} // extern "C"
|
||||||
|
|
||||||
|
static bool getMainClass(char* pName, int maxLen)
|
||||||
|
{
|
||||||
|
if(0 == LoadString(NULL, RESID_MAIN_CLASS, pName, maxLen))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Main class not specified\n");
|
||||||
|
strcpy(pName, "Main");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int ac, const char** av)
|
||||||
|
{
|
||||||
|
JavaVMInitArgs vmArgs;
|
||||||
|
vmArgs.version = JNI_VERSION_1_2;
|
||||||
|
vmArgs.nOptions = 1;
|
||||||
|
vmArgs.ignoreUnrecognized = JNI_TRUE;
|
||||||
|
|
||||||
|
JavaVMOption options[vmArgs.nOptions];
|
||||||
|
vmArgs.options = options;
|
||||||
|
|
||||||
|
options[0].optionString = const_cast<char*>("-Xbootclasspath:[bootJar]");
|
||||||
|
|
||||||
|
JavaVM* vm;
|
||||||
|
void* env;
|
||||||
|
JNI_CreateJavaVM(&vm, &env, &vmArgs);
|
||||||
|
JNIEnv* e = static_cast<JNIEnv*>(env);
|
||||||
|
|
||||||
|
char mainClass[256];
|
||||||
|
getMainClass(mainClass, sizeof(mainClass));
|
||||||
|
|
||||||
|
jclass c = e->FindClass(mainClass);
|
||||||
|
if (not e->ExceptionCheck()) {
|
||||||
|
jmethodID m = e->GetStaticMethodID(c, "main", "([Ljava/lang/String;)V");
|
||||||
|
if (not e->ExceptionCheck()) {
|
||||||
|
jclass stringClass = e->FindClass("java/lang/String");
|
||||||
|
if (not e->ExceptionCheck()) {
|
||||||
|
jobjectArray a = e->NewObjectArray(ac-1, stringClass, 0);
|
||||||
|
if (not e->ExceptionCheck()) {
|
||||||
|
for (int i = 1; i < ac; ++i) {
|
||||||
|
e->SetObjectArrayElement(a, i-1, e->NewStringUTF(av[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
e->CallStaticVoidMethod(c, m, a);
|
||||||
|
} else fprintf(stderr, "Couldn't create array\n");
|
||||||
|
} else fprintf(stderr, "java.lang.String not found\n");
|
||||||
|
} else fprintf(stderr, "main method not found\n");
|
||||||
|
} else fprintf(stderr, "Main class not found\n");
|
||||||
|
|
||||||
|
int exitCode = 0;
|
||||||
|
if(e->ExceptionCheck()) {
|
||||||
|
exitCode = -1;
|
||||||
|
e->ExceptionDescribe();
|
||||||
|
e->ExceptionClear();
|
||||||
|
}
|
||||||
|
|
||||||
|
vm->DestroyJavaVM();
|
||||||
|
|
||||||
|
return exitCode;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user