diff --git a/packages/flutter_tools/lib/src/ohos/hvigor.dart b/packages/flutter_tools/lib/src/ohos/hvigor.dart index 99e0560836482d1ae352a0f86d54170e0220c99c..b305d18f29e1f43e33ff79430131588e22cf7fb5 100644 --- a/packages/flutter_tools/lib/src/ohos/hvigor.dart +++ b/packages/flutter_tools/lib/src/ohos/hvigor.dart @@ -33,6 +33,9 @@ import '../build_system/build_system.dart'; import '../build_system/targets/ohos.dart'; import '../cache.dart'; import '../globals.dart' as globals; +import '../platform_plugins.dart'; +import '../plugins.dart'; +import '../flutter_plugins.dart'; import '../project.dart'; import '../reporting/reporting.dart'; import 'application_package.dart'; @@ -141,7 +144,7 @@ Future invokeCmd( final String cmd = command.join(' '); logger?.printTrace('Invoke cmd: $cmd'); final Process server = - await processManager.start(command, workingDirectory: workDirectory); + await processManager.start(command, environment: {'ALBuildFlutter':'1'}, workingDirectory: workDirectory); server.stderr .transform(utf8.decoder) @@ -582,8 +585,13 @@ class OhosHvigorBuilder implements OhosBuilder { cleanAndCopyFlutterAsset( _ohosProject, ohosBuildInfo, _logger, _ohosRootPath, output); - cleanAndCopyFlutterRuntime( - _ohosProject, ohosBuildInfo, _logger, _ohosRootPath, _ohosBuildData); + if(flutterProject.isModule) { + cleanAndCopyFlutterRuntime( + _ohosProject, ohosBuildInfo, _logger, _ohosProject.flutterModuleDirectory.path, _ohosBuildData); + } else { + cleanAndCopyFlutterRuntime( + _ohosProject, ohosBuildInfo, _logger, _ohosRootPath, _ohosBuildData); + } // ohpm install for all modules // ohosProject.deleteOhModulesCache(); @@ -608,22 +616,34 @@ class OhosHvigorBuilder implements OhosBuilder { final Status status = _logger.startProgress( 'Running Hvigor task assembleHar...', ); + /// + final String onlyBuildFlutter = Platform.environment['ONLY_BUILD_Flutter'] ?? ''; + if (onlyBuildFlutter != '') { + parseData(project, _logger); + await flutterBuildPre(project, ohosBuildInfo, target); + status.stop(); + return; + } else { - await addPluginsModules(project); - await addFlutterModuleAndPluginsSrcOverrides(project); - - parseData(project, _logger); - - await flutterBuildPre(project, ohosBuildInfo, target); - - /// 生成 module 和所有 plugin 的 har - await assembleHars(_processUtils, project, ohosBuildInfo, _logger); - await assembleHsps(_processUtils, project, ohosBuildInfo, _logger); + parseData(project, _logger); + await flutterBuildPre(project, ohosBuildInfo, target); + /// 生成 module 和所有 plugin 的 har + await assemblePluginsHars(_processUtils, project, ohosBuildInfo, _logger); - await removePluginsModules(project); - await addFlutterModuleAndPluginsOverrides(project); - status.stop(); - printHowToConsumeHar(logger: _logger); + await changeOhosPluginsDependencies(project,true); + await ohpmInstall( + processUtils: _processUtils, + workingDirectory: _ohosRootPath, + logger: _logger, + ); + /// 编译portal har + await assembleModuleHar(_processUtils, project, ohosBuildInfo, _logger); + /// 去掉依赖 + await changeOhosPluginsDependencies(project,false); + status.stop(); + printHowToConsumeHar(logger: _logger); + return; + } } /// Prints how to consume the har from a host app. @@ -638,12 +658,6 @@ class OhosHvigorBuilder implements OhosBuilder { "dependencies": { "@ohos/flutter_module": "file:path/to/har/flutter_module.har" } - - 3. Override flutter and plugins dependencies: - - "overrides" { - "@ohos/flutter_ohos": "file:path/to/har/flutter.har", - } '''); } @@ -790,6 +804,107 @@ class OhosHvigorBuilder implements OhosBuilder { } } + Future assemblePluginsHars( + ProcessUtils processUtils, + FlutterProject project, + OhosBuildInfo ohosBuildInfo, + Logger? logger, + ) async { + final String ohosProjectPath = project.ohos.ohosRoot.path; + List modules = []; + final String modulePath = project.ohos.flutterModuleDirectory.path; + + final List plugins = (await findPlugins(project)) + .where((Plugin p) => p.platforms.containsKey(OhosPlugin.kConfigKey)) + .toList(); + if (plugins.isEmpty) { + return; + } + + for (final Plugin plugin in plugins) { + OhosModule module = OhosModule.fromModulePath(modulePath: plugin.path+'ohos'); + modules.add(module); + } + + + // compile hars. parallel compilation. + final String hvigorwPath = getHvigorwPath(ohosProjectPath, checkMod: true); + final String moduleName = + _moduleNameWithFlavor(modules, ohosBuildInfo.buildInfo.flavor); + final int errorCode = await assembleHar( + processUtils: processUtils, + workPath: ohosProjectPath, + moduleName: moduleName, + hvigorwPath: hvigorwPath, + buildMode: ohosBuildInfo.buildInfo.modeName, + logger: logger); + if (errorCode != 0) { + throwToolExit('Oops! assembleHars failed! please check log.'); + } + + // copy hars + for (final OhosModule module in modules) { + final File originHar = globals.fs.file(globals.fs.path.join( + module.srcPath, + 'build', + 'default', + 'outputs', + module.flavor, + '${module.name}.har')); + if (!originHar.existsSync()) { + throwToolExit('Oops! Failed to find: ${originHar.path}'); + } + final String desPath = + globals.fs.path.join(modulePath, 'har', '${module.name}.har'); + ensureParentExists(desPath); + originHar.copySync(desPath); + } + } + + Future assembleModuleHar( + ProcessUtils processUtils, + FlutterProject project, + OhosBuildInfo ohosBuildInfo, + Logger? logger, + ) async { + final String ohosProjectPath = project.ohos.ohosRoot.path; + List modules = []; + final String modulePath = project.ohos.flutterModuleDirectory.path; + modules.add(OhosModule.fromModulePath(modulePath: modulePath)); + + final String hvigorwPath = getHvigorwPath(ohosProjectPath, checkMod: true); + final String moduleName = + _moduleNameWithFlavor(modules, ohosBuildInfo.buildInfo.flavor); + final int errorCode = await assembleHar( + processUtils: processUtils, + workPath: ohosProjectPath, + moduleName: moduleName, + hvigorwPath: hvigorwPath, + buildMode: ohosBuildInfo.buildInfo.modeName, + logger: logger); + if (errorCode != 0) { + throwToolExit('Oops! assembleHars failed! please check log.'); + } + + // copy hars + for (final OhosModule module in modules) { + final File originHar = globals.fs.file(globals.fs.path.join( + module.srcPath, + 'build', + 'default', + 'outputs', + module.flavor, + '${module.name}.har')); + if (!originHar.existsSync()) { + throwToolExit('Oops! Failed to find: ${originHar.path}'); + } + final String desPath = + globals.fs.path.join(ohosProjectPath, 'har', '${module.name}.har'); + ensureParentExists(desPath); + originHar.copySync(desPath); + } + } + Future assembleHsps( ProcessUtils processUtils, FlutterProject project, diff --git a/packages/flutter_tools/lib/src/ohos/ohos_plugins_manager.dart b/packages/flutter_tools/lib/src/ohos/ohos_plugins_manager.dart index c0a4dd22246d4dc2985e3f7d4356b502b5a46507..d1ac12ec8b5d3526ad3457f0c3298879423f546a 100644 --- a/packages/flutter_tools/lib/src/ohos/ohos_plugins_manager.dart +++ b/packages/flutter_tools/lib/src/ohos/ohos_plugins_manager.dart @@ -5,6 +5,7 @@ */ import 'dart:convert'; +import 'dart:ffi'; import 'package:json5/json5.dart'; @@ -16,6 +17,7 @@ import '../globals.dart' as globals; import '../platform_plugins.dart'; import '../plugins.dart'; import '../project.dart'; +import 'dart:io' as io; const String kUseAbsolutePathOfHar = 'useAbsolutePathOfHar'; @@ -37,17 +39,31 @@ Future checkOhosPluginsDependencies(FlutterProject flutterProject) async { final Map config = JSON5.parse(packageConfig) as Map; final Map dependencies = config['dependencies'] as Map; + + if (flutterProject.isModule) { + dependencies['@ohos/flutter_ohos'] = 'file:./har/flutter.har'; + } + final List removeList = []; for (final Plugin plugin in plugins) { + ///修改plugin中对@ohos/flutter的依赖版本为* + changePluginFlutterHarDependency(plugin); + for (final String key in dependencies.keys) { if (key.startsWith('@ohos') && key.contains(plugin.name)) { removeList.add(key); } } - final String absolutePath = globals.fs.path.join(flutterProject.ohos.ohosRoot.path, 'har/${plugin.name}.har'); - if (useAbsolutePathOfHar && flutterProject.isModule) { - dependencies[plugin.name] = 'file:$absolutePath'; + + if (flutterProject.isModule) { + if (useAbsolutePathOfHar) { + dependencies[plugin.name] = 'file:./har/${plugin.path}.har'; + } else { + final String relativePath = _relative('${plugin.path}ohos', globals.fs.path.dirname(packageFile.path)); + dependencies[plugin.name] = 'file:${relativePath}'; + } } else { + final String absolutePath = globals.fs.path.join(flutterProject.ohos.ohosRoot.path, 'har/${plugin.name}.har'); final String relativePath = _relative(absolutePath, globals.fs.path.dirname(packageFile.path)); dependencies[plugin.name] = 'file:$relativePath'; } @@ -61,6 +77,18 @@ Future checkOhosPluginsDependencies(FlutterProject flutterProject) async { packageFile.writeAsStringSync(configNew, flush: true); } +void changePluginFlutterHarDependency(Plugin plugin){ + + final String pluginPackagePath = globals.fs.path.join(plugin.path, OhosPlugin.kConfigKey,'oh-package.json5'); + final io.File file = io.File(pluginPackagePath); + final String pluginConfig = file.readAsStringSync(); + final Map pluginConfigMap = JSON5.parse(pluginConfig) as Map; + final Map dependencies = (pluginConfigMap['dependencies'] as Map).cast(); + dependencies['@ohos/flutter_ohos'] = '*'; + final String pluginConfigMapNew = const JsonEncoder.withIndent(' ').convert(pluginConfigMap); + file.writeAsStringSync(pluginConfigMapNew, flush: true); +} + /// 添加到工程级 build-profile.json5 的 modules 中 Future addPluginsModules(FlutterProject flutterProject) async { final List plugins = (await findPlugins(flutterProject)) @@ -99,6 +127,48 @@ Future addPluginsModules(FlutterProject flutterProject) async { buildProfileFile.writeAsStringSync(buildProfileNew, flush: true); } + +Future changeOhosPluginsDependencies(FlutterProject flutterProject,bool useHar) async { + final List plugins = (await findPlugins(flutterProject)) + .where((Plugin p) => p.platforms.containsKey(OhosPlugin.kConfigKey)) + .toList(); + final File packageFile = flutterProject.ohos.flutterModulePackageFile; + if (!packageFile.existsSync()) { + globals.logger.printTrace('check if oh-package.json5 file:($packageFile) exist ?'); + return; + } + + final String packageConfig = packageFile.readAsStringSync(); + final Map config = JSON5.parse(packageConfig) as Map; + final Map dependencies = + config['dependencies'] as Map; + + final List removeList = []; + + for (final Plugin plugin in plugins) { + for (final String key in dependencies.keys) { + if (key.startsWith('@ohos') && key.contains(plugin.name)) { + removeList.add(key); + } + } + + if (useHar) { + dependencies[plugin.name] = 'file:./har/${plugin.name}.har'; + } else { + dependencies[plugin.name] = 'file:${plugin.path}ohos'; + } + } + + for (final String key in removeList) { + globals.printStatus( + 'OhosDependenciesManager: deprecated plugin dependencies "$key" has been removed.'); + dependencies.remove(key); + } + final String configNew = const JsonEncoder.withIndent(' ').convert(config); + packageFile.writeAsStringSync(configNew, flush: true); +} + + /// 在工程级的的oh-package.json5里添加flutter_module以及plugins的配置 Future addFlutterModuleAndPluginsSrcOverrides(FlutterProject flutterProject) async { final List plugins = (await findPlugins(flutterProject)) diff --git a/packages/flutter_tools/templates/module/ohos/host_config/oh-package.json5.tmpl b/packages/flutter_tools/templates/module/ohos/host_config/oh-package.json5.tmpl index 38968fc7e4daf80c37a2adf005519941daca9d28..1d8c524f2725422aa63ea848b1feaca1aa5f9912 100644 --- a/packages/flutter_tools/templates/module/ohos/host_config/oh-package.json5.tmpl +++ b/packages/flutter_tools/templates/module/ohos/host_config/oh-package.json5.tmpl @@ -27,6 +27,6 @@ "@ohos/hypium": "1.0.6" }, "overrides": { - '@ohos/flutter_ohos': 'file:./har/flutter.har', + '@ohos/flutter_ohos': 'file:./flutter_module/har/flutter.har', }, } diff --git a/packages/flutter_tools/templates/module/ohos/hvigor_plugin/hvigorconfig.ts.tmpl b/packages/flutter_tools/templates/module/ohos/hvigor_plugin/hvigorconfig.ts.tmpl new file mode 100644 index 0000000000000000000000000000000000000000..daefe9221215b0ddf8b3b023a440701da945eecc --- /dev/null +++ b/packages/flutter_tools/templates/module/ohos/hvigor_plugin/hvigorconfig.ts.tmpl @@ -0,0 +1,33 @@ +import { hvigor, HvigorNode, HvigorPlugin, hvigorCore } from '@ohos/hvigor'; +import * as fs from 'fs'; +import * as path from 'path'; + +const hvigorConfig = hvigor.getHvigorConfig(); +const allNodeDescriptors = hvigor.getHvigorConfig().getAllNodeDescriptor(); + +for (const item of allNodeDescriptors) { + if (item.name === 'flutter_module') { + var pluginsFilePath = path.resolve(item.srcPath, '../../.flutter-plugins-dependencies'); + if (fs.existsSync(pluginsFilePath)) { + const data = fs.readFileSync( pluginsFilePath, 'utf8'); + const jsonData = JSON.parse(data); + if (jsonData && jsonData["plugins"] && jsonData["plugins"]["ohos"]){ + var ohosPlugs = jsonData["plugins"]["ohos"]; + for (const plugin of ohosPlugs) { + var isFind = false; + for (const tItem of allNodeDescriptors) { + if (tItem.name == plugin.name) { + isFind = true; + } + } + if (!isFind) { + hvigorConfig.includeNode(plugin.name, path.relative('./', plugin.path+'ohos')); + console.log('主壳中增加module:'+ plugin.name + 'from path: '+ plugin.path+'ohos'); + } else { + console.log('plugin:'+ plugin.name + '已经在主动制定过,将不在动态追加'); + } + } + } + } + } +} \ No newline at end of file diff --git a/packages/flutter_tools/templates/module/ohos/module_library/flutter_module.tmpl/hvigorfile.ts.tmpl b/packages/flutter_tools/templates/module/ohos/module_library/flutter_module.tmpl/hvigorfile.ts.tmpl index d3aba127d60569f70f3bc6eacc9db994eb9af8f6..3f0c477d95e62337019d0440296b9bb897c36ade 100644 --- a/packages/flutter_tools/templates/module/ohos/module_library/flutter_module.tmpl/hvigorfile.ts.tmpl +++ b/packages/flutter_tools/templates/module/ohos/module_library/flutter_module.tmpl/hvigorfile.ts.tmpl @@ -14,8 +14,90 @@ */ import { harTasks } from '@ohos/hvigor-ohos-plugin'; +import { harTasks, OhosHarContext, OhosPluginId, Target,OhosAppContext } from '@ohos/hvigor-ohos-plugin'; +import { execSync } from 'child_process'; +import { hvigor, HvigorNode, HvigorPlugin } from '@ohos/hvigor'; +import * as fs from 'fs'; +import * as path from 'path'; -export default { - system: harTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ - plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +function fileExists(filePath: string): boolean { + try { + const stats = fs.statSync(filePath); + return true; + } catch (error) { + return false + } +} +export function buildFlutterPlugin(): HvigorPlugin { + return { + pluginId: 'buildFlutterPlugin', + context() { + return { + data: 'customPlugin xxx' + }; + }, + async apply(currentNode: HvigorNode): Promise { + hvigor.nodesEvaluated(async () => { + hapTask(currentNode); + }); + } + }; +} +function hapTask(currentNode: HvigorNode) { + let env = process.env; + //是否包含自动构建flutter + let ALBuildFlutter = process.env.ALBuildFlutter; + if (ALBuildFlutter==1) {// + console.log('命令包含构建Flutter,不在module内部构建Flutter') + return; + } + //判断是否是源码flutter module工程。 + const harContext = currentNode.getContext(OhosPluginId.OHOS_HAR_PLUGIN) as OhosHarContext; + const parentDirectory = path.dirname(harContext.getModulePath()); // 获取父目录路径 + const grandDirectory = path.dirname(parentDirectory); // 获取父目录路径 + if (!fileExists(grandDirectory+'/pubspec.yaml')) { + console.log('不存在pubspec.yaml,不进行Flutter编译') + return; + } + + let isBuild = false; + let cmdArray = hvigor.getCommandEntryTask(); + if (cmdArray.length > 0) { + for (let i = 0; i < cmdArray.length; i++) { + if (cmdArray[i] == 'clean') { + var cleanCmd = `cd ${grandDirectory} && flutter clean`; + const output = execSync(cleanCmd, { maxBuffer: 1024 * 1024 * 1000 }); + console.log('clean flutter的编译产物'); + } + if (cmdArray[i].startsWith('assemble')) { + isBuild = true; + } + } + } + + if (!isBuild) { + console.log('不存在编译命令,不进行编译'); + return; + } + const parentNode = currentNode.getParentNode(); + const AppContext = parentNode.getContext(OhosPluginId.OHOS_APP_PLUGIN) as OhosAppContext; + + console.log(AppContext.getBuildMode()); + let nodeHome = env.NODE_HOME; + if (nodeHome.endsWith('/bin')) { + nodeHome = nodeHome.slice(0, -'/bin'.length); + } + var buildCmd = `cd ${grandDirectory} && export NODE_HOME=${nodeHome} && export ONLY_BUILD_Flutter=1 && flutter build har --debug --target lib/main.dart`; + if (AppContext.getBuildMode() != 'debug') + buildCmd = `cd ${grandDirectory} && export NODE_HOME=${nodeHome} && export ONLY_BUILD_Flutter=1 && flutter build har --release --target lib/main.dart`; + console.log(buildCmd); + const output = execSync(buildCmd, { maxBuffer: 1024 * 1024 * 1000 }); + console.log('编译完成'); } + +export default { + system: harTasks, // Hvigor内置插件,不可修改 + plugins: [ + buildFlutterPlugin(), + ] +} \ No newline at end of file diff --git a/packages/flutter_tools/templates/module/ohos/module_library/flutter_module.tmpl/oh-package.json5.tmpl b/packages/flutter_tools/templates/module/ohos/module_library/flutter_module.tmpl/oh-package.json5.tmpl index 1fa6a4dfea9bdf543faaced48884a2f6cfbbeb73..584b991fa61ddc1ab2ded51980d56f51c605d3ee 100644 --- a/packages/flutter_tools/templates/module/ohos/module_library/flutter_module.tmpl/oh-package.json5.tmpl +++ b/packages/flutter_tools/templates/module/ohos/module_library/flutter_module.tmpl/oh-package.json5.tmpl @@ -21,7 +21,7 @@ "author": "", "license": "OpenValley", "dependencies": { - "@ohos/flutter_ohos": "file:../har/flutter.har" + "@ohos/flutter_ohos": "file:./har/flutter.har" }, }