OpenHarmony Tripartite library porting
Tutorial on tripartite library porting process for OpenHarmony systems.
1. Download the native library
When downloading the native library, do not download the master branch, but download the latest version branch.
2. Generate a Makefile
Downloading different native third-party libraries may provide different compilation methods, according to the README file of the native third-party library, you can know how to compile, the following two compilation methods:
1.cmake build
In the root directory of the downloaded method library, CMakeLists exists.txt file
#Create a new build directory
mkdir mybuild && cd mybuild
Through cmake.. Build, at this time, the Makefile file will be generated according to the default configuration options
Through cmake-gui.. Build, the build optional pop-up box will pop up at this time, and the Makefile file will be generated with optional configuration
2.Makefile.am build
Generally, Makefile.am is used to build, and the autogen.sh and configure.ac files exist in the native library.
./autogen.sh
./configure
A Makefile will be generated at this time
3. Analyze the dependence of the library on external libraries
Analyze the log information in the process of generating the Makefile and find the dependencies of this library on other libraries. During the log analysis process, the following situations generally exist:
1. The library name cannot be found in the log. When some third-party libraries generate Makefile files, if the corresponding library can be found in the system, it will not be printed in the log. This kind of situation will be transplanted to OpenHarmony. The compilation process will be reflected in errors. Typically, the header file path cannot be found or the function symbol is missing when linking;
2. Found or not found libraries can be found in the log. By default, these libraries do not exist on OpenHarmony, so these libraries need to be analyzed.
1. os-developed libraries, which can be found in the third_party directory of OpenHarmony;
2. Undeveloped libraries and libraries that are in the plan can be transplanted first, reported and the workload re-evaluated;
3. Undeveloped libraries and libraries that are not planned. Analyze these libraries. Generally, these libraries are divided into two categories. ① There is an impact on the library function, ② There is no impact on the library function. In this part, you need to find the library-related Local analysis code, if it does not affect the function, you can consider ignoring it, otherwise report it and re-evaluate the workload problem;
Each dependent third-party library generally has a corresponding macro definition to control the compilation of the code in the library. During the process of transplanting the third-party library, if there are many library dependencies, you need to pay attention to the switches of these macro definitions.
You can refer to minizip library dependency analysis
四、编译库,并分析Makefile
By analyzing the Makefile,
1. Find the source code required to generate the library, header file path, cflags/cflags_cc, macro definitions, and dependent libraries
2. Find the source code required to generate test/demo, header file path, cflags/cflags_cc, macro definitions, and dependent libraries
5. GNIZATION
The results obtained from the analysis are compiled into the OHOS system, and refer to the compilation and construction guide on the official website.
Explain with zxing-cpp-1.2.0, download zxing-cpp-1.2.0 from github and put it in the third_party of OpenHarmony-3.2-Beta1. Warehouse address.
Modify the following file to add zxing-cpp-1.2.0 to the RK3568 board:
vendor/hihope/rk3568/config.json
Add code:
{
"subsystem": "zxing-cpp-1.2.0",
"components": [
{
"component": "zxing-cpp-1.2.0",
"features": []
}
]
},
Modify the following file to add zxing-cpp-1.2.0 to the subsystem:
build/subsystem_config.json
Add code:
"zxing-cpp-1.2.0": {
"path": "third_party/zxing-cpp-1.2.0",
"name": "zxing-cpp-1.2.0"
},
Create zxing-cpp-1.2.0 to create the compilation component ohos.build:
third_party/zxing-cpp-1.2.0/ohos.build
Add code:
{
"subsystem": "zxing-cpp-1.2.0",
"parts": {
"zxing-cpp-1.2.0": {
"module_list": [
"//third_party/zxing-cpp-1.2.0/example:ZXingReader",
"//third_party/zxing-cpp-1.2.0/example:ZXingWriter"
],
"inner_kits": [
],
"system_kits": [
],
"test_list": [
]
}
}
}
Create a GNN file of zxing-cpp-1.2.0 test:
third_party/zxing-cpp-1.2.0/example/BUILD.gn
Add the code as follows:
#Copyright (c) 2021 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//build/ohos.gni")
config("public"){
cflags_cc = [
"-fexceptions",
"-O3",
"-DNDEBUG",
"-std=c++11",
]
}
config("libnl_config") {
include_dirs = [
"//third_party/zxing-cpp-1.2.0/core",
"//third_party/zxing-cpp-1.2.0/thirdparty/stb"
]
}
ohos_executable("ZXingReader") {
sources = [
"ZXingReader.cpp"
]
public_configs = [ ":libnl_config" ]
deps = [
"//third_party/zxing-cpp-1.2.0:zxing_share"
]
configs = [ ":public" ]
part_name = "zxing-cpp-1.2.0"
}
ohos_executable("ZXingWriter") {
sources = [
"ZXingWriter.cpp"
]
public_configs = [ ":libnl_config" ]
deps = [
"//third_party/zxing-cpp-1.2.0:zxing_share"
]
configs = [ ":public" ]
part_name = "zxing-cpp-1.2.0"
}
Create a dynamic library GNN file for zxing-cpp-1.2.0:
third_party/zxing-cpp-1.2.0/BUILD.gn
Add the code as follows:
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation version 2.1
# of the License.
#
# Copyright(c) 2021-2022 Huawei Device Co., Ltd.
if (!defined(ohos_lite)) {
import("//build/ohos.gni")
}
config("public"){
cflags_cc = [
"-fexceptions",
"-O3",
"-DNDEBUG",
"-fPIC",
"-Wall",
"-Wextra",
"-Wno-missing-braces",
"-Werror=undef",
"-pthread",
"-std=c++17",
"-Wno-error=deprecated-declarations",
"-Wno-deprecated-declarations",
"-Wno-error=sign-compare"
]
}
if (!defined(ohos_lite)) {
config("libnl_config") {
include_dirs = [
"core/src",
"core/aztec",
"core/datamatrix",
"core/maxicode",
"core/oned",
"core/pdf417",
"core/qrcode",
"core/textcodex",
]
}
ohos_shared_library("zxing_share") {
public_configs = [ ":libnl_config" ]
sources = [
"core/src/CharacterSetECI.cpp",
"core/src/BitSource.cpp",
"core/src/ZXBigInteger.cpp",
"core/src/TextUtfEncoding.cpp",
"core/src/HybridBinarizer.cpp",
"core/src/TextEncoder.cpp",
"core/src/BitMatrixIO.cpp",
"core/src/textcodec/KRTextEncoder.cpp",
"core/src/textcodec/Big5TextDecoder.cpp",
"core/src/textcodec/JPTextDecoder.cpp",
"core/src/textcodec/KRHangulMapping.cpp",
"core/src/textcodec/JPTextEncoder.cpp",
"core/src/textcodec/Big5MapTable.cpp",
"core/src/textcodec/GBTextEncoder.cpp",
"core/src/textcodec/Big5TextEncoder.cpp",
"core/src/textcodec/KRTextDecoder.cpp",
"core/src/textcodec/GBTextDecoder.cpp",
"core/src/MultiFormatReader.cpp",
"core/src/GenericGF.cpp",
"core/src/qrcode/QRFormatInformation.cpp",
"core/src/qrcode/QRErrorCorrectionLevel.cpp",
"core/src/qrcode/QRCodecMode.cpp",
"core/src/qrcode/QRMatrixUtil.cpp",
"core/src/qrcode/QRMaskUtil.cpp",
"core/src/qrcode/QRReader.cpp",
"core/src/qrcode/QRWriter.cpp",
"core/src/qrcode/QRDataBlock.cpp",
"core/src/qrcode/QRBitMatrixParser.cpp",
"core/src/qrcode/QRDecoder.cpp",
"core/src/qrcode/QREncoder.cpp",
"core/src/qrcode/QRDetector.cpp",
"core/src/qrcode/QRVersion.cpp",
"core/src/PerspectiveTransform.cpp",
"core/src/pdf417/PDFModulusPoly.cpp",
"core/src/pdf417/PDFBarcodeValue.cpp",
"core/src/pdf417/PDFDetector.cpp",
"core/src/pdf417/PDFCodewordDecoder.cpp",
"core/src/pdf417/PDFBoundingBox.cpp",
"core/src/pdf417/PDFDecodedBitStreamParser.cpp",
"core/src/pdf417/PDFWriter.cpp",
"core/src/pdf417/PDFModulusGF.cpp",
"core/src/pdf417/PDFReader.cpp",
"core/src/pdf417/PDFHighLevelEncoder.cpp",
"core/src/pdf417/PDFEncoder.cpp",
"core/src/pdf417/PDFDetectionResult.cpp",
"core/src/pdf417/PDFScanningDecoder.cpp",
"core/src/pdf417/PDFDetectionResultColumn.cpp",
"core/src/GTIN.cpp",
"core/src/GenericLuminanceSource.cpp",
"core/src/GenericGFPoly.cpp",
"core/src/Result.cpp",
"core/src/BinaryBitmap.cpp",
"core/src/ConcentricFinder.cpp",
"core/src/datamatrix/DMHighLevelEncoder.cpp",
"core/src/datamatrix/DMDetector.cpp",
"core/src/datamatrix/DMVersion.cpp",
"core/src/datamatrix/DMReader.cpp",
"core/src/datamatrix/DMECEncoder.cpp",
"core/src/datamatrix/DMDataBlock.cpp",
"core/src/datamatrix/DMDecoder.cpp",
"core/src/datamatrix/DMSymbolInfo.cpp",
"core/src/datamatrix/DMBitLayout.cpp",
"core/src/datamatrix/DMWriter.cpp",
"core/src/MultiFormatWriter.cpp",
"core/src/BarcodeFormat.cpp",
"core/src/GlobalHistogramBinarizer.cpp",
"core/src/WhiteRectDetector.cpp",
"core/src/TextDecoder.cpp",
"core/src/LuminanceSource.cpp",
"core/src/BitMatrix.cpp",
"core/src/DecodeStatus.cpp",
"core/src/ReedSolomonDecoder.cpp",
"core/src/oned/ODMultiUPCEANReader.cpp",
"core/src/oned/ODCode128Patterns.cpp",
"core/src/oned/ODUPCAWriter.cpp",
"core/src/oned/ODDataBarExpandedReader.cpp",
"core/src/oned/rss/ODRSSGenericAppIdDecoder.cpp",
"core/src/oned/rss/ODRSSFieldParser.cpp",
"core/src/oned/rss/ODRSSExpandedBinaryDecoder.cpp",
"core/src/oned/ODDataBarReader.cpp",
"core/src/oned/ODDataBarCommon.cpp",
"core/src/oned/ODRowReader.cpp",
"core/src/oned/ODCode93Reader.cpp",
"core/src/oned/ODCode128Reader.cpp",
"core/src/oned/ODCode93Writer.cpp",
"core/src/oned/ODEAN13Writer.cpp",
"core/src/oned/ODCode39Writer.cpp",
"core/src/oned/ODCode128Writer.cpp",
"core/src/oned/ODITFWriter.cpp",
"core/src/oned/ODITFReader.cpp",
"core/src/oned/ODEAN8Writer.cpp",
"core/src/oned/ODUPCEANCommon.cpp",
"core/src/oned/ODCodabarReader.cpp",
"core/src/oned/ODCode39Reader.cpp",
"core/src/oned/ODCodabarWriter.cpp",
"core/src/oned/ODWriterHelper.cpp",
"core/src/oned/ODUPCEWriter.cpp",
"core/src/oned/ODReader.cpp",
"core/src/ReadBarcode.cpp",
"core/src/DecodeHints.cpp",
"core/src/ResultMetadata.cpp",
"core/src/ResultPoint.cpp",
"core/src/ReedSolomonEncoder.cpp",
"core/src/BitArray.cpp",
"core/src/maxicode/MCBitMatrixParser.cpp",
"core/src/maxicode/MCDecoder.cpp",
"core/src/maxicode/MCReader.cpp",
"core/src/aztec/AZHighLevelEncoder.cpp",
"core/src/aztec/AZReader.cpp",
"core/src/aztec/AZDetector.cpp",
"core/src/aztec/AZWriter.cpp",
"core/src/aztec/AZEncoder.cpp",
"core/src/aztec/AZToken.cpp",
"core/src/aztec/AZDecoder.cpp",
"core/src/GridSampler.cpp",
]
defines = [
"NL_DEBUG",
"ZXing_EXPORTS",
]
configs = [ ":public" ]
part_name = "zxing-cpp-1.2.0"
}
}
6. Test on the board
Enter HB SET, select RK3568, and then enter HB Build to compile.
For the programming program, refer to RK3568 programming
After the compilation is completed on the PC side, two test programs will be generated: ZXingReader and ZXingWriter, and you can run the program directly to view the functions:
Writing a shell script through the program's functions is actually running all the functions supported by the program (file zxing-cpp-1.2.0/test/libzxing_test.sh).
Verification on the PC side
Run the following without error:
OpenHarmony3.2_Beta verify the following in the RK3568 board:
7. API interface export
Run this API interface export script on the PC side, and use the dynamic library SO to run the export script.
1. Create allHeads.h, which contains the header files exported from all libraries. zxing-cpp has two test programs, ZXingReader and ZXingWriter, and the header files of the libZXing.so used are as follows:
2. Add the allDySos directory, which places all generated dynamic libraries:
3. Add the allTests directory, which places all the generated test files:
4. Create a new automated test script export_interface.sh, the script code is as follows, and when executing, you need to pass the parameters of the compilation header file to the script, such as ./export_interface.sh -I The path where the header file is located -D macro definition (the parameters in cflags/cflags_cc when compiling all dynamic libraries).
where cxx="1" indicates that the export is based on the cpp file:
#!/bin/sh
#C++库
cxx="1"
mixed_api() {
while read line
do
if [ $cxx != "1" -o "$4" == "1" ];then
tmp=$line
else
tmp=`echo $line | sed "s/(.*$//g" | sed "s/^.*:://g"`
fi
res=`cat $2 |grep "$tmp" -F`
if [ "$res" != "" ];then
echo "$line" >> $3
fi
done < $1
}
remove_standard_api() {
flag="0"
while read line
do
tmp1=`echo $line |grep ".*#.*\/usr\/"`
tmp2=`echo $line |grep ".*#.*[0-9].*\".*\""`
if [ "$tmp1" != "" ];then
flag="0"
elif [ "$tmp2" != "" ];then
flag="1"
elif [ $flag == "1" ];then
echo "$line" >> $2
fi
done < $1
}
src1="allHeads.h"
src2="allDySos"
src3="allTests"
if [ $cxx == "1" ];then
flags_D="-DC"
flags_DU="-DCu"
CC=g++
else
flags_D="-D"
flags_DU="-Du"
CC=gcc
fi
if [ ! -e $src1 ];then
echo "$src1 is not exist!"
exit 1
fi
if [ ! -e $src2 ];then
echo "$src2 is not exist!"
exit 1
fi
if [ ! -e $src3 ];then
echo "$src3 is not exist!"
exit 1
fi
rm -rf $src1.i* $src2.txt $src3.txt export_api.txt tested_api.txt
$CC -E $* $src1 -o $src1.i
if [ "$?" != "0" ];then
exit 1
fi
remove_standard_api $src1.i $src1.i.tmp
nm $src2/* $flags_D | sort -u | grep " T " | sed "s/^.* T //g" >> $src2.txt
nm $src3/* $flags_DU | sort -u | sed "s/^.* U //g" >> $src3.txt
mixed_api $src2.txt $src1.i.tmp export_api.txt 0
mixed_api export_api.txt $src3.txt tested_api.txt 1
rm -rf $src1.i* $src2.txt $src3.txt
In the export zxing-cpp field, enter the following command:
./export_interface.sh -I../core/src/ -I../thirdparty/stb/ -DZXing_EXPORTS
Generate export_api.txt (export SO external API interface) and testd_api.txt (export SO external export API interface used by export test program).
8. Go to the warehouse
At present, the sig repository is not ready, after the migration is completed, temporarily upload the personal repository, the uploaded content includes the native library code (except for the part that needs to modify the native library code, nothing else can be uploaded, such as the intermediate file generated during compilation), BUILD.gn, README.Opensource, all API interface export_api.txt exported from the library, and the tested API interface tested_api.txt
README. Opensource, the format is as follows:
[
{
"Name" : "zxing-cpp",
"License" : "Apache License"
"License File" : "LICENSE",
"Version Number" : "1.2.0",
"Owner" : "zhangrong50@h-partners.com",
"Upstream URL" : "https://github.com/nu-book/zxing-cpp",
"Description" : "ZXing-C++ ("zebra crossing") is an open-source, multi-format 1D/2D barcode image processing library implemented in C++"
}
]