Skip to content

Commit f9978be

Browse files
committed
Harden clean target integration stubs for native builds
1 parent f829c69 commit f9978be

File tree

3 files changed

+93
-14
lines changed

3 files changed

+93
-14
lines changed

vm/tests/src/test/java/com/codename1/tools/translator/CleanTargetIntegrationTest.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.ArrayList;
2222
import java.util.Arrays;
2323
import java.util.List;
24+
import java.util.stream.Stream;
2425
import java.util.stream.Collectors;
2526

2627
import static org.junit.jupiter.api.Assertions.*;
@@ -192,6 +193,22 @@ static void replaceLibraryWithExecutableTarget(Path cmakeLists, String sourceDir
192193
Files.write(cmakeLists, replacement.getBytes(StandardCharsets.UTF_8));
193194
}
194195

196+
static void copyObjcSourcesAsC(Path srcRoot) throws IOException {
197+
try (Stream<Path> files = Files.list(srcRoot)) {
198+
files.filter(p -> p.getFileName().toString().endsWith(".m"))
199+
.forEach(p -> {
200+
Path asC = p.resolveSibling(p.getFileName().toString().replaceAll("\\.m$", ".c"));
201+
if (!Files.exists(asC)) {
202+
try {
203+
Files.copy(p, asC);
204+
} catch (IOException ignore) {
205+
// Best-effort copy for clean targets; failures are tolerated during tests.
206+
}
207+
}
208+
});
209+
}
210+
}
211+
195212
static List<String> cmakeCompilerArgs() {
196213
String cCompiler = findCompiler("clang", "gcc", "cc");
197214
if (cCompiler == null) {

vm/tests/src/test/java/com/codename1/tools/translator/ReadWriteLockIntegrationTest.java

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ void verifiesReadWriteLockBehavior(CompilerHelper.CompilerConfig config) throws
9393
assertTrue(Files.exists(cmakeLists));
9494

9595
Path srcRoot = distDir.resolve("ReadWriteLockTestApp-src");
96+
CleanTargetIntegrationTest.copyObjcSourcesAsC(srcRoot);
9697
CleanTargetIntegrationTest.patchCn1Globals(srcRoot);
9798
CleanTargetIntegrationTest.patchFileHeader(srcRoot);
9899
patchHashMapNativeSupport(srcRoot);
@@ -654,16 +655,18 @@ private void writeRuntimeStubs(Path srcRoot) throws java.io.IOException {
654655
+ "#include \"java_lang_StringToReal.h\"\n"
655656
+ "#include \"java_lang_ArrayIndexOutOfBoundsException.h\"\n"
656657
+ "#include \"java_lang_Thread.h\"\n\n"
657-
+ "int *classInstanceOf[] = { 0 };\n"
658-
+ "struct clazz* classesList[] = { 0 };\n"
659-
+ "int classListSize = 0;\n"
660-
+ "JAVA_OBJECT* constantPoolObjects = NULL;\n\n"
658+
+ "extern int *classInstanceOf[];\n"
659+
+ "extern struct clazz* classesList[];\n"
660+
+ "extern int classListSize;\n\n"
661661
+ "JAVA_OBJECT java_lang_String_toCharNoCopy___R_char_1ARRAY(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT str) { return JAVA_NULL; }\n"
662662
+ "JAVA_OBJECT java_lang_StringToReal_invalidReal___java_lang_String_boolean_R_java_lang_NumberFormatException(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT s, JAVA_BOOLEAN strict) { return JAVA_NULL; }\n"
663663
+ "JAVA_VOID java_lang_Thread_runImpl___long(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT t, JAVA_LONG id) { }\n"
664664
+ "JAVA_VOID java_lang_ArrayIndexOutOfBoundsException___INIT_____int(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT obj, JAVA_INT idx) { }\n"
665665
+ "JAVA_OBJECT get_field_java_lang_Throwable_stack(JAVA_OBJECT t) { return JAVA_NULL; }\n"
666-
+ "void set_field_java_lang_Throwable_stack(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT val, JAVA_OBJECT t) { }\n";
666+
+ "void set_field_java_lang_Throwable_stack(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT val, JAVA_OBJECT t) { }\n"
667+
+ "JAVA_VOID java_lang_Thread_start0__(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT t) { }\n"
668+
+ "JAVA_VOID java_lang_Thread_sleep0___long(CODENAME_ONE_THREAD_STATE, JAVA_LONG millis) { }\n"
669+
+ "JAVA_OBJECT java_lang_Object_getClass___R_java_lang_Class(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT obj) { return JAVA_NULL; }\n";
667670
Files.write(stubs, content.getBytes(StandardCharsets.UTF_8));
668671
}
669672

@@ -767,6 +770,34 @@ private void patchHashMapNativeMethods(Path srcRoot) throws java.io.IOException
767770
content = content.replaceFirst("#include \\\"java_lang_System.h\\\"\\n\\n",
768771
"#include \"java_lang_System.h\"\n\nJAVA_OBJECT java_lang_Class_getName___R_java_lang_String(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT cls);\nJAVA_OBJECT java_lang_Throwable_getStack___R_java_lang_String(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT t);\n\n");
769772

773+
String[][] duplicateRuntimeSymbols = new String[][] {
774+
{"JAVA_BOOLEAN java_lang_String_equals___java_lang_Object_R_boolean", "JAVA_BOOLEAN java_lang_String_equals___java_lang_Object_R_boolean\\(.*?\n}\\n"},
775+
{"JAVA_OBJECT java_lang_Object_toString___R_java_lang_String", "JAVA_OBJECT java_lang_Object_toString___R_java_lang_String\\(.*?\n}\\n"},
776+
{"JAVA_OBJECT java_lang_String_toString___R_java_lang_String", "JAVA_OBJECT java_lang_String_toString___R_java_lang_String\\(.*?\n}\\n"},
777+
{"JAVA_VOID java_lang_String_getChars___int_int_char_1ARRAY_int", "JAVA_VOID java_lang_String_getChars___int_int_char_1ARRAY_int\\(.*?\n}\\n"},
778+
{"JAVA_OBJECT java_lang_StringBuilder_append___java_lang_String_R_java_lang_StringBuilder", "JAVA_OBJECT java_lang_StringBuilder_append___java_lang_String_R_java_lang_StringBuilder\\(.*?\n}\\n"},
779+
{"JAVA_OBJECT java_lang_StringBuilder_append___java_lang_Object_R_java_lang_StringBuilder", "JAVA_OBJECT java_lang_StringBuilder_append___java_lang_Object_R_java_lang_StringBuilder\\(.*?\n}\\n"},
780+
{"JAVA_VOID java_lang_System_arraycopy___java_lang_Object_int_java_lang_Object_int_int", "JAVA_VOID java_lang_System_arraycopy___java_lang_Object_int_java_lang_Object_int_int\\(.*?\n}\\n"},
781+
{"JAVA_LONG java_lang_System_currentTimeMillis___R_long", "JAVA_LONG java_lang_System_currentTimeMillis___R_long\\(.*?\n}\\n"},
782+
{"JAVA_VOID java_lang_StringBuilder_getChars___int_int_char_1ARRAY_int", "JAVA_VOID java_lang_StringBuilder_getChars___int_int_char_1ARRAY_int\\(.*?\n}\\n"},
783+
{"JAVA_OBJECT java_lang_StringBuilder_append___char_R_java_lang_StringBuilder", "JAVA_OBJECT java_lang_StringBuilder_append___char_R_java_lang_StringBuilder\\(.*?\n}\\n"},
784+
{"JAVA_VOID java_lang_Thread_sleep___long", "JAVA_VOID java_lang_Thread_sleep___long\\(.*?\n}\\n"},
785+
{"JAVA_VOID java_lang_Thread_start__", "JAVA_VOID java_lang_Thread_start__\\(.*?\n}\\n"},
786+
{"JAVA_BOOLEAN java_lang_Thread_isInterrupted___boolean_R_boolean", "JAVA_BOOLEAN java_lang_Thread_isInterrupted___boolean_R_boolean\\(.*?\n}\\n"}
787+
};
788+
789+
for (String[] pattern : duplicateRuntimeSymbols) {
790+
Pattern p = Pattern.compile(pattern[1], Pattern.DOTALL);
791+
Matcher m = p.matcher(content);
792+
if (m.find()) {
793+
content = m.replaceFirst("\n");
794+
}
795+
}
796+
797+
content = content.replace("JAVA_OBJECT* constantPoolObjects = 0;", "extern JAVA_OBJECT* constantPoolObjects;");
798+
content = content.replace("void initConstantPool() {\n // Allocate dummy pool to prevent segfaults, though contents will be null\n constantPoolObjects = calloc(65536, sizeof(void*));\n}\n",
799+
"void initConstantPool() {}\n");
800+
770801
Pattern areEqualKeys = Pattern.compile(
771802
"JAVA_BOOLEAN java_util_HashMap_areEqualKeys___java_lang_Object_java_lang_Object_R_boolean\\(.*?\n}\n",
772803
Pattern.DOTALL);

vm/tests/src/test/java/com/codename1/tools/translator/StampedLockIntegrationTest.java

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ void verifiesStampedLockBehavior(CompilerHelper.CompilerConfig config) throws Ex
9090
assertTrue(Files.exists(cmakeLists));
9191

9292
Path srcRoot = distDir.resolve("StampedLockTestApp-src");
93+
CleanTargetIntegrationTest.copyObjcSourcesAsC(srcRoot);
9394
CleanTargetIntegrationTest.patchCn1Globals(srcRoot);
9495
CleanTargetIntegrationTest.patchFileHeader(srcRoot);
9596
writeRuntimeStubs(srcRoot);
@@ -472,15 +473,15 @@ private void writeMockJavaClasses(Path sourceDir) throws Exception {
472473
Files.write(io.resolve("FileWriter.java"), ("package java.io;\n" +
473474
"public class FileWriter {\n" +
474475
" private final FileOutputStream out;\n" +
475-
" public FileWriter(String name) { this.out = new FileOutputStream(name); }\n" +
476-
" public FileWriter(File file) { this.out = new FileOutputStream(file); }\n" +
476+
" public FileWriter(String name) throws java.io.IOException { this.out = new FileOutputStream(name); }\n" +
477+
" public FileWriter(File file) throws java.io.IOException { this.out = new FileOutputStream(file); }\n" +
477478
" public void write(String s) throws java.io.IOException {\n" +
478479
" if (s == null) return;\n" +
479480
" byte[] data = s.getBytes();\n" +
480481
" out.write(data, 0, data.length);\n" +
481482
" }\n" +
482-
" public void flush() { out.flush(); }\n" +
483-
" public void close() { out.close(); }\n" +
483+
" public void flush() throws java.io.IOException { out.flush(); }\n" +
484+
" public void close() throws java.io.IOException { out.close(); }\n" +
484485
"}\n").getBytes(StandardCharsets.UTF_8));
485486

486487
// java.util.concurrent.TimeUnit
@@ -625,16 +626,18 @@ private void writeRuntimeStubs(Path srcRoot) throws java.io.IOException {
625626
+ "#include \"java_lang_StringToReal.h\"\n"
626627
+ "#include \"java_lang_ArrayIndexOutOfBoundsException.h\"\n"
627628
+ "#include \"java_lang_Thread.h\"\n\n"
628-
+ "int *classInstanceOf[] = { 0 };\n"
629-
+ "struct clazz* classesList[] = { 0 };\n"
630-
+ "int classListSize = 0;\n"
631-
+ "JAVA_OBJECT* constantPoolObjects = NULL;\n\n"
629+
+ "extern int *classInstanceOf[];\n"
630+
+ "extern struct clazz* classesList[];\n"
631+
+ "extern int classListSize;\n\n"
632632
+ "JAVA_OBJECT java_lang_String_toCharNoCopy___R_char_1ARRAY(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT str) { return JAVA_NULL; }\n"
633633
+ "JAVA_OBJECT java_lang_StringToReal_invalidReal___java_lang_String_boolean_R_java_lang_NumberFormatException(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT s, JAVA_BOOLEAN strict) { return JAVA_NULL; }\n"
634634
+ "JAVA_VOID java_lang_Thread_runImpl___long(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT t, JAVA_LONG id) { }\n"
635635
+ "JAVA_VOID java_lang_ArrayIndexOutOfBoundsException___INIT_____int(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT obj, JAVA_INT idx) { }\n"
636636
+ "JAVA_OBJECT get_field_java_lang_Throwable_stack(JAVA_OBJECT t) { return JAVA_NULL; }\n"
637-
+ "void set_field_java_lang_Throwable_stack(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT val, JAVA_OBJECT t) { }\n";
637+
+ "void set_field_java_lang_Throwable_stack(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT val, JAVA_OBJECT t) { }\n"
638+
+ "JAVA_VOID java_lang_Thread_start0__(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT t) { }\n"
639+
+ "JAVA_VOID java_lang_Thread_sleep0___long(CODENAME_ONE_THREAD_STATE, JAVA_LONG millis) { }\n"
640+
+ "JAVA_OBJECT java_lang_Object_getClass___R_java_lang_Class(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT obj) { return JAVA_NULL; }\n";
638641
Files.write(stubs, content.getBytes(StandardCharsets.UTF_8));
639642
}
640643

@@ -738,6 +741,34 @@ private void patchHashMapNativeMethods(Path srcRoot) throws java.io.IOException
738741
content = content.replaceFirst("#include \\\"java_lang_System.h\\\"\\n\\n",
739742
"#include \"java_lang_System.h\"\n\nJAVA_OBJECT java_lang_Class_getName___R_java_lang_String(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT cls);\nJAVA_OBJECT java_lang_Throwable_getStack___R_java_lang_String(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT t);\n\n");
740743

744+
String[][] duplicateRuntimeSymbols = new String[][] {
745+
{"JAVA_BOOLEAN java_lang_String_equals___java_lang_Object_R_boolean", "JAVA_BOOLEAN java_lang_String_equals___java_lang_Object_R_boolean\\(.*?\n}\\n"},
746+
{"JAVA_OBJECT java_lang_Object_toString___R_java_lang_String", "JAVA_OBJECT java_lang_Object_toString___R_java_lang_String\\(.*?\n}\\n"},
747+
{"JAVA_OBJECT java_lang_String_toString___R_java_lang_String", "JAVA_OBJECT java_lang_String_toString___R_java_lang_String\\(.*?\n}\\n"},
748+
{"JAVA_VOID java_lang_String_getChars___int_int_char_1ARRAY_int", "JAVA_VOID java_lang_String_getChars___int_int_char_1ARRAY_int\\(.*?\n}\\n"},
749+
{"JAVA_OBJECT java_lang_StringBuilder_append___java_lang_String_R_java_lang_StringBuilder", "JAVA_OBJECT java_lang_StringBuilder_append___java_lang_String_R_java_lang_StringBuilder\\(.*?\n}\\n"},
750+
{"JAVA_OBJECT java_lang_StringBuilder_append___java_lang_Object_R_java_lang_StringBuilder", "JAVA_OBJECT java_lang_StringBuilder_append___java_lang_Object_R_java_lang_StringBuilder\\(.*?\n}\\n"},
751+
{"JAVA_VOID java_lang_System_arraycopy___java_lang_Object_int_java_lang_Object_int_int", "JAVA_VOID java_lang_System_arraycopy___java_lang_Object_int_java_lang_Object_int_int\\(.*?\n}\\n"},
752+
{"JAVA_LONG java_lang_System_currentTimeMillis___R_long", "JAVA_LONG java_lang_System_currentTimeMillis___R_long\\(.*?\n}\\n"},
753+
{"JAVA_VOID java_lang_StringBuilder_getChars___int_int_char_1ARRAY_int", "JAVA_VOID java_lang_StringBuilder_getChars___int_int_char_1ARRAY_int\\(.*?\n}\\n"},
754+
{"JAVA_OBJECT java_lang_StringBuilder_append___char_R_java_lang_StringBuilder", "JAVA_OBJECT java_lang_StringBuilder_append___char_R_java_lang_StringBuilder\\(.*?\n}\\n"},
755+
{"JAVA_VOID java_lang_Thread_sleep___long", "JAVA_VOID java_lang_Thread_sleep___long\\(.*?\n}\\n"},
756+
{"JAVA_VOID java_lang_Thread_start__", "JAVA_VOID java_lang_Thread_start__\\(.*?\n}\\n"},
757+
{"JAVA_BOOLEAN java_lang_Thread_isInterrupted___boolean_R_boolean", "JAVA_BOOLEAN java_lang_Thread_isInterrupted___boolean_R_boolean\\(.*?\n}\\n"}
758+
};
759+
760+
for (String[] pattern : duplicateRuntimeSymbols) {
761+
Pattern p = Pattern.compile(pattern[1], Pattern.DOTALL);
762+
Matcher m = p.matcher(content);
763+
if (m.find()) {
764+
content = m.replaceFirst("\n");
765+
}
766+
}
767+
768+
content = content.replace("JAVA_OBJECT* constantPoolObjects = 0;", "extern JAVA_OBJECT* constantPoolObjects;");
769+
content = content.replace("void initConstantPool() {\n // Allocate dummy pool to prevent segfaults, though contents will be null\n constantPoolObjects = calloc(65536, sizeof(void*));\n}\n",
770+
"void initConstantPool() {}\n");
771+
741772
Pattern areEqualKeys = Pattern.compile(
742773
"JAVA_BOOLEAN java_util_HashMap_areEqualKeys___java_lang_Object_java_lang_Object_R_boolean\\(.*?\n}\n",
743774
Pattern.DOTALL);

0 commit comments

Comments
 (0)