Skip to content

Commit fa72b96

Browse files
committed
Introduce -H:±GenerateBuildArtifactsFile option.
and deprecate `.build_artifacts.txt` files.
1 parent 269467d commit fa72b96

File tree

10 files changed

+287
-55
lines changed

10 files changed

+287
-55
lines changed
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
{
2+
"$id": "https://github.com/oracle/graal/blob/master/docs/reference-manual/native-image/assets/build-artifacts-schema-v0.9.0.json",
3+
"$schema": "https://json-schema.org/draft/2019-09/schema",
4+
"default": {},
5+
"examples": [
6+
{
7+
"build_info": [
8+
"build-output.json"
9+
],
10+
"debug_info": [
11+
"helloworld",
12+
"sources"
13+
],
14+
"executables": [
15+
"helloworld"
16+
]
17+
}
18+
],
19+
"properties": {
20+
"build_info": {
21+
"default": [],
22+
"items": {
23+
"format": "uri-reference",
24+
"title": "Relative path to file or directory",
25+
"type": "string"
26+
},
27+
"title": "Build information generated by Native Image (not needed at run-time)",
28+
"type": "array"
29+
},
30+
"c_headers": {
31+
"default": [],
32+
"items": {
33+
"format": "uri-reference",
34+
"title": "Relative path to file or directory",
35+
"type": "string"
36+
},
37+
"title": "C header files generated by Native Image (not needed at run-time)",
38+
"type": "array"
39+
},
40+
"debug_info": {
41+
"default": [],
42+
"items": {
43+
"format": "uri-reference",
44+
"title": "Relative path to file or directory",
45+
"type": "string"
46+
},
47+
"title": "Debug information generated by Native Image (not needed at run-time)",
48+
"type": "array"
49+
},
50+
"executables": {
51+
"default": [],
52+
"items": {
53+
"format": "uri-reference",
54+
"title": "Relative path to file or directory",
55+
"type": "string"
56+
},
57+
"title": "Executables generated by Native Image (needed at run-time)",
58+
"type": "array"
59+
},
60+
"import_libraries": {
61+
"default": [],
62+
"items": {
63+
"format": "uri-reference",
64+
"title": "Relative path to file or directory",
65+
"type": "string"
66+
},
67+
"title": "Import libraries generated by Native Image (not needed at run-time)",
68+
"type": "array"
69+
},
70+
"jdk_libraries": {
71+
"default": [],
72+
"items": {
73+
"format": "uri-reference",
74+
"title": "Relative path to file or directory",
75+
"type": "string"
76+
},
77+
"title": "JDK libraries copied by Native Image (needed at run-time)",
78+
"type": "array"
79+
},
80+
"language_home": {
81+
"default": [],
82+
"items": {
83+
"format": "uri-reference",
84+
"title": "Relative path to file or directory",
85+
"type": "string"
86+
},
87+
"title": "Language home artifacts for Truffle languages (needed at run-time)",
88+
"type": "array"
89+
},
90+
"shared_libraries": {
91+
"default": [],
92+
"items": {
93+
"format": "uri-reference",
94+
"title": "Relative path to file or directory",
95+
"type": "string"
96+
},
97+
"title": "Shared libraries generated by Native Image (not needed at run-time)",
98+
"type": "array"
99+
}
100+
},
101+
"required": [],
102+
"title": "JSON schema for the build artifacts of GraalVM Native Image",
103+
"type": "object"
104+
}

substratevm/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ This changelog summarizes major changes to GraalVM Native Image.
99
* (GR-41674) Class instanceOf and isAssignableFrom checks do need to make the checked type reachable.
1010
* (GR-41100) Add support for `-XX:HeapDumpPath` to control where heap dumps are created.
1111
* (GR-42148) Adjust build output to report types (primitives, classes, interfaces, and arrays) instead of classes and revise the output schema of `-H:BuildOutputJSONFile`.
12+
* (GR-42375) Add `-H:±GenerateBuildArtifactsFile` option, which generates a `build-artifacts.json` file with a list of all artifacts produced by Native Image. `.build_artifacts.txt` files are now deprecated, disabled (can be re-enabled with env setting `NATIVE_IMAGE_DEPRECATED_BUILD_ARTIFACTS_TXT=true`), and will be removed in a future release.
1213

1314
## Version 22.3.0
1415
* (GR-35721) Remove old build output style and the `-H:±BuildOutputUseNewStyle` option.

substratevm/mx.substratevm/mx_substratevm.py

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -415,28 +415,35 @@ def help_stdout_check(output):
415415
if t:
416416
hellomodule(args.extra_image_builder_arguments)
417417

