Skip to content

Commit bf303c1

Browse files
committed
Add support for OpenHarmony platform
1 parent 6798d1d commit bf303c1

5 files changed

Lines changed: 183 additions & 0 deletions

File tree

nvm.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2253,6 +2253,18 @@ nvm_get_os() {
22532253
AIX\ *) NVM_OS=aix ;;
22542254
CYGWIN* | MSYS* | MINGW*) NVM_OS=win ;;
22552255
esac
2256+
2257+
# OpenHarmony can't be identified from `uname` alone: a device may run either
2258+
# a Linux kernel or a HarmonyOS kernel. Ask the userland, but only when
2259+
# `uname` has not already identified some other OS.
2260+
case "${NVM_OS-}" in
2261+
'' | linux)
2262+
if [ -x /system/bin/param ] && /system/bin/param get const.ohos.fullname </dev/null 2>/dev/null | nvm_grep -q '^OpenHarmony'; then
2263+
NVM_OS=openharmony
2264+
fi
2265+
;;
2266+
esac
2267+
22562268
nvm_echo "${NVM_OS-}"
22572269
}
22582270

test/fast/Unit tests/nvm_get_os

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
#!/bin/sh
2+
3+
# Save the PATH as it was when the test started to restore it when it finishes
4+
ORIG_PATH="${PATH}"
5+
6+
cleanup() {
7+
# Restore the PATH as it was when the test started
8+
export PATH="${ORIG_PATH}"
9+
rm -rf "${TMP_DIR}"
10+
}
11+
12+
die() {
13+
cleanup
14+
echo "$@"
15+
exit 1
16+
}
17+
18+
: nvm.sh
19+
\. ../../../nvm.sh
20+
21+
# Directory where mocked binaries used by nvm_get_os for each OS/arch are located
22+
MOCKS_DIR="$(pwd)/../../mocks"
23+
24+
# Sets the PATH for these tests to include the symlinks to the mocked binaries
25+
export PATH=".:${PATH}"
26+
27+
TMP_DIR=$(mktemp -d)
28+
29+
# Setups mock binaries for a given OS and arch that mimic the output of
30+
# the real binaries used by nvm_get_os to guess the OS of a given system.
31+
setup_mock_os() {
32+
local OS
33+
OS=$1
34+
local ARCH
35+
ARCH=$2
36+
ln -sf "${MOCKS_DIR}/uname_${OS}_${ARCH}" ./uname
37+
}
38+
39+
# Cleans up the setup done by setup_mock_os.
40+
cleanup_mock_os() {
41+
rm -f ./uname
42+
}
43+
44+
# Runs nvm_get_os for OS $OS and arch $ARCH, and compares the expected
45+
# output $EXPECTED_OUTPUT with the actual output. Does nothing and exits
46+
# cleanly if they match, dies otherwise.
47+
run_test() {
48+
local EXPECTED
49+
EXPECTED=$1
50+
local OUTPUT
51+
OUTPUT="$(nvm_get_os)"
52+
[ "_${OUTPUT}" = "_${EXPECTED}" ] ||
53+
die "nvm_get_os produced \"${OUTPUT}\", expected \"${EXPECTED}\""
54+
}
55+
56+
# Pre-existing arms
57+
58+
setup_mock_os linux aarch64
59+
run_test "linux"
60+
cleanup_mock_os
61+
62+
setup_mock_os osx amd64
63+
run_test "darwin"
64+
cleanup_mock_os
65+
66+
setup_mock_os smartos amd64
67+
run_test "sunos"
68+
cleanup_mock_os
69+
70+
# HarmonyOS kernel without OpenHarmony userland
71+
72+
setup_mock_os harmonyos aarch64
73+
run_test ""
74+
cleanup_mock_os
75+
76+
# OpenHarmony detection via chroot
77+
78+
setup_chroot() {
79+
chroot_dir=$1
80+
param_mock=$2
81+
uname_mock=$3
82+
83+
# Directories
84+
mkdir -p "${chroot_dir}/etc"
85+
mkdir -p "${chroot_dir}/bin"
86+
mkdir -p "${chroot_dir}/usr/bin"
87+
mkdir -p "${chroot_dir}/lib64"
88+
mkdir -p "${chroot_dir}/dev"
89+
mkdir -p "${chroot_dir}/system/bin"
90+
91+
# Files and binaries
92+
cp ../../../nvm.sh "${chroot_dir}/"
93+
cp /bin/sh /usr/bin/dirname /usr/bin/grep "${chroot_dir}/usr/bin/"
94+
cp "${uname_mock}" "${chroot_dir}/usr/bin/uname"
95+
chmod +x "${chroot_dir}/usr/bin/uname"
96+
ln -sf ../usr/bin/sh "${chroot_dir}/bin/sh"
97+
98+
# Fake OpenHarmony param binary
99+
cp "${param_mock}" "${chroot_dir}/system/bin/param"
100+
chmod +x "${chroot_dir}/system/bin/param"
101+
102+
# Libraries
103+
for binary in /bin/sh /usr/bin/dirname /usr/bin/uname /usr/bin/grep; do
104+
for lib in $(ldd $binary | awk '{print $3}' | grep "^/"); do
105+
dir=$(dirname "${lib}")
106+
mkdir -p "${chroot_dir}${dir}"
107+
cp "${lib}" "${chroot_dir}${dir}/"
108+
done
109+
done
110+
111+
# Dynamic linker
112+
cp /lib64/ld-linux-x86-64.so.2 "${chroot_dir}/lib64/"
113+
114+
# /dev/null
115+
sudo mknod "${chroot_dir}/dev/null" c 1 3
116+
}
117+
118+
# The chroot fixtures assume a glibc layout (fixed dynamic-linker path
119+
# under /lib64, coreutils binaries). On musl Alpine that setup does not
120+
# apply, and nvm_get_os's OpenHarmony probe cannot be exercised there;
121+
# skip the chroot checks on Alpine.
122+
if [ -f "/etc/alpine-release" ]; then
123+
echo "on Alpine; skipping chroot OpenHarmony checks"
124+
else
125+
CHROOT_UNAME_LINUX_PARAM_OPENHARMONY="${TMP_DIR}/uname_linux_param_openharmony"
126+
CHROOT_UNAME_LINUX_PARAM_OTHER="${TMP_DIR}/uname_linux_param_other"
127+
CHROOT_UNAME_HARMONYOS_PARAM_OPENHARMONY="${TMP_DIR}/uname_harmonyos_param_openharmony"
128+
CHROOT_UNAME_HARMONYOS_PARAM_OTHER="${TMP_DIR}/uname_harmonyos_param_other"
129+
130+
setup_chroot "${CHROOT_UNAME_LINUX_PARAM_OPENHARMONY}" "${MOCKS_DIR}/param_openharmony" "${MOCKS_DIR}/uname_linux_aarch64"
131+
setup_chroot "${CHROOT_UNAME_LINUX_PARAM_OTHER}" "${MOCKS_DIR}/param_other" "${MOCKS_DIR}/uname_linux_aarch64"
132+
setup_chroot "${CHROOT_UNAME_HARMONYOS_PARAM_OPENHARMONY}" "${MOCKS_DIR}/param_openharmony" "${MOCKS_DIR}/uname_harmonyos_aarch64"
133+
setup_chroot "${CHROOT_UNAME_HARMONYOS_PARAM_OTHER}" "${MOCKS_DIR}/param_other" "${MOCKS_DIR}/uname_harmonyos_aarch64"
134+
135+
# Linux kernel with an OpenHarmony param -> openharmony
136+
OS_UNAME_LINUX_PARAM_OPENHARMONY=$(sudo chroot "${CHROOT_UNAME_LINUX_PARAM_OPENHARMONY}" /bin/sh -c ". ./nvm.sh && nvm_get_os")
137+
if [ "${OS_UNAME_LINUX_PARAM_OPENHARMONY}" != "openharmony" ]; then
138+
die "nvm_get_os produced \"${OS_UNAME_LINUX_PARAM_OPENHARMONY}\", expected \"openharmony\""
139+
fi
140+
141+
# Linux kernel with an unrelated param stays linux
142+
OS_UNAME_LINUX_PARAM_OTHER=$(sudo chroot "${CHROOT_UNAME_LINUX_PARAM_OTHER}" /bin/sh -c ". ./nvm.sh && nvm_get_os")
143+
if [ "${OS_UNAME_LINUX_PARAM_OTHER}" != "linux" ]; then
144+
die "nvm_get_os produced \"${OS_UNAME_LINUX_PARAM_OTHER}\", expected \"linux\""
145+
fi
146+
147+
# HarmonyOS kernel with an OpenHarmony param -> openharmony
148+
OS_UNAME_HARMONYOS_PARAM_OPENHARMONY=$(sudo chroot "${CHROOT_UNAME_HARMONYOS_PARAM_OPENHARMONY}" /bin/sh -c ". ./nvm.sh && nvm_get_os")
149+
if [ "${OS_UNAME_HARMONYOS_PARAM_OPENHARMONY}" != "openharmony" ]; then
150+
die "nvm_get_os produced \"${OS_UNAME_HARMONYOS_PARAM_OPENHARMONY}\", expected \"openharmony\""
151+
fi
152+
153+
# HarmonyOS kernel with an unrelated param stays empty
154+
OS_UNAME_HARMONYOS_PARAM_OTHER=$(sudo chroot "${CHROOT_UNAME_HARMONYOS_PARAM_OTHER}" /bin/sh -c ". ./nvm.sh && nvm_get_os")
155+
if [ "_${OS_UNAME_HARMONYOS_PARAM_OTHER}" != "_" ]; then
156+
die "nvm_get_os produced \"${OS_UNAME_HARMONYOS_PARAM_OTHER}\", expected \"\""
157+
fi
158+
fi
159+
160+
cleanup

test/mocks/param_openharmony

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
if [ "$#" -eq 2 ] && [ "$1" = "get" ] && [ "$2" = "const.ohos.fullname" ]; then
2+
echo "OpenHarmony-6.1.0.31"
3+
fi

test/mocks/param_other

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
if [ "$#" -eq 2 ] && [ "$1" = "get" ] && [ "$2" = "const.ohos.fullname" ]; then
2+
echo "SomeOtherOS-1.2.3"
3+
fi

test/mocks/uname_harmonyos_aarch64

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
if [ "_$1" = "_-m" ]; then
2+
echo "aarch64"
3+
else
4+
echo "HarmonyOS localhost HongMeng Kernel 1.12.0 #1 SMP Tue Jul 14 09:40:51 UTC 2026 aarch64 Toybox"
5+
fi

0 commit comments

Comments
 (0)