1#!/bin/bash 2 3# Copyright (c) 2022 Huawei Device Co., Ltd. 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16set -e 17 18CUR_PATH=$(cd $(dirname ${BASH_SOURCE[0]}) && pwd) 19BASE_PATH=$(dirname ${CUR_PATH}) 20ROOT_PATH=$(cd ${CUR_PATH}/../../.. && pwd) && cd - 21 22arg_project="" 23arg_sdk_path="" 24arg_build_sdk="false" 25arg_help="0" 26arg_url="" 27arg_branch="" 28arg_npm="" 29arg_ohpm="" 30arg_out_path="${ROOT_PATH}/out/hap" 31arg_sign_tool="${ROOT_PATH}/developtools/hapsigner/dist" 32arg_p7b="" 33arg_apl="normal" 34arg_feature="hos_normal_app" 35arg_profile="UnsgnedReleasedProfileTemplate.json" 36arg_bundle_name="" 37 38ohos_sdk_path="${ROOT_PATH}/out/sdk/packages/ohos-sdk/linux" 39 40function print_help() { 41 cat <<EOF 42 use assembleHap [options] <mainclass> [args...] 43 44EOF 45} 46 47 48function clear_dir(){ 49 if [ ! -d "$1" ]; then 50 mkdir -p $1 51 fi 52} 53 54 55function is_project_root(){ 56 if [[ -f $1"/build-profile.json5" && -f $1"/hvigorfile.js" ]]; then 57 return 0 58 else 59 return 1 60 fi 61} 62 63function build_sdk() { 64 if [ -d ${ohos_sdk_path} ]; then 65 echo "ohos-sdk exists." 66 return 0 67 fi 68 pushd ${ROOT_PATH} 69 echo "building the latest ohos-sdk..." 70 export CCACHE_BASE="${PWD}" && export NO_DEVTOOL=1 && export CCACHE_LOCAL_DIR=.ccache_xts && export ZIP_COMPRESS_LEVEL=1 && export CCACHE_NOHASHDIR="true" && export CCACHE_SLOPPINESS="include_file_ctime" 71 start_time=$(date +%s.%N) 72 ./build.sh --product-name ohos-sdk --get-warning-list=false --compute-overlap-rate=false --deps-guard=false --generate-ninja-trace=false --gn-args skip_generate_module_list_file=true --gn-args sdk_platform=linux 73 end_time=$(date +%s.%N) 74 runtime=$(echo "$end_time - $start_time" | bc) 75 echo "ohos-sdk build cost $runtime" 76 pushd ${ohos_sdk_path} 77 ls -d */ | xargs rm -rf 78 for i in $(ls); do 79 unzip $i 80 done 81 api_version=$(grep apiVersion toolchains/oh-uni-package.json | awk '{print $2}' | sed -r 's/\",?//g') 82 sdk_version=$(grep version toolchains/oh-uni-package.json | awk '{print $2}' | sed -r 's/\",?//g') 83 for i in $(ls -d */); do 84 mkdir -p $api_version 85 mv $i $api_version 86 mkdir $i 87 ln -s ../$api_version/$i $i/$sdk_version 88 done 89 popd 90 popd 91} 92 93function parse_arguments() { 94 local helperKey=""; 95 local helperValue=""; 96 local current=""; 97 98 while [ "$1" != "" ]; do 99 current=$1; 100 helperKey=${current#*--}; 101 helperKey=${helperKey%%=*}; 102 helperKey=$(echo "$helperKey" | tr '-' '_'); 103 helperValue=${current#*=}; 104 if [ "$helperValue" == "$current" ]; then 105 helperValue="1"; 106 fi 107 #echo "eval arg_$helperKey=\"$helperValue\""; 108 109 eval "arg_$helperKey=\"$helperValue\""; 110 shift 111 done 112} 113 114 115parse_arguments "${@}"; 116 117if [ "$arg_help" != "0" ]; then 118 print_help; 119 exit 1; 120fi 121 122# Called in the warm-up process to ensure that the docker is the latest SDK every day 123# Called like this: ./build.sh --build_sdk 124if [ "$arg_build_sdk" == "1" ]; then 125 rm -rf ${ohos_sdk_path} 126 build_sdk 127 exit 0; 128fi 129 130if [ "${arg_project}" == "" -a "${arg_url}" == "" ]; then 131 echo "--project or --url is not null" 132 exit 1; 133fi 134 135 136if [ ! -d "${arg_project}" ]; then 137 echo "${arg_project} is not dir" 138 exit 1; 139fi 140 141 142if [[ ${arg_project} = */ ]]; then 143 arg_project=${arg_project%/} 144fi 145 146 147if [[ ${arg_sign_tool} = */ ]]; then 148 arg_sign_tool=${arg_sign_tool%/} 149fi 150 151if [[ ${arg_p7b} = "" ]]; then 152 arg_p7b=$(find ${arg_project} -name *.p7b | head -n 1) 153 if [[ ${arg_p7b} = "" ]]; then 154 arg_p7b=openharmony_sx.p7b 155 fi 156fi 157 158clear_dir ${arg_out_path} 159 160 161if [ "${arg_url}" != "" ]; then 162 if [ "${arg_branch}" == "" ]; then 163 echo "branch is not null" 164 exit 1 165 fi 166 project_name=${arg_url##*/} 167 project_name=${project_name%%.git*} 168 if test -d ${BASE_PATH}/projects/${project_name} 169 then 170 echo "${project_name} exists,ready for update..." 171 cd ${BASE_PATH}/projects/${project_name} 172 git fetch origin ${arg_branch} 173 git reset --hard origin/${arg_branch} 174 git pull 175 else 176 echo "${project_name} dose not exist,ready to download..." 177 cd ${BASE_PATH}/projects 178 git clone -b ${arg_branch} ${arg_url} ${project_name} 179 fi 180 arg_project=${BASE_PATH}/projects/${project_name} 181fi 182 183 184if ! is_project_root ${arg_project}; then 185 echo "${arg_project} is not OpenHarmony Project" 186 exit 1; 187fi 188 189if [ "${arg_build_sdk}" == "true" ]; then 190 build_sdk 191 export OHOS_SDK_HOME=${ohos_sdk_path} 192 echo "set OHOS_SDK_HOME to" ${OHOS_SDK_HOME} 193fi 194 195if [ "${arg_sdk_path}" != "" ]; then 196 export OHOS_SDK_HOME=${arg_sdk_path} 197fi 198export OHOS_BASE_SDK_HOME=${OHOS_SDK_HOME} 199 200echo "start build hap..." 201cd ${arg_project} 202echo "sdk.dir=${OHOS_SDK_HOME}" > ./local.properties 203echo "nodejs.dir=${NODE_HOME}" >> ./local.properties 204 205echo "use sdk:"${OHOS_SDK_HOME} 206 207is_ohpm=true 208package_json_name="oh-package.json5" 209if [ ! -f ${arg_project}/${package_json_name} ]; then 210 is_ohpm=false 211 package_json_name="package.json" 212fi 213 214if ${is_ohpm}; then 215 if [ "${arg_ohpm}" == "" ]; then 216 arg_ohpm="@ohos:registry https://ohpm.openharmony.cn/ohpm/" 217 fi 218 echo "ohpm config set ${arg_ohpm}" 219 ohpm config set ${arg_ohpm} 220else 221 if [ "${arg_npm}" == "" ]; then 222 arg_npm="@ohos:registry=https://repo.harmonyos.com/npm/" 223 fi 224 echo "npm config set ${arg_npm}" 225 npm config set ${arg_npm} 226fi 227 228module_list=() 229module_name=() 230out_module=() 231bundle_name="" 232 233 234function del_module_name(){ 235 name=${1} 236 for i in "${!module_name[@]}" 237 do 238 if [[ "${module_name[i]}" == "${name}" ]]; then 239 unset module_name[i] 240 echo "移除"${name}" , 剩余 : "${module_name[@]} 241 return 0 242 fi 243 done 244 return 1 245} 246 247 248function load_dep(){ 249 local cur_m_n=${1} 250 local cur_module 251 for cur_module in ${module_list[@]} 252 do 253 if [[ "${cur_module}" =~ "${cur_m_n}" ]]; then 254 del_module_name ${cur_m_n} 255 for m_n_1 in ${module_name[@]} 256 do 257 rr=$(cat ${cur_module}"/${package_json_name}" | grep "${m_n_1}" || true) 258 if [[ "${rr}" != "" ]]; then 259 load_dep ${m_n_1} 260 fi 261 done 262 cd ${cur_module} 263 echo ${cur_module}" 执行npm/ohpm install" 264 if ${is_ohpm}; then 265 ohpm install 266 else 267 npm i 268 fi 269 270 fi 271 done 272} 273 274 275while read line 276do 277 if [[ ${line} =~ "srcPath" ]]; then 278 pa=${line%\"*} 279 pa=${pa##*\".} 280 module_list[${#module_list[*]}]=${arg_project}${pa} 281 module_name[${#module_name[*]}]=${pa} 282 if [ -d "${arg_project}/AppScope" ]; then 283 cur_bundle_line=`cat ${arg_project}/AppScope/app.json5 | grep "\"bundleName\""` 284 bundle_name=${cur_bundle_line%\"*} 285 bundle_name=${bundle_name##*\"} 286 # echo "bundleName : "${bundle_name} 287 is_entry=`cat ${arg_project}${pa}/src/main/module.json5 | sed 's/ //g' | grep "\"type\":\"entry\"" || true` 288 is_feature=`cat ${arg_project}${pa}/src/main/module.json5 | sed 's/ //g' | grep "\"type\":\"feature\"" || true` 289 if [[ "${is_entry}" != "" || "${is_feature}" != "" ]]; then 290 echo "hap输出module: "${arg_project}${pa} 291 out_module[${#out_module[*]}]=${arg_project}${pa} 292 fi 293 else 294 cur_bundle_line=`cat ${arg_project}${pa}/src/main/config.json | grep "\"bundleName\""` 295 bundle_name=${cur_bundle_line%\"*} 296 bundle_name=${bundle_name##*\"} 297 # echo "bundleName : "${bundle_name} 298 is_entry=`cat ${arg_project}${pa}/src/main/config.json | sed 's/ //g' | grep "\"moduleType\":\"entry\"" || true` 299 is_feature=`cat ${arg_project}${pa}/src/main/config.json | sed 's/ //g' | grep "\"moduleType\":\"feature\"" || true` 300 if [[ "${is_entry}" != "" || "${is_feature}" != "" ]]; then 301 echo "hap输出module: "${arg_project}${pa} 302 out_module[${#out_module[*]}]=${arg_project}${pa} 303 fi 304 fi 305 fi 306done < ${arg_project}"/build-profile.json5" 307 308 309for module in ${module_list[@]} 310do 311 if del_module_name ${module##${arg_project}}; then 312 for m_n in ${module_name[@]} 313 do 314 rr=$(cat ${module}"/${package_json_name}" | grep "${m_n}" || true) 315 if [[ "${rr}" != "" ]]; then 316 load_dep ${m_n} 317 fi 318 done 319 cd ${module} 320 echo ${module}" 执行npm/ohpm install" 321 if ${is_ohpm}; then 322 ohpm install 323 else 324 npm i 325 fi 326 fi 327done 328 329 330cd ${arg_project} 331echo ${arg_project}" 执行npm/ohpm install" 332if ${is_ohpm}; then 333 ohpm install 334 chmod +x hvigorw 335 # Historical reasons need to be compatible with NODE_HOME path issue 336 if grep -q "\${NODE_HOME}/bin/node" hvigorw ; then 337 # node home path include "bin" 338 if [ ! -x "${NODE_HOME}/bin/node" ];then 339 export NODE_HOME=$(dirname ${NODE_HOME}) 340 fi 341 else 342 # node home path does not include "bin" 343 if [ -x "${NODE_HOME}/bin/node" ];then 344 export NODE_HOME=${NODE_HOME}/bin 345 fi 346 fi 347 ./hvigorw clean --no-daemon 348 ./hvigorw assembleHap --mode module -p product=default -p debuggable=false --no-daemon 349else 350 npm install 351 node ./node_modules/@ohos/hvigor/bin/hvigor.js clean 352 node ./node_modules/@ohos/hvigor/bin/hvigor.js --mode module clean assembleHap -p debuggable=false 353fi 354 355 356 357for module in ${out_module[@]} 358do 359 cur_out_module_name=${module##*/} 360 is_sign=false 361 echo "module = ${module} , cur_out_module_name=${cur_out_module_name}" 362 if [ ! -d ${module}/build/default/outputs/default/ ]; then 363 echo "module = ${module}, assembleHap error !!!" 364 continue 365 fi 366 for out_file in `ls ${module}/build/default/outputs/default/` 367 do 368 if [[ "${out_file}" =~ "-signed.hap" ]]; then 369 is_sign=true 370 echo "发现signed包 : "${out_file}",直接归档" 371 cp ${module}/build/default/outputs/default/${out_file} ${arg_out_path}/ 372 break 373 fi 374 done 375 if test ${is_sign} = false 376 then 377 hap_name=${arg_project##*/} 378 # echo "${hap_name},skip sign 'hap'. Invalid signingConfig is configured for 'default' product." 379 for out_file in `ls ${module}/build/default/outputs/default/` 380 do 381 if [[ "${out_file}" =~ "-unsigned.hap" ]]; then 382 echo "发现unsigned包 : "${out_file}",开始使用签名工具签名" 383 nosign_hap_path=${module}/build/default/outputs/default/${out_file} 384 sign_hap_path=${module}/build/default/outputs/default/${out_file/unsigned/signed} 385 cp -r ${arg_sign_tool} ${arg_project}/ 386 cd ${arg_project}/dist 387 if [ ! -e ${arg_profile} ]; then 388 echo "${arg_profile} not exist! ! !" 389 exit 1 390 fi 391 if [ "${arg_bundle_name}" != "" ]; then 392 sed -i "s/\"com.OpenHarmony.app.test\"/\"${arg_bundle_name}\"/g" ${arg_profile} 393 else 394 sed -i "s/\"com.OpenHarmony.app.test\"/\"${bundle_name}\"/g" ${arg_profile} 395 fi 396 sed -i "s/\"normal\"/\"${arg_apl}\"/g" ${arg_profile} 397 sed -i "s/\"system_basic\"/\"${arg_apl}\"/g" ${arg_profile} 398 sed -i "s/\"system_core\"/\"${arg_apl}\"/g" ${arg_profile} 399 sed -i "s/\"hos_normal_app\"/\"${arg_feature}\"/g" ${arg_profile} 400 sed -i "s/\"hos_system_app\"/\"${arg_feature}\"/g" ${arg_profile} 401 java -jar hap-sign-tool.jar sign-profile -keyAlias "openharmony application profile release" -signAlg "SHA256withECDSA" -mode "localSign" -profileCertFile "OpenHarmonyProfileRelease.pem" -inFile "${arg_profile}" -keystoreFile "OpenHarmony.p12" -outFile "openharmony_sx.p7b" -keyPwd "123456" -keystorePwd "123456" 402 java -jar hap-sign-tool.jar sign-app -keyAlias "openharmony application release" -signAlg "SHA256withECDSA" -mode "localSign" -appCertFile "OpenHarmonyApplication.pem" -profileFile "${arg_p7b}" -inFile "${nosign_hap_path}" -keystoreFile "OpenHarmony.p12" -outFile "${sign_hap_path}" -keyPwd "123456" -keystorePwd "123456" 403 cp ${sign_hap_path} ${arg_out_path}/ 404 is_sign=true 405 fi 406 done 407 if test ${is_sign} = false 408 then 409 echo "${module} assembleHap error !!!" 410 rm -rf ${arg_project}/sign_helper 411 exit 1 412 fi 413 fi 414done 415rm -rf ${arg_project}/sign_helper 416 417# backup sourceMaps.json files for DFR 418cd ${arg_project} 419find . -name "sourceMaps.json" -type f | while read file; do 420 sourceMaps_path=$(echo ${file} | sed 's/^\.\///;s/\/sourceMaps.json$//') 421 mkdir -p ${arg_out_path}/${sourceMaps_path} 422 cp ${file} ${arg_out_path}/${sourceMaps_path}/ 423done 424 425exit 0 426