kotlin.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. "use strict";
  2. var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
  3. if (k2 === undefined) k2 = k;
  4. var desc = Object.getOwnPropertyDescriptor(m, k);
  5. if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
  6. desc = { enumerable: true, get: function() { return m[k]; } };
  7. }
  8. Object.defineProperty(o, k2, desc);
  9. }) : (function(o, m, k, k2) {
  10. if (k2 === undefined) k2 = k;
  11. o[k2] = m[k];
  12. }));
  13. var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
  14. Object.defineProperty(o, "default", { enumerable: true, value: v });
  15. }) : function(o, v) {
  16. o["default"] = v;
  17. });
  18. var __importStar = (this && this.__importStar) || function (mod) {
  19. if (mod && mod.__esModule) return mod;
  20. var result = {};
  21. if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
  22. __setModuleDefault(result, mod);
  23. return result;
  24. };
  25. var __importDefault = (this && this.__importDefault) || function (mod) {
  26. return (mod && mod.__esModule) ? mod : { "default": mod };
  27. };
  28. Object.defineProperty(exports, "__esModule", { value: true });
  29. exports.getUniModulesJars = exports.getUniModulesCacheJars = exports.checkAndroidVersionTips = exports.resolveJarPath = exports.resolveDexFile = exports.resolveD8Args = exports.resolveKotlincArgs = exports.compile = exports.resolveAndroidDepFiles = exports.runKotlinDev = exports.runKotlinProd = exports.createKotlinResolveTypeReferenceName = void 0;
  30. const os_1 = __importDefault(require("os"));
  31. const fs_extra_1 = __importDefault(require("fs-extra"));
  32. const path_1 = __importStar(require("path"));
  33. const adm_zip_1 = __importDefault(require("adm-zip"));
  34. const fast_glob_1 = require("fast-glob");
  35. const shared_1 = require("@vue/shared");
  36. const android_versions_1 = require("android-versions");
  37. const shared_2 = require("./shared");
  38. const utils_1 = require("./utils");
  39. const stacktrace_1 = require("./stacktrace");
  40. const manifest_1 = require("./manifest");
  41. function createKotlinResolveTypeReferenceName(_namespace, _ast) {
  42. return (name) => name;
  43. }
  44. exports.createKotlinResolveTypeReferenceName = createKotlinResolveTypeReferenceName;
  45. function parseKotlinPackage(filename) {
  46. const res = (0, utils_1.resolvePackage)(filename);
  47. if (!res) {
  48. return { id: '', package: '' };
  49. }
  50. return {
  51. id: res.id,
  52. package: (0, utils_1.parseKotlinPackageWithPluginId)(res.name, res.is_uni_modules),
  53. };
  54. }
  55. async function runKotlinProd(filename, components, { isPlugin, isX, extApis, }) {
  56. // 文件有可能是 app-ios 里边的,因为编译到 android 时,为了保证不报错,可能会去读取 ios 下的 uts
  57. if (filename.includes('app-ios')) {
  58. return;
  59. }
  60. const inputDir = process.env.UNI_INPUT_DIR;
  61. const outputDir = process.env.UNI_OUTPUT_DIR;
  62. const result = await compile(filename, {
  63. inputDir,
  64. outputDir,
  65. sourceMap: true,
  66. components,
  67. isX,
  68. isPlugin,
  69. extApis,
  70. });
  71. if (!result) {
  72. return;
  73. }
  74. if (result.error) {
  75. throw (0, stacktrace_1.parseUTSSyntaxError)(result.error, inputDir);
  76. }
  77. (0, utils_1.genUTSPlatformResource)(filename, {
  78. inputDir,
  79. outputDir,
  80. platform: 'app-android',
  81. extname: '.kt',
  82. components,
  83. package: parseKotlinPackage(filename).package + '.',
  84. });
  85. }
  86. exports.runKotlinProd = runKotlinProd;
  87. async function runKotlinDev(filename, { components, isX, isPlugin, cacheDir, pluginRelativeDir, is_uni_modules, extApis, }) {
  88. // 文件有可能是 app-ios 里边的,因为编译到 android 时,为了保证不报错,可能会去读取 ios 下的 uts
  89. if (filename.includes('app-ios')) {
  90. return;
  91. }
  92. const inputDir = process.env.UNI_INPUT_DIR;
  93. const outputDir = process.env.UNI_OUTPUT_DIR;
  94. const result = (await compile(filename, {
  95. inputDir,
  96. outputDir,
  97. sourceMap: true,
  98. components,
  99. isX,
  100. isPlugin,
  101. extApis,
  102. }));
  103. if (!result) {
  104. return;
  105. }
  106. if (result.error) {
  107. throw (0, stacktrace_1.parseUTSSyntaxError)(result.error, inputDir);
  108. }
  109. result.type = 'kotlin';
  110. result.changed = [];
  111. const kotlinFile = (0, utils_1.resolveUTSPlatformFile)(filename, {
  112. inputDir,
  113. outputDir,
  114. platform: 'app-android',
  115. extname: '.kt',
  116. components,
  117. package: '',
  118. });
  119. // 开发模式下,需要生成 dex
  120. if (fs_extra_1.default.existsSync(kotlinFile)) {
  121. const compilerServer = (0, utils_1.getCompilerServer)('uniapp-runextension');
  122. if (!compilerServer) {
  123. throw `项目使用了uts插件,正在安装 uts Android 运行扩展...`;
  124. }
  125. const { getDefaultJar, getKotlincHome, compile: compileDex, checkDependencies, checkRResources, } = compilerServer;
  126. let deps = [];
  127. if (checkDependencies) {
  128. deps = await checkDeps(filename, checkDependencies);
  129. }
  130. let resDeps = [];
  131. if (checkRResources) {
  132. resDeps = await checkRes(filename, checkRResources);
  133. }
  134. // time = Date.now()
  135. const jarFile = resolveJarPath('app-android', cacheDir, pluginRelativeDir, kotlinFile);
  136. const options = {
  137. kotlinc: resolveKotlincArgs(kotlinFile, jarFile, getKotlincHome(), (isX ? getDefaultJar(2) : getDefaultJar())
  138. .concat(resolveLibs(filename))
  139. .concat(deps)
  140. .concat(resDeps)
  141. // .concat(getUniModulesCacheJars(cacheDir))
  142. // .concat(getUniModulesJars(outputDir))
  143. ),
  144. d8: resolveD8Args(jarFile),
  145. sourceRoot: inputDir,
  146. sourceMapPath: (0, utils_1.resolveSourceMapFile)(outputDir, kotlinFile),
  147. };
  148. const res = await compileDex(options, inputDir);
  149. // console.log('dex compile time: ' + (Date.now() - time) + 'ms')
  150. if (res) {
  151. try {
  152. // 其他插件或 x 需要该插件的 jar 做编译
  153. // fs.unlinkSync(jarFile)
  154. // 短期内先不删除,方便排查问题
  155. // fs.unlinkSync(kotlinFile)
  156. }
  157. catch (e) { }
  158. const dexFile = resolveDexFile(jarFile);
  159. if (fs_extra_1.default.existsSync(dexFile)) {
  160. const newDexFile = (0, manifest_1.restoreDex)(pluginRelativeDir, cacheDir, outputDir, is_uni_modules);
  161. result.changed = [
  162. (0, shared_2.normalizePath)(path_1.default.relative(outputDir, newDexFile || dexFile)),
  163. ];
  164. }
  165. }
  166. // else {
  167. // throw `${normalizePath(
  168. // path.relative(process.env.UNI_INPUT_DIR, filename)
  169. // )} 编译失败`
  170. // }
  171. }
  172. return result;
  173. }
  174. exports.runKotlinDev = runKotlinDev;
  175. function checkDeps(filename, checkDependencies) {
  176. const configJsonFile = resolveConfigJsonFile(filename);
  177. if (configJsonFile && hasDeps(configJsonFile)) {
  178. return checkDependencies(configJsonFile).then(({ code, msg, data }) => {
  179. if (code !== 0) {
  180. console.error(msg);
  181. return [];
  182. }
  183. return data;
  184. });
  185. }
  186. return Promise.resolve([]);
  187. }
  188. function hasDeps(configJsonFile) {
  189. const deps = (0, shared_2.parseJson)(fs_extra_1.default.readFileSync(configJsonFile, 'utf8')).dependencies || [];
  190. if ((0, shared_1.isArray)(deps) && deps.length) {
  191. return true;
  192. }
  193. return false;
  194. }
  195. function checkRes(filename, checkRResources) {
  196. const resDir = resolveResDir(filename);
  197. if (resDir) {
  198. return checkRResources(resDir).then(({ code, msg, data }) => {
  199. if (code !== 0) {
  200. console.error(msg);
  201. return [];
  202. }
  203. return [data.jarPath];
  204. });
  205. }
  206. return Promise.resolve([]);
  207. }
  208. function resolveResDir(filename) {
  209. const resDir = path_1.default.resolve((0, utils_1.resolveAndroidDir)(filename), 'res');
  210. if (fs_extra_1.default.existsSync(resDir)) {
  211. return resDir;
  212. }
  213. }
  214. function resolveAndroidResourceClass(filename) {
  215. const resDir = resolveResDir(filename);
  216. if (resDir && fs_extra_1.default.readdirSync(resDir).length) {
  217. const pkg = resolveAndroidManifestPackage(filename);
  218. if (pkg) {
  219. return pkg + '.R';
  220. }
  221. }
  222. }
  223. const packageRe = /\s+package="(.*)"/;
  224. function resolveAndroidManifestPackage(filename) {
  225. const manifestXmlPath = path_1.default.resolve((0, utils_1.resolveAndroidDir)(filename), 'AndroidManifest.xml');
  226. if (fs_extra_1.default.existsSync(manifestXmlPath)) {
  227. const matches = fs_extra_1.default.readFileSync(manifestXmlPath, 'utf8').match(packageRe);
  228. if (matches && matches[1]) {
  229. return matches[1];
  230. }
  231. }
  232. }
  233. const deps = ['AndroidManifest.xml', 'config.json'];
  234. function resolveAndroidDepFiles(filename) {
  235. const dir = (0, utils_1.resolveAndroidDir)(filename);
  236. return deps.map((dep) => path_1.default.resolve(dir, dep));
  237. }
  238. exports.resolveAndroidDepFiles = resolveAndroidDepFiles;
  239. function resolveConfigJsonFile(filename) {
  240. const configJsonFile = path_1.default.resolve((0, utils_1.resolveAndroidDir)(filename), 'config.json');
  241. if (fs_extra_1.default.existsSync(configJsonFile)) {
  242. return configJsonFile;
  243. }
  244. }
  245. const DEFAULT_IMPORTS = [
  246. 'kotlinx.coroutines.async',
  247. 'kotlinx.coroutines.CoroutineScope',
  248. 'kotlinx.coroutines.Deferred',
  249. 'kotlinx.coroutines.Dispatchers',
  250. 'io.dcloud.uts.Map',
  251. 'io.dcloud.uts.UTSAndroid',
  252. 'io.dcloud.uts.*',
  253. ];
  254. async function compile(filename, { inputDir, outputDir, sourceMap, components, isX, isPlugin, extApis, }) {
  255. const { bundle, UTSTarget } = (0, utils_1.getUTSCompiler)();
  256. // let time = Date.now()
  257. const imports = [...DEFAULT_IMPORTS];
  258. const rClass = resolveAndroidResourceClass(filename);
  259. if (rClass) {
  260. imports.push(rClass);
  261. }
  262. const componentsCode = (0, utils_1.genComponentsCode)(filename, components, isX);
  263. const { package: pluginPackage, id: pluginId } = parseKotlinPackage(filename);
  264. const input = {
  265. root: inputDir,
  266. filename,
  267. pluginId,
  268. paths: {},
  269. };
  270. const isUTSFileExists = fs_extra_1.default.existsSync(filename);
  271. if (componentsCode) {
  272. if (!isUTSFileExists) {
  273. input.fileContent = componentsCode;
  274. }
  275. else {
  276. input.fileContent =
  277. fs_extra_1.default.readFileSync(filename, 'utf8') + `\n` + componentsCode;
  278. }
  279. }
  280. else {
  281. // uts文件不存在,且也无组件
  282. if (!isUTSFileExists) {
  283. return;
  284. }
  285. }
  286. const options = {
  287. input,
  288. output: {
  289. isX,
  290. isPlugin,
  291. outDir: outputDir,
  292. package: pluginPackage,
  293. sourceMap: sourceMap ? (0, utils_1.resolveUTSSourceMapPath)() : false,
  294. extname: 'kt',
  295. imports,
  296. logFilename: true,
  297. noColor: !(0, utils_1.isColorSupported)(),
  298. transform: {
  299. uniExtApiDefaultNamespace: 'io.dcloud.uts.extapi',
  300. uniExtApiNamespaces: extApis,
  301. },
  302. },
  303. };
  304. const result = await bundle(UTSTarget.KOTLIN, options);
  305. sourceMap &&
  306. (0, utils_1.moveRootIndexSourceMap)(filename, {
  307. inputDir,
  308. outputDir,
  309. platform: 'app-android',
  310. extname: '.kt',
  311. components,
  312. package: '',
  313. });
  314. return result;
  315. }
  316. exports.compile = compile;
  317. function resolveKotlincArgs(filename, dest, kotlinc, jars) {
  318. return [
  319. filename,
  320. '-cp',
  321. resolveClassPath(jars),
  322. '-d',
  323. dest,
  324. '-kotlin-home',
  325. kotlinc,
  326. ];
  327. }
  328. exports.resolveKotlincArgs = resolveKotlincArgs;
  329. function resolveD8Args(filename) {
  330. return [
  331. filename,
  332. '--no-desugaring',
  333. '--min-api',
  334. '19',
  335. '--output',
  336. resolveDexPath(filename),
  337. ];
  338. }
  339. exports.resolveD8Args = resolveD8Args;
  340. function resolveLibs(filename) {
  341. const libsPath = path_1.default.resolve((0, utils_1.resolveAndroidDir)(filename), 'libs');
  342. const libs = [];
  343. if (fs_extra_1.default.existsSync(libsPath)) {
  344. libs.push(...(0, fast_glob_1.sync)('*.jar', { cwd: libsPath, absolute: true }));
  345. const zips = (0, fast_glob_1.sync)('*.aar', { cwd: libsPath });
  346. zips.forEach((name) => {
  347. const outputPath = resolveAndroidArchiveOutputPath(name);
  348. if (!fs_extra_1.default.existsSync(outputPath)) {
  349. // 解压
  350. const zip = new adm_zip_1.default(path_1.default.resolve(libsPath, name));
  351. zip.extractAllTo(outputPath, true);
  352. }
  353. libs.push(...(0, fast_glob_1.sync)('**/*.jar', {
  354. cwd: outputPath,
  355. absolute: true,
  356. }));
  357. });
  358. }
  359. return libs;
  360. }
  361. function resolveAndroidArchiveOutputPath(aar) {
  362. return path_1.default.resolve(process.env.UNI_OUTPUT_DIR, '../.uts/aar', aar ? aar.replace('.aar', '') : '');
  363. }
  364. function resolveDexFile(jarFile) {
  365. return (0, shared_2.normalizePath)(path_1.default.resolve(path_1.default.dirname(jarFile), 'classes.dex'));
  366. }
  367. exports.resolveDexFile = resolveDexFile;
  368. function resolveDexPath(filename) {
  369. return path_1.default.dirname(filename);
  370. }
  371. function resolveJarPath(platform, cacheDir, pluginRelativeDir, filename) {
  372. if (cacheDir) {
  373. return (0, path_1.join)(cacheDir, platform, 'uts', pluginRelativeDir, path_1.default.basename(filename).replace(path_1.default.extname(filename), '.jar'));
  374. }
  375. return filename.replace(path_1.default.extname(filename), '.jar');
  376. }
  377. exports.resolveJarPath = resolveJarPath;
  378. function resolveClassPath(jars) {
  379. return jars.join(os_1.default.platform() === 'win32' ? ';' : ':');
  380. }
  381. function checkAndroidVersionTips(pluginId, pluginDir, is_uni_modules) {
  382. const configJsonFile = (0, path_1.join)(pluginDir, is_uni_modules ? 'utssdk' : '', 'app-android', 'config.json');
  383. if (configJsonFile && fs_extra_1.default.existsSync(configJsonFile)) {
  384. try {
  385. const configJson = (0, shared_2.parseJson)(fs_extra_1.default.readFileSync(configJsonFile, 'utf8'));
  386. if (configJson.minSdkVersion && parseInt(configJson.minSdkVersion) > 19) {
  387. const androidVersion = (0, android_versions_1.get)(configJson.minSdkVersion);
  388. if (androidVersion) {
  389. return `uts插件[${pluginId}]需在 Android ${androidVersion.semver} 版本及以上方可正常使用`;
  390. }
  391. }
  392. }
  393. catch (e) { }
  394. }
  395. }
  396. exports.checkAndroidVersionTips = checkAndroidVersionTips;
  397. function getUniModulesCacheJars(cacheDir) {
  398. if (cacheDir) {
  399. return (0, fast_glob_1.sync)('app-android/uts/uni_modules/*/index.jar', {
  400. cwd: cacheDir,
  401. absolute: true,
  402. });
  403. }
  404. return [];
  405. }
  406. exports.getUniModulesCacheJars = getUniModulesCacheJars;
  407. function getUniModulesJars(outputDir) {
  408. return (0, fast_glob_1.sync)('*/utssdk/app-android/index.jar', {
  409. cwd: path_1.default.resolve(outputDir, 'uni_modules'),
  410. absolute: true,
  411. });
  412. }
  413. exports.getUniModulesJars = getUniModulesJars;