1/* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import path from 'path'; 17import fs from 'fs'; 18import { 19 ArkObfuscator, 20 readProjectProperties 21} from "arkguard" 22 23import { 24 TS2ABC, 25 ESMODULE, 26 AOT_FULL, 27 AOT_PARTIAL, 28 AOT_TYPE, 29 AOT_PROFILE_SUFFIX, 30 NODE_MODULES, 31 OH_MODULES, 32 FAIL, 33 OBFUSCATION_TOOL 34} from './ark_define'; 35import { isAotMode, isDebug } from '../utils'; 36import { 37 isLinux, 38 isMac, 39 isWindows 40} from '../../../utils'; 41import { getArkBuildDir } from '../../../ark_utils'; 42import { checkAotConfig } from '../../../gen_aot'; 43import { projectConfig as mainProjectConfig } from '../../../../main'; 44import { MergedConfig, ObConfigResolver, readNameCache} from './ob_config_resolver' 45 46type ArkConfig = { 47 arkRootPath: string; 48 ts2abcPath: string; 49 js2abcPath: string; 50 mergeAbcPath: string; 51 es2abcPath: string; 52 aotCompilerPath: string; 53 nodePath: string; 54 isDebug: boolean; 55}; 56 57let arkConfig: ArkConfig = {}; 58export function initArkConfig(projectConfig: any) { 59 let arkRootPath: string = path.join(__dirname, '..', '..', '..', '..', 'bin', 'ark'); 60 if (projectConfig.arkFrontendDir) { 61 arkRootPath = projectConfig.arkFrontendDir; 62 } 63 arkConfig.nodePath = 'node'; 64 if (projectConfig.nodeJs) { 65 arkConfig.nodePath = projectConfig.nodePath; 66 } 67 processPlatformInfo(arkRootPath); 68 processCompatibleVersion(projectConfig, arkRootPath); 69 arkConfig.isDebug = isDebug(projectConfig); 70 arkConfig.arkRootPath = arkRootPath; 71 72 return arkConfig; 73} 74 75export function initArkProjectConfig(share: any) { 76 let projectConfig: any = share.projectConfig; 77 let arkProjectConfig: any = {}; 78 if (projectConfig.aceBuildJson && fs.existsSync(projectConfig.aceBuildJson)) { 79 const buildJsonInfo = JSON.parse(fs.readFileSync(projectConfig.aceBuildJson).toString()); 80 arkProjectConfig.projectRootPath = buildJsonInfo.projectRootPath; 81 arkProjectConfig.modulePathMap = buildJsonInfo.modulePathMap; 82 arkProjectConfig.isOhosTest = buildJsonInfo.isOhosTest; 83 if (buildJsonInfo.patchConfig) { 84 arkProjectConfig.oldMapFilePath = buildJsonInfo.patchConfig.oldMapFilePath; 85 } 86 if (checkAotConfig(projectConfig.compileMode, buildJsonInfo, 87 (error: string) => { share.throwArkTsCompilerError(error) })) { 88 arkProjectConfig.processTs = true; 89 arkProjectConfig.pandaMode = TS2ABC; 90 arkProjectConfig.anBuildOutPut = buildJsonInfo.anBuildOutPut; 91 arkProjectConfig.anBuildMode = buildJsonInfo.anBuildMode; 92 arkProjectConfig.apPath = buildJsonInfo.apPath; 93 } else { 94 arkProjectConfig.processTs = false; 95 arkProjectConfig.pandaMode = buildJsonInfo.pandaMode; 96 } 97 98 if (projectConfig.compileMode === ESMODULE) { 99 arkProjectConfig.nodeModulesPath = buildJsonInfo.nodeModulesPath; 100 arkProjectConfig.harNameOhmMap = buildJsonInfo.harNameOhmMap; 101 projectConfig.packageDir = buildJsonInfo.packageManagerType === 'ohpm' ? OH_MODULES : NODE_MODULES; 102 } 103 } 104 if (projectConfig.aceManifestPath && fs.existsSync(projectConfig.aceManifestPath)) { 105 const manifestJsonInfo = JSON.parse(fs.readFileSync(projectConfig.aceManifestPath).toString()); 106 if (manifestJsonInfo.minPlatformVersion) { 107 arkProjectConfig.minPlatformVersion = manifestJsonInfo.minPlatformVersion; 108 } 109 } 110 if (projectConfig.aceModuleJsonPath && fs.existsSync(projectConfig.aceModuleJsonPath)) { 111 const moduleJsonInfo = JSON.parse(fs.readFileSync(projectConfig.aceModuleJsonPath).toString()); 112 if (moduleJsonInfo.app.minAPIVersion) { 113 arkProjectConfig.minPlatformVersion = moduleJsonInfo.app.minAPIVersion; 114 } 115 if (moduleJsonInfo.module) { 116 arkProjectConfig.moduleName = moduleJsonInfo.module.name; 117 } 118 if (moduleJsonInfo.app) { 119 arkProjectConfig.bundleName = moduleJsonInfo.app.bundleName; 120 } 121 } 122 123 // Hotreload attributes are initialized by arkui in main.js, just copy them. 124 arkProjectConfig.hotReload = mainProjectConfig.hotReload; 125 arkProjectConfig.patchAbcPath = mainProjectConfig.patchAbcPath; 126 arkProjectConfig.changedFileList = mainProjectConfig.changedFileList; 127 128 if(mainProjectConfig.es2abcCompileTsInAotMode || mainProjectConfig.es2abcCompileTsInNonAotMode) { 129 arkProjectConfig.pandaMode = mainProjectConfig.pandaMode; 130 arkProjectConfig.processTs = mainProjectConfig.processTs; 131 } 132 arkProjectConfig.compileMode = projectConfig.compileMode; 133 134 if (projectConfig.compileHar || !isDebug(projectConfig)) { 135 const logger: any = share.getLogger(OBFUSCATION_TOOL); 136 initObfuscationConfig(projectConfig, arkProjectConfig, logger); 137 } 138 return arkProjectConfig; 139} 140 141function initObfuscationConfig(projectConfig: any, arkProjectConfig: any, logger: any): void { 142 const obConfig: ObConfigResolver = new ObConfigResolver(projectConfig, logger, true); 143 const mergedObConfig: MergedConfig = obConfig.resolveObfuscationConfigs(); 144 const isHarCompiled: boolean = projectConfig.compileHar; 145 if (mergedObConfig.options.disableObfuscation) { 146 return; 147 } 148 149 let projectAndLibsReservedProperties: string[]; 150 if (mergedObConfig.options.enablePropertyObfuscation) { 151 projectAndLibsReservedProperties = readProjectProperties([projectConfig.modulePath], 152 { mNameObfuscation: {mReservedProperties: [], mKeepStringProperty: !mergedObConfig.options.enableStringPropertyObfuscation } }, true); 153 mergedObConfig.reservedPropertyNames.push(...projectAndLibsReservedProperties); 154 } 155 arkProjectConfig.obfuscationMergedObConfig = mergedObConfig; 156 157 if (isAotMode(arkProjectConfig)) { 158 arkProjectConfig.arkObfuscator = initArkGuardConfig(projectConfig.obfuscationOptions?.obfuscationCacheDir, logger, mergedObConfig); 159 return; 160 } 161 arkProjectConfig.terserConfig = initTerserConfig(projectConfig, logger, mergedObConfig, isHarCompiled); 162} 163 164function initTerserConfig(projectConfig: any, logger: any, mergedObConfig: MergedConfig, isHarCompiled: boolean): any { 165 const isCompact = projectConfig.obfuscationOptions ? mergedObConfig.options.compact : isHarCompiled; 166 const minifyOptions = { 167 format: { 168 beautify: !isCompact, 169 indent_level: 2 170 }, 171 compress: { 172 join_vars: false, 173 sequences: 0, 174 directives: false, 175 drop_console: mergedObConfig.options.removeLog 176 }, 177 mangle: { 178 reserved: mergedObConfig.reservedNames, 179 toplevel: mergedObConfig.options.enableToplevelObfuscation 180 } 181 } 182 const applyNameCache: string | undefined = mergedObConfig.options.applyNameCache; 183 if (applyNameCache && applyNameCache.length > 0) { 184 if (fs.existsSync(applyNameCache)) { 185 minifyOptions.nameCache = JSON.parse(fs.readFileSync(applyNameCache, 'utf-8')); 186 } else { 187 logger.error(`ArkTS:ERROR Namecache file ${applyNameCache} does not exist`); 188 } 189 } else { 190 if (projectConfig.obfuscationOptions && projectConfig.obfuscationOptions.obfuscationCacheDir) { 191 const defaultNameCachePath: string = path.join(projectConfig.obfuscationOptions.obfuscationCacheDir,"nameCache.json"); 192 if (fs.existsSync(defaultNameCachePath)) { 193 minifyOptions.nameCache = JSON.parse(fs.readFileSync(defaultNameCachePath, 'utf-8')); 194 } else { 195 minifyOptions.nameCache = {}; 196 } 197 } 198 } 199 200 if (mergedObConfig.options.enablePropertyObfuscation) { 201 minifyOptions.mangle.properties = { 202 reserved: mergedObConfig.reservedPropertyNames, 203 keep_quoted: !mergedObConfig.options.enableStringPropertyObfuscation 204 }; 205 } 206 return minifyOptions; 207} 208 209function initArkGuardConfig(obfuscationCacheDir: string | undefined, logger: any, mergedObConfig: any) { 210 const arkguardConfig = { 211 mCompact: mergedObConfig.options.compact, 212 mDisableHilog: false, 213 mDisableConsole: mergedObConfig.options.removeLog, 214 mSimplify: false, 215 mTopLevel: mergedObConfig.options.enableToplevelObfuscation, 216 mNameObfuscation: { 217 mEnable: true, 218 mNameGeneratorType: 1, 219 mReservedNames: mergedObConfig.reservedNames, 220 mRenameProperties: mergedObConfig.options.enablePropertyObfuscation, 221 mReservedProperties: mergedObConfig.reservedPropertyNames, 222 mKeepStringProperty: !mergedObConfig.options.enableStringPropertyObfuscation 223 }, 224 mEnableSourceMap: true, 225 mEnableNameCache: true 226 } 227 228 const arkObfuscator: ArkObfuscator = new ArkObfuscator(); 229 arkObfuscator.init(arkguardConfig); 230 if (mergedObConfig.options.applyNameCache && mergedObConfig.options.applyNameCache.length > 0) { 231 readNameCache(mergedObConfig.options.applyNameCache, logger); 232 } else { 233 if (obfuscationCacheDir) { 234 const defaultNameCachePath: string = path.join(obfuscationCacheDir,"nameCache.json"); 235 if (fs.existsSync(defaultNameCachePath)) { 236 readNameCache(defaultNameCachePath, logger); 237 } 238 } 239 } 240 return arkObfuscator; 241} 242 243function processPlatformInfo(arkRootPath: string): void { 244 const arkPlatformPath: string = getArkBuildDir(arkRootPath); 245 if (isWindows()) { 246 arkConfig.es2abcPath = path.join(arkPlatformPath, 'bin', 'es2abc.exe'); 247 arkConfig.ts2abcPath = path.join(arkPlatformPath, 'src', 'index.js'); 248 arkConfig.mergeAbcPath = path.join(arkPlatformPath, 'bin', 'merge_abc.exe'); 249 arkConfig.js2abcPath = path.join(arkPlatformPath, 'bin', 'js2abc.exe'); 250 arkConfig.aotCompilerPath = path.join(arkPlatformPath, 'bin', 'ark_aot_compiler.exe'); 251 return; 252 } 253 if (isLinux() || isMac()) { 254 arkConfig.es2abcPath = path.join(arkPlatformPath, 'bin', 'es2abc'); 255 arkConfig.ts2abcPath = path.join(arkPlatformPath, 'src', 'index.js'); 256 arkConfig.mergeAbcPath = path.join(arkPlatformPath, 'bin', 'merge_abc'); 257 arkConfig.js2abcPath = path.join(arkPlatformPath, 'bin', 'js2abc'); 258 arkConfig.aotCompilerPath = path.join(arkPlatformPath, 'bin', 'ark_aot_compiler'); 259 return; 260 } 261} 262 263function processCompatibleVersion(projectConfig: any, arkRootPath: string) { 264 const platformPath: string = getArkBuildDir(arkRootPath); 265 if (projectConfig.minPlatformVersion && projectConfig.minPlatformVersion.toString() === '8') { 266 // use ts2abc to compile apps with 'CompatibleSdkVersion' set to 8 267 arkConfig.ts2abcPath = path.join(platformPath, 'legacy_api8', 'src', 'index.js'); 268 projectConfig.pandaMode = TS2ABC; 269 } 270} 271