react-native-update 10.47.0 → 10.48.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/jni/Android.mk +2 -0
- package/android/jni/hpatch.c +55 -20
- package/android/jni/hpatch.h +0 -6
- package/android/lib/arm64-v8a/librnupdate.so +0 -0
- package/android/lib/armeabi-v7a/librnupdate.so +0 -0
- package/android/lib/x86/librnupdate.so +0 -0
- package/android/lib/x86_64/librnupdate.so +0 -0
- package/android/src/main/java/cn/reactnative/modules/update/DownloadTask.java +29 -6
- package/android/src/main/java/cn/reactnative/modules/update/DownloadTaskParams.java +2 -0
- package/android/src/main/java/cn/reactnative/modules/update/ErrorCodes.java +1 -0
- package/android/src/main/java/cn/reactnative/modules/update/NativeUpdateCore.java +12 -0
- package/android/src/main/java/cn/reactnative/modules/update/UpdateContext.java +47 -2
- package/android/src/main/java/cn/reactnative/modules/update/UpdateEventEmitter.java +12 -3
- package/android/src/main/java/cn/reactnative/modules/update/UpdateModuleImpl.java +13 -0
- package/android/src/main/java/cn/reactnative/modules/update/UpdateModuleSupport.java +11 -0
- package/android/src/newarch/cn/reactnative/modules/update/UpdateModule.java +5 -0
- package/android/src/oldarch/cn/reactnative/modules/update/UpdateModule.java +5 -0
- package/cpp/patch_core/error_codes.h +3 -0
- package/cpp/patch_core/hbc_transform.cpp +147 -0
- package/cpp/patch_core/hbc_transform.h +53 -0
- package/cpp/patch_core/hbc_transform_wire.cpp +327 -0
- package/cpp/patch_core/hbc_transform_wire.h +52 -0
- package/cpp/patch_core/patch_core.cpp +126 -4
- package/cpp/patch_core/patch_core.h +5 -0
- package/cpp/patch_core/patch_core_android.cpp +3 -1
- package/cpp/patch_core/tests/fixtures/rawstored.lzma2label.patch.bin +0 -0
- package/cpp/patch_core/tests/fixtures/rawstored.new.bin +0 -0
- package/cpp/patch_core/tests/fixtures/rawstored.old.bin +0 -0
- package/cpp/patch_core/tests/fixtures/v96.hbc +0 -0
- package/cpp/patch_core/tests/fixtures/v96.meta.json +1 -0
- package/cpp/patch_core/tests/fixtures/v96.streampatch.bin +0 -0
- package/cpp/patch_core/tests/fixtures/v96.t.hbc +0 -0
- package/cpp/patch_core/tests/fixtures/v96.tpatch.bin +0 -0
- package/cpp/patch_core/tests/fixtures/v96.tstreampatch.bin +0 -0
- package/cpp/patch_core/tests/fixtures/v96b.hbc +0 -0
- package/cpp/patch_core/tests/fixtures/v98.hbc +0 -0
- package/cpp/patch_core/tests/fixtures/v98.t.hbc +0 -0
- package/cpp/patch_core/tests/fixtures/v98b.hbc +0 -0
- package/cpp/patch_core/tests/fixtures/v98b.t.hbc +0 -0
- package/cpp/patch_core/tests/hbc_transform_test.cpp +384 -0
- package/cpp/patch_core/tests/patch_core_test.cpp +150 -1
- package/cpp/patch_core/update_core_android.cpp +10 -0
- package/harmony/pushy/src/main/cpp/CMakeLists.txt +33 -39
- package/harmony/pushy/src/main/cpp/pushy.cpp +31 -6
- package/harmony/pushy/src/main/ets/DownloadTask.ts +34 -2
- package/harmony/pushy/src/main/ets/NativePatchCore.ts +4 -0
- package/harmony/pushy/src/main/ets/PushyTurboModule.ts +12 -0
- package/harmony/pushy/src/main/ets/UpdateContext.ts +79 -2
- package/harmony/pushy.har +0 -0
- package/ios/RCTPushy/RCTPushy.mm +93 -1
- package/ios/RCTPushy/RCTPushyDownloader.mm +11 -2
- package/package.json +1 -1
- package/react-native-update.podspec +2 -0
- package/src/NativePushy.ts +1 -0
- package/src/client.ts +167 -38
- package/src/context.ts +4 -0
- package/src/core.ts +4 -0
- package/src/error.ts +51 -5
- package/src/locales/en.ts +2 -0
- package/src/locales/zh.ts +2 -0
- package/src/provider.tsx +32 -15
- package/src/telemetry.ts +6 -1
- package/src/type.ts +3 -0
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
// hbc_transform 宿主机测试:
|
|
2
|
+
// 1) 与 JS 参考实现(react-native-update-cli src/utils/hbcTransform.ts)
|
|
3
|
+
// 做 golden 对拍——fixtures/*.t.hbc 由 JS 实现生成;
|
|
4
|
+
// 2) 可逆性 property check;
|
|
5
|
+
// 3) 非法输入/非法描述表拒绝(buffer 必须保持原样);
|
|
6
|
+
// 4) wire 解析器(ParseHbcTransformMeta/BuildLayout)的正向/负向直测——
|
|
7
|
+
// 它解析的是随 patch 下发的不可信输入,拒绝分支必须逐条有覆盖。
|
|
8
|
+
#include "../hbc_transform.h"
|
|
9
|
+
#include "../hbc_transform_wire.h"
|
|
10
|
+
|
|
11
|
+
#include <cstdio>
|
|
12
|
+
#include <cstring>
|
|
13
|
+
#include <fstream>
|
|
14
|
+
#include <string>
|
|
15
|
+
#include <vector>
|
|
16
|
+
|
|
17
|
+
namespace {
|
|
18
|
+
|
|
19
|
+
using pushy::hbc::BuildLayout;
|
|
20
|
+
using pushy::hbc::HbcDeltaField;
|
|
21
|
+
using pushy::hbc::HbcLayoutDesc;
|
|
22
|
+
using pushy::hbc::HbcSectionDesc;
|
|
23
|
+
using pushy::hbc::HbcTransformMeta;
|
|
24
|
+
using pushy::hbc::ParseHbcTransformMeta;
|
|
25
|
+
using pushy::hbc::TransformHbcInPlace;
|
|
26
|
+
|
|
27
|
+
int g_failures = 0;
|
|
28
|
+
|
|
29
|
+
#define CHECK(cond) \
|
|
30
|
+
do { \
|
|
31
|
+
if (!(cond)) { \
|
|
32
|
+
std::fprintf(stderr, "FAIL %s:%d: %s\n", __FILE__, __LINE__, #cond); \
|
|
33
|
+
++g_failures; \
|
|
34
|
+
} \
|
|
35
|
+
} while (0)
|
|
36
|
+
|
|
37
|
+
std::vector<uint8_t> ReadFileOrDie(const std::string& path) {
|
|
38
|
+
std::ifstream in(path, std::ios::binary);
|
|
39
|
+
if (!in) {
|
|
40
|
+
std::fprintf(stderr, "cannot open fixture: %s\n", path.c_str());
|
|
41
|
+
std::exit(1);
|
|
42
|
+
}
|
|
43
|
+
return std::vector<uint8_t>(
|
|
44
|
+
(std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// ---- 布局描述表(测试用常量;生产路径从 patch 元数据的 wire 格式构建)----
|
|
48
|
+
// 与 CLI 的 HBC_LAYOUTS 逐字段对应。counts 槽位约定:0 = fileLength,
|
|
49
|
+
// 最后一个 = debugInfoOffset。
|
|
50
|
+
|
|
51
|
+
const HbcDeltaField kFuncOffset25[] = {{0, 0, 25}};
|
|
52
|
+
const HbcDeltaField kFuncOffsets25x2[] = {{0, 0, 25}, {8, 0, 25}};
|
|
53
|
+
const HbcDeltaField kStringOffset23[] = {{0, 1, 23}};
|
|
54
|
+
const HbcDeltaField kPairOffset32[] = {{0, 0, 32}};
|
|
55
|
+
|
|
56
|
+
// v87~v96:19 个计数槽
|
|
57
|
+
// [0]fileLength [1]globalCodeIndex [2]functionCount [3]stringKindCount
|
|
58
|
+
// [4]identifierCount [5]stringCount [6]overflowStringCount
|
|
59
|
+
// [7]stringStorageSize [8]bigIntCount [9]bigIntStorageSize [10]regExpCount
|
|
60
|
+
// [11]regExpStorageSize [12]arrayBufferSize [13]objKeyBufferSize
|
|
61
|
+
// [14]objValueBufferSize [15]segmentID [16]cjsModuleCount
|
|
62
|
+
// [17]functionSourceCount [18]debugInfoOffset
|
|
63
|
+
const HbcSectionDesc kSectionsV96[] = {
|
|
64
|
+
{2, 16, kFuncOffsets25x2, 2}, // functionHeaders
|
|
65
|
+
{3, 4, nullptr, 0}, // stringKinds
|
|
66
|
+
{4, 4, nullptr, 0}, // identifierHashes
|
|
67
|
+
{5, 4, kStringOffset23, 1}, // smallStringTable
|
|
68
|
+
{6, 8, kPairOffset32, 1}, // overflowStringTable
|
|
69
|
+
{7, 1, nullptr, 0}, // stringStorage
|
|
70
|
+
{12, 1, nullptr, 0}, // arrayBuffer
|
|
71
|
+
{13, 1, nullptr, 0}, // objKeyBuffer
|
|
72
|
+
{14, 1, nullptr, 0}, // objValueBuffer
|
|
73
|
+
{8, 8, kPairOffset32, 1}, // bigIntTable
|
|
74
|
+
{9, 1, nullptr, 0}, // bigIntStorage
|
|
75
|
+
{10, 8, kPairOffset32, 1}, // regExpTable
|
|
76
|
+
{11, 1, nullptr, 0}, // regExpStorage
|
|
77
|
+
{16, 8, nullptr, 0}, // cjsModuleTable
|
|
78
|
+
{17, 8, nullptr, 0}, // functionSourceTable
|
|
79
|
+
};
|
|
80
|
+
const HbcLayoutDesc kLayoutV96 = {19, kSectionsV96, 15};
|
|
81
|
+
|
|
82
|
+
// v98 早期变体(Static Hermes,19 槽):SmallFuncHeader 12B、
|
|
83
|
+
// objShapeTable 取代 objValueBuffer
|
|
84
|
+
const HbcSectionDesc kSectionsV98[] = {
|
|
85
|
+
{2, 12, kFuncOffset25, 1}, // functionHeaders
|
|
86
|
+
{3, 4, nullptr, 0}, // stringKinds
|
|
87
|
+
{4, 4, nullptr, 0}, // identifierHashes
|
|
88
|
+
{5, 4, kStringOffset23, 1}, // smallStringTable
|
|
89
|
+
{6, 8, kPairOffset32, 1}, // overflowStringTable
|
|
90
|
+
{7, 1, nullptr, 0}, // stringStorage
|
|
91
|
+
{12, 1, nullptr, 0}, // literalValueBuffer
|
|
92
|
+
{13, 1, nullptr, 0}, // objKeyBuffer
|
|
93
|
+
{14, 8, kPairOffset32, 1}, // objShapeTable
|
|
94
|
+
{8, 8, kPairOffset32, 1}, // bigIntTable
|
|
95
|
+
{9, 1, nullptr, 0}, // bigIntStorage
|
|
96
|
+
{10, 8, kPairOffset32, 1}, // regExpTable
|
|
97
|
+
{11, 1, nullptr, 0}, // regExpStorage
|
|
98
|
+
{16, 8, nullptr, 0}, // cjsModuleTable
|
|
99
|
+
{17, 8, nullptr, 0}, // functionSourceTable
|
|
100
|
+
};
|
|
101
|
+
const HbcLayoutDesc kLayoutV98 = {19, kSectionsV98, 15};
|
|
102
|
+
|
|
103
|
+
// v98 晚期变体(生产主流,20 槽):槽 15 = numStringSwitchImms,
|
|
104
|
+
// 其后 segmentID/cjs/functionSource/debugInfo 依次后移一位
|
|
105
|
+
const HbcSectionDesc kSectionsV98Late[] = {
|
|
106
|
+
{2, 12, kFuncOffset25, 1}, // functionHeaders
|
|
107
|
+
{3, 4, nullptr, 0}, // stringKinds
|
|
108
|
+
{4, 4, nullptr, 0}, // identifierHashes
|
|
109
|
+
{5, 4, kStringOffset23, 1}, // smallStringTable
|
|
110
|
+
{6, 8, kPairOffset32, 1}, // overflowStringTable
|
|
111
|
+
{7, 1, nullptr, 0}, // stringStorage
|
|
112
|
+
{12, 1, nullptr, 0}, // literalValueBuffer
|
|
113
|
+
{13, 1, nullptr, 0}, // objKeyBuffer
|
|
114
|
+
{14, 8, kPairOffset32, 1}, // objShapeTable
|
|
115
|
+
{8, 8, kPairOffset32, 1}, // bigIntTable
|
|
116
|
+
{9, 1, nullptr, 0}, // bigIntStorage
|
|
117
|
+
{10, 8, kPairOffset32, 1}, // regExpTable
|
|
118
|
+
{11, 1, nullptr, 0}, // regExpStorage
|
|
119
|
+
{17, 8, nullptr, 0}, // cjsModuleTable
|
|
120
|
+
{18, 8, nullptr, 0}, // functionSourceTable
|
|
121
|
+
};
|
|
122
|
+
const HbcLayoutDesc kLayoutV98Late = {20, kSectionsV98Late, 15};
|
|
123
|
+
|
|
124
|
+
void TestGoldenPair(
|
|
125
|
+
const std::string& dir,
|
|
126
|
+
const char* plainName,
|
|
127
|
+
const char* goldenName,
|
|
128
|
+
const HbcLayoutDesc& layout) {
|
|
129
|
+
const std::vector<uint8_t> plain = ReadFileOrDie(dir + plainName);
|
|
130
|
+
const std::vector<uint8_t> golden = ReadFileOrDie(dir + goldenName);
|
|
131
|
+
CHECK(plain.size() == golden.size());
|
|
132
|
+
|
|
133
|
+
// T(plain) == golden(与 JS 实现逐字节一致)
|
|
134
|
+
std::vector<uint8_t> forward = plain;
|
|
135
|
+
CHECK(TransformHbcInPlace(forward.data(), forward.size(), layout, false));
|
|
136
|
+
CHECK(forward == golden);
|
|
137
|
+
CHECK(forward != plain); // 确实改写了字节
|
|
138
|
+
|
|
139
|
+
// T⁻¹(golden) == plain
|
|
140
|
+
std::vector<uint8_t> backward = golden;
|
|
141
|
+
CHECK(TransformHbcInPlace(backward.data(), backward.size(), layout, true));
|
|
142
|
+
CHECK(backward == plain);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
void TestRejections(const std::string& dir) {
|
|
146
|
+
const std::vector<uint8_t> good = ReadFileOrDie(dir + "v98.hbc");
|
|
147
|
+
|
|
148
|
+
// 太短
|
|
149
|
+
{
|
|
150
|
+
std::vector<uint8_t> buf(good.begin(), good.begin() + 64);
|
|
151
|
+
CHECK(!TransformHbcInPlace(buf.data(), buf.size(), kLayoutV98, false));
|
|
152
|
+
}
|
|
153
|
+
// 坏 magic → 拒绝且 buffer 不被修改
|
|
154
|
+
{
|
|
155
|
+
std::vector<uint8_t> buf = good;
|
|
156
|
+
buf[0] ^= 0xff;
|
|
157
|
+
const std::vector<uint8_t> before = buf;
|
|
158
|
+
CHECK(!TransformHbcInPlace(buf.data(), buf.size(), kLayoutV98, false));
|
|
159
|
+
CHECK(buf == before);
|
|
160
|
+
}
|
|
161
|
+
// fileLength 与实际大小不符(截断)
|
|
162
|
+
{
|
|
163
|
+
std::vector<uint8_t> buf(good.begin(), good.end() - 8);
|
|
164
|
+
const std::vector<uint8_t> before = buf;
|
|
165
|
+
CHECK(!TransformHbcInPlace(buf.data(), buf.size(), kLayoutV98, false));
|
|
166
|
+
CHECK(buf == before);
|
|
167
|
+
}
|
|
168
|
+
// 计数爆表 → 段越界
|
|
169
|
+
{
|
|
170
|
+
std::vector<uint8_t> buf = good;
|
|
171
|
+
buf[32 + 2 * 4] = 0xff;
|
|
172
|
+
buf[32 + 2 * 4 + 1] = 0xff;
|
|
173
|
+
buf[32 + 2 * 4 + 2] = 0xff;
|
|
174
|
+
buf[32 + 2 * 4 + 3] = 0x0f;
|
|
175
|
+
const std::vector<uint8_t> before = buf;
|
|
176
|
+
CHECK(!TransformHbcInPlace(buf.data(), buf.size(), kLayoutV98, false));
|
|
177
|
+
CHECK(buf == before);
|
|
178
|
+
}
|
|
179
|
+
// 非法描述表:countIndex 越界
|
|
180
|
+
{
|
|
181
|
+
std::vector<uint8_t> buf = good;
|
|
182
|
+
const HbcSectionDesc bad[] = {{99, 4, nullptr, 0}};
|
|
183
|
+
const HbcLayoutDesc badLayout = {19, bad, 1};
|
|
184
|
+
CHECK(!TransformHbcInPlace(buf.data(), buf.size(), badLayout, false));
|
|
185
|
+
}
|
|
186
|
+
// 非法描述表:差分字段超出条目
|
|
187
|
+
{
|
|
188
|
+
std::vector<uint8_t> buf = good;
|
|
189
|
+
const HbcDeltaField badField[] = {{4, 0, 32}}; // byte 4 + 4 > entrySize 4
|
|
190
|
+
const HbcSectionDesc bad[] = {{5, 4, badField, 1}};
|
|
191
|
+
const HbcLayoutDesc badLayout = {19, bad, 1};
|
|
192
|
+
CHECK(!TransformHbcInPlace(buf.data(), buf.size(), badLayout, false));
|
|
193
|
+
}
|
|
194
|
+
// 非法描述表:位域越过 32 位
|
|
195
|
+
{
|
|
196
|
+
std::vector<uint8_t> buf = good;
|
|
197
|
+
const HbcDeltaField badField[] = {{0, 8, 25}};
|
|
198
|
+
const HbcSectionDesc bad[] = {{5, 4, badField, 1}};
|
|
199
|
+
const HbcLayoutDesc badLayout = {19, bad, 1};
|
|
200
|
+
CHECK(!TransformHbcInPlace(buf.data(), buf.size(), badLayout, false));
|
|
201
|
+
}
|
|
202
|
+
// CP2-1 回归:bit=0xFFFFFFFF 时 bit+bits 的 uint32 求和回绕为 0,
|
|
203
|
+
// 曾绕过 >32 检查进入改写阶段(移位量 ≥32 的 UB)。必须拒绝且不改字节。
|
|
204
|
+
{
|
|
205
|
+
std::vector<uint8_t> buf = good;
|
|
206
|
+
const std::vector<uint8_t> before = buf;
|
|
207
|
+
const HbcDeltaField badField[] = {{0, 0xffffffffu, 1}};
|
|
208
|
+
const HbcSectionDesc bad[] = {{5, 4, badField, 1}};
|
|
209
|
+
const HbcLayoutDesc badLayout = {19, bad, 1};
|
|
210
|
+
CHECK(!TransformHbcInPlace(buf.data(), buf.size(), badLayout, false));
|
|
211
|
+
CHECK(buf == before);
|
|
212
|
+
}
|
|
213
|
+
// bit=31 本身合法,但 bit+bits=33 不回绕也必须拒绝
|
|
214
|
+
{
|
|
215
|
+
std::vector<uint8_t> buf = good;
|
|
216
|
+
const HbcDeltaField badField[] = {{0, 31, 2}};
|
|
217
|
+
const HbcSectionDesc bad[] = {{5, 4, badField, 1}};
|
|
218
|
+
const HbcLayoutDesc badLayout = {19, bad, 1};
|
|
219
|
+
CHECK(!TransformHbcInPlace(buf.data(), buf.size(), badLayout, false));
|
|
220
|
+
}
|
|
221
|
+
// 非法描述表:bits=0
|
|
222
|
+
{
|
|
223
|
+
std::vector<uint8_t> buf = good;
|
|
224
|
+
const HbcDeltaField badField[] = {{0, 0, 0}};
|
|
225
|
+
const HbcSectionDesc bad[] = {{5, 4, badField, 1}};
|
|
226
|
+
const HbcLayoutDesc badLayout = {19, bad, 1};
|
|
227
|
+
CHECK(!TransformHbcInPlace(buf.data(), buf.size(), badLayout, false));
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// ---- wire 解析器直测 ----
|
|
232
|
+
|
|
233
|
+
std::string ReadTextFileOrDie(const std::string& path) {
|
|
234
|
+
const std::vector<uint8_t> raw = ReadFileOrDie(path);
|
|
235
|
+
return std::string(raw.begin(), raw.end());
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
void TestWireParser(const std::string& dir) {
|
|
239
|
+
// 正向:真实 fixture 解析 + BuildLayout 后与手写 kLayoutV96 等效
|
|
240
|
+
// (对 v96.hbc 变换产物与 golden 逐字节一致 = 端到端等效性证明)
|
|
241
|
+
{
|
|
242
|
+
HbcTransformMeta meta;
|
|
243
|
+
CHECK(ParseHbcTransformMeta(ReadTextFileOrDie(dir + "v96.meta.json"), &meta));
|
|
244
|
+
CHECK(meta.v == 1);
|
|
245
|
+
CHECK(meta.hbcVersion == 96);
|
|
246
|
+
CHECK(meta.headerCountFields == 19);
|
|
247
|
+
CHECK(meta.sections.size() == 15);
|
|
248
|
+
std::vector<HbcSectionDesc> scratch;
|
|
249
|
+
const HbcLayoutDesc layout = BuildLayout(meta, &scratch);
|
|
250
|
+
std::vector<uint8_t> buf = ReadFileOrDie(dir + "v96.hbc");
|
|
251
|
+
CHECK(TransformHbcInPlace(buf.data(), buf.size(), layout, false));
|
|
252
|
+
CHECK(buf == ReadFileOrDie(dir + "v96.t.hbc"));
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const std::string minimalLayout =
|
|
256
|
+
R"("layout":{"counts":19,"sections":[[5,4,[]]]})";
|
|
257
|
+
const std::string minimal =
|
|
258
|
+
R"({"v":1,"hbcVersion":96,)" + minimalLayout + "}";
|
|
259
|
+
|
|
260
|
+
// 正向:最小合法输入;未知键(各种值形态)被跳过;边界位域 [0,31,1] 合法
|
|
261
|
+
{
|
|
262
|
+
HbcTransformMeta meta;
|
|
263
|
+
CHECK(ParseHbcTransformMeta(minimal, &meta));
|
|
264
|
+
CHECK(ParseHbcTransformMeta(
|
|
265
|
+
R"({"v":1,"hbcVersion":96,"future":{"a":[1,"s\"x",true,null],"b":-1.5e3},)" +
|
|
266
|
+
minimalLayout + "}",
|
|
267
|
+
&meta));
|
|
268
|
+
CHECK(ParseHbcTransformMeta(
|
|
269
|
+
R"({"v":1,"hbcVersion":96,"layout":{"counts":19,"sections":[[5,4,[[0,31,1]]]]}})",
|
|
270
|
+
&meta));
|
|
271
|
+
CHECK(meta.sections[0].deltaFields[0].bit == 31);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// 负向:每条拒绝分支单测,解析必须返回 false
|
|
275
|
+
const char* rejects[] = {
|
|
276
|
+
// 非 JSON / 结构破损
|
|
277
|
+
"not json",
|
|
278
|
+
"",
|
|
279
|
+
"{",
|
|
280
|
+
R"({"v":1,"hbcVersion":96})", // 缺 layout
|
|
281
|
+
R"({"v":1,"layout":{"counts":19,"sections":[[5,4,[]]]}})", // 缺 hbcVersion
|
|
282
|
+
R"({"hbcVersion":96,"layout":{"counts":19,"sections":[[5,4,[]]]}})", // 缺 v
|
|
283
|
+
R"({"v":1,"hbcVersion":96,"layout":{"counts":19}})", // 缺 sections
|
|
284
|
+
R"({"v":1,"hbcVersion":96,"layout":{"sections":[[5,4,[]]]}})", // 缺 counts
|
|
285
|
+
R"({"v":1,"hbcVersion":96,"layout":{"counts":19,"sections":[]}})", // 空 sections
|
|
286
|
+
R"({"v":1,"hbcVersion":96,"layout":{"counts":0,"sections":[[5,4,[]]]}})", // counts=0
|
|
287
|
+
R"({"v":1,"hbcVersion":96,"layout":[1,2]})", // layout 非对象
|
|
288
|
+
// 尾部多余内容
|
|
289
|
+
R"({"v":1,"hbcVersion":96,"layout":{"counts":19,"sections":[[5,4,[]]]}} x)",
|
|
290
|
+
// 键含转义(本格式的键不允许反斜杠;raw string 里 \x 就是两个字符)
|
|
291
|
+
R"({"v\x":1,"v":1,"hbcVersion":96,"layout":{"counts":19,"sections":[[5,4,[]]]}})",
|
|
292
|
+
// ParseUInt 溢出(>0xffffffff)与负数
|
|
293
|
+
R"({"v":4294967296,"hbcVersion":96,"layout":{"counts":19,"sections":[[5,4,[]]]}})",
|
|
294
|
+
R"({"v":-1,"hbcVersion":96,"layout":{"counts":19,"sections":[[5,4,[]]]}})",
|
|
295
|
+
// 位域语义:CP2-1 的 bit 溢出、bit+bits>32、bits=0、bits=33
|
|
296
|
+
R"({"v":1,"hbcVersion":96,"layout":{"counts":19,"sections":[[5,4,[[0,4294967295,1]]]]}})",
|
|
297
|
+
R"({"v":1,"hbcVersion":96,"layout":{"counts":19,"sections":[[5,4,[[0,31,2]]]]}})",
|
|
298
|
+
R"({"v":1,"hbcVersion":96,"layout":{"counts":19,"sections":[[5,4,[[0,0,0]]]]}})",
|
|
299
|
+
R"({"v":1,"hbcVersion":96,"layout":{"counts":19,"sections":[[5,4,[[0,0,33]]]]}})",
|
|
300
|
+
// delta field 元组长度不对
|
|
301
|
+
R"({"v":1,"hbcVersion":96,"layout":{"counts":19,"sections":[[5,4,[[0,0]]]]}})",
|
|
302
|
+
};
|
|
303
|
+
for (const char* json : rejects) {
|
|
304
|
+
HbcTransformMeta meta;
|
|
305
|
+
if (ParseHbcTransformMeta(json, &meta)) {
|
|
306
|
+
std::fprintf(stderr, "FAIL: wire parser accepted: %s\n", json);
|
|
307
|
+
++g_failures;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// 负向:输入尺寸上限(64KB)
|
|
312
|
+
{
|
|
313
|
+
std::string huge = minimal;
|
|
314
|
+
huge.insert(1, std::string(65 * 1024, ' '));
|
|
315
|
+
HbcTransformMeta meta;
|
|
316
|
+
CHECK(!ParseHbcTransformMeta(huge, &meta));
|
|
317
|
+
}
|
|
318
|
+
// 负向:未知键的值嵌套深度超限(kMaxDepth=8)
|
|
319
|
+
{
|
|
320
|
+
std::string deep = R"({"v":1,"hbcVersion":96,"x":)";
|
|
321
|
+
for (int i = 0; i < 12; ++i) deep += '[';
|
|
322
|
+
deep += '1';
|
|
323
|
+
for (int i = 0; i < 12; ++i) deep += ']';
|
|
324
|
+
deep += ',' + minimalLayout + "}";
|
|
325
|
+
HbcTransformMeta meta;
|
|
326
|
+
CHECK(!ParseHbcTransformMeta(deep, &meta));
|
|
327
|
+
}
|
|
328
|
+
// 负向:sections 超过 64 个
|
|
329
|
+
{
|
|
330
|
+
std::string many = R"({"v":1,"hbcVersion":96,"layout":{"counts":19,"sections":[)";
|
|
331
|
+
for (int i = 0; i < 65; ++i) {
|
|
332
|
+
if (i) many += ',';
|
|
333
|
+
many += "[5,4,[]]";
|
|
334
|
+
}
|
|
335
|
+
many += "]}}";
|
|
336
|
+
HbcTransformMeta meta;
|
|
337
|
+
CHECK(!ParseHbcTransformMeta(many, &meta));
|
|
338
|
+
}
|
|
339
|
+
// 负向:单段 deltaFields 超过 8 个
|
|
340
|
+
{
|
|
341
|
+
std::string many = R"({"v":1,"hbcVersion":96,"layout":{"counts":19,"sections":[[5,64,[)";
|
|
342
|
+
for (int i = 0; i < 9; ++i) {
|
|
343
|
+
if (i) many += ',';
|
|
344
|
+
many += "[0,0,8]";
|
|
345
|
+
}
|
|
346
|
+
many += "]]]}}";
|
|
347
|
+
HbcTransformMeta meta;
|
|
348
|
+
CHECK(!ParseHbcTransformMeta(many, &meta));
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
} // namespace
|
|
353
|
+
|
|
354
|
+
int main(int argc, char** argv) {
|
|
355
|
+
std::string fixturesDir = "cpp/patch_core/tests/fixtures/";
|
|
356
|
+
if (argc > 1) {
|
|
357
|
+
fixturesDir = argv[1];
|
|
358
|
+
if (!fixturesDir.empty() && fixturesDir.back() != '/') {
|
|
359
|
+
fixturesDir += '/';
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
TestGoldenPair(fixturesDir, "v96.hbc", "v96.t.hbc", kLayoutV96);
|
|
364
|
+
TestGoldenPair(fixturesDir, "v98.hbc", "v98.t.hbc", kLayoutV98);
|
|
365
|
+
TestGoldenPair(fixturesDir, "v98b.hbc", "v98b.t.hbc", kLayoutV98Late);
|
|
366
|
+
TestRejections(fixturesDir);
|
|
367
|
+
TestWireParser(fixturesDir);
|
|
368
|
+
|
|
369
|
+
// 变体互斥:19 槽布局作用于 20 槽文件(或反之)必须被结构校验拒绝
|
|
370
|
+
{
|
|
371
|
+
std::vector<uint8_t> late = ReadFileOrDie(fixturesDir + "v98b.hbc");
|
|
372
|
+
CHECK(!TransformHbcInPlace(late.data(), late.size(), kLayoutV98, false));
|
|
373
|
+
std::vector<uint8_t> early = ReadFileOrDie(fixturesDir + "v98.hbc");
|
|
374
|
+
CHECK(
|
|
375
|
+
!TransformHbcInPlace(early.data(), early.size(), kLayoutV98Late, false));
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
if (g_failures > 0) {
|
|
379
|
+
std::fprintf(stderr, "hbc_transform_test: %d failure(s)\n", g_failures);
|
|
380
|
+
return 1;
|
|
381
|
+
}
|
|
382
|
+
std::printf("hbc_transform_test: all checks passed\n");
|
|
383
|
+
return 0;
|
|
384
|
+
}
|
|
@@ -137,6 +137,146 @@ void ExpectEq(const std::string& left, const std::string& right, const std::stri
|
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
+
std::string g_fixtures_dir = "cpp/patch_core/tests/fixtures";
|
|
141
|
+
|
|
142
|
+
// 变换域 bundle patch 端到端:真实 hpatch + wire 元数据 → T(origin) →
|
|
143
|
+
// hpatch → T⁻¹,结果必须与新 bundle 逐字节一致(fixtures 由 CLI 的 JS
|
|
144
|
+
// 实现生成,同时充当跨实现 golden)。
|
|
145
|
+
void TestApplyPatchWithHbcTransform() {
|
|
146
|
+
TempDir temp;
|
|
147
|
+
const std::string origin = JoinPath(g_fixtures_dir, "v96.hbc");
|
|
148
|
+
const std::string patch = JoinPath(g_fixtures_dir, "v96.tpatch.bin");
|
|
149
|
+
const std::string expected = ReadFile(JoinPath(g_fixtures_dir, "v96b.hbc"));
|
|
150
|
+
const std::string meta = ReadFile(JoinPath(g_fixtures_dir, "v96.meta.json"));
|
|
151
|
+
Expect(!expected.empty() && !meta.empty(), "hbc fixtures must exist");
|
|
152
|
+
|
|
153
|
+
FileSourcePatchOptions options;
|
|
154
|
+
options.source_root = JoinPath(temp.path, "src");
|
|
155
|
+
options.target_root = JoinPath(temp.path, "dst");
|
|
156
|
+
options.origin_bundle_path = origin;
|
|
157
|
+
options.bundle_patch_path = patch;
|
|
158
|
+
options.bundle_output_path = JoinPath(temp.path, "out/index.bundlejs");
|
|
159
|
+
options.enable_merge = false;
|
|
160
|
+
options.bundle_hbc_transform_meta = meta;
|
|
161
|
+
|
|
162
|
+
Status status = ApplyPatchFromFileSource(options);
|
|
163
|
+
Expect(status.ok, "hbc transform patch should succeed: " + status.message);
|
|
164
|
+
ExpectEq(
|
|
165
|
+
ReadFile(options.bundle_output_path).size() == expected.size()
|
|
166
|
+
? std::string("same-size")
|
|
167
|
+
: std::string("size-mismatch"),
|
|
168
|
+
"same-size",
|
|
169
|
+
"restored bundle size");
|
|
170
|
+
Expect(
|
|
171
|
+
ReadFile(options.bundle_output_path) == expected,
|
|
172
|
+
"restored bundle must equal new bundle byte-for-byte");
|
|
173
|
+
|
|
174
|
+
// 临时文件必须被清理
|
|
175
|
+
Expect(
|
|
176
|
+
!Exists(options.bundle_output_path + ".hbct-origin") &&
|
|
177
|
+
!Exists(options.bundle_output_path + ".hbct-patched"),
|
|
178
|
+
"hbc transform temp files must be removed");
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
void TestApplyPatchWithHbcTransformRejectsBadMeta() {
|
|
182
|
+
TempDir temp;
|
|
183
|
+
FileSourcePatchOptions options;
|
|
184
|
+
options.source_root = JoinPath(temp.path, "src");
|
|
185
|
+
options.target_root = JoinPath(temp.path, "dst");
|
|
186
|
+
options.origin_bundle_path = JoinPath(g_fixtures_dir, "v96.hbc");
|
|
187
|
+
options.bundle_patch_path = JoinPath(g_fixtures_dir, "v96.tpatch.bin");
|
|
188
|
+
options.bundle_output_path = JoinPath(temp.path, "out/index.bundlejs");
|
|
189
|
+
options.enable_merge = false;
|
|
190
|
+
|
|
191
|
+
// 不可解析的元数据 → 失败(绝不能忽略元数据直接 hpatch)
|
|
192
|
+
options.bundle_hbc_transform_meta = "not json";
|
|
193
|
+
Expect(
|
|
194
|
+
!ApplyPatchFromFileSource(options).ok,
|
|
195
|
+
"malformed hbcTransform metadata must fail");
|
|
196
|
+
Expect(!Exists(options.bundle_output_path), "no output on failure");
|
|
197
|
+
|
|
198
|
+
// 不支持的变换规范版本 → 失败(调用方回退整包)
|
|
199
|
+
std::string meta = ReadFile(JoinPath(g_fixtures_dir, "v96.meta.json"));
|
|
200
|
+
const std::string needle = "\"v\":1";
|
|
201
|
+
const size_t pos = meta.find(needle);
|
|
202
|
+
Expect(pos != std::string::npos, "meta fixture must contain v:1");
|
|
203
|
+
meta.replace(pos, needle.size(), "\"v\":9");
|
|
204
|
+
options.bundle_hbc_transform_meta = meta;
|
|
205
|
+
Status status = ApplyPatchFromFileSource(options);
|
|
206
|
+
Expect(!status.ok, "unsupported hbcTransform version must fail");
|
|
207
|
+
Expect(
|
|
208
|
+
status.message.find("Unsupported hbcTransform version") !=
|
|
209
|
+
std::string::npos,
|
|
210
|
+
"error should identify unsupported version: " + status.message);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// HDIFF13(diffStream)格式:hpatch_by_file 按 magic 自动分派,
|
|
214
|
+
// v2 轨道的大 bundle patch 走此路径。fixtures 由 node-hdiffpatch 生成并
|
|
215
|
+
// 已在 JS 侧验证过 round-trip。
|
|
216
|
+
void TestApplyStreamFormatBundlePatch() {
|
|
217
|
+
TempDir temp;
|
|
218
|
+
FileSourcePatchOptions options;
|
|
219
|
+
options.source_root = JoinPath(temp.path, "src");
|
|
220
|
+
options.target_root = JoinPath(temp.path, "dst");
|
|
221
|
+
options.origin_bundle_path = JoinPath(g_fixtures_dir, "v96.hbc");
|
|
222
|
+
options.bundle_patch_path = JoinPath(g_fixtures_dir, "v96.streampatch.bin");
|
|
223
|
+
options.bundle_output_path = JoinPath(temp.path, "out/index.bundlejs");
|
|
224
|
+
options.enable_merge = false;
|
|
225
|
+
|
|
226
|
+
Status status = ApplyPatchFromFileSource(options);
|
|
227
|
+
Expect(status.ok, "stream-format patch should apply: " + status.message);
|
|
228
|
+
Expect(
|
|
229
|
+
ReadFile(options.bundle_output_path) ==
|
|
230
|
+
ReadFile(JoinPath(g_fixtures_dir, "v96b.hbc")),
|
|
231
|
+
"stream-format restored bundle must equal new bundle");
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
void TestApplyStreamFormatWithHbcTransform() {
|
|
235
|
+
TempDir temp;
|
|
236
|
+
FileSourcePatchOptions options;
|
|
237
|
+
options.source_root = JoinPath(temp.path, "src");
|
|
238
|
+
options.target_root = JoinPath(temp.path, "dst");
|
|
239
|
+
options.origin_bundle_path = JoinPath(g_fixtures_dir, "v96.hbc");
|
|
240
|
+
options.bundle_patch_path = JoinPath(g_fixtures_dir, "v96.tstreampatch.bin");
|
|
241
|
+
options.bundle_output_path = JoinPath(temp.path, "out/index.bundlejs");
|
|
242
|
+
options.enable_merge = false;
|
|
243
|
+
options.bundle_hbc_transform_meta =
|
|
244
|
+
ReadFile(JoinPath(g_fixtures_dir, "v96.meta.json"));
|
|
245
|
+
|
|
246
|
+
Status status = ApplyPatchFromFileSource(options);
|
|
247
|
+
Expect(
|
|
248
|
+
status.ok,
|
|
249
|
+
"transform + stream-format patch should apply: " + status.message);
|
|
250
|
+
Expect(
|
|
251
|
+
ReadFile(options.bundle_output_path) ==
|
|
252
|
+
ReadFile(JoinPath(g_fixtures_dir, "v96b.hbc")),
|
|
253
|
+
"transform+stream restored bundle must equal new bundle");
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// HDIFFSF20 允许 compressedSize==0 表示 diff payload 为 RAW。node-hdiffpatch
|
|
257
|
+
// 2.x 的 v5 writer 在这种小 diff 上仍会保留 lzma2 标签,客户端必须按
|
|
258
|
+
// compressedSize 判定是否解压,不能只看 compressType。
|
|
259
|
+
void TestApplySingleFormatRawStoredWithLzma2Label() {
|
|
260
|
+
TempDir temp;
|
|
261
|
+
FileSourcePatchOptions options;
|
|
262
|
+
options.source_root = JoinPath(temp.path, "src");
|
|
263
|
+
options.target_root = JoinPath(temp.path, "dst");
|
|
264
|
+
options.origin_bundle_path = JoinPath(g_fixtures_dir, "rawstored.old.bin");
|
|
265
|
+
options.bundle_patch_path =
|
|
266
|
+
JoinPath(g_fixtures_dir, "rawstored.lzma2label.patch.bin");
|
|
267
|
+
options.bundle_output_path = JoinPath(temp.path, "out/index.bundlejs");
|
|
268
|
+
options.enable_merge = false;
|
|
269
|
+
|
|
270
|
+
Status status = ApplyPatchFromFileSource(options);
|
|
271
|
+
Expect(
|
|
272
|
+
status.ok,
|
|
273
|
+
"raw-stored single-format patch should apply: " + status.message);
|
|
274
|
+
Expect(
|
|
275
|
+
ReadFile(options.bundle_output_path) ==
|
|
276
|
+
ReadFile(JoinPath(g_fixtures_dir, "rawstored.new.bin")),
|
|
277
|
+
"raw-stored single-format restored bundle must equal new bundle");
|
|
278
|
+
}
|
|
279
|
+
|
|
140
280
|
void TestApplyPatchFromFileSourceMergesAndCopies() {
|
|
141
281
|
TempDir temp;
|
|
142
282
|
const std::string source = JoinPath(temp.path, "origin");
|
|
@@ -609,8 +749,17 @@ void TestStateCoreSwitchToSameVersion() {
|
|
|
609
749
|
|
|
610
750
|
} // namespace
|
|
611
751
|
|
|
612
|
-
int main() {
|
|
752
|
+
int main(int argc, char** argv) {
|
|
753
|
+
if (argc > 1) {
|
|
754
|
+
g_fixtures_dir = argv[1];
|
|
755
|
+
}
|
|
613
756
|
const std::vector<std::pair<std::string, void (*)()>> tests = {
|
|
757
|
+
{"ApplyStreamFormatBundlePatch", TestApplyStreamFormatBundlePatch},
|
|
758
|
+
{"ApplyStreamFormatWithHbcTransform", TestApplyStreamFormatWithHbcTransform},
|
|
759
|
+
{"ApplySingleFormatRawStoredWithLzma2Label",
|
|
760
|
+
TestApplySingleFormatRawStoredWithLzma2Label},
|
|
761
|
+
{"ApplyPatchWithHbcTransform", TestApplyPatchWithHbcTransform},
|
|
762
|
+
{"ApplyPatchWithHbcTransformRejectsBadMeta", TestApplyPatchWithHbcTransformRejectsBadMeta},
|
|
614
763
|
{"ApplyPatchFromFileSourceMergesAndCopies", TestApplyPatchFromFileSourceMergesAndCopies},
|
|
615
764
|
{"ApplyPatchMergeHardLinksUnchangedFiles", TestApplyPatchMergeHardLinksUnchangedFiles},
|
|
616
765
|
{"ApplyPatchMergeFallsBackToByteCopy", TestApplyPatchMergeFallsBackToByteCopy},
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
#include <vector>
|
|
5
5
|
|
|
6
6
|
#include "archive_patch_core.h"
|
|
7
|
+
#include "hbc_transform_wire.h"
|
|
7
8
|
#include "jni_util.h"
|
|
8
9
|
#include "state_core.h"
|
|
9
10
|
#include "state_ops.h"
|
|
@@ -289,6 +290,15 @@ jobject MakeStateResult(
|
|
|
289
290
|
|
|
290
291
|
} // namespace
|
|
291
292
|
|
|
293
|
+
// 客户端可消费的 diff 轨道版本(能力上报,而非 SDK 版本映射);JS 层经
|
|
294
|
+
// getConstants 暴露,随 checkUpdate 以 diffV 上报,服务端据此下发 v2 轨道。
|
|
295
|
+
extern "C" JNIEXPORT jint JNICALL
|
|
296
|
+
Java_cn_reactnative_modules_update_NativeUpdateCore_getSupportedDiffVersion(
|
|
297
|
+
JNIEnv*,
|
|
298
|
+
jclass) {
|
|
299
|
+
return static_cast<jint>(pushy::hbc::kSupportedDiffVersion);
|
|
300
|
+
}
|
|
301
|
+
|
|
292
302
|
extern "C" JNIEXPORT jobject JNICALL
|
|
293
303
|
Java_cn_reactnative_modules_update_UpdateContext_syncStateWithBinaryVersion(
|
|
294
304
|
JNIEnv* env,
|
|
@@ -5,12 +5,6 @@ set(CMAKE_C_STANDARD 11)
|
|
|
5
5
|
set(CMAKE_CXX_STANDARD 17)
|
|
6
6
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
7
7
|
|
|
8
|
-
set(PUSHY_MODULE_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
|
|
9
|
-
set(PUSHY_ABI ${CMAKE_OHOS_ARCH_ABI})
|
|
10
|
-
if(NOT PUSHY_ABI)
|
|
11
|
-
set(PUSHY_ABI ${OHOS_ARCH})
|
|
12
|
-
endif()
|
|
13
|
-
set(PREBUILT_RNUPDATE_PATH ${PUSHY_MODULE_ROOT}/libs/${PUSHY_ABI}/librnupdate.so)
|
|
14
8
|
set(CMAKE_VERBOSE_MAKEFILE on)
|
|
15
9
|
|
|
16
10
|
set(REPO_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../)
|
|
@@ -24,42 +18,42 @@ if(NOT EXISTS ${PATCH_CORE_DIR}/patch_core.cpp)
|
|
|
24
18
|
set(PATCH_CORE_DIR ${STAGED_NATIVE_DIR}/patch_core)
|
|
25
19
|
endif()
|
|
26
20
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
21
|
+
# Always compile from source. A prebuilt-import branch used to live here, but
|
|
22
|
+
# it had no symbol verification: a stale libs/<abi>/librnupdate.so missing a
|
|
23
|
+
# newly added export (e.g. getSupportedDiffVersion) would silently ship and
|
|
24
|
+
# crash getConstants at runtime.
|
|
25
|
+
set(HDIFFPATCH_DIR ${ANDROID_JNI_DIR}/HDiffPatch)
|
|
26
|
+
set(LZMA_DIR ${ANDROID_JNI_DIR}/lzma)
|
|
27
|
+
set(HDP_SOURCES
|
|
28
|
+
${CMAKE_CURRENT_SOURCE_DIR}/pushy.cpp
|
|
29
|
+
${PATCH_CORE_DIR}/archive_patch_core.cpp
|
|
30
|
+
${PATCH_CORE_DIR}/hbc_transform.cpp
|
|
31
|
+
${PATCH_CORE_DIR}/hbc_transform_wire.cpp
|
|
32
|
+
${PATCH_CORE_DIR}/patch_core.cpp
|
|
33
|
+
${PATCH_CORE_DIR}/state_core.cpp
|
|
34
|
+
${ANDROID_JNI_DIR}/hpatch.c
|
|
35
|
+
${HDIFFPATCH_DIR}/libHDiffPatch/HPatch/patch.c
|
|
36
|
+
${HDIFFPATCH_DIR}/file_for_patch.c
|
|
37
|
+
${LZMA_DIR}/C/LzmaDec.c
|
|
38
|
+
${LZMA_DIR}/C/Lzma2Dec.c
|
|
39
|
+
)
|
|
45
40
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
41
|
+
add_library(rnupdate SHARED
|
|
42
|
+
${HDP_SOURCES}
|
|
43
|
+
)
|
|
49
44
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
45
|
+
target_include_directories(rnupdate PRIVATE
|
|
46
|
+
${CMAKE_CURRENT_SOURCE_DIR}
|
|
47
|
+
${PATCH_CORE_DIR}
|
|
48
|
+
${ANDROID_JNI_DIR}
|
|
49
|
+
${HDIFFPATCH_DIR}
|
|
50
|
+
${HDIFFPATCH_DIR}/libHDiffPatch/HPatch
|
|
51
|
+
${LZMA_DIR}/C
|
|
52
|
+
)
|
|
58
53
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
endif()
|
|
54
|
+
target_link_libraries(rnupdate PUBLIC
|
|
55
|
+
libace_napi.z.so
|
|
56
|
+
)
|
|
63
57
|
|
|
64
58
|
if(TARGET rnoh)
|
|
65
59
|
add_library(rnoh_pushy SHARED
|