Skip to content

Commit 73b3023

Browse files
committed
[GR-19890] Set up build environments for Windows users.
PullRequest: graal/13666
2 parents e170267 + 602bba6 commit 73b3023

File tree

9 files changed

+159
-13
lines changed

9 files changed

+159
-13
lines changed

docs/getting-started/graalvm-community/windows.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,4 @@ There are two installation options:
6060
- Install the Visual Studio Build Tools with the Windows 10 SDK
6161
- Install Visual Studio with the Windows 10 SDK
6262

63-
The last prerequisite is the proper [Developer Command Prompt](https://docs.microsoft.com/en-us/cpp/build/building-on-the-command-line?view=vs-2019#developer_command_prompt_shortcuts) for your version of [Visual Studio](https://visualstudio.microsoft.com/vs/).
64-
On Windows, the `native-image` tool only works when it is executed from the **x64 Native Tools Command Prompt**.
65-
6663
Step-by-step instructions on installing Visual Studio Build Tools and Windows 10 SDK, and starting using Native Image can be found [here](https://medium.com/graalvm/using-graalvm-and-native-image-on-windows-10-9954dc071311).

docs/getting-started/graalvm-enterprise/installation-windows.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,4 @@ There are two installation options:
5555
- Install the Visual Studio Build Tools with the Windows 10 SDK
5656
- Install Visual Studio with the Windows 10 SDK
5757

58-
The last prerequisite is the proper [Developer Command Prompt](https://docs.microsoft.com/en-us/cpp/build/building-on-the-command-line?view=vs-2019#developer_command_prompt_shortcuts) for your version of [Visual Studio](https://visualstudio.microsoft.com/vs/).
59-
On Windows the `native-image` tool only works when it is executed from the **x64 Native Tools Command Prompt**.
60-
6158
Step by step instructions on installing Visual Studio Build Tools and Windows 10 SDK, and starting using Native Image can be found [here](https://medium.com/graalvm/using-graalvm-and-native-image-on-windows-10-9954dc071311).

docs/reference-manual/native-image/FAQ.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ Everything that is included in a product (GraalVM Native Image) or produced by a
2020

2121
### Native Image doesn't work on my Windows 10?
2222

23-
Make sure you execute the `native-image` command from the **x64 Native Tools Command Prompt**.
24-
This is the prerequisite for Windows: installing [Visual Studio](https://visualstudio.microsoft.com/vs/) and Microsoft Visual C++ (MSVC) with the Windows 10 SDK.
23+
Please make sure [Visual Studio](https://visualstudio.microsoft.com/vs/) and Microsoft Visual C++ (MSVC) with the Windows 10 SDK are installed on your system.
2524
You can use Visual Studio 2017 version 15.9 or later.
2625

2726
Check [this link](https://medium.com/graalvm/using-graalvm-and-native-image-on-windows-10-9954dc071311) for more information and step-by-step instructions.

docs/reference-manual/native-image/README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,7 @@ There are two installation options:
9393
9494
You can use Visual Studio 2017 version 15.9 or later.
9595
96-
The `native-image` builder will only work when it is run from the **x64 Native Tools Command Prompt**.
97-
The command for initiating an x64 Native Tools command prompt varies according to whether you only have the Visual Studio Build Tools installed or if you have the full Visual Studio 2019 installed. For more information, see [Using GraalVM and Native Image on Windows 10](https://medium.com/graalvm/using-graalvm-and-native-image-on-windows-10-9954dc071311). -->
96+
For more information, see [Using GraalVM and Native Image on Windows 10](https://medium.com/graalvm/using-graalvm-and-native-image-on-windows-10-9954dc071311). -->
9897

9998
## Build a Native Executable
10099

docs/tools/vscode/graalvm/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ If you use the Micronaut framework to create your Java project, you can build a
233233
### Building Native Images on Windows
234234

235235
To use Native Image on Windows, you need Visual Studio Build Tools with Windows SDK installed.
236-
The `native-image` builder only works when it is executed from the **x64 Native Tools Command Prompt**. Check [this link](https://medium.com/graalvm/using-graalvm-and-native-image-on-windows-10-9954dc071311) for more details.
236+
Check [this link](https://medium.com/graalvm/using-graalvm-and-native-image-on-windows-10-9954dc071311) for more details.
237237

238238
For Windows users, the extension provides a pre-configured x64 command prompt using Microsoft Developer Tools. Assuming you already have Visual Studio Build Tools with Windows SDK, GraalVM with Native Image installed, and opened your Java project in VS Code.
239239

docs/tools/vscode/micronaut/README.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,6 @@ For more information, visit the [Micronaut documentation](https://guides.microna
171171

172172
### Windows Users
173173

174-
On Windows the `native-image` builder will only work when it is executed from the **x64 Native Tools Command Prompt**.
175-
176174
For Micronaut users targeting GraalVM Native Image for their Micronaut applications, the extension provides a dedicated **x64 command prompt using Microsoft Developer Tools**.
177175
You can check it by invoking the **Micronaut: Build Native Image** task from Command Palette.
178176
Notice which shell is active:

substratevm/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ This changelog summarizes major changes to GraalVM Native Image.
1515
* (GR-41912) The builder now generated reports for internal errors, which users can share when creating issues. By default, error reports follow the `svm_err_b_<timestamp>_pid<pid>.md` pattern and are created in the working directory. Use `-H:ErrorFile` to adjust the path or filename.
1616
* (GR-36951) Add [RISC-V support](https://medium.com/p/899be38eddd9) for Native Image through the LLVM backend.
1717
* (GR-42964) Deprecate `--enable-monitoring` without an argument. The option will no longer default to `all` in a future release. Instead, please always explicitly specify the list of monitoring features to be enabled (for example, `--enable-monitoring=heapdump,jfr,jvmstat`").
18+
* (GR-19890) Native Image now sets up build environments for Windows users automatically. Running in an x64 Native Tools Command Prompt is no longer a requirement.
1819

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

substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1428,6 +1428,9 @@ protected int buildImage(List<String> javaArgs, LinkedHashSet<Path> cp, LinkedHa
14281428
ProcessBuilder pb = new ProcessBuilder();
14291429
pb.command(command);
14301430
pb.environment().put(ModuleSupport.ENV_VAR_USE_MODULE_SYSTEM, Boolean.toString(config.modulePathBuild));
1431+
if (OS.getCurrent() == OS.WINDOWS) {
1432+
WindowsBuildEnvironmentUtil.propagateEnv(pb.environment());
1433+
}
14311434
sanitizeJVMEnvironment(pb.environment());
14321435
p = pb.inheritIO().start();
14331436
imageBuilderPid = p.pid();
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
/*
2+
* Copyright (c) 2023, 2023, 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.driver;
26+
27+
import java.io.BufferedReader;
28+
import java.io.IOException;
29+
import java.io.InputStreamReader;
30+
import java.nio.file.Files;
31+
import java.nio.file.Path;
32+
import java.nio.file.Paths;
33+
import java.util.Comparator;
34+
import java.util.HashMap;
35+
import java.util.List;
36+
import java.util.Map;
37+
import java.util.function.BiConsumer;
38+
import java.util.stream.Stream;
39+
40+
/**
41+
* This utility helps set up a build environment for Windows users automatically.
42+
*/
43+
class WindowsBuildEnvironmentUtil {
44+
private static final String VSINSTALLDIR_ENV = "VSINSTALLDIR";
45+
private static final Path[] KNOWN_VS_LOCATIONS = {
46+
Paths.get("C:", "Program Files", "Microsoft Visual Studio"),
47+
// prefer x64 location over x86
48+
Paths.get("C:", "Program Files (x86)", "Microsoft Visual Studio")};
49+
private static final String[] KNOWN_VS_EDITIONS = {
50+
// prefer Enterprise over Professional over Community
51+
"Enterprise", "Professional", "Community"};
52+
private static final String VCVARSALL = "vcvarsall.bat";
53+
private static final Path VCVARSALL_SUBPATH = Paths.get("VC", "Auxiliary", "Build", VCVARSALL);
54+
private static final String OUTPUT_SEPARATOR = "!NEXTCOMMAND!";
55+
56+
static void propagateEnv(Map<String, String> environment) {
57+
if (isCCompilerOnPath()) {
58+
return; // nothing to do, build environment initialized by user
59+
}
60+
Path vcVarsAllLocation = null;
61+
for (Path visualStudioLocation : KNOWN_VS_LOCATIONS) {
62+
if (!Files.isDirectory(visualStudioLocation)) {
63+
continue;
64+
}
65+
List<Path> installationCandidates;
66+
try (Stream<Path> pathStream = Files.list(visualStudioLocation)) {
67+
installationCandidates = pathStream
68+
// only keep sub-directories matching 20\d\d
69+
.filter(p -> p.toFile().getName().matches("20\\d\\d"))
70+
// sort years
71+
.sorted(Comparator.comparing(p -> p.toFile().getName()))
72+
// reverse order to ensure latest year is first
73+
.sorted(Comparator.reverseOrder())
74+
.toList();
75+
} catch (IOException e) {
76+
throw fail("Failed to traverse known Visual Studio locations.", e);
77+
}
78+
for (Path installation : installationCandidates) {
79+
for (String edition : KNOWN_VS_EDITIONS) {
80+
Path possibleLocation = installation.resolve(edition).resolve(VCVARSALL_SUBPATH);
81+
if (Files.isRegularFile(possibleLocation) && Files.isReadable(possibleLocation)) {
82+
vcVarsAllLocation = possibleLocation;
83+
break;
84+
}
85+
}
86+
}
87+
}
88+
if (vcVarsAllLocation == null) {
89+
throw fail(String.format("Failed to find '%s' in a Visual Studio installation.", VCVARSALL));
90+
}
91+
Map<String, String> originalEnv = new HashMap<>();
92+
int numSeenOutputSeparators = 0;
93+
try {
94+
// call `set`, then `vcvarsall.bat`, and then `set` again with separators in between
95+
String commandSequence = String.format("cmd.exe /c set && echo %s && \"%s\" x64 && echo %s && set",
96+
OUTPUT_SEPARATOR, vcVarsAllLocation, OUTPUT_SEPARATOR);
97+
Process p = Runtime.getRuntime().exec(new String[]{"cmd.exe", "/c", commandSequence});
98+
try (BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
99+
String line = null;
100+
while ((line = reader.readLine()) != null) {
101+
if (line.startsWith(OUTPUT_SEPARATOR)) {
102+
numSeenOutputSeparators++;
103+
} else if (numSeenOutputSeparators == 0) {
104+
// collect environment variables from 1st `set` invocation
105+
processLineWithKeyValue(line, (key, value) -> originalEnv.put(key, value));
106+
} else if (numSeenOutputSeparators == 2) {
107+
// iterate through updated environment variables from 2nd `set` invocation
108+
processLineWithKeyValue(line, (key, value) -> {
109+
boolean isNewOrModifiedEnvVar = !originalEnv.getOrDefault(key, "").equals(value);
110+
if (isNewOrModifiedEnvVar) {
111+
environment.put(key, value);
112+
}
113+
});
114+
}
115+
}
116+
}
117+
p.waitFor();
118+
} catch (IOException | InterruptedException e) {
119+
throw fail("Failed to detect variables of Windows build environment.", e);
120+
}
121+
if (!environment.containsKey(VSINSTALLDIR_ENV)) {
122+
throw fail("Failed to automatically set up Windows build environment.");
123+
}
124+
}
125+
126+
private static boolean isCCompilerOnPath() {
127+
try {
128+
return Runtime.getRuntime().exec(new String[]{"cmd.exe", "/c", "where", "cl.exe"}).waitFor() == 0;
129+
} catch (IOException | InterruptedException e) {
130+
throw NativeImage.showError("Failed to check for 'cl.exe'.", e);
131+
}
132+
}
133+
134+
private static void processLineWithKeyValue(String line, BiConsumer<String, String> consumeKeyValue) {
135+
String[] parts = line.split("=");
136+
if (parts.length == 2) {
137+
consumeKeyValue.accept(parts[0], parts[1]);
138+
}
139+
}
140+
141+
private static Error fail(String reason) {
142+
return fail(reason, null);
143+
}
144+
145+
private static Error fail(String reason, Throwable e) {
146+
throw NativeImage.showError(reason + System.lineSeparator() +
147+
"Please make sure that Visual Studio 2017 version 15.5 or later (C/C++ Optimizing Compiler Version 19.12 or later) is installed on your system. " +
148+
"You can download it at https://visualstudio.microsoft.com/downloads/. " +
149+
"If this error persists, please try and run GraalVM Native Image in an x64 Native Tools Command Prompt or file a ticket.",
150+
e);
151+
}
152+
}

0 commit comments

Comments
 (0)