• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 
16 #include "libabckit/include/c/abckit.h"
17 #include "utils/pandargs.h"
18 #include "libabckit/src/abckit_options.h"
19 
20 #include <dlfcn.h>
21 #include <iostream>
22 
23 #if __has_include(<filesystem>)
24 #include <filesystem>
25 namespace fs = std::filesystem;
26 #elif __has_include(<experimental/filesystem>)
27 #include <experimental/filesystem>
28 namespace fs = std::experimental::filesystem;
29 #endif
30 
31 static auto g_impl = AbckitGetApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
32 
PrintHelp(panda::PandArgParser & paParser)33 static void PrintHelp(panda::PandArgParser &paParser)
34 {
35     std::cerr << "Usage:" << std::endl;
36     std::cerr << "abckit --plugin-path <libabckitplugin.so> --input-file <input.abc> [--output-file <output.abc>]"
37               << std::endl;
38     std::cerr << "Supported options:" << std::endl;
39     std::cerr << paParser.GetHelpString() << std::endl;
40 }
41 
ProcessArgs(panda::PandArgParser & paParser,int,const char **)42 static bool ProcessArgs(panda::PandArgParser &paParser, int /*argc*/, const char ** /*argv*/)
43 {
44     if (libabckit::g_abckitOptions.GetInputFile().empty()) {
45         std::cerr << "ERROR: --input-file is required\n";
46         PrintHelp(paParser);
47         return false;
48     }
49 
50     if (!fs::exists(libabckit::g_abckitOptions.GetInputFile())) {
51         std::cerr << "ERROR: file doesn't exist: " << libabckit::g_abckitOptions.GetInputFile() << '\n';
52         PrintHelp(paParser);
53         return false;
54     }
55 
56     if (libabckit::g_abckitOptions.GetPluginPath().empty()) {
57         std::cerr << "ERROR: --plugin-path is required\n";
58         PrintHelp(paParser);
59         return false;
60     }
61 
62     if (!fs::exists(libabckit::g_abckitOptions.GetPluginPath())) {
63         std::cerr << "ERROR: file doesn't exist: " << libabckit::g_abckitOptions.GetPluginPath() << '\n';
64         PrintHelp(paParser);
65         return false;
66     }
67 
68     return true;
69 }
70 
main(int argc,const char ** argv)71 int main(int argc, const char **argv)
72 {
73     panda::PandArgParser paParser;
74     libabckit::g_abckitOptions.AddOptions(&paParser);
75     if (!paParser.Parse(argc, argv)) {
76         std::cerr << "Error: " << paParser.GetErrorString() << "\n";
77         PrintHelp(paParser);
78         return 1;
79     }
80 
81     if (!ProcessArgs(paParser, argc, argv)) {
82         return 1;
83     }
84 
85     if (libabckit::g_abckitOptions.IsHelp()) {
86         PrintHelp(paParser);
87         return 0;
88     }
89 
90     void *handler = dlopen(libabckit::g_abckitOptions.GetPluginPath().c_str(), RTLD_LAZY);
91     if (handler == nullptr) {
92         std::cerr << "ERROR: failed load plugin: " << libabckit::g_abckitOptions.GetPluginPath() << '\n';
93         return 1;
94     }
95     auto *entry = reinterpret_cast<int (*)(AbckitFile *)>(dlsym(handler, "Entry"));
96     if (entry == nullptr) {
97         std::cerr << "ERROR: failed find symbol 'Entry'\n";
98         return 1;
99     }
100 
101     auto inputPath = libabckit::g_abckitOptions.GetInputFile();
102     AbckitFile *file = g_impl->openAbc(inputPath.c_str(), inputPath.size());
103     if (g_impl->getLastError() != ABCKIT_STATUS_NO_ERROR || file == nullptr) {
104         std::cerr << "ERROR: failed to open: " << inputPath << '\n';
105         return 1;
106     }
107 
108     int ret = entry(file);
109     if (ret != 0) {
110         std::cerr << "ERROR: plugin returned non-zero return code";
111         return ret;
112     }
113 
114     auto outputPath = libabckit::g_abckitOptions.GetOutputFile();
115     if (!outputPath.empty()) {
116         g_impl->writeAbc(file, outputPath.c_str(), outputPath.size());
117         if (g_impl->getLastError() != ABCKIT_STATUS_NO_ERROR || file == nullptr) {
118             std::cerr << "ERROR: failed to write: " << outputPath << '\n';
119             return 1;
120         }
121         g_impl->closeFile(file);
122     }
123 
124     return 0;
125 }
126