418-
with Task('Validate JSON build output', tasks, tags=[mx_gate.Tags.style]) as t:
418+
with Task('Validate JSON build info', tasks, tags=[mx_gate.Tags.style]) as t:
419419
if t:
420420
import json
421421
try:
422422
from jsonschema import validate as json_validate
423423
from jsonschema.exceptions import ValidationError, SchemaError
424424
except ImportError:
425425
mx.abort('Unable to import jsonschema')
426+
with open(join(suite.dir, '..', 'docs', 'reference-manual', 'native-image', 'assets', 'build-artifacts-schema-v0.9.0.json')) as f:
427+
build_artifacts_schema = json.load(f)
426428
with open(join(suite.dir, '..', 'docs', 'reference-manual', 'native-image', 'assets', 'build-output-schema-v0.9.1.json')) as f:
427-
json_schema = json.load(f)
428-
with tempfile.NamedTemporaryFile(prefix='build_json') as json_file:
429-
helloworld(['--output-path', svmbuild_dir(), f'-H:BuildOutputJSONFile={json_file.name}'])
430-
try:
431-
with open(json_file.name) as f:
429+
build_output_schema = json.load(f)
430+
with tempfile.NamedTemporaryFile(prefix='build_json') as build_output_json:
431+
helloworld(['--output-path', svmbuild_dir(), f'-H:BuildOutputJSONFile={build_output_json.name}', '-H:+GenerateBuildArtifactsFile'])
432+
json_file_and_schema_pairs = [
433+
(build_output_json.name, build_output_schema),
434+
(join(svmbuild_dir(), 'build-artifacts.json'), build_artifacts_schema)
435+
]
436+
try:
437+
for file_name, schema in json_file_and_schema_pairs:
438+
with open(file_name) as f:
432439
json_output = json.load(f)
433-
json_validate(json_output, json_schema)
434-
except IOError as e:
435-
mx.abort(f'Unable to load JSON build output: {e}')
436-
except ValidationError as e:
437-
mx.abort(f'Unable to validate JSON build output against the schema: {e}')
438-
except SchemaError as e:
439-
mx.abort(f'JSON schema not valid: {e}')
440+
json_validate(json_output, schema)
441+
except IOError as e:
442+
mx.abort(f'Unable to load JSON build info: {e}')
443+
except ValidationError as e:
444+
mx.abort(f'Unable to validate JSON build info against the schema: {e}')
445+
except SchemaError as e:
446+
mx.abort(f'JSON schema not valid: {e}')
440447

441448

442449
def native_unittests_task(extra_build_args=None):

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/BuildArtifacts.java

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -30,15 +30,50 @@
3030

