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