mirror of
https://github.com/corda/corda.git
synced 2025-01-17 02:09:50 +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
|
||||
shared += -Wl,--add-stdcall-alias
|
||||
endif
|
||||
|
||||
embed = $(build-embed)/embed.exe
|
||||
embed-loader = $(build-embed-loader)/embed-loader.exe
|
||||
embed-loader-o = $(build-embed)/embed-loader.o
|
||||
endif
|
||||
|
||||
ifeq ($(mode),debug)
|
||||
@ -640,6 +644,15 @@ vm-asm-sources = $(src)/$(asm).S
|
||||
|
||||
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)
|
||||
vm-sources += \
|
||||
$(src)/compiler.cpp \
|
||||
@ -890,7 +903,7 @@ test-args = $(test-flags) $(input)
|
||||
.PHONY: build
|
||||
build: $(static-library) $(executable) $(dynamic-library) $(lzma-loader) \
|
||||
$(lzma-encoder) $(executable-dynamic) $(classpath-dep) $(test-dep) \
|
||||
$(test-extra-dep)
|
||||
$(test-extra-dep) $(embed)
|
||||
|
||||
$(test-dep): $(classpath-dep)
|
||||
|
||||
@ -1005,6 +1018,38 @@ else
|
||||
$(ld) $(^) $(shared) $(lflags) -o $(@)
|
||||
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
|
||||
@echo "compiling $(@)"
|
||||
@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…
Reference in New Issue
Block a user