Skip to content

Commit 4bd9297

Browse files
authored
[build] Don't use ls(1) to find JDK paths (#314)
Fixes: dotnet/android#1493 On some machines, `make prepare` fails: build-tools/scripts/jdk.mk:130: *** missing separator. Stop. make: *** [prepare-external] Error 2 Eventually, we "found" the "cause": This make fragment: $(shell ls -dtr $(_DARWIN_JDK_FALLBACK_DIRS) | sort | tail -1) was dying a terrible horrible no good death: _DARWIN_JDK_ROOT=/Library/Java/JavaVirtualMachines/jdk1.8.0_161.jdk kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkin/sh: 49m: command not found [Turns Out™][0], **ls**(1) should be *avoided*, as its output is *unsafe* (I'm not sure *why*, and I'm not able to repro the above failure on my machine, but it's *clearly* bad). [0]: http://mywiki.wooledge.org/ParsingLs Why are we using **ls**(1)? To sort by timestamp, via `ls -dtr`. What's the recommended replacement? > If you truly need a list of all the files in a directory in order > by mtime so that you can process them in sequence, switch to perl, > and have your perl program do its own directory opening and sorting LOL? Which brings us to the solution: we don't want to use Perl -- we *want* something plausibly cross-platform -- so let's use our existing cross-platform dependency: MSBuild! Update the `<JdkInfo/>` task so that in addition to probing a variety of Windows-specific registry locations, it can now do `jdk.mk`-style directory probing, allowing us to find the maximum installed JDK version which is (optionally) less than `$(JI_MAX_JDK)`. Additionally, further enhance `<JdkInfo/>` so that it will *also* check `$JAVA_HOME` and execute the following command: java -XshowSettings:properties -version 2>&1 | grep java.home `$JAVA_HOME` is preferred, if specified and it fulfills the requirements of `$(JI_MAX_JDK)`. Additionally, drastically simplify `jdk.mk`. Instead of computing the desired JDK directory *on every build*, instead generate a new `bin/Build$(CONFIGURATION)/JdkInfo.mk` file which contains the JDK informatino. The `make prepare` target will generate this file. This approach simplifes `jdk.mk` -- trying to maintain it was beginning to give me a headache, so as part of this we're dropping support for 32-bit JVMs on macOS, as if anyone uses those -- and also brings the macOS/Linux build closer-in-spirit to Windows, which was already using the `<JdkInfo/>` task.
1 parent 0418d22 commit 4bd9297

File tree

7 files changed

+305
-206
lines changed

7 files changed

+305
-206
lines changed

Makefile

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,15 @@ xa-all: $(PACKAGES) $(XA_INTEGRATION_OUTPUTS)
5353

5454
run-all-tests: run-tests run-test-jnimarshal run-test-generator-core run-ptests
5555