3131
/** Interface for collecting artifacts produced during native image build. */
3232
public interface BuildArtifacts {
33+
34+
/**
35+
* Artifact types generated by Native Image. Changing this enum requires updating the
36+
* corresponding JSON schema (see {@code SubstrateOptions#GenerateBuildArtifactsFile}).
37+
*/
3338
enum ArtifactType {
34-
EXECUTABLE,
35-
SHARED_LIB,
36-
JDK_LIB,
37-
JDK_LIB_SHIM,
38-
HEADER,
39-
IMPORT_LIB,
40-
DEBUG_INFO,
41-
LANGUAGE_HOME,
39+
/* RUN-TIME-CRITICAL ARTIFACTS: */
40+
41+
/* For all executables needed at run-time. */
42+
EXECUTABLE("executables"),
43+
/* For all shared libraries that are not JDK-related and needed at run-time. */
44+
SHARED_LIBRARY("shared_libraries"),
45+
46+
/* For all shared libraries from the JDK needed at run-time. */
47+
JDK_LIBRARY("jdk_libraries"),
48+
/* For all library shims for the JDK needed at run-time. */
49+
JDK_LIBRARY_SHIM(JDK_LIBRARY.getJsonKey()), // distinction should not be important to users.
50+
51+
/* Language home artifacts for Truffle languages needed at run-time. */
52+
LANGUAGE_HOME("language_home"),
53+
54+
/* ARTIFACTS NOT NEEDED AT RUN-TIME: */
55+
56+
/*
57+
* For all artifacts from image generator (e.g., build statistics, lists, call trees, ...).
58+
*/
59+
BUILD_INFO("build_info"),
60+
/* For all debugging-related artifacts. */
61+
DEBUG_INFO("debug_info"),
62+
63+
/* For C header files. */
64+
C_HEADER("c_headers"),
65+
/* For all import libraries. */
66+
IMPORT_LIBRARY("import_libraries");
67+
68+
private final String jsonKey;
69+
70+
ArtifactType(String jsonKey) {
71+
this.jsonKey = jsonKey;
72+
}
73+
74+
public String getJsonKey() {
75+
return jsonKey;
76+
}
4277
}
4378

4479
static BuildArtifacts singleton() {

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,11 @@ public Boolean getValue(OptionValues values) {
414414
@Option(help = "Alignment of AOT and JIT compiled code in bytes.")//
415415
public static final HostedOptionKey<Integer> CodeAlignment = new HostedOptionKey<>(16);
416416

417+
public static final String BUILD_ARTIFACTS_FILE_NAME = "build-artifacts.json";
418+
@Option(help = "Create a " + BUILD_ARTIFACTS_FILE_NAME + " file in the build directory. The output conforms to the JSON schema located at: " +
419+
"docs/reference-manual/native-image/assets/build-artifacts-schema-v0.9.0.json", type = OptionType.User)//
420+
public static final HostedOptionKey<Boolean> GenerateBuildArtifactsFile = new HostedOptionKey<>(false);
421+
417422
/*
418423
* Build output options.
419424
*/
@@ -440,7 +445,7 @@ public Boolean getValue(OptionValues values) {
440445
public static final HostedOptionKey<Boolean> BuildOutputGCWarnings = new HostedOptionKey<>(true);
441446

442447
@Option(help = "Print build output statistics as JSON to the specified file. " +
443-
"The output is according to the JSON schema located at: " +
448+
"The output conforms to the JSON schema located at: " +
444449
"docs/reference-manual/native-image/assets/build-output-schema-v0.9.1.json", type = OptionType.User)//
445450
public static final HostedOptionKey<String> BuildOutputJSONFile = new HostedOptionKey<>("");
446451

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
* Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.oracle.svm.hosted;
26+
27+
import java.io.IOException;
28+
import java.io.PrintWriter;
29+
import java.nio.file.Path;
30+
import java.util.Collection;
31+
import java.util.Comparator;
32+
import java.util.List;
33+
import java.util.Map;
34+
import java.util.function.Consumer;
35+
36+
import com.oracle.graal.pointsto.reports.ReportUtils;
37+
import com.oracle.svm.core.BuildArtifacts;
38+
import com.oracle.svm.core.BuildArtifacts.ArtifactType;
39+
import com.oracle.svm.core.SubstrateOptions;
40+
import com.oracle.svm.core.option.HostedOptionValues;
41+
import com.oracle.svm.core.util.VMError;
42+
import com.oracle.svm.core.util.json.JsonPrinter;
43+
import com.oracle.svm.core.util.json.JsonWriter;
44+
45+
public class BuildArtifactsExporter {
46+
private static final String ENV_VAR_REENABLE_DEPRECATED = "NATIVE_IMAGE_DEPRECATED_BUILD_ARTIFACTS_TXT";
47+
48+
public static void run(String imageName, BuildArtifacts buildArtifacts, Map<ArtifactType, List<Path>> buildArtifactsMap) {
49+
run(buildArtifacts, buildArtifactsMap);
50+
if ("true".equalsIgnoreCase(System.getenv().get(ENV_VAR_REENABLE_DEPRECATED))) {
51+
reportDeprecatedBuildArtifacts(imageName, buildArtifacts, buildArtifactsMap);
52+
}
53+
}
54+
55+
private static void run(BuildArtifacts buildArtifacts, Map<ArtifactType, List<Path>> buildArtifactsMap) {
56+
if (buildArtifactsMap.isEmpty() || !SubstrateOptions.GenerateBuildArtifactsFile.getValue()) {
57+
return; // nothing to do
58+
}
59+
Path buildPath = NativeImageGenerator.generatedFiles(HostedOptionValues.singleton());
60+
Path targetPath = buildPath.resolve(SubstrateOptions.BUILD_ARTIFACTS_FILE_NAME);
61+
try (JsonWriter writer = new JsonWriter(targetPath)) {
62+
writer.append('{');
63+
var iterator = buildArtifactsMap.entrySet().iterator();
64+
while (iterator.hasNext()) {
65+
var entry = iterator.next();
66+
writer.quote(entry.getKey().getJsonKey()).append(":");
67+
JsonPrinter.printCollection(writer, (Collection<Path>) entry.getValue(), Comparator.naturalOrder(), (p, w) -> w.quote(buildPath.relativize(p.toAbsolutePath()).toString()));
68+
if (iterator.hasNext()) {
69+
writer.append(',');
70+
}
71+
}
72+
writer.append('}');
73+
buildArtifacts.add(ArtifactType.BUILD_INFO, targetPath);
74+
} catch (IOException e) {
75+
throw VMError.shouldNotReachHere("Unable to create " + SubstrateOptions.BUILD_ARTIFACTS_FILE_NAME, e);
76+
}
77+
}
78+
79+
private static void reportDeprecatedBuildArtifacts(String imageName, BuildArtifacts buildArtifacts, Map<ArtifactType, List<Path>> buildArtifactsMap) {
80+
Path buildDir = NativeImageGenerator.generatedFiles(HostedOptionValues.singleton());
81+
Consumer<PrintWriter> writerConsumer = writer -> buildArtifactsMap.forEach((artifactType, paths) -> {
82+
writer.println("[" + artifactType + "]");
83+
if (artifactType == BuildArtifacts.ArtifactType.JDK_LIBRARY_SHIM) {
84+
writer.println("# Note that shim JDK libraries depend on this");
85+
writer.println("# particular native image (including its name)");
86+
writer.println("# and therefore cannot be used with others.");
87+
}
88+
paths.stream().map(Path::toAbsolutePath).map(buildDir::relativize).forEach(writer::println);
89+
writer.println();
90+
});
91+
buildArtifacts.add(ArtifactType.BUILD_INFO, ReportUtils.report("build artifacts", buildDir.resolve(imageName + ".build_artifacts.txt"), writerConsumer, false));
92+
}
93+
}

0 commit comments

Comments
 (0)