@@ -423,6 +423,14 @@ def svm_gate_body(args, tasks):
423
423
with native_image_context (IMAGE_ASSERTION_FLAGS ) as native_image :
424
424
debuginfotest (['--output-path' , svmbuild_dir ()] + args .extra_image_builder_arguments )
425
425
426
+ with Task ('image layereddebuginfotest' , tasks , tags = [GraalTags .debuginfotest ]) as t :
427
+ if t :
428
+ if mx .is_windows ():
429
+ mx .warn ('layereddebuginfotest does not work on Windows' )
430
+ else :
431
+ with native_image_context (IMAGE_ASSERTION_FLAGS ) as native_image :
432
+ layereddebuginfotest (['--output-path' , svmbuild_dir ()] + args .extra_image_builder_arguments )
433
+
426
434
with Task ('image debughelpertest' , tasks , tags = [GraalTags .debuginfotest ]) as t :
427
435
if t :
428
436
if mx .is_windows ():
@@ -678,14 +686,7 @@ def batched(iterable, n):
678
686
679
687
def _native_junit (native_image , unittest_args , build_args = None , run_args = None , blacklist = None , whitelist = None , preserve_image = False , test_classes_per_run = None ):
680
688
build_args = build_args or []
681
- javaProperties = {}
682
- for dist in suite .dists :
683
- if isinstance (dist , mx .ClasspathDependency ):
684
- for cpEntry in mx .classpath_entries (dist ):
685
- if hasattr (cpEntry , "getJavaProperties" ):
686
- for key , value in cpEntry .getJavaProperties ().items ():
687
- javaProperties [key ] = value
688
- for key , value in javaProperties .items ():
689
+ for key , value in get_java_properties ().items ():
689
690
build_args .append ("-D" + key + "=" + value )
690
691
691
692
build_args .append ('--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED' )
@@ -913,6 +914,17 @@ class HelloWorld {
913
914
}
914
915
915
916
917
+ def get_java_properties ():
918
+ javaProperties = {}
919
+ for dist in suite .dists :
920
+ if isinstance (dist , mx .ClasspathDependency ):
921
+ for cpEntry in mx .classpath_entries (dist ):
922
+ if hasattr (cpEntry , "getJavaProperties" ):
923
+ for key , value in cpEntry .getJavaProperties ().items ():
924
+ javaProperties [key ] = value
925
+ return javaProperties
926
+
927
+
916
928
def _helloworld (native_image , javac_command , path , build_only , args , variant = list (_helloworld_variants .keys ())[0 ]):
917
929
mx_util .ensure_dir_exists (path )
918
930
hello_file = os .path .join (path , 'HelloWorld.java' )
@@ -923,14 +935,7 @@ def _helloworld(native_image, javac_command, path, build_only, args, variant=lis
923
935
fp .flush ()
924
936
mx .run (javac_command + [hello_file ])
925
937
926
- javaProperties = {}
927
- for dist in suite .dists :
928
- if isinstance (dist , mx .ClasspathDependency ):
929
- for cpEntry in mx .classpath_entries (dist ):
930
- if hasattr (cpEntry , "getJavaProperties" ):
931
- for key , value in cpEntry .getJavaProperties ().items ():
932
- javaProperties [key ] = value
933
- for key , value in javaProperties .items ():
938
+ for key , value in get_java_properties ().items ():
934
939
args .append ("-D" + key + "=" + value )
935
940
936
941
binary_path = join (path , "helloworld" )
@@ -977,39 +982,18 @@ def _collector(x):
977
982
raise Exception ('Unexpected output: ' + str (actual_output ) + " != " + str (expected_output ))
978
983
979
984
def _debuginfotest (native_image , path , build_only , with_isolates_only , args ):
980
- mx .log (f"path={ path } " )
981
985
sourcepath = mx .project ('com.oracle.svm.test' ).source_dirs ()[0 ]
982
- mx .log (f"sourcepath={ sourcepath } " )
983
- sourcecache = join (path , 'sources' )
984
- mx .log (f"sourcecache={ sourcecache } " )
985
986
# the header file for foreign types resides at the root of the
986
987
# com.oracle.svm.test source tree
987
988
cincludepath = sourcepath
988
- javaProperties = {}
989
- for dist in suite .dists :
990
- if isinstance (dist , mx .ClasspathDependency ):
991
- for cpEntry in mx .classpath_entries (dist ):
992
- if hasattr (cpEntry , "getJavaProperties" ):
993
- for key , value in cpEntry .getJavaProperties ().items ():
994
- javaProperties [key ] = value
995
- for key , value in javaProperties .items ():
989
+ for key , value in get_java_properties ().items ():
996
990
args .append ("-D" + key + "=" + value )
997
991
998
- # set property controlling inclusion of foreign struct header
999
- args .append ("-DbuildDebugInfoTestExample=true" )
1000
-
1001
- native_image_args = [
1002
- '--native-compiler-options=-I' + cincludepath ,
1003
- '-H:CLibraryPath=' + sourcepath ,
1004
- '--native-image-info' ,
1005
- '-cp' , classpath ('com.oracle.svm.test' ),
1006
- '-Djdk.graal.LogFile=graal.log' ,
1007
- '-g' ,
1008
- ] + svm_experimental_options ([
1009
- '-H:+VerifyNamingConventions' ,
1010
- '-H:+SourceLevelDebug' ,
1011
- '-H:DebugInfoSourceSearchPath=' + sourcepath ,
1012
- ]) + args
992
+ native_image_args = (
993
+ testhello_ni_args (cincludepath , sourcepath ) +
994
+ svm_experimental_options (['-H:+VerifyNamingConventions' ]) +
995
+ args
996
+ )
1013
997
1014
998
def build_debug_test (variant_name , image_name , extra_args ):
1015
999
per_build_path = join (path , variant_name )
@@ -1020,9 +1004,13 @@ def build_debug_test(variant_name, image_name, extra_args):
1020
1004
mx .log (f'native_image { build_args } ' )
1021
1005
return native_image (build_args )
1022
1006
1007
+ env = os .environ .copy ()
1023
1008
# build with and without Isolates and check both work
1024
1009
if '--libc=musl' in args :
1025
- os .environ .update ({'debuginfotest_musl' : 'yes' })
1010
+ env ['debuginfotest_musl' ] = 'yes'
1011
+
1012
+ # this is a non-layered build
1013
+ env ['debuginfotest_layered' ] = 'no'
1026
1014
1027
1015
testhello_py = join (suite .dir , 'mx.substratevm' , 'testhello.py' )
1028
1016
testhello_args = [
@@ -1031,33 +1019,104 @@ def build_debug_test(variant_name, image_name, extra_args):
1031
1019
'hello.Hello'
1032
1020
]
1033
1021
if mx .get_os () == 'linux' and not build_only :
1034
- os . environ . update ({ 'debuginfotest_arch' : mx .get_arch ()} )
1022
+ env [ 'debuginfotest_arch' ] = mx .get_arch ()
1035
1023
1036
1024
if not with_isolates_only :
1037
1025
hello_binary = build_debug_test ('isolates_off' , 'hello_image' , testhello_args + svm_experimental_options (['-H:-SpawnIsolates' ]))
1038
1026
if mx .get_os () == 'linux' and not build_only :
1039
- os . environ . update ({ 'debuginfotest_isolates' : 'no' })
1040
- mx .run ([ os . environ . get ( 'GDB_BIN' , 'gdb' ), '--nx' , '-q' , '-iex' , 'set pagination off' , '-ex' , 'python "ISOLATES=False"' , '- x' , testhello_py , hello_binary ])
1027
+ env [ 'debuginfotest_isolates' ] = 'no'
1028
+ mx .run (gdb_base_command () + [ '- x' , testhello_py , hello_binary ], env = env )
1041
1029
1042
1030
hello_binary = build_debug_test ('isolates_on' , 'hello_image' , testhello_args + svm_experimental_options (['-H:+SpawnIsolates' ]))
1043
1031
if mx .get_os () == 'linux' and not build_only :
1044
- os . environ . update ({ 'debuginfotest_isolates' : 'yes' })
1045
- mx .run ([ os . environ . get ( 'GDB_BIN' , 'gdb' ), '--nx' , '-q' , '-iex' , 'set pagination off' , '-ex' , 'python "ISOLATES=True"' , '- x' , testhello_py , hello_binary ])
1032
+ env [ 'debuginfotest_isolates' ] = 'yes'
1033
+ mx .run (gdb_base_command () + [ '- x' , testhello_py , hello_binary ], env = env )
1046
1034
1047
1035
1048
- def gdb_base_command (logfile , autoload_path ):
1049
- return [
1050
- os .environ .get ('GDB_BIN' , 'gdb' ),
1051
- '--nx' ,
1052
- '-q' , # do not print the introductory and copyright messages
1053
- '-iex' , 'set pagination off' , # messages from enabling logging could already cause pagination, so this must be done first
1036
+ def _layereddebuginfotest (native_image , output_path , skip_base_layer , with_isolates_only , args ):
1037
+ sourcepath = mx .project ('com.oracle.svm.test' ).source_dirs ()[0 ]
1038
+ cincludepath = sourcepath
1039
+
1040
+ for key , value in get_java_properties ().items ():
1041
+ args .append ("-D" + key + "=" + value )
1042
+
1043
+ # fetch arguments used in all layers
1044
+ testhello_args = testhello_ni_args (cincludepath , sourcepath ) + args
1045
+
1046
+ def build_layer (layer_path , layer_args ):
1047
+ # clean / create layer output directory
1048
+ if exists (layer_path ):
1049
+ mx .rmtree (layer_path )
1050
+ mx_util .ensure_dir_exists (layer_path )
1051
+ # build layer
1052
+ return native_image (testhello_args + layer_args )
1053
+
1054
+ base_layer_path = join (output_path , 'base-layer' )
1055
+ base_layer_name = 'libbase'
1056
+ # Build base layer if missing or not skipped.
1057
+ if not (skip_base_layer and exists (join (base_layer_path , base_layer_name + '.nil' ))):
1058
+ build_layer (base_layer_path , [
1059
+ '-o' , join (base_layer_path , base_layer_name ),
1060
+ ] + svm_experimental_options ([
1061
+ f'-H:LayerCreate={ base_layer_name } .nil,module=java.base,package=com.oracle.svm.test'
1062
+ ]))
1063
+
1064
+ app_layer_path = join (output_path , 'app-layer' )
1065
+ app_layer_name = 'hello_image'
1066
+ # build app layer
1067
+ app_layer = build_layer (app_layer_path , [
1068
+ '-o' , join (app_layer_path , app_layer_name ),
1069
+ # We do not want to step into class initializer, so initialize everything at build time.
1070
+ '--initialize-at-build-time=hello' ,
1071
+ 'hello.Hello'
1072
+ ] + svm_experimental_options ([
1073
+ f'-H:LayerUse={ join (base_layer_path , base_layer_name )} .nil' ,
1074
+ ]))
1075
+
1076
+ # prepare environment
1077
+ env = os .environ .copy ()
1078
+ env ['debuginfotest_isolates' ] = 'yes'
1079
+ env ['debuginfotest_layered' ] = 'yes'
1080
+ env ['LD_LIBRARY_PATH' ] = base_layer_path
1081
+
1082
+ # fetch python test file
1083
+ testhello_py = join (suite .dir , 'mx.substratevm' , 'testhello.py' )
1084
+
1085
+ # run gdb
1086
+ mx .run (gdb_base_command () + ['-x' , testhello_py , app_layer ], cwd = app_layer_path , env = env )
1087
+
1088
+
1089
+ def gdb_logging_command (logfile , autoload_path ):
1090
+ return gdb_base_command () + [
1054
1091
'-iex' , 'set logging redirect on' ,
1055
1092
'-iex' , 'set logging overwrite off' ,
1056
1093
'-iex' , f"set logging file { logfile } " ,
1057
1094
'-iex' , 'set logging enabled on' ,
1058
1095
'-iex' , f"set auto-load safe-path { autoload_path } " ,
1059
1096
]
1060
1097
1098
+ def gdb_base_command ():
1099
+ return [
1100
+ os .environ .get ('GDB_BIN' , 'gdb' ),
1101
+ '--nx' ,
1102
+ '-q' , # do not print the introductory and copyright messages
1103
+ '-iex' , 'set pagination off' , # messages from enabling logging could already cause pagination, so this must be done first
1104
+ ]
1105
+
1106
+ def testhello_ni_args (cincludepath , sourcepath ):
1107
+ return [
1108
+ '-J-ea' , '-J-esa' ,
1109
+ '-g' ,
1110
+ '--native-compiler-options=-I' + cincludepath ,
1111
+ '-H:CLibraryPath=' + sourcepath ,
1112
+ '--native-image-info' ,
1113
+ '-cp' , classpath ('com.oracle.svm.test' ),
1114
+ '-Djdk.graal.LogFile=graal.log' ,
1115
+ '-DbuildDebugInfoTestExample=true' , # set property controlling inclusion of foreign struct header
1116
+ ] + svm_experimental_options ([
1117
+ '-H:+SourceLevelDebug' ,
1118
+ '-H:DebugInfoSourceSearchPath=' + sourcepath ,
1119
+ ])
1061
1120
1062
1121
def _gdbdebughelperstest (native_image , path , with_isolates_only , args ):
1063
1122
@@ -1124,7 +1183,7 @@ def run_debug_test(image_name: str, testfile: str, source_path: str, with_isolat
1124
1183
'-H:CLibraryPath=' + source_path ,
1125
1184
'--native-image-info' ,
1126
1185
'-Djdk.graal.LogFile=graal.log' ,
1127
- '-g' , '-O0' ,
1186
+ '-g' ,
1128
1187
] + svm_experimental_options ([
1129
1188
'-H:+VerifyNamingConventions' ,
1130
1189
'-H:+SourceLevelDebug' ,
@@ -1160,7 +1219,7 @@ def run_debug_test(image_name: str, testfile: str, source_path: str, with_isolat
1160
1219
if mx .get_os () == 'linux' :
1161
1220
logfile = join (path , pathlib .Path (testfile ).stem + ('' if with_isolates else '_no_isolates' ) + '.log' )
1162
1221
os .environ .update ({'gdb_logfile' : logfile })
1163
- gdb_command = gdb_base_command (logfile , join (build_dir , 'gdb-debughelpers.py' )) + [
1222
+ gdb_command = gdb_logging_command (logfile , join (build_dir , 'gdb-debughelpers.py' )) + [
1164
1223
'-x' , testfile , join (build_dir , image_name )
1165
1224
]
1166
1225
# unittest may result in different exit code, nonZeroIsFatal ensures that we can go on with other test
@@ -1209,7 +1268,7 @@ def _runtimedebuginfotest(native_image, output_path, with_isolates_only, args=No
1209
1268
1210
1269
# Build the native image from Java code
1211
1270
build_args = [
1212
- '-g' , '-O0' ,
1271
+ '-g' ,
1213
1272
# set property controlling inclusion of foreign struct header
1214
1273
'-DbuildDebugInfoTestExample=true' ,
1215
1274
'--native-compiler-options=-I' + test_source_path ,
@@ -1230,7 +1289,7 @@ def _runtimedebuginfotest(native_image, output_path, with_isolates_only, args=No
1230
1289
1231
1290
logfile = join (output_path , 'test_runtime_compilation.log' )
1232
1291
os .environ .update ({'gdb_logfile' : logfile })
1233
- gdb_command = gdb_base_command (logfile , join (output_path , 'gdb-debughelpers.py' )) + [
1292
+ gdb_command = gdb_logging_command (logfile , join (output_path , 'gdb-debughelpers.py' )) + [
1234
1293
'-x' , test_runtime_compilation_py , runtime_compile_binary
1235
1294
]
1236
1295
# unittest may result in different exit code, nonZeroIsFatal ensures that we can go on with other test
@@ -1244,12 +1303,12 @@ def run_js_test(eager: bool = False):
1244
1303
'-H:+RuntimeDebugInfo' ,
1245
1304
'-H:-LazyDeoptimization' if eager else '-H:+LazyDeoptimization' ,
1246
1305
]) +
1247
- ['-g' , '-O0' , '- -macro:jsvm-library' ]
1306
+ ['-g' , '--macro:jsvm-library' ]
1248
1307
))
1249
1308
js_launcher = get_js_launcher (jslib )
1250
1309
logfile = join (output_path , 'test_runtime_deopt_' + ('eager' if eager else 'lazy' ) + '.log' )
1251
1310
os .environ .update ({'gdb_logfile' : logfile })
1252
- gdb_command = gdb_base_command (logfile , join (output_path , 'gdb-debughelpers.py' )) + [
1311
+ gdb_command = gdb_logging_command (logfile , join (output_path , 'gdb-debughelpers.py' )) + [
1253
1312
'-x' , test_runtime_deopt_py , '--args' , js_launcher , testdeopt_js
1254
1313
]
1255
1314
# unittest may result in different exit code, nonZeroIsFatal ensures that we can go on with other test
@@ -1813,6 +1872,30 @@ def debuginfotest(args, config=None):
1813
1872
config = config
1814
1873
)
1815
1874
1875
+ @mx .command (suite_name = suite .name , command_name = 'layereddebuginfotest' , usage_msg = '[options]' )
1876
+ def layereddebuginfotest (args , config = None ):
1877
+ """
1878
+ Builds a layered native image and tests it with gdb.
1879
+ Base layer: java.base, com.oracle.svm.test
1880
+ App Layer: hello.Hello
1881
+ """
1882
+ parser = ArgumentParser (prog = 'mx layereddebuginfotest' )
1883
+ all_args = ['--output-path' , '--skip-base-layer' , '--with-isolates-only' ]
1884
+ masked_args = [_mask (arg , all_args ) for arg in args ]
1885
+ parser .add_argument (all_args [0 ], metavar = '<output-path>' , nargs = 1 , help = 'Path of the generated image' , default = [join (svmbuild_dir (), "layereddebuginfotest" )])
1886
+ parser .add_argument (all_args [1 ], action = 'store_true' , help = 'Skip building the base layer if it already exists' )
1887
+ parser .add_argument (all_args [2 ], action = 'store_true' , help = 'Only build and test the native image with isolates' )
1888
+ parser .add_argument ('image_args' , nargs = '*' , default = [])
1889
+ parsed = parser .parse_args (masked_args )
1890
+ output_path = unmask (parsed .output_path )[0 ]
1891
+ skip_base_layer = parsed .skip_base_layer
1892
+ with_isolates_only = parsed .with_isolates_only
1893
+ native_image_context_run (
1894
+ lambda native_image , a :
1895
+ _layereddebuginfotest (native_image , output_path , skip_base_layer , with_isolates_only , a ), unmask (parsed .image_args ),
1896
+ config = config
1897
+ )
1898
+
1816
1899
@mx .command (suite_name = suite .name , command_name = 'debuginfotestshared' , usage_msg = '[options]' )
1817
1900
def debuginfotestshared (args , config = None ):
1818
1901
"""
@@ -2424,15 +2507,8 @@ def native_image_on_jvm(args, **kwargs):
2424
2507
if not exists (executable ):
2425
2508
mx .abort ("Can not find " + executable + "\n Did you forget to build? Try `mx build`" )
2426
2509
2427
- javaProperties = {}
2428
- for dist in suite .dists :
2429
- if isinstance (dist , mx .ClasspathDependency ):
2430
- for cpEntry in mx .classpath_entries (dist ):
2431
- if hasattr (cpEntry , "getJavaProperties" ):
2432
- for key , value in cpEntry .getJavaProperties ().items ():
2433
- javaProperties [key ] = value
2434
2510
if not any (arg .startswith ('--help' ) or arg == '--version' for arg in args ):
2435
- for key , value in javaProperties .items ():
2511
+ for key , value in get_java_properties () .items ():
2436
2512
args .append ("-D" + key + "=" + value )
2437
2513
2438
2514
jacoco_args = mx_gate .get_jacoco_agent_args (agent_option_prefix = '-J' )
0 commit comments