56-
prepare:: prepare-external
56+
include build-tools/scripts/msbuild.mk
57+
58+
prepare:: prepare-bootstrap prepare-external
59+
60+
prepare-bootstrap: bin/Build$(CONFIGURATION)/Java.Interop.BootstrapTasks.dll
61+
62+
bin/Build$(CONFIGURATION)/Java.Interop.BootstrapTasks.dll: src/Java.Interop.BootstrapTasks/Java.Interop.BootstrapTasks.csproj \
63+
$(wildcard src/Java.Interop.BootstrapTasks/Java.Interop.BootstrapTasks/*.cs)
64+
$(MSBUILD) $(MSBUILD_FLAGS) src/Java.Interop.BootstrapTasks/Java.Interop.BootstrapTasks.csproj
5765

5866
prepare-external: $(PACKAGES) $(NUNIT_CONSOLE)
5967
git submodule update --init --recursive
@@ -65,7 +73,6 @@ clean:
6573

6674
include build-tools/scripts/mono.mk
6775
include build-tools/scripts/jdk.mk
68-
include build-tools/scripts/msbuild.mk
6976

7077
$(PACKAGES) $(NUNIT_CONSOLE):
7178
nuget restore

build-tools/scripts/PrepareWindows.targets

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,12 @@
1919
DestinationFiles="$(_NuGet)"
2020
/>
2121
<Exec Command="$(_NuGet) restore Java.Interop.sln" WorkingDirectory="$(_TopDir)" />
22-
<JdkInfo Output="$(_TopDir)\bin\Build$(Configuration)\JdkInfo.props">
23-
<Output TaskParameter="JavaSdkDirectory" PropertyName="_JavaSdkDirectory" />
22+
<JdkInfo
23+
JdksRoot="$(ProgramFiles)\Java"
24+
MakeFragmentFile="$(MSBuildThisFileDirectory)..\..\bin\Build$(Configuration)\JdkInfo.mk"
25+
MaximumJdkVersion="$(JI_MAX_MDK)"
26+
PropertyFile="$(_TopDir)\bin\Build$(Configuration)\JdkInfo.props">
27+
<Output TaskParameter="JavaHomePath" PropertyName="_JavaSdkDirectory" />
2428
</JdkInfo>
2529
</Target>
2630
</Project>

build-tools/scripts/jdk.mk

Lines changed: 11 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -26,157 +26,22 @@
2626
# Location of the JDK `/bin` directory, which contains `java/`javac`/etc.
2727

2828
OS ?= $(shell uname)
29-
JI_JAVAC_PATH = javac
30-
JI_JAR_PATH = jar
3129

32-
JI_JDK_BIN_PATH = $(dir $(shell which java))
30+
_INCLUDE_MK = bin/Build$(CONFIGURATION)/JdkInfo.mk
3331

32+
prepare:: $(_INCLUDE_MK)
3433

35-
# Filter on <= JI_MAX_JDK
36-
ifneq ($(JI_MAX_JDK),)
37-
_VERSION_MAX := | awk '$$1 <= $(JI_MAX_JDK)'
38-
endif #JI_MAX_JDK
39-
40-
# Sort numerically on version numbers with `sort -n`, filtering on $(JI_MAX_JDK) if needed
41-
# Replace each line so it starts with a number (sed 's/...'\1 &/), sort on the leading number, then remove the leading number.
42-
# Grab the last path name printed.
43-
_VERSION_SORT := sed 's/[^0-9]*\([0-9.]*\)/\1 &/' $(_VERSION_MAX) | sort -n | sed 's/^[0-9.]* //g' | tail -1
34+
-include $(_INCLUDE_MK)
4435

4536
ifeq ($(OS),Darwin)
46-
47-
_MONO_BITNESS = $(shell file `which $(word 1, $(RUNTIME))` | awk 'BEGIN { val = "32-bit" } /64-bit/ { val = "64-bit" } END { print val; }')
48-
49-
ifeq ($(_MONO_BITNESS),32-bit)
50-
# The only 32-bit JVM I know of is the Apple-provided one.
51-
JI_JVM_PATH = /System/Library/Frameworks/JavaVM.framework/JavaVM
52-
endif # 32-bit
53-
54-
# Darwin supports three possible search locations:
55-
#
56-
# 1. `/Library/Java/JavaVirtualMachines/jdk*`
57-
# These are where 3rd party JDKs are installed, such as the Oracle JDK.
58-
# This is the preferred search directory.
59-
#
60-
# 2. The Xcode.app MacOSX.platform SDK, which is for the ancient JDK6 that
61-
# continues to be available
62-
#
63-
# 3. A "locally" hosted .pkg, in case Xcode.app isn't installed.
64-
65-
_DARWIN_JDK_FALLBACK_DIRS = $(wildcard /Library/Java/JavaVirtualMachines/jdk*)
66-
_DARWIN_JDK_JNI_INCLUDE_DIR = Contents/Home/include
67-
_DARWIN_JDK_JNI_OS_INCLUDE_DIR = $(_DARWIN_JDK_JNI_INCLUDE_DIR)/darwin
68-
69-
_XCODE_APP_JAVAVM_FRAMEWORK_PATH = \
70-
$(word 1, $(wildcard /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX*.sdk/System/Library/Frameworks/JavaVM.framework/Headers))
71-
72-
73-
_LOCAL_JDK_PKG = JavaDeveloper-2013005_dp__11m4609.pkg
74-
_LOCAL_JDK_URL = http://storage.bos.xamarin.com/android-sdk-tool/archives/$(FALLBACK_JDK_PKG)
75-
_LOCAL_JDK_HEADERS = LocalJDK/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers
76-
77-
# Ancient source for (3)
78-
_APPLE_JDK6_URL = http://adcdownload.apple.com/Developer_Tools/java_for_os_x_2013005_developer_package/java_for_os_x_2013005_dp__11m4609.dmg
79-
80-
ifneq ($(_DARWIN_JDK_FALLBACK_DIRS),)
81-
_DARWIN_JDK_ROOT := $(shell ls -dtr $(_DARWIN_JDK_FALLBACK_DIRS) | $(_VERSION_SORT))
82-
JI_JDK_BIN_PATH = $(_DARWIN_JDK_ROOT)/Contents/Home/bin
83-
JI_JAVAC_PATH = $(_DARWIN_JDK_ROOT)/Contents/Home/bin/javac
84-
JI_JAR_PATH = $(_DARWIN_JDK_ROOT)/Contents/Home/bin/jar
85-
JI_JDK_INCLUDE_PATHS = \
86-
$(_DARWIN_JDK_ROOT)/$(_DARWIN_JDK_JNI_INCLUDE_DIR) \
87-
$(_DARWIN_JDK_ROOT)/$(_DARWIN_JDK_JNI_OS_INCLUDE_DIR)
88-
89-
ifeq ($(_MONO_BITNESS),64-bit)
90-
JI_JVM_PATH = $(shell find $(_DARWIN_JDK_ROOT)/Contents/Home -name libjli.dylib)
91-
endif # 64-bit
92-
93-
else # (1) failed; try Xcode.app's copy?
94-
ifneq ($(_XCODE_APP_JAVAVM_FRAMEWORK_PATH),)
95-
JI_JDK_INCLUDE_PATHS = $(_XCODE_APP_JAVAVM_FRAMEWORK_PATH)
96-
else # (2) failed; hail mary pass!
97-
JI_JDK_INCLUDE_PATHS = LocalJDK/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers
98-
99-
bin/Build$(CONFIGURATION)/JdkHeaders.props: $(JI_JDK_INCLUDE_PATHS)/jni.h
100-
101-
$(JI_JDK_INCLUDE_PATHS)/jni.h:
102-
@if [ ! -f $(_LOCAL_JDK_PKG) ]; then \
103-
curl -o $(_LOCAL_JDK_PKG) $(_LOCAL_JDK_URL) ; \
104-
fi
105-
-mkdir LocalJDK
106-
_jdk="$$(cd `dirname "$(_LOCAL_JDK_PKG)"`; pwd)/`basename "$(_LOCAL_JDK_PKG)"`" ; \
107-
(cd LocalJDK; xar -xf $$_jdk)
108-
(cd LocalJDK; gunzip -c JavaEssentialsDev.pkg/Payload | cpio -i)
109-
endif # (3)
110-
endif # (1)
111-
112-
endif # Darwin
113-
37+
_JDKS_ROOT := /Library/Java/JavaVirtualMachines
38+
endif # $(OS)=Darwin
11439

11540
ifeq ($(OS),Linux)
41+
_JDKS_ROOT := /usr/lib/jvm
42+
endif # $(OS)=Linux
11643

117-
# This is for all linux distributions with which and java installed
118-
_DEFAULT_LINUX_JAVA_ROOT = $(shell java -XshowSettings:properties -help 2>&1 | grep java.home | sed 's/^.*java.home = //g')/../
119-
_DEFAULT_LINUX_JAVA_INCLUDE_DIRS = $(_DEFAULT_LINUX_JAVA_ROOT)/include/
120-
_LINUX_JAVA_FALLBACK_DIRS = /usr/lib/jvm/java*
121-
_LINUX_JAVA_JNI_INCLUDE_DIR = include
122-
_LINUX_JAVA_ROOT = $(_DEFAULT_LINUX_JAVA_ROOT)
123-
_LINUX_JAVA_ARCH_64 = amd64
124-
_LINUX_JAVA_ARCH_32 = i386
125-
126-
_DESKTOP_JAVA_INCLUDE_DIRS = $(_DEFAULT_LINUX_JAVA_INCLUDE_DIRS)
127-
128-
ifeq ($(wildcard $(_DESKTOP_JAVA_INCLUDE_DIRS)),)
129-
_DESKTOP_JAVA_INCLUDE_DIRS = $(wildcard $(JAVA_HOME)/include)
130-
_LINUX_JAVA_ROOT = $(JAVA_HOME)
131-
endif # No default Java location, $JAVA_HOME check
132-
133-
ifeq ($(wildcard $(_DESKTOP_JAVA_INCLUDE_DIRS)),)
134-
LATEST_JDK := $(shell ls -dtr $(_LINUX_JAVA_FALLBACK_DIRS) | $(_VERSION_SORT))
135-
_DESKTOP_JAVA_INCLUDE_DIRS = $(LATEST_JDK)/$(_LINUX_JAVA_JNI_INCLUDE_DIR)
136-
_LINUX_JAVA_ROOT = $(LATEST_JDK)
137-
endif # No $JAVA_HOME, find the latest version
138-
139-
JI_JDK_INCLUDE_PATHS = $(_DESKTOP_JAVA_INCLUDE_DIRS) $(_DESKTOP_JAVA_INCLUDE_DIRS)/linux
140-
141-
ifneq ($(wildcard $(_LINUX_JAVA_ROOT)/jre/lib/$(_LINUX_JAVA_ARCH_64)/server/libjvm.so),)
142-
JI_JVM_PATH = $(_LINUX_JAVA_ROOT)/jre/lib/$(_LINUX_JAVA_ARCH_64)/server/libjvm.so
143-
endif # Find 64-bit libjvm
144-
145-
ifeq ($(JI_JVM_PATH),) # (1) No 64-bit java arch
146-
ifneq ($(wildcard $(_LINUX_JAVA_ROOT)/jre/lib/$(_LINUX_JAVA_ARCH_32)/server/libjvm.so),) # (2) check 32-bit instead, even on a 64-bit system
147-
JI_JVM_PATH = $(_LINUX_JAVA_ROOT)/jre/lib/$(_LINUX_JAVA_ARCH_32)/server/libjvm.so
148-
endif # (2)
149-
endif # (1)
150-
151-
JI_JDK_BIN_PATH = $(_LINUX_JAVA_ROOT)/bin
152-
JI_JAVAC_PATH = $(_LINUX_JAVA_ROOT)/bin/javac
153-
JI_JAR_PATH = $(_LINUX_JAVA_ROOT)/bin/jar
154-
155-
endif # Linux
156-
157-
$(JI_JVM_PATH):
158-
@echo "error: No JVM found\!";
159-
@exit 1
160-
161-
bin/Build$(CONFIGURATION)/JdkInfo.props: $(JI_JDK_INCLUDE_PATHS) $(JI_JVM_PATH)
162-
-mkdir -p `dirname "$@"`
163-
-rm "$@"
164-
echo '<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">' > "$@"
165-
echo ' <Choose>' >> "$@"
166-
echo " <When Condition=\" '\$$(JdkJvmPath)' == '' \">" >> "$@"
167-
echo ' <PropertyGroup>' >> "$@"
168-
echo " <JdkJvmPath>$(JI_JVM_PATH)</JdkJvmPath>" >> "$@"
169-
echo ' </PropertyGroup>' >> "$@"
170-
echo ' <ItemGroup>' >> "$@"
171-
for p in $(JI_JDK_INCLUDE_PATHS); do \
172-
echo " <JdkIncludePath Include=\"$$p\" />" >> "$@"; \
173-
done
174-
echo ' </ItemGroup>' >> "$@"
175-
echo ' </When>' >> "$@"
176-
echo ' </Choose>' >> "$@"
177-
echo ' <PropertyGroup>' >> "$@"
178-
echo " <JdkBinPath Condition=\" '\$$(JdkBinPath)' == '' \">$(JI_JDK_BIN_PATH)</JdkBinPath>" >> "$@"
179-
echo " <JavaCPath Condition=\" '\$$(JavaCPath)' == '' \">$(JI_JAVAC_PATH)</JavaCPath>" >> "$@"
180-
echo " <JarPath Condition=\" '\$$(JarPath)' == '' \">$(JI_JAR_PATH)</JarPath>" >> "$@"
181-
echo ' </PropertyGroup>' >> "$@"
182-
echo '</Project>' >> "$@"
44+
$(_INCLUDE_MK): bin/Build$(CONFIGURATION)/Java.Interop.BootstrapTasks.dll
45+
$(MSBUILD) $(MSBUILD_FLAGS) build-tools/scripts/jdk.targets /t:GetPreferredJdkRoot \
46+
/p:JdksRoot="$(_JDKS_ROOT)" \
47+
$(if $(JI_MAX_JDK),"/p:MaximumJdkVersion=$(JI_MAX_JDK)")

build-tools/scripts/jdk.targets

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<UsingTask TaskName="Java.Interop.BootstrapTasks.JdkInfo" AssemblyFile="$(MSBuildThisFileDirectory)..\..\bin\Build$(Configuration)\Java.Interop.BootstrapTasks.dll" />
4+
<Target Name="GetPreferredJdkRoot">
5+
<JdkInfo
6+
JdksRoot="$(JdksRoot)"
7+
MakeFragmentFile="$(MSBuildThisFileDirectory)..\..\bin\Build$(Configuration)\JdkInfo.mk"
8+
MaximumJdkVersion="$(MaximumJdkVersion)"
9+
PropertyFile="$(MSBuildThisFileDirectory)..\..\bin\Build$(Configuration)\JdkInfo.props">
10+
<Output TaskParameter="JavaHomePath" PropertyName="_JavaHome"/>
11+
</JdkInfo>
12+
</Target>
13+
</Project>

src/Java.Interop.BootstrapTasks/Java.Interop.BootstrapTasks.csproj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,17 @@
3333
<Reference Include="System" />
3434
<Reference Include="System.Net.Http" />
3535
<Reference Include="System.Xml" />
36+
<Reference Include="System.Xml.Linq" />
3637
<Reference Include="Microsoft.Build.Framework" />
3738
<Reference Include="Microsoft.Build.Utilities.v4.0" />
3839
</ItemGroup>
3940
<ItemGroup>
4041
<Compile Include="Java.Interop.BootstrapTasks\DownloadUri.cs" />
4142
<Compile Include="Java.Interop.BootstrapTasks\JdkInfo.cs" />
43+
<Compile Include="Java.Interop.BootstrapTasks\OS.cs" />
4244
<Compile Include="Java.Interop.BootstrapTasks\RegistryEx.cs" />
43-
<Compile Include="Properties\AssemblyInfo.cs" />
4445
<Compile Include="Java.Interop.BootstrapTasks\SetEnvironmentVariable.cs" />
46+
<Compile Include="Properties\AssemblyInfo.cs" />
4547
</ItemGroup>
4648
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
4749
</Project>

0 commit comments

Comments
 (0)