diff --git a/docs/ENSEMBLE_METHOD_ZH.md b/docs/ENSEMBLE_METHOD_ZH.md index 48cb3833dc06871418bbf95788aea2931eb353fb..5d992d5daab4f1f1a64784431240026138fdd502 100755 --- a/docs/ENSEMBLE_METHOD_ZH.md +++ b/docs/ENSEMBLE_METHOD_ZH.md @@ -3,11 +3,12 @@ ## 场景说明 为了实现工具生成的接口被其他子系统或者应用调用,需将生成的代码编译集成到OpenHarmony系统中,使其生成动态库,供OpenHarmony应用层调用。 -本文介绍如何将工具生成的源码利用OpenHarmony编译系统生成动态库供应用层调用。 +本文介绍如何将工具生成的源码利用OpenHarmony编译系统生成动态库供应用层调用,主要是有以下两种方式,分别为增加ohos.build文件方式和增加bundle.json文件方式。 -## 建立模块位置 +## ohos.build方式集成 +### 建立模块位置 -模块目录理论上可以建立在OpenHarmony代码库的任何地方,为行方便,假设OpenHarmony代码库的目录为`OHOS_SRC`,在`OHOS_SRC`目录下,例如建立此次测试模块目录:napitest。此时,`OHOS_SRC`目录下应该有 ark, foundation, device, …, napitest等目录,其中napitest就是刚刚建立的,在napitest目录下,把之前用可执行文件或者插件转换出来的文件全部拷贝到该目录下,并且在该目录下新建一个文件ohos.build。例如napitest目录下有以下文件: +模块目录理论上可以建立在OpenHarmony代码库的任何地方,假设OpenHarmony代码库的目录为`OHOS_SRC`,在`OHOS_SRC/foundation`目录下,例如建立此次测试模块目录:napitest。此时,`OHOS_SRC/foundation`目录下应该有aafwk,ace,ai, …, napitest等目录,其中napitest就是刚刚建立的,在napitest目录下,把之前用可执行文件或者插件转换出来的文件全部拷贝到该目录下,并且在该目录下新建一个文件ohos.build。例如napitest目录下有以下文件: foundation/napitest |-- binding.gyp @@ -20,50 +21,47 @@ |-- x_napi_tool.cpp |-- x_napi_tool.h -## 编译修改点 +### 编译修改点 -### 修改build.gn文件 +#### 修改build.gn文件 ``` -import("//build/ohos.gni") + import("//build/ohos.gni") -ohos_shared_library("napitest") -{ - # 指定编译源文件 - sources = [ - "napitest_middle.cpp", - "napitest.cpp", - "x_napi_tool.cpp", - ] - include_dirs = [ - ".", - "//third_party/node/src", - ] - # 指定编译依赖,如果依赖第三方库,需要在此添加 - deps=[ - "//foundation/ace/napi:ace_napi", - "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog", - ] - public_deps = [ - "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog", - ] - remove_configs = [ "//build/config/compiler:no_rtti" ] - cflags=[ - ] - cflags_cc=[ - "-frtti", - ] - ldflags = [ - ] - # 指定库生成的路径 - relative_install_dir = "module" - # 主要是修改下面两条内容,子系统及其组件,后面会引用 - part_name = "napitest_interface" - subsystem_name = "napitest" -} + ohos_shared_library("napitest") + { + # 指定编译源文件 + sources = [ + "napitest_middle.cpp", + "napitest.cpp", + "x_napi_tool.cpp", + ] + include_dirs = [ + ".", + "//third_party/node/src", + ] + # 指定编译依赖,如果依赖第三方库,需要在此添加 + deps=[ + "//foundation/ace/napi:ace_napi", + "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog", + ] + remove_configs = [ "//build/config/compiler:no_rtti" ] + cflags=[ + ] + cflags_cc=[ + "-frtti", + ] + ldflags = [ + ] + # 指定库生成的路径 + relative_install_dir = "module" + # 主要是修改下面两条内容,子系统及其组件,后面会引用 + part_name = "napitest_interface" + subsystem_name = "napitest" + } ``` -### 修改ohos.build文件 +#### 修改ohos.build文件 其中module_list选项中的"//foundation/napitest"指的是napitest目录,":napitest"指的是上面BUILD.gn中的目标ohos_shared_library("napitest")。 ``` @@ -80,7 +78,186 @@ ohos_shared_library("napitest") } ``` -### 增加子系统 +#### 修改napitest.cpp文件 + +为方便调试,在napitest.cpp文件或napitest_middle.cpp文件中加入打印日志语句。以修改napitest.cpp文件为例,增加以下代码: + + +``` + #include "napitest.h" + #include + using namespace OHOS; + namespace { + constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0, "NAPITESTNAPILayer" }; + #define NAPITEST_LOG(fmt, ...) HiviewDFX::HiLog::Info(LABEL, \ + "%{public}s:%{public}d " fmt, __func__, __LINE__, ##__VA_ARGS__) + } + namespace napitest { + bool fun1(std::string &v, std::string &out) + { + NAPITEST_LOG("napitest fun1 begin!!!!!!!!!!!!!!"); + return true; + } + } +``` +#### 增加子系统 + +在源码/build/subsystem_config.json中增加子系统选项。如下所示: + +``` +"napitest": { + "project": "hmf/napitest", + "path": "foundation/napitest", + "name": "napitest", + "dir": "foundation" + } +``` + +### 添加功能模块 +在产品配置中添加上述子系统的功能模块,编译到产品产出文件中,例如在源码/productdefine/common/products/rk3566.json中增加part选项,其中napitest就是上面填的subsystem_name,napitest_interface就是上面填的part_name。 + + "napitest:napitest_interface":{} + +### 编译验证 + +编译成功后,就会生成libnapitest.z.so,目录如下所示: + + /out/ohos-arm-release/packages/phone/system/lib/module + +## bundle.json方式集成 +### 建立模块位置 + +模块目录理论上可以建立在OpenHarmony代码库的任何地方,假设OpenHarmony代码库的目录为`OHOS_SRC`,在`OHOS_SRC/foundation`目录下,例如建立此次测试模块目录:napitest。此时,`OHOS_SRC/foundation`目录下应该有aafwk,ace,ai, …, napitest等目录,其中napitest就是刚刚建立的,在napitest目录下,把之前用可执行文件或者插件转换出来的文件全部拷贝到该目录下,并且在该目录下新建一个文件bundle.json。例如napitest目录下有以下文件: + + foundation/napitest + |-- binding.gyp + |-- BUILD.gn + |-- bundle.json + |-- napitest.cpp + |-- napitest.h + |-- napitest_middle.cpp + |-- test.sh + |-- x_napi_tool.cpp + |-- x_napi_tool.h + +### 编译修改点 + +#### 修改build.gn文件 + +``` + + import("//build/ohos.gni") + + ohos_shared_library("napitest") + { + # 指定编译源文件 + sources = [ + "napitest_middle.cpp", + "napitest.cpp", + "x_napi_tool.cpp", + ] + include_dirs = [ + ".", + "//third_party/node/src", + ] + # 指定编译依赖,如果依赖第三方库,需要在此添加 + deps=[ + "//foundation/ace/napi:ace_napi", + "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog", + ] + remove_configs = [ "//build/config/compiler:no_rtti" ] + cflags=[ + ] + cflags_cc=[ + "-frtti", + ] + ldflags = [ + ] + # 指定库生成的路径 + relative_install_dir = "module" + # 主要是修改下面两条内容,子系统及其组件,后面会引用 + part_name = "napitest_interface" + subsystem_name = "napitest" + } +``` + +#### 修改bundle.json文件 +其中destPath选项中的"//foundation/napitest"指的是napitest目录,":napitest"指的是上面BUILD.gn中的目标ohos_shared_library("napitest")。 + +``` +{ + "name": "@ohos/napitest", + "description": "napitest provides atomic capabilities", + "version": "3.1", + "license": "Apache License 2.0", + "publishAs": "code-segment", + "segment": { + "destPath": "foundation/napitest" + }, + "dirs": {}, + "scripts": {}, + "component": { + "name": "napitest_interface", + "subsystem": "napitest", + "features": [], + "adapted_system_type": [ + "standard" + ], + "rom": "10000KB", + "ram": "10000KB", + "deps": { + "components": [ + "ace_napi", + "ipc_core", + "libhilog" + ], + "third_party": [ + "node" + ] + }, + "build": { + "sub_component": [ + "//foundation/napitest:napitest" + ], + "inner_kits": [ + { + "header": { + "header_base": "//foundation/napitest", + "header_files": [ + "x_napi_tool.h", + "napitest.h" + ] + }, + "name": "//foundation/napitest:napitest" + } + ] + } + } +} +``` + +#### 修改napitest.cpp文件 +为方便调试,在napitest.cpp文件或napitest_middle.cpp文件中加入打印日志语句。以修改napitest.cpp文件为例,增加以下代码: + + +``` + #include "napitest.h" + #include + using namespace OHOS; + namespace { + constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0, "NAPITESTNAPILayer" }; + #define NAPITEST_LOG(fmt, ...) HiviewDFX::HiLog::Info(LABEL, \ + "%{public}s:%{public}d " fmt, __func__, __LINE__, ##__VA_ARGS__) + } + namespace napitest { + bool fun1(std::string &v, std::string &out) + { + NAPITEST_LOG("napitest fun1 begin!!!!!!!!!!!!!!"); + return true; + } + } +``` +#### 增加子系统 在源码/build/subsystem_config.json中增加子系统选项。如下所示: @@ -94,15 +271,21 @@ ohos_shared_library("napitest") ``` ### 添加功能模块 -在产品配置中添加上述子系统的功能模块,编译到产品产出文件中,例如在源码/productdefine/common/products/rk3566.json中增加part选项,其中napitest就是上面填的part_name,napitest_interface就是上面填的subsystem_name。 +在产品配置中添加上述子系统的功能模块,编译到产品产出文件中,例如在源码/productdefine/common/products/rk3566.json中增加part选项,其中napitest就是上面填的subsystem_name,napitest_interface就是上面填的part_name。 "napitest:napitest_interface":{} -## 编译验证 +### 编译验证 编译成功后,就会生成libnapitest.z.so,目录如下所示: /out/ohos-arm-release/packages/phone/system/lib/module +## 总结 + +两种集成方式使用场景说明: + +ohos.build方式集成:适合3.0前版本使用。 +bundle.json方式集成:兼容ohos.build方式,但3.1及以后版本建议使用此种方式集成。 diff --git a/docs/INTEGRATION_TESTING_ZH.md b/docs/INTEGRATION_TESTING_ZH.md index 1214e09088f20291fb40cc0b141be5f158851a86..884e6c06f66eb8b908fe7a02c09f6edfbe3bba5e 100755 --- a/docs/INTEGRATION_TESTING_ZH.md +++ b/docs/INTEGRATION_TESTING_ZH.md @@ -1,7 +1,7 @@ # NAPI框架生成工具集成测试 ## 简介 - 本文主要介绍如何将NAPI框架生成代码集成NAPI到OpenHarmony系统,进而进行集成测试。 + 本文主要介绍如何将NAPI框架生成代码集成到OpenHarmony系统,进而进行集成测试。 ## 准备 @@ -11,14 +11,61 @@ 系统镜像的具体生成方法,可以左键单击以下链接了解: - [生成代码集成到OpenHarmony的方法](https://gitee.com/openharmony/napi_generator/blob/master/docs/ENSEMBLE_METHOD_ZH.md) + [生成代码集成到OpenHarmony](https://gitee.com/openharmony/napi_generator/blob/master/docs/ENSEMBLE_METHOD_ZH.md) 3.应用hap包:hap包及源码路径如下: -``` +``` napi_generator/examples/app ``` + hap包的具体生成方法,可参考OpenHarmony/docs/zh-cn/application-dev文档中使用JS语言开发(FA模型)。其中修改index.js文件内容如下: + + +``` + + import router from '@ohos.router'; + import napitest from '@ohos.napitest'; + export default { + data: { + title: "" + }, + onInit(){ + this.title = this.$t('strings.world'); + }, + onclick: function () { + router.push({ + url: "pages/second/second" + }) + }, + ontest: function () { + console.log("napitest begin AAAAAAAAAAAAAAAAAA") + var Entity = { + ENTITY_DEFAULT : "entity.system.default", + ENTITY_HOME : "entity.system.home", + ENTITY_VOICE : "entity.system.voice", + ENTITY_BROWSABLE : "entity.system.browsable", + ENTITY_VIDEO : "entity.system.video" + } + napitest.Space3.fun1("ggggg",Entity.ENTITY_DEFAULT); + console.log("napitest end AAAAAAAAAAAAAAAAAA") + } + } +``` + 修改index.html文件内容如下: + +``` + + +
+ + Hello World + + + + +
+``` ## 使用说明 步骤一:安装镜像环境。 @@ -44,12 +91,14 @@ napi_generator/examples/app 然后单击设备中安装的APP,进入APP后单击测试按钮,执行完成后会在hdc安装目录下出现log.txt文件。 ## 查看结果 -log.txt中包含“===isScreenOn===”日志表示接口调用成功。如下所示: - - 03-01 19:48:19.594 916 940 I 00000/power_interface: ===isScreenOn=== - 03-01 19:48:19.594 916 925 I 00000/ProducerEglSurface: <342>AddEglData: bufferImpl is reused return. - 03-01 19:48:19.594 916 925 I 00000/ProducerEglSurface: (Window)<217>WaitForReleaseFence: releaseFence 39. - 03-01 19:48:19.594 916 923 I 03b00/JSApp: app Log: power_is_screen_on_promise_test screenOn is 0 +log.txt中包含“======fun1(name: string, flags: Entity): number======”日志表示接口调用成功。如下所示: + + 01-01 00:13:10.355 2020 2027 I 00000/NAPITESTNAPILayer: fun1_middle:93 *******fun1_middle begin********** + 01-01 00:13:10.357 2020 2038 D 01400/OHOS::ROSEN: RSRenderThread ProcessCommands size: 2 + 01-01 00:13:10.358 2020 2038 D 01400/OHOS::ROSEN: RSRenderThread DrawFrame(790351535051) in GPU + 01-01 00:13:10.360 2020 2027 I 00000/NAPITESTNAPILayer: fun1_middle:107 *****fun1_middle xxxxx********** + 01-01 00:13:10.360 2020 2027 I 00000/NAPITESTNAPILayer: fun1:28 ======fun1(name: string, flags: Entity): number====== + 01-01 00:13:10.360 2020 2027 I 00000/NAPITESTNAPILayer: fun1_middle:113 *******fun1_middle end********* ## 相关仓 diff --git a/napi_vs_plugin/src/extension.js b/napi_vs_plugin/src/extension.js index 55db25b65d027bb4ddd4a1bdd77b4723f764d4d2..fde053276074b7ae314858a32d33b664f05aa3d3 100644 --- a/napi_vs_plugin/src/extension.js +++ b/napi_vs_plugin/src/extension.js @@ -20,6 +20,7 @@ const fs = require('fs'); const re = require("./gen/tools/VsPluginRe"); const { VsPluginLog } = require("./gen/tools/VsPluginLog"); const { detectPlatform, readFile } = require('./gen/tools/VsPluginTool'); +const path = require('path'); var exeFilePath = null; // this method is called when your extension is activated // your extension is activated the very first time the command is executed @@ -59,7 +60,7 @@ function executor(name, genDir, mode) { function genCommand(name, genDir, mode) { var genFileMode = mode == 0 ? " -f " : " -d "; - if (genDir == "") { + if (genDir == ""){ return exeFilePath + genFileMode + name; } return exeFilePath + genFileMode + name + " -o " + genDir; @@ -79,30 +80,73 @@ function register(context, command) { const panel = vscode.window.createWebviewPanel( 'generate', // Identifies the type of WebView 'Generate Napi Frame', // Title of the panel displayed to the user - vscode.ViewColumn.One, // Display the WebView panel in the form of new columns in the editor + vscode.ViewColumn.Two, // Display the WebView panel in the form of new columns in the editor { enableScripts: true, // Enable or disable JS, default is Enable retainContextWhenHidden: true, // Keep the WebView state when it is hidden to avoid being reset } ); - panel.webview.html = getWebviewContent(); + panel.webview.html = getWebviewContent(context); panel.webview.onDidReceiveMessage(message => { - if (message == "cancel") { + let msg = message.msg; + if (msg == "cancel") { panel.dispose(); - } else { + } else if(msg == "param") { let mode = message.mode; let name = message.fileNames; let genDir = message.genDir; checkMode(name, genDir, mode); + } else { + selectPath(panel, message); } }, undefined, context.subscriptions); let fn = re.getFileInPath(uri.fsPath); let tt = re.match("@ohos.[a-zA-Z_0-9]+.d.ts", fn); - panel.webview.postMessage(tt ? uri.fsPath : ""); + var result = { + msg: "selectInterPath", + path: tt ? uri.fsPath : "" + } + panel.webview.postMessage(result); }); return disposable; } +/** +* 选择本地目录/文件夹 +*/ + function selectPath(panel, message) { + let mode = 1; + if (message.mode != undefined) { + mode = message.mode; + } + const options = { + canSelectMany: mode == 0 ? true : false,//是否可以选择多个 + openLabel: mode == 0 ? '选择文件' : '选择文件夹',//打开选择的右下角按钮label + canSelectFiles: mode == 0 ? true : false,//是否选择文件 + canSelectFolders: mode == 0 ? false : true,//是否选择文件夹 + defaultUri:vscode.Uri.file(''),//默认打开本地路径 + filters: { + 'Text files': ['d.ts'] + } + }; + + return vscode.window.showOpenDialog(options).then(fileUri => { + if (fileUri && fileUri[0]) { + console.log('Selected file: ' + fileUri[0].fsPath); + let filePath = ""; + for (let index = 0; index < fileUri.length; index++) { + filePath += fileUri[index].fsPath.concat(","); + } + var result = { + msg: message.msg, + path: filePath.length > 0 ? filePath.substring(0, filePath.length - 1) : filePath + } + panel.webview.postMessage(result); + return fileUri[0].fsPath + } + }); +} + function checkMode(name, genDir, mode) { name = re.replaceAll(name, " ", ""); if ("" == name) { @@ -110,13 +154,13 @@ function checkMode(name, genDir, mode) { return; } if (mode == 0) { - if (name.indexOf(".") < 0) { + if (name.indexOf(".") < 0 || !fs.lstatSync(name).isFile()) { vscode.window.showErrorMessage("Please enter the correct file path!"); return; } } else { - if (name.indexOf(".") > 0) { - vscode.window.showErrorMessage("Please enter the correct folder path!"); + if (name.indexOf(".") > 0 || !fs.lstatSync(name).isDirectory()) { + vscode.window.showErrorMessage("Please enter the correct folder folder!"); return; } } @@ -130,11 +174,24 @@ function checkMode(name, genDir, mode) { // this method is called when your extension is deactivated function deactivate() { } -function getWebviewContent() { +function getWebviewContent(context) { let data = readFile(__dirname + '/vs_plugin_view.html'); + data = getWebViewContent(context, '/vs_plugin_view.html'); return data.toString(); } +function getWebViewContent(context, templatePath) { + const resourcePath = path.join(context.extensionPath, templatePath); + const dirPath = path.dirname(resourcePath); + let html = fs.readFileSync(resourcePath, 'utf-8'); + html = html.replace(/( { + if($2.indexOf("https://")<0)return $1 + vscode.Uri.file(path.resolve(dirPath, $2)) + .with({ scheme: 'vscode-resource' }).toString() + '"'; + else return $1 + $2+'"'; + }); + return html; +} + module.exports = { activate, deactivate diff --git a/napi_vs_plugin/src/images/file.png b/napi_vs_plugin/src/images/file.png new file mode 100644 index 0000000000000000000000000000000000000000..f5c365a02e99414acb29c643fc2d64d150cff9f0 Binary files /dev/null and b/napi_vs_plugin/src/images/file.png differ diff --git a/napi_vs_plugin/src/images/path.png b/napi_vs_plugin/src/images/path.png new file mode 100644 index 0000000000000000000000000000000000000000..56f408a584f243956fab1916d9152f34364cdf78 Binary files /dev/null and b/napi_vs_plugin/src/images/path.png differ diff --git a/napi_vs_plugin/src/vs_plugin_view.html b/napi_vs_plugin/src/vs_plugin_view.html index 437ce254508770944de971eb49262e20cc1a77ac..8570f35eba22ab7d5fed23bb3d8091b8334e26c2 100644 --- a/napi_vs_plugin/src/vs_plugin_view.html +++ b/napi_vs_plugin/src/vs_plugin_view.html @@ -10,7 +10,7 @@