Compare commits
292 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
434160afa8 | |
|
|
01754c8fb4 | |
|
|
1934d90f27 | |
|
|
814572e1a1 | |
|
|
d505624c78 | |
|
|
e36bbb9022 | |
|
|
0642726469 | |
|
|
d86572db37 | |
|
|
b5944ea834 | |
|
|
73654e76d2 | |
|
|
1537690bb5 | |
|
|
7f158f814a | |
|
|
ee7af5c592 | |
|
|
ab41cd0144 | |
|
|
59a3c3974a | |
|
|
c9ff293dfe | |
|
|
56486b8a76 | |
|
|
8e27e8d41b | |
|
|
fca130bbfa | |
|
|
c21dbcc60a | |
|
|
7f2fa52f37 | |
|
|
da46e71534 | |
|
|
804418fddb | |
|
|
7a0032934b | |
|
|
b301b44cd3 | |
|
|
ddc3332958 | |
|
|
52f25bdb2a | |
|
|
31be818bb6 | |
|
|
213a11ff25 | |
|
|
585be97be9 | |
|
|
361873803f | |
|
|
46f308ed5e | |
|
|
34406b1c13 | |
|
|
e5b52922f7 | |
|
|
e44fa663db | |
|
|
903cf9faa2 | |
|
|
3fe41a8cba | |
|
|
603b0ccb24 | |
|
|
9429a4d24d | |
|
|
ea592ba20c | |
|
|
8d1280a1bd | |
|
|
528240b52b | |
|
|
4768c039d2 | |
|
|
10dc749d7a | |
|
|
0c5ef00c12 | |
|
|
1553582ec1 | |
|
|
756b906a21 | |
|
|
355e24fbe8 | |
|
|
9e4946aa45 | |
|
|
8e571d594d | |
|
|
b8dd2be1e4 | |
|
|
de7b60695a | |
|
|
a11ebecf93 | |
|
|
019412fa81 | |
|
|
84bf6d59db | |
|
|
82163d2e50 | |
|
|
208372e6af | |
|
|
dd8d812641 | |
|
|
c19b34542e | |
|
|
e30306d7e1 | |
|
|
20f34c9b14 | |
|
|
45749ffb5c | |
|
|
b176d63d93 | |
|
|
0c99afd58e | |
|
|
2458c9a9ba | |
|
|
4d0fef095b | |
|
|
642d2cd644 | |
|
|
e54ce36b0e | |
|
|
ac8b649d50 | |
|
|
9ca9cd5aa7 | |
|
|
37dafd7b3c | |
|
|
f58d12c2cb | |
|
|
d5eaa350c5 | |
|
|
1f0053a3c9 | |
|
|
15dccc7427 | |
|
|
7d287a2293 | |
|
|
f19ba3eb30 | |
|
|
4e172129d8 | |
|
|
2414e77fef | |
|
|
77517a9814 | |
|
|
162f21f6a5 | |
|
|
bd7c3293bc | |
|
|
e25be945c7 | |
|
|
925921c27c | |
|
|
64a6d26fa3 | |
|
|
c24617d864 | |
|
|
59bc259cc8 | |
|
|
c413cd6143 | |
|
|
c614cdcf4e | |
|
|
08f493ab3e | |
|
|
3705ca6e1f | |
|
|
34df279943 | |
|
|
b85ed1aa92 | |
|
|
faf4a328af | |
|
|
53f4f33bf0 | |
|
|
48c91f497b | |
|
|
9afbe3bd84 | |
|
|
2d5f71f6b7 | |
|
|
5747458bf2 | |
|
|
0b455eb882 | |
|
|
e086228d90 | |
|
|
909e96ca7c | |
|
|
75b24345f6 | |
|
|
88e20505f8 | |
|
|
b4b486944c | |
|
|
360ba38805 | |
|
|
e5a6952777 | |
|
|
9330cf682c | |
|
|
16a7d5d529 | |
|
|
303c6c7b35 | |
|
|
e4cf9e9086 | |
|
|
b977a85b23 | |
|
|
0fcb51a369 | |
|
|
d61511924d | |
|
|
aca7dd0a67 | |
|
|
fc685a99ca | |
|
|
d431aeb019 | |
|
|
63d0aaa6e6 | |
|
|
d45974c6b4 | |
|
|
3de931a3af | |
|
|
b96d6fc10d | |
|
|
ef1b78caae | |
|
|
47622bf49c | |
|
|
846d7103a3 | |
|
|
170f13082e | |
|
|
60016d7481 | |
|
|
97dae7fed2 | |
|
|
f935127cd3 | |
|
|
ec5f2ef05e | |
|
|
6d0ceaa4f5 | |
|
|
95922aec1e | |
|
|
3259c11828 | |
|
|
74bab1d935 | |
|
|
fd81edb495 | |
|
|
12bafb897f | |
|
|
a6befb1312 | |
|
|
a36e3fe72d | |
|
|
d9776d1793 | |
|
|
2697eb5a90 | |
|
|
4879bb7f44 | |
|
|
24f85780a2 | |
|
|
6c679cc3ab | |
|
|
20a06f1ec5 | |
|
|
5446bd937c | |
|
|
ae88dd0eec | |
|
|
a5c006d67c | |
|
|
67c487f521 | |
|
|
6ffb977ef3 | |
|
|
f59ba2623a | |
|
|
4b57138935 | |
|
|
276cd0a4a8 | |
|
|
22a9793b9d | |
|
|
1b7947b196 | |
|
|
188fdc9430 | |
|
|
ff0f225423 | |
|
|
36ca398543 | |
|
|
f30e2f5b33 | |
|
|
a531a213c2 | |
|
|
2b42376505 | |
|
|
ef103d8351 | |
|
|
db87b92f78 | |
|
|
51da1d4c43 | |
|
|
71ad34d7ac | |
|
|
7c29ab804b | |
|
|
9b269ea4c2 | |
|
|
c9ad6880cb | |
|
|
372fa9e06e | |
|
|
3df95d138d | |
|
|
410bb9b542 | |
|
|
15155b9a46 | |
|
|
f810ede6d7 | |
|
|
63d9e7f4c3 | |
|
|
3cea936aa4 | |
|
|
d90faed922 | |
|
|
febff1c658 | |
|
|
94a329a522 | |
|
|
84ed2e6b9d | |
|
|
47fbd443c1 | |
|
|
d5b52cc8db | |
|
|
d9ed27abfb | |
|
|
f51c2803c1 | |
|
|
05a34d4d12 | |
|
|
216d09f7b6 | |
|
|
8d441a02d2 | |
|
|
de2bc21f20 | |
|
|
4aba5c2a5e | |
|
|
b573e61504 | |
|
|
69de3d733d | |
|
|
a77ed7369a | |
|
|
1bd27a3e22 | |
|
|
4da7c1a524 | |
|
|
5c750e9c02 | |
|
|
cc09487671 | |
|
|
b024a18ba1 | |
|
|
4587cb7c19 | |
|
|
beec0b73e6 | |
|
|
61fb0cfe34 | |
|
|
260909bd4b | |
|
|
06a250b9fa | |
|
|
dc884d36b8 | |
|
|
1168d51e93 | |
|
|
7270e9194d | |
|
|
1d50dfcb6e | |
|
|
1eaaf44c97 | |
|
|
9cf8f19517 | |
|
|
22760c6c7c | |
|
|
47e43b0afa | |
|
|
58c7073073 | |
|
|
9dafabd1ee | |
|
|
5857696b56 | |
|
|
f2807f4838 | |
|
|
f46c180181 | |
|
|
1e14a5f30f | |
|
|
dfa11d11c3 | |
|
|
69d3303f3d | |
|
|
9eb6dda71b | |
|
|
10e0568251 | |
|
|
1f9faf49a3 | |
|
|
3f1b34682d | |
|
|
c3f6325e4a | |
|
|
a9f5608ecf | |
|
|
8a95fd57f5 | |
|
|
679c21da43 | |
|
|
52bab856ed | |
|
|
844b2fb62f | |
|
|
88404cbbfc | |
|
|
9b4aa904ef | |
|
|
a71153d414 | |
|
|
bec8c84c56 | |
|
|
79bab0459c | |
|
|
1d09f72460 | |
|
|
058270c658 | |
|
|
210c781fad | |
|
|
6757f6df5b | |
|
|
41c73fe35b | |
|
|
4d487fa4c4 | |
|
|
2f71bb515d | |
|
|
0d8b001dd2 | |
|
|
3d68dc4db3 | |
|
|
2988aef85a | |
|
|
768512bcfa | |
|
|
4492449b73 | |
|
|
be113567ba | |
|
|
e45a789569 | |
|
|
0a82b0d339 | |
|
|
c8cd323bb0 | |
|
|
2f09f88ca2 | |
|
|
8e178c0e37 | |
|
|
40711cbf38 | |
|
|
7749b6448e | |
|
|
1459992ec4 | |
|
|
c09dad4ae1 | |
|
|
271dc70626 | |
|
|
c462aeb2ef | |
|
|
adbdbf3a00 | |
|
|
10684d29cd | |
|
|
7d58454fdd | |
|
|
21b85aa2d3 | |
|
|
8439e4176d | |
|
|
4b43870ff2 | |
|
|
b49b94521e | |
|
|
49873ba6ed | |
|
|
97f083f07d | |
|
|
941bbc723a | |
|
|
18def7886d | |
|
|
f1336c56d4 | |
|
|
8f89651d10 | |
|
|
8d0634620a | |
|
|
f5afc43625 | |
|
|
f8eee2ba49 | |
|
|
07b52bed05 | |
|
|
3139fbefa6 | |
|
|
fbeeb3d959 | |
|
|
1f4e754adb | |
|
|
f63bbc8a52 | |
|
|
b17751b8a8 | |
|
|
05e721cf02 | |
|
|
29646f1294 | |
|
|
3702411ac8 | |
|
|
d205f00a1b | |
|
|
2894701063 | |
|
|
1045538b40 | |
|
|
8fd9b2ec82 | |
|
|
0ccdd424ab | |
|
|
c083e4ada4 | |
|
|
4c6dd1249a | |
|
|
b8b990bfc1 | |
|
|
252e6add67 | |
|
|
6e76b96f97 | |
|
|
dd18ecdba5 | |
|
|
2ff3e276d2 | |
|
|
1d5f2a953c |
|
|
@ -1,5 +0,0 @@
|
||||||
# change logs
|
|
||||||
|
|
||||||
- 2022.8.30 创建
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 94322e93a1f61b340bdc1d5042dab659
|
|
||||||
TextScriptImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: d104ab5da8136154899a40116dc88731
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,12 @@
|
||||||
|
#include "../Il2CppCompatibleDef.h"
|
||||||
|
|
||||||
|
namespace hybridclr
|
||||||
|
{
|
||||||
|
const char* g_placeHolderAssemblies[] =
|
||||||
|
{
|
||||||
|
//!!!{{PLACE_HOLDER
|
||||||
|
|
||||||
|
//!!!}}PLACE_HOLDER
|
||||||
|
nullptr,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
#include <codegen/il2cpp-codegen-metadata.h>
|
||||||
|
#if HYBRIDCLR_UNITY_2023_OR_NEW
|
||||||
|
#include <codegen/il2cpp-codegen.h>
|
||||||
|
#elif HYBRIDCLR_UNITY_2022
|
||||||
|
#include <codegen/il2cpp-codegen-il2cpp.h>
|
||||||
|
#elif HYBRIDCLR_UNITY_2020 || HYBRIDCLR_UNITY_2021
|
||||||
|
#include <codegen/il2cpp-codegen-common-big.h>
|
||||||
|
#else
|
||||||
|
#include <codegen/il2cpp-codegen-common.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "vm/ClassInlines.h"
|
||||||
|
#include "vm/Object.h"
|
||||||
|
#include "vm/Class.h"
|
||||||
|
#include "vm/ScopedThreadAttacher.h"
|
||||||
|
|
||||||
|
#include "../metadata/MetadataUtil.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "../interpreter/InterpreterModule.h"
|
||||||
|
#include "../interpreter/MethodBridge.h"
|
||||||
|
#include "../interpreter/Interpreter.h"
|
||||||
|
#include "../interpreter/MemoryUtil.h"
|
||||||
|
#include "../interpreter/InstrinctDef.h"
|
||||||
|
|
||||||
|
using namespace hybridclr::interpreter;
|
||||||
|
using namespace hybridclr::metadata;
|
||||||
|
|
||||||
|
//!!!{{CODE
|
||||||
|
|
||||||
|
|
||||||
|
//!!!}}CODE
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
#include <codegen/il2cpp-codegen-metadata.h>
|
|
||||||
#include "vm/ClassInlines.h"
|
|
||||||
#include "vm/Object.h"
|
|
||||||
#include "vm/Class.h"
|
|
||||||
|
|
||||||
#include "../metadata/MetadataModule.h"
|
|
||||||
#include "../metadata/MetadataUtil.h"
|
|
||||||
|
|
||||||
#include "../interpreter/MethodBridge.h"
|
|
||||||
#include "../interpreter/Interpreter.h"
|
|
||||||
#include "../interpreter/MemoryUtil.h"
|
|
||||||
#include "../interpreter/InstrinctDef.h"
|
|
||||||
|
|
||||||
using namespace hybridclr::interpreter;
|
|
||||||
|
|
||||||
#if {PLATFORM_ABI}
|
|
||||||
//!!!{{CODE
|
|
||||||
|
|
||||||
//!!!}}CODE
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
#include "../metadata/ReversePInvokeMethodStub.h"
|
|
||||||
#include "../metadata/MetadataModule.h"
|
|
||||||
|
|
||||||
namespace hybridclr
|
|
||||||
{
|
|
||||||
namespace metadata
|
|
||||||
{
|
|
||||||
#if {PLATFORM_ABI}
|
|
||||||
|
|
||||||
//!!!{{CODE
|
|
||||||
|
|
||||||
void __ReversePInvokeMethod_0(void* xState)
|
|
||||||
{
|
|
||||||
CallLuaFunction(xState, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void __ReversePInvokeMethod_1(void* xState)
|
|
||||||
{
|
|
||||||
CallLuaFunction(xState, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Il2CppMethodPointer s_ReversePInvokeMethodStub[]
|
|
||||||
{
|
|
||||||
(Il2CppMethodPointer)__ReversePInvokeMethod_0,
|
|
||||||
(Il2CppMethodPointer)__ReversePInvokeMethod_1,
|
|
||||||
nullptr,
|
|
||||||
};
|
|
||||||
|
|
||||||
//!!!}}CODE
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
//!!!{{UNITY_VERSION
|
||||||
|
|
||||||
|
|
||||||
|
//!!!}}UNITY_VERSION
|
||||||
|
|
@ -2,18 +2,38 @@
|
||||||
"versions": [
|
"versions": [
|
||||||
{
|
{
|
||||||
"unity_version":"2019",
|
"unity_version":"2019",
|
||||||
"hybridclr" : { "branch":"v2.0.3"},
|
"hybridclr" : { "branch":"v8.6.0"},
|
||||||
"il2cpp_plus": { "branch":"v2019-2.0.1"}
|
"il2cpp_plus": { "branch":"v2019-8.1.0"}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"unity_version":"2020",
|
"unity_version":"2020",
|
||||||
"hybridclr" : { "branch":"v2.0.3"},
|
"hybridclr" : { "branch":"v8.6.0"},
|
||||||
"il2cpp_plus": { "branch":"v2020-2.0.2"}
|
"il2cpp_plus": { "branch":"v2020-8.1.0"}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"unity_version":"2021",
|
"unity_version":"2021",
|
||||||
"hybridclr" : { "branch":"v2.0.3"},
|
"hybridclr" : { "branch":"v8.6.0"},
|
||||||
"il2cpp_plus": { "branch":"v2021-2.0.2"}
|
"il2cpp_plus": { "branch":"v2021-8.1.0"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"unity_version":"2022",
|
||||||
|
"hybridclr" : { "branch":"v8.6.0"},
|
||||||
|
"il2cpp_plus": { "branch":"v2022-8.2.0"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"unity_version":"2022-tuanjie",
|
||||||
|
"hybridclr" : { "branch":"v8.6.0"},
|
||||||
|
"il2cpp_plus": { "branch":"v2022-tuanjie-8.6.0"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"unity_version":"2023",
|
||||||
|
"hybridclr" : { "branch":"v8.6.0"},
|
||||||
|
"il2cpp_plus": { "branch":"v2023-8.1.0"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"unity_version":"6000",
|
||||||
|
"hybridclr" : { "branch":"v8.6.0"},
|
||||||
|
"il2cpp_plus": { "branch":"v6000-8.1.0"}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -1,88 +0,0 @@
|
||||||
# file: CMakeList.txt
|
|
||||||
cmake_minimum_required(VERSION 3.0)
|
|
||||||
set(CMAKE_OSX_DEPLOYMENT_TARGET iOS)
|
|
||||||
|
|
||||||
set(TMP $ENV{HUATUO_IL2CPP_SOURCE_DIR})
|
|
||||||
if ( NOT TMP )
|
|
||||||
message(FATAL_ERROR "需要设置环境变量: HUATUO_IL2CPP_SOURCE_DIR")
|
|
||||||
else()
|
|
||||||
message(STATUS "unity il2cpp 路径为: ${TMP}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(SDK_VERSION $ENV{IPHONESIMULATOR_VERSION})
|
|
||||||
if ( SDK_VERSION )
|
|
||||||
message(STATUS "使用iPhoneSimulator版本:" ${SDK_VERSION})
|
|
||||||
else()
|
|
||||||
message(STATUS "当前使用默认版本的iPhoneSimulator,可以通过设置环境变量IPHONESIMULATOR_VERSION,指定版本")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
project(il2cpp)
|
|
||||||
execute_process(COMMAND sh gen_lump.sh ${PROJECT_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
|
||||||
|
|
||||||
add_subdirectory(external)
|
|
||||||
add_subdirectory(objective)
|
|
||||||
|
|
||||||
|
|
||||||
set(IL2CPP_SOURCE_DIR $ENV{HUATUO_IL2CPP_SOURCE_DIR})
|
|
||||||
|
|
||||||
message(STATUS "il2cpp project, binary dir: " ${CMAKE_BINARY_DIR})
|
|
||||||
message(STATUS "il2cpp project, build dir: " ${PROJECT_BINARY_DIR})
|
|
||||||
message(STATUS "il2cpp project, il2cpp source dir: " ${IL2CPP_SOURCE_DIR})
|
|
||||||
|
|
||||||
|
|
||||||
SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)
|
|
||||||
find_program(CLANG_EXECUTABLE NAMES clang clang-7 clang-8 clang-9 clang-10)
|
|
||||||
if (NOT CLANG_EXECUTABLE)
|
|
||||||
message(FATAL_ERROR "Cannot find any clang executable.")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
set(CMAKE_OSX_SYSROOT /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator${SDK_VERSION}.sdk)
|
|
||||||
|
|
||||||
#set(CMAKE_VERBOSE_MAKEFILE ON)
|
|
||||||
set(CMAKE_CXX_COMPILER clang++)
|
|
||||||
set(CMAKE_C_COMPILER clang)
|
|
||||||
#add_compile_options(-x objective-c++)
|
|
||||||
|
|
||||||
# 以下命令为复制的Xcode生成中的命令
|
|
||||||
set(CMAKE_CXX_FLAGS "-target arm64-apple-ios11.0 -fmessage-length=0 -fdiagnostics-show-note-include-stack -fmacro-backtrace-limit=0 -std=gnu++1z -fmodules -fmodules-prune-interval=86400 -fmodules-prune-after=345600 -fmodules-ignore-macro=IL2CPP_TARGET_IOS=1 -fembed-bitcode -fmodules-ignore-macro=BASELIB_DYNAMICLIBRARY=1 -fmodules-ignore-macro=BASELIB_INLINE_NAMESPACE=il2cpp_baselib -fmodules-ignore-macro=AARCH64 -fmodules-ignore-macro=__aarch64__ -fmodules-ignore-macro=IL2CPP_SUPPORT_THREADS -fmodules-ignore-macro=IL2CPP_THREADS_PTHREAD -Wnon-modular-include-in-framework-module -Werror=non-modular-include-in-framework-module -Wno-trigraphs -fpascal-strings -Os -fno-common -Wno-missing-field-initializers -Wno-missing-prototypes -Werror=return-type -Wdocumentation -Wunreachable-code -Wquoted-include-in-framework-header -Werror=deprecated-objc-isa-usage -Werror=objc-root-class -Wno-non-virtual-dtor -Wno-overloaded-virtual -Wno-exit-time-destructors -Wno-missing-braces -Wparentheses -Wswitch -Wno-unused-function -Wno-unused-label -Wno-unused-parameter -Wno-unused-variable -Wunused-value -Wempty-body -Wuninitialized -Wconditional-uninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-conversion -Wconstant-conversion -Wint-conversion -Wbool-conversion -Wenum-conversion -Wno-float-conversion -Wnon-literal-null-conversion -Wobjc-literal-conversion -Wshorten-64-to-32 -Wno-newline-eof -Wno-c++11-extensions -DIL2CPP_TARGET_IOS=1 -isysroot ${CMAKE_OSX_SYSROOT} -fasm-blocks -fstrict-aliasing -Wdeprecated-declarations -Winvalid-offsetof -g -Wno-sign-conversion -Winfinite-recursion -Wmove -Wcomma -Wblock-capture-autoreleasing -Wstrict-prototypes -Wrange-loop-analysis -Wno-semicolon-before-method-body -Wunguarded-availability ")
|
|
||||||
|
|
||||||
|
|
||||||
add_definitions(-DIL2CPP_TARGET_IOS=1)
|
|
||||||
add_definitions(-DBASELIB_DYNAMICLIBRARY=1)
|
|
||||||
add_definitions(-DBASELIB_INLINE_NAMESPACE=il2cpp_baselib)
|
|
||||||
add_definitions(-DAARCH64)
|
|
||||||
add_definitions(-D__aarch64__)
|
|
||||||
add_definitions(-DIL2CPP_SUPPORT_THREADS)
|
|
||||||
add_definitions(-DIL2CPP_THREADS_PTHREAD)
|
|
||||||
#add_definitions(-DCMAKE_C_COMPILER=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang)
|
|
||||||
#add_definitions(-DCMAKE_CXX_COMPILER=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++)
|
|
||||||
#add_definitions(-DIL2CPP_TARGET_DARWIN)
|
|
||||||
add_definitions(-DIL2CPP_PLATFORM_SUPPORTS_TIMEZONEINFO)
|
|
||||||
|
|
||||||
add_definitions(-MMD)
|
|
||||||
add_definitions(-MT dependencies)
|
|
||||||
|
|
||||||
|
|
||||||
include_directories(${IL2CPP_SOURCE_DIR}/libil2cpp/)
|
|
||||||
include_directories(${IL2CPP_SOURCE_DIR}/external/)
|
|
||||||
include_directories(${IL2CPP_SOURCE_DIR}/external/baselib/Include/)
|
|
||||||
include_directories(${IL2CPP_SOURCE_DIR}/external/bdwgc/include/)
|
|
||||||
include_directories(${IL2CPP_SOURCE_DIR}/external/baselib/Platforms/OSX/Include/)
|
|
||||||
|
|
||||||
# 修改为本机对应SDK路径
|
|
||||||
include_directories(SYSTEM /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/c++/v1)
|
|
||||||
include_directories(SYSTEM /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include)
|
|
||||||
|
|
||||||
aux_source_directory(${PROJECT_BINARY_DIR}/lump_cpp LUMP_SOURCE_LIST)
|
|
||||||
aux_source_directory(${IL2CPP_SOURCE_DIR}/libil2cpp LIBIL2CPP_SOURCE_LIST)
|
|
||||||
|
|
||||||
#find_library(zlib ${PROJECT_SOURCE_DIR}/external)
|
|
||||||
add_library(il2cpp_original STATIC ${LIBIL2CPP_SOURCE_LIST} ${LUMP_SOURCE_LIST})
|
|
||||||
add_dependencies(il2cpp_original external objective)
|
|
||||||
|
|
||||||
add_custom_command(TARGET il2cpp_original
|
|
||||||
POST_BUILD
|
|
||||||
COMMAND xcrun -r libtool -static -o libil2cpp.a libil2cpp_original.a external/libexternal.a objective/libobjective.a
|
|
||||||
COMMENT "post build this is command combine libil2cpp_original.a, libojjective.a and libzlib.a into libil2cpp"
|
|
||||||
)
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
export HUATUO_IL2CPP_SOURCE_DIR=$(pushd ../LocalIl2CppData-OSXEditor/il2cpp > /dev/null && pwd && popd > /dev/null)
|
|
||||||
export IPHONESIMULATOR_VERSION=
|
|
||||||
|
|
||||||
rm -rf build
|
|
||||||
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake -DCMAKE_SYSTEM_PROCESSOR=arm64 -DCMAKE_OSX_ARCHITECTURES=arm64 ..
|
|
||||||
make -j24
|
|
||||||
|
|
||||||
if [ -f "libil2cpp.a" ]
|
|
||||||
then
|
|
||||||
echo 'build succ'
|
|
||||||
else
|
|
||||||
echo "build fail"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
# file: external/CMakeList.txt
|
|
||||||
cmake_minimum_required(VERSION 3.0)
|
|
||||||
set(CMAKE_OSX_DEPLOYMENT_TARGET iOS)
|
|
||||||
|
|
||||||
set(IL2CPP_SOURCE_DIR $ENV{HUATUO_IL2CPP_SOURCE_DIR})
|
|
||||||
set(SDK_VERSION $ENV{IPHONESIMULATOR_VERSION})
|
|
||||||
|
|
||||||
message(STATUS "external project, external source dir: " ${IL2CPP_SOURCE_DIR})
|
|
||||||
|
|
||||||
SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)
|
|
||||||
|
|
||||||
find_program(CLANG_EXECUTABLE NAMES clang clang-7 clang-8 clang-9 clang-10)
|
|
||||||
if (NOT CLANG_EXECUTABLE)
|
|
||||||
message(FATAL_ERROR "Cannot find any clang executable.")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(CMAKE_OSX_SYSROOT /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator${SDK_VERSION}.sdk)
|
|
||||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
|
||||||
set(CMAKE_C_COMPILER clang)
|
|
||||||
|
|
||||||
set(CMAKE_C_FLAGS "-x c -target arm64-apple-ios11.0 -fmessage-length=0 -fdiagnostics-show-note-include-stack -fmacro-backtrace-limit=0 -std=gnu11 -fmodules -fmodules-prune-interval=86400 -fmodules-prune-after=345600 -fmodules-ignore-macro=IL2CPP_TARGET_IOS=1 -fembed-bitcode -fmodules-ignore-macro=BASELIB_DYNAMICLIBRARY=1 -fmodules-ignore-macro=BASELIB_INLINE_NAMESPACE=il2cpp_baselib -fmodules-ignore-macro=AARCH64 -fmodules-ignore-macro=__aarch64__ -fmodules-ignore-macro=IL2CPP_SUPPORT_THREADS -fmodules-ignore-macro=IL2CPP_THREADS_PTHREAD -Wnon-modular-include-in-framework-module -Werror=non-modular-include-in-framework-module -Wno-trigraphs -fpascal-strings -Os -fno-common -Wno-missing-field-initializers -Wno-missing-prototypes -Werror=return-type -Wdocumentation -Wunreachable-code -Wquoted-include-in-framework-header -Werror=deprecated-objc-isa-usage -Werror=objc-root-class -Wno-missing-braces -Wparentheses -Wswitch -Wunused-function -Wno-unused-label -Wno-unused-parameter -Wunused-variable -Wunused-value -Wempty-body -Wuninitialized -Wconditional-uninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-conversion -Wconstant-conversion -Wint-conversion -Wbool-conversion -Wenum-conversion -Wno-float-conversion -Wnon-literal-null-conversion -Wobjc-literal-conversion -Wshorten-64-to-32 -Wpointer-sign -Wno-newline-eof -DIL2CPP_TARGET_IOS=1 -isysroot ${CMAKE_OSX_SYSROOT} -fstrict-aliasing -Wdeprecated-declarations -g -Wno-sign-conversion -Winfinite-recursion -Wcomma -Wblock-capture-autoreleasing -Wstrict-prototypes -Wno-semicolon-before-method-body -Wunguarded-availability")
|
|
||||||
|
|
||||||
|
|
||||||
add_definitions(-DIL2CPP_TARGET_IOS=1)
|
|
||||||
add_definitions(-DBASELIB_DYNAMICLIBRARY=1)
|
|
||||||
add_definitions(-DBASELIB_INLINE_NAMESPACE=il2cpp_baselib)
|
|
||||||
add_definitions(-DAARCH64)
|
|
||||||
add_definitions(-D__aarch64__)
|
|
||||||
#add_definitions(-D__arm64__)
|
|
||||||
add_definitions(-DIL2CPP_SUPPORT_THREADS)
|
|
||||||
add_definitions(-DIL2CPP_THREADS_PTHREAD)
|
|
||||||
#add_definitions(-DCMAKE_C_COMPILER=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang)
|
|
||||||
#add_definitions(-DCMAKE_CXX_COMPILER=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++)
|
|
||||||
#add_definitions(-DIL2CPP_TARGET_DARWIN)
|
|
||||||
add_definitions(-DIL2CPP_PLATFORM_SUPPORTS_TIMEZONEINFO=0)
|
|
||||||
|
|
||||||
add_definitions(-MMD)
|
|
||||||
add_definitions(-MT dependencies)
|
|
||||||
|
|
||||||
include_directories(${IL2CPP_SOURCE_DIR}/external/)
|
|
||||||
include_directories(${IL2CPP_SOURCE_DIR}/external/baselib/Include/)
|
|
||||||
include_directories(${IL2CPP_SOURCE_DIR}/external/bdwgc/include/)
|
|
||||||
include_directories(${IL2CPP_SOURCE_DIR}/external/baselib/Platforms/OSX/Include/)
|
|
||||||
|
|
||||||
aux_source_directory(${IL2CPP_SOURCE_DIR}/external/zlib/ ZLIB_C_SOURCE_LIST)
|
|
||||||
add_library(external STATIC ${ZLIB_C_SOURCE_LIST})
|
|
||||||
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
||||||
echo '====================================================================='
|
|
||||||
echo 'gen lump'
|
|
||||||
echo '$HUATUO_IL2CPP_SOURCE_DIR='${HUATUO_IL2CPP_SOURCE_DIR} #/Applications/Unity/Unity.app/Contents/il2cpp/
|
|
||||||
|
|
||||||
GEN_SOURCE_DIR=$1
|
|
||||||
BASE_DIR=${HUATUO_IL2CPP_SOURCE_DIR}/libil2cpp
|
|
||||||
echo base dir: ${BASE_DIR}
|
|
||||||
echo " "
|
|
||||||
#BASE_DIR=${HUATUO_IL2CPP_SOURCE_DIR}/libil2cpp
|
|
||||||
function SearchCppFile()
|
|
||||||
{
|
|
||||||
for f in $(ls $1)
|
|
||||||
do
|
|
||||||
SUB_DIR=$1/$f
|
|
||||||
if [ -d ${SUB_DIR} ]; then
|
|
||||||
SearchCppFile ${SUB_DIR}
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
CPP_FILE_NUM=`ls -l $1/ | grep "\.cpp$"|wc -l`
|
|
||||||
if (( ${CPP_FILE_NUM} > 0 ))
|
|
||||||
then
|
|
||||||
for f in $1/*.cpp
|
|
||||||
do
|
|
||||||
echo "#include \""$f"\"" >> ${OUTPUT_FILE_NAME}
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
MM_FILE_NUM=`ls -l $1/ | grep "\.mm$"|wc -l`
|
|
||||||
if (( ${MM_FILE_NUM} > 0 ))
|
|
||||||
then
|
|
||||||
for f in $1/*.mm
|
|
||||||
do
|
|
||||||
echo "#include \""$f"\"" >> ${OBJECTIVE_FILE_NAME}
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
rm -rf "${GEN_SOURCE_DIR}"/lump_cpp
|
|
||||||
rm -rf "${GEN_SOURCE_DIR}"/lump_mm
|
|
||||||
mkdir "${GEN_SOURCE_DIR}"/lump_cpp
|
|
||||||
mkdir "${GEN_SOURCE_DIR}"/lump_mm
|
|
||||||
|
|
||||||
OBJECTIVE_FILE_NAME=${GEN_SOURCE_DIR}/lump_mm/lump_libil2cpp_ojective.mm
|
|
||||||
echo "#include \"${BASE_DIR}/il2cpp-config.h\"" > ${OBJECTIVE_FILE_NAME}
|
|
||||||
echo gen file: ${OBJECTIVE_FILE_NAME}
|
|
||||||
|
|
||||||
for FOLDER in hybridclr vm pch utils vm-utils codegen metadata os debugger mono gc icalls
|
|
||||||
do
|
|
||||||
OUTPUT_FILE_NAME=${GEN_SOURCE_DIR}/lump_cpp/lump_libil2cpp_${FOLDER}.cpp
|
|
||||||
echo "#include \"${BASE_DIR}/il2cpp-config.h\"" > ${OUTPUT_FILE_NAME}
|
|
||||||
if [ $FOLDER = hybridclr ] || [ $FOLDER = vm ]
|
|
||||||
then
|
|
||||||
echo "#include \"${BASE_DIR}/codegen/il2cpp-codegen.h\"" >> ${OUTPUT_FILE_NAME}
|
|
||||||
fi
|
|
||||||
SearchCppFile ${BASE_DIR}/${FOLDER}
|
|
||||||
echo gen file: ${OUTPUT_FILE_NAME}
|
|
||||||
done
|
|
||||||
|
|
||||||
echo gen done.
|
|
||||||
echo '====================================================================='
|
|
||||||
echo " "
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
# file: CMakeList.txt
|
|
||||||
cmake_minimum_required(VERSION 3.0)
|
|
||||||
set(CMAKE_OSX_DEPLOYMENT_TARGET iOS)
|
|
||||||
project(il2cpp)
|
|
||||||
|
|
||||||
set(IL2CPP_SOURCE_DIR $ENV{HUATUO_IL2CPP_SOURCE_DIR})
|
|
||||||
set(SDK_VERSION $ENV{IPHONESIMULATOR_VERSION})
|
|
||||||
|
|
||||||
message(STATUS "objective project, binary dir: " ${PROJECT_BINARY_DIR})
|
|
||||||
message(STATUS "objective project, il2cpp source dir: " ${PROJECT_SOURCE_DIR})
|
|
||||||
|
|
||||||
|
|
||||||
SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)
|
|
||||||
find_program(CLANG_EXECUTABLE NAMES clang clang-7 clang-8 clang-9 clang-10)
|
|
||||||
if (NOT CLANG_EXECUTABLE)
|
|
||||||
message(FATAL_ERROR "Cannot find any clang executable.")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
set(CMAKE_OSX_SYSROOT /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator${SDK_VERSION}.sdk)
|
|
||||||
|
|
||||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
|
||||||
set(CMAKE_CXX_COMPILER clang++)
|
|
||||||
set(CMAKE_C_COMPILER clang)
|
|
||||||
#add_compile_options(-x objective-c++)
|
|
||||||
|
|
||||||
# 以下命令为复制的Xcode生成中的命令
|
|
||||||
set(CMAKE_CXX_FLAGS "-target arm64-apple-ios11.0 -fmessage-length=0 -fdiagnostics-show-note-include-stack -fmacro-backtrace-limit=0 -std=gnu++1z -fmodules -fmodules-prune-interval=86400 -fmodules-prune-after=345600 -fmodules-ignore-macro=IL2CPP_TARGET_IOS=1 -fembed-bitcode -fmodules-ignore-macro=BASELIB_DYNAMICLIBRARY=1 -fmodules-ignore-macro=BASELIB_INLINE_NAMESPACE=il2cpp_baselib -fmodules-ignore-macro=AARCH64 -fmodules-ignore-macro=__aarch64__ -fmodules-ignore-macro=IL2CPP_SUPPORT_THREADS -fmodules-ignore-macro=IL2CPP_THREADS_PTHREAD -Wnon-modular-include-in-framework-module -Werror=non-modular-include-in-framework-module -Wno-trigraphs -fpascal-strings -Os -fno-common -Wno-missing-field-initializers -Wno-missing-prototypes -Werror=return-type -Wdocumentation -Wunreachable-code -Wquoted-include-in-framework-header -Werror=deprecated-objc-isa-usage -Werror=objc-root-class -Wno-non-virtual-dtor -Wno-overloaded-virtual -Wno-exit-time-destructors -Wno-missing-braces -Wparentheses -Wswitch -Wno-unused-function -Wno-unused-label -Wno-unused-parameter -Wno-unused-variable -Wunused-value -Wempty-body -Wuninitialized -Wconditional-uninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-conversion -Wconstant-conversion -Wint-conversion -Wbool-conversion -Wenum-conversion -Wno-float-conversion -Wnon-literal-null-conversion -Wobjc-literal-conversion -Wshorten-64-to-32 -Wno-newline-eof -Wno-c++11-extensions -DIL2CPP_TARGET_IOS=1 -isysroot ${SDK_VERSION} -fasm-blocks -fstrict-aliasing -Wdeprecated-declarations -Winvalid-offsetof -g -Wno-sign-conversion -Winfinite-recursion -Wmove -Wcomma -Wblock-capture-autoreleasing -Wstrict-prototypes -Wrange-loop-analysis -Wno-semicolon-before-method-body -Wunguarded-availability ")
|
|
||||||
|
|
||||||
|
|
||||||
add_definitions(-DIL2CPP_TARGET_IOS=1)
|
|
||||||
add_definitions(-DBASELIB_DYNAMICLIBRARY=1)
|
|
||||||
add_definitions(-DBASELIB_INLINE_NAMESPACE=il2cpp_baselib)
|
|
||||||
add_definitions(-DAARCH64)
|
|
||||||
add_definitions(-D__aarch64__)
|
|
||||||
add_definitions(-DIL2CPP_SUPPORT_THREADS)
|
|
||||||
add_definitions(-DIL2CPP_THREADS_PTHREAD)
|
|
||||||
#add_definitions(-DCMAKE_C_COMPILER=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang)
|
|
||||||
#add_definitions(-DCMAKE_CXX_COMPILER=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++)
|
|
||||||
#add_definitions(-DIL2CPP_TARGET_DARWIN)
|
|
||||||
add_definitions(-DIL2CPP_PLATFORM_SUPPORTS_TIMEZONEINFO)
|
|
||||||
|
|
||||||
add_definitions(-MMD)
|
|
||||||
add_definitions(-MT dependencies)
|
|
||||||
|
|
||||||
|
|
||||||
include_directories(${IL2CPP_SOURCE_DIR}/libil2cpp)
|
|
||||||
include_directories(${IL2CPP_SOURCE_DIR}/external)
|
|
||||||
include_directories(${IL2CPP_SOURCE_DIR}/external/baselib/Include/)
|
|
||||||
include_directories(${IL2CPP_SOURCE_DIR}/external/bdwgc/include/)
|
|
||||||
include_directories(${IL2CPP_SOURCE_DIR}/external/baselib/Platforms/OSX/Include/)
|
|
||||||
|
|
||||||
# 修改为本机对应SDK路径
|
|
||||||
include_directories(SYSTEM /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/c++/v1)
|
|
||||||
include_directories(SYSTEM /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include)
|
|
||||||
|
|
||||||
get_filename_component(PARENT_PATH ${PROJECT_BINARY_DIR} PATH)
|
|
||||||
aux_source_directory(${PARENT_PATH}/lump_mm LUMP_SOURCE_LIST)
|
|
||||||
|
|
||||||
#find_library(zlib ${PROJECT_SOURCE_DIR}/external)
|
|
||||||
add_library(objective STATIC ${LUMP_SOURCE_LIST})
|
|
||||||
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 4455f7304f8678f408dd6cf21734f55e
|
guid: 8f2dd29d56a640d4ebd1c2fd374b7638
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
|
|
|
||||||
|
|
@ -116,8 +116,8 @@ namespace MonoHook
|
||||||
|
|
||||||
static void SetupFlushICacheFunc()
|
static void SetupFlushICacheFunc()
|
||||||
{
|
{
|
||||||
string processorType = SystemInfo.processorType;
|
string processorType = SystemInfo.processorType.ToLowerInvariant();
|
||||||
if (processorType.Contains("Intel") || processorType.Contains("AMD"))
|
if (processorType.Contains("intel") || processorType.Contains("amd"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (IntPtr.Size == 4)
|
if (IntPtr.Size == 4)
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,11 @@ namespace MonoHook
|
||||||
|
|
||||||
static HookUtils()
|
static HookUtils()
|
||||||
{
|
{
|
||||||
jit_write_protect_supported = pthread_jit_write_protect_supported_np() != 0;
|
try
|
||||||
|
{
|
||||||
|
jit_write_protect_supported = pthread_jit_write_protect_supported_np() != 0;
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
|
||||||
PropertyInfo p_SystemPageSize = typeof(Environment).GetProperty("SystemPageSize");
|
PropertyInfo p_SystemPageSize = typeof(Environment).GetProperty("SystemPageSize");
|
||||||
if (p_SystemPageSize == null)
|
if (p_SystemPageSize == null)
|
||||||
|
|
@ -35,6 +39,16 @@ namespace MonoHook
|
||||||
|
|
||||||
public static void MemCpy_Jit(void* pDst, byte[] src)
|
public static void MemCpy_Jit(void* pDst, byte[] src)
|
||||||
{
|
{
|
||||||
|
if (!jit_write_protect_supported)
|
||||||
|
{
|
||||||
|
fixed(void * pSrc = &src[0])
|
||||||
|
{
|
||||||
|
MemCpy(pDst, pSrc, src.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
fixed(void * p = &src[0])
|
fixed(void * p = &src[0])
|
||||||
{
|
{
|
||||||
memcpy_jit(new IntPtr(pDst), new IntPtr(p), src.Length);
|
memcpy_jit(new IntPtr(pDst), new IntPtr(p), src.Length);
|
||||||
|
|
|
||||||
|
|
@ -1,277 +0,0 @@
|
||||||
#if ENABLE_HOOK_TEST_CASE
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Text;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEditor.Callbacks;
|
|
||||||
using UnityEngine;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace MonoHook.Test
|
|
||||||
{
|
|
||||||
// 有需求时可以打开,也可以手动按需注册Hook
|
|
||||||
[InitializeOnLoad]
|
|
||||||
public class BuildPipeline_StripDll_HookTest
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 裁剪执行完毕的回调,可能会被调用多次,一般而言同一次打包只需要处理第一次回调
|
|
||||||
/// </summary>
|
|
||||||
public static Action<string, BuildPostProcessArgs, BeeDriverResult> OnAssemblyStripped;
|
|
||||||
|
|
||||||
// 尝试 Hook 4个函数,至少一个被调用就可以达到要求
|
|
||||||
private static MethodHook _hook_PostprocessBuildPlayer_CompleteBuild;
|
|
||||||
private static MethodHook _hook_Default_PostProcess;
|
|
||||||
private static MethodHook _hook_ReportBuildResults;
|
|
||||||
private static MethodHook _hook_StripAssembliesTo;
|
|
||||||
|
|
||||||
#region Fake Internal Structures
|
|
||||||
public struct BuildPostProcessArgs
|
|
||||||
{
|
|
||||||
public BuildTarget target;
|
|
||||||
public int subTarget;
|
|
||||||
public string stagingArea;
|
|
||||||
public string stagingAreaData;
|
|
||||||
public string stagingAreaDataManaged;
|
|
||||||
public string playerPackage;
|
|
||||||
public string installPath;
|
|
||||||
public string companyName;
|
|
||||||
public string productName;
|
|
||||||
public Guid productGUID;
|
|
||||||
public BuildOptions options;
|
|
||||||
public UnityEditor.Build.Reporting.BuildReport report;
|
|
||||||
internal /*RuntimeClassRegistry*/object usedClassRegistry;
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class BeeDriverResult
|
|
||||||
{
|
|
||||||
public /*NodeResult*/object[] NodeResults { get; set; }
|
|
||||||
public bool Success { get; set; }
|
|
||||||
public /*Message*/object[] BeeDriverMessages { get; set; }
|
|
||||||
public override string ToString() => Success.ToString();
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
static BuildPipeline_StripDll_HookTest()
|
|
||||||
{
|
|
||||||
InstallHook();
|
|
||||||
#if ENABLE_HOOK_TEST_CASE
|
|
||||||
OnAssemblyStripped = DemoStripCallback;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 示例裁剪回调函数
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="outputFolder"></param>
|
|
||||||
/// <param name="args"></param>
|
|
||||||
/// <param name="result"></param>
|
|
||||||
static void DemoStripCallback(string outputFolder, BuildPostProcessArgs args, BeeDriverResult result)
|
|
||||||
{
|
|
||||||
if (outputFolder != null)
|
|
||||||
Debug.Log($"stripped outputFolder is:{outputFolder}");
|
|
||||||
else if (args.stagingAreaDataManaged != null)
|
|
||||||
Debug.Log($"stripped staging folder is:{args.stagingAreaDataManaged}");
|
|
||||||
else if (result != null)
|
|
||||||
Debug.Log($"stripped result is: {result.Success}");
|
|
||||||
else
|
|
||||||
Debug.Log("stripped test called");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void InstallHook()
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
Type type = Type.GetType("UnityEditor.PostprocessBuildPlayer,UnityEditor, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
|
|
||||||
if (type == null)
|
|
||||||
{
|
|
||||||
Debug.LogError($"can not find type: UnityEditor.PostprocessBuildPlayer");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
MethodInfo miTarget = type.GetMethod("PostProcessCompletedBuild", BindingFlags.Static | BindingFlags.Public);
|
|
||||||
|
|
||||||
if (miTarget == null)
|
|
||||||
{
|
|
||||||
Debug.LogError($"can not find method: UnityEditor.PostprocessBuildPlayer.PostProcessCompletedBuild");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
MethodInfo miReplace = typeof(BuildPipeline_StripDll_HookTest).GetMethod(nameof(PostprocessBuildPlayer_CompleteBuild_Replace), BindingFlags.Static | BindingFlags.NonPublic);
|
|
||||||
MethodInfo miProxy = typeof(BuildPipeline_StripDll_HookTest).GetMethod(nameof(PostprocessBuildPlayer_CompleteBuild_Proxy), BindingFlags.Static | BindingFlags.NonPublic);
|
|
||||||
|
|
||||||
_hook_PostprocessBuildPlayer_CompleteBuild = new MethodHook(miTarget, miReplace, miProxy);
|
|
||||||
_hook_PostprocessBuildPlayer_CompleteBuild.Install();
|
|
||||||
|
|
||||||
Debug.Log("Hook BuildPipeline_StripDll_HookTest.PostprocessBuildPlayer_CompleteBuild installed");
|
|
||||||
} while (false);
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
Type type = Type.GetType("UnityEditor.Modules.DefaultBuildPostprocessor,UnityEditor.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
|
|
||||||
if (type == null)
|
|
||||||
{
|
|
||||||
Debug.LogError($"can not find type: UnityEditor.Modules.DefaultBuildPostprocessor");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
MethodInfo[] miTargets = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);
|
|
||||||
MethodInfo miTarget = (from mi in miTargets where mi.Name == "PostProcess" && mi.GetParameters().Length == 2 select mi).FirstOrDefault();
|
|
||||||
|
|
||||||
if (miTarget == null)
|
|
||||||
{
|
|
||||||
Debug.LogError($"can not find method: UnityEditor.Modules.DefaultBuildPostprocessor.PostProcess");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
MethodInfo miReplace = typeof(BuildPipeline_StripDll_HookTest).GetMethod(nameof(Default_PostProcess_Replace), BindingFlags.Static | BindingFlags.NonPublic);
|
|
||||||
MethodInfo miProxy = typeof(BuildPipeline_StripDll_HookTest).GetMethod(nameof(Default_PostProcess_Proxy), BindingFlags.Static | BindingFlags.NonPublic);
|
|
||||||
|
|
||||||
_hook_Default_PostProcess = new MethodHook(miTarget, miReplace, miProxy);
|
|
||||||
_hook_Default_PostProcess.Install();
|
|
||||||
|
|
||||||
Debug.Log("Hook BuildPipeline_StripDll_HookTest.PostProcess installed");
|
|
||||||
} while (false);
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
Type type = Type.GetType("UnityEditor.Modules.BeeBuildPostprocessor,UnityEditor.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
|
|
||||||
if (type == null)
|
|
||||||
{
|
|
||||||
Debug.LogError($"can not find type: UnityEditor.Modules.BeeBuildPostprocessor");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
MethodInfo miTarget = type.GetMethod("ReportBuildResults", BindingFlags.Instance | BindingFlags.NonPublic);
|
|
||||||
if (miTarget == null)
|
|
||||||
{
|
|
||||||
Debug.LogError($"can not find method: UnityEditor.Modules.BeeBuildPostprocessor.ReportBuildResults");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
MethodInfo miReplace = typeof(BuildPipeline_StripDll_HookTest).GetMethod(nameof(ReportBuildResults_Replace), BindingFlags.Static | BindingFlags.NonPublic);
|
|
||||||
MethodInfo miProxy = typeof(BuildPipeline_StripDll_HookTest).GetMethod(nameof(ReportBuildResults_Proxy), BindingFlags.Static | BindingFlags.NonPublic);
|
|
||||||
|
|
||||||
_hook_ReportBuildResults = new MethodHook(miTarget, miReplace, miProxy);
|
|
||||||
_hook_ReportBuildResults.Install();
|
|
||||||
|
|
||||||
Debug.Log("Hook BuildPipeline_StripDll_HookTest.ReportBuildResults installed");
|
|
||||||
} while (false);
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
Type type = Type.GetType("UnityEditorInternal.AssemblyStripper,UnityEditor.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
|
|
||||||
if (type == null)
|
|
||||||
{
|
|
||||||
Debug.LogError($"can not find type: UnityEditorInternal.AssemblyStripper");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
MethodInfo miTarget = type.GetMethod("StripAssembliesTo", BindingFlags.Static | BindingFlags.NonPublic);
|
|
||||||
if (miTarget == null)
|
|
||||||
{
|
|
||||||
Debug.LogError($"can not find method: UnityEditorInternal.AssemblyStripper.StripAssembliesTo");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
MethodInfo miReplace = typeof(BuildPipeline_StripDll_HookTest).GetMethod(nameof(StripAssembliesTo_Replace), BindingFlags.Static | BindingFlags.NonPublic);
|
|
||||||
MethodInfo miProxy = typeof(BuildPipeline_StripDll_HookTest).GetMethod(nameof(StripAssembliesTo_Proxy), BindingFlags.Static | BindingFlags.NonPublic);
|
|
||||||
|
|
||||||
_hook_StripAssembliesTo = new MethodHook(miTarget, miReplace, miProxy);
|
|
||||||
_hook_StripAssembliesTo.Install();
|
|
||||||
|
|
||||||
Debug.Log("Hook BuildPipeline_StripDll_HookTest.StripAssembliesTo installed");
|
|
||||||
} while (false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void UninstallHook()
|
|
||||||
{
|
|
||||||
_hook_PostprocessBuildPlayer_CompleteBuild?.Uninstall();
|
|
||||||
_hook_Default_PostProcess?.Uninstall();
|
|
||||||
_hook_ReportBuildResults?.Uninstall();
|
|
||||||
_hook_StripAssembliesTo?.Uninstall();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void PostprocessBuildPlayer_CompleteBuild_Replace(BuildPostProcessArgs args)
|
|
||||||
{
|
|
||||||
Debug.Log("PostprocessBuildPlayer_CompleteBuild_Replace called");
|
|
||||||
|
|
||||||
OnAssemblyStripped?.Invoke(null, args, null);
|
|
||||||
PostprocessBuildPlayer_CompleteBuild_Proxy(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Default_PostProcess_Replace(object obj, BuildPostProcessArgs args, out /*BuildProperties*/ object outProperties)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// 注意:此函数中途可能会被 Unity throw Exception
|
|
||||||
Default_PostProcess_Proxy(obj, args, out outProperties);
|
|
||||||
}
|
|
||||||
catch(Exception ex)
|
|
||||||
{
|
|
||||||
throw ex;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Debug.Log("PostProcess_Replace called");
|
|
||||||
OnAssemblyStripped?.Invoke(null, args, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ReportBuildResults_Replace(object obj, BeeDriverResult result)
|
|
||||||
{
|
|
||||||
// TODO: 可以在这里把 Library\Bee\artifacts\WinPlayerBuildProgram\ManagedStripped 目录下的文件复制出来
|
|
||||||
Debug.Log("ReportBuildResults_Replace called");
|
|
||||||
|
|
||||||
OnAssemblyStripped?.Invoke(null, default(BuildPostProcessArgs), result);
|
|
||||||
ReportBuildResults_Proxy(obj, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool StripAssembliesTo_Replace(string outputFolder, out string output, out string error, IEnumerable<string> linkXmlFiles, /*UnityLinkerRunInformation*/ object runInformation)
|
|
||||||
{
|
|
||||||
bool ret = StripAssembliesTo_Proxy(outputFolder, out output, out error, linkXmlFiles, runInformation);
|
|
||||||
|
|
||||||
// TODO: 可以在这里把 Temp\StagingArea\Data\Managed\tempStrip 目录下的文件复制出来
|
|
||||||
Debug.Log("StripAssembliesTo_Replace called");
|
|
||||||
|
|
||||||
OnAssemblyStripped?.Invoke(outputFolder, default(BuildPostProcessArgs), null);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Proxy Methods
|
|
||||||
[MethodImpl(MethodImplOptions.NoOptimization)]
|
|
||||||
static void PostprocessBuildPlayer_CompleteBuild_Proxy(BuildPostProcessArgs args)
|
|
||||||
{
|
|
||||||
Debug.Log("dummy code" + 200);
|
|
||||||
Debug.Log(args.companyName);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.NoOptimization)]
|
|
||||||
static void Default_PostProcess_Proxy(object obj, BuildPostProcessArgs args, out /*BuildProperties*/ object outProperties)
|
|
||||||
{
|
|
||||||
Debug.Log("dummy code" + 100);
|
|
||||||
outProperties = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.NoOptimization)]
|
|
||||||
static void ReportBuildResults_Proxy(object obj, /*BeeDriverResult*/ object result)
|
|
||||||
{
|
|
||||||
// dummy code
|
|
||||||
Debug.Log("something" + obj.ToString() + result.ToString() + 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.NoOptimization)]
|
|
||||||
static bool StripAssembliesTo_Proxy(string outputFolder, out string output, out string error, IEnumerable<string> linkXmlFiles, /*UnityLinkerRunInformation*/ object runInformation)
|
|
||||||
{
|
|
||||||
Debug.Log("StripAssembliesTo_Proxy called");
|
|
||||||
output = null;
|
|
||||||
error = null;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -12,7 +12,7 @@ using System.IO;
|
||||||
|
|
||||||
namespace HybridCLR.MonoHook
|
namespace HybridCLR.MonoHook
|
||||||
{
|
{
|
||||||
#if UNITY_2021_1_OR_NEWER && UNITY_IOS
|
#if UNITY_2021_1_OR_NEWER && !UNITY_2023_1_OR_NEWER
|
||||||
[InitializeOnLoad]
|
[InitializeOnLoad]
|
||||||
public class CopyStrippedAOTAssembliesHook
|
public class CopyStrippedAOTAssembliesHook
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using MonoHook;
|
||||||
|
using HybridCLR.Editor.BuildProcessors;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace HybridCLR.MonoHook
|
||||||
|
{
|
||||||
|
#if UNITY_2022 || UNITY_2023_1_OR_NEWER
|
||||||
|
[InitializeOnLoad]
|
||||||
|
public class GetIl2CppFolderHook
|
||||||
|
{
|
||||||
|
private static MethodHook _hook;
|
||||||
|
|
||||||
|
static GetIl2CppFolderHook()
|
||||||
|
{
|
||||||
|
if (_hook == null)
|
||||||
|
{
|
||||||
|
Type type = typeof(UnityEditor.EditorApplication).Assembly.GetType("UnityEditorInternal.IL2CPPUtils");
|
||||||
|
MethodInfo miTarget = type.GetMethod("GetIl2CppFolder", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, null,
|
||||||
|
new Type[] { typeof(bool).MakeByRefType() }, null);
|
||||||
|
|
||||||
|
MethodInfo miReplacement = new StripAssembliesDel(OverrideMethod).Method;
|
||||||
|
MethodInfo miProxy = new StripAssembliesDel(PlaceHolderMethod).Method;
|
||||||
|
|
||||||
|
_hook = new MethodHook(miTarget, miReplacement, miProxy);
|
||||||
|
_hook.Install();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private delegate string StripAssembliesDel(out bool isDevelopmentLocation);
|
||||||
|
|
||||||
|
private static string OverrideMethod(out bool isDevelopmentLocation)
|
||||||
|
{
|
||||||
|
//Debug.Log("[GetIl2CppFolderHook] OverrideMethod");
|
||||||
|
string result = PlaceHolderMethod(out isDevelopmentLocation);
|
||||||
|
isDevelopmentLocation = false;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.NoOptimization)]
|
||||||
|
private static string PlaceHolderMethod(out bool isDevelopmentLocation)
|
||||||
|
{
|
||||||
|
Debug.LogError("[GetIl2CppFolderHook] PlaceHolderMethod");
|
||||||
|
isDevelopmentLocation = false;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: ed8859610137d404e87f332b7082c19b
|
guid: 96c2bc28db69e1644892219abef3d4b5
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
|
|
@ -12,7 +12,7 @@ using System.IO;
|
||||||
|
|
||||||
namespace HybridCLR.MonoHook
|
namespace HybridCLR.MonoHook
|
||||||
{
|
{
|
||||||
#if UNITY_2021_1_OR_NEWER && UNITY_WEBGL
|
#if UNITY_2021_1_OR_NEWER && (UNITY_WEBGL || UNITY_WEIXINMINIGAME)
|
||||||
[InitializeOnLoad]
|
[InitializeOnLoad]
|
||||||
public class PatchScriptingAssembliesJsonHook
|
public class PatchScriptingAssembliesJsonHook
|
||||||
{
|
{
|
||||||
|
|
@ -35,12 +35,29 @@ namespace HybridCLR.MonoHook
|
||||||
|
|
||||||
private static string BuildMainWindowTitle()
|
private static string BuildMainWindowTitle()
|
||||||
{
|
{
|
||||||
string tempJsonPath = $"{Application.dataPath}/../Library/PlayerDataCache/WebGL/Data/ScriptingAssemblies.json";
|
var cacheDir = $"{Application.dataPath}/../Library/PlayerDataCache";
|
||||||
if (File.Exists(tempJsonPath))
|
if (Directory.Exists(cacheDir))
|
||||||
{
|
{
|
||||||
var patcher = new PatchScriptingAssemblyList();
|
foreach (var tempJsonPath in Directory.GetDirectories(cacheDir, "*", SearchOption.TopDirectoryOnly))
|
||||||
patcher.PathScriptingAssembilesFile(Path.GetDirectoryName(tempJsonPath));
|
{
|
||||||
|
string dirName = Path.GetFileName(tempJsonPath);
|
||||||
|
#if UNITY_WEIXINMINIGAME
|
||||||
|
if (!dirName.Contains("WeixinMiniGame"))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (!dirName.Contains("WebGL"))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
var patcher = new PatchScriptingAssemblyList();
|
||||||
|
patcher.PathScriptingAssembilesFile(tempJsonPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string newTitle = BuildMainWindowTitleProxy();
|
string newTitle = BuildMainWindowTitleProxy();
|
||||||
return newTitle;
|
return newTitle;
|
||||||
}
|
}
|
||||||
|
|
@ -48,6 +65,8 @@ namespace HybridCLR.MonoHook
|
||||||
[MethodImpl(MethodImplOptions.NoOptimization)]
|
[MethodImpl(MethodImplOptions.NoOptimization)]
|
||||||
private static string BuildMainWindowTitleProxy()
|
private static string BuildMainWindowTitleProxy()
|
||||||
{
|
{
|
||||||
|
// 为满足MonoHook要求的最小代码长度而特地加入的无用填充代码,
|
||||||
|
UnityEngine.Debug.Log(12345.ToString());
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace DotNetDetour
|
namespace DotNetDetour
|
||||||
{
|
{
|
||||||
|
|
@ -641,15 +642,8 @@ namespace DotNetDetour
|
||||||
if(s_isArm.HasValue)
|
if(s_isArm.HasValue)
|
||||||
return s_isArm.Value;
|
return s_isArm.Value;
|
||||||
|
|
||||||
string processorType = UnityEngine.SystemInfo.processorType;
|
var arch = RuntimeInformation.ProcessArchitecture;
|
||||||
|
s_isArm = arch == Architecture.Arm || arch == Architecture.Arm64;
|
||||||
/*
|
|
||||||
* appple M 系列
|
|
||||||
* SystemInfo.processorType 返回值为: Apple M1 Max, Apple M2 等
|
|
||||||
* SystemInfo.operatingSystem 返回值为: Mac OS X xx.x.x
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
s_isArm = processorType.Contains("ARM") || processorType.Contains("Apple M");
|
|
||||||
|
|
||||||
return s_isArm.Value;
|
return s_isArm.Value;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
/*
|
/*
|
||||||
Desc: 一个可以运行时 Hook Mono 方法的工具,让你可以无需修改 UnityEditor.dll 等文件就可以重写其函数功能
|
Desc: 一个可以运行时 Hook Mono 方法的工具,让你可以无需修改 UnityEditor.dll 等文件就可以重写其函数功能
|
||||||
Author: Misaka Mikoto
|
Author: Misaka Mikoto
|
||||||
Github: https://github.com/Misaka-Mikoto-Tech/MonoHook
|
Github: https://github.com/Misaka-Mikoto-Tech/MonoHook
|
||||||
|
|
@ -85,7 +85,7 @@ namespace MonoHook
|
||||||
|
|
||||||
private CodePatcher _codePatcher;
|
private CodePatcher _codePatcher;
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR && !UNITY_2020_3_OR_NEWER
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// call `MethodInfo.MethodHandle.GetFunctionPointer()`
|
/// call `MethodInfo.MethodHandle.GetFunctionPointer()`
|
||||||
/// will visit static class `UnityEditor.IMGUI.Controls.TreeViewGUI.Styles` and invoke its static constructor,
|
/// will visit static class `UnityEditor.IMGUI.Controls.TreeViewGUI.Styles` and invoke its static constructor,
|
||||||
|
|
@ -97,7 +97,7 @@ namespace MonoHook
|
||||||
|
|
||||||
static MethodHook()
|
static MethodHook()
|
||||||
{
|
{
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR && !UNITY_2020_3_OR_NEWER
|
||||||
s_fi_GUISkin_current = typeof(GUISkin).GetField("current", BindingFlags.Static | BindingFlags.NonPublic);
|
s_fi_GUISkin_current = typeof(GUISkin).GetField("current", BindingFlags.Static | BindingFlags.NonPublic);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
@ -126,7 +126,7 @@ namespace MonoHook
|
||||||
if (isHooked)
|
if (isHooked)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR && !UNITY_2020_3_OR_NEWER
|
||||||
if (s_fi_GUISkin_current.GetValue(null) != null)
|
if (s_fi_GUISkin_current.GetValue(null) != null)
|
||||||
DoInstall();
|
DoInstall();
|
||||||
else
|
else
|
||||||
|
|
@ -191,7 +191,7 @@ namespace MonoHook
|
||||||
if (targetMethod.IsAbstract)
|
if (targetMethod.IsAbstract)
|
||||||
throw new Exception($"WRANING: you can not hook abstract method [{methodName}]");
|
throw new Exception($"WRANING: you can not hook abstract method [{methodName}]");
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR && !UNITY_2020_3_OR_NEWER
|
||||||
int minMethodBodySize = 10;
|
int minMethodBodySize = 10;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
@ -358,13 +358,19 @@ namespace MonoHook
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR && !UNITY_2020_3_OR_NEWER
|
||||||
private void OnEditorUpdate()
|
private void OnEditorUpdate()
|
||||||
{
|
{
|
||||||
if (s_fi_GUISkin_current.GetValue(null) != null)
|
if (s_fi_GUISkin_current.GetValue(null) != null)
|
||||||
{
|
{
|
||||||
DoInstall();
|
try
|
||||||
EditorApplication.update -= OnEditorUpdate;
|
{
|
||||||
|
DoInstall();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
EditorApplication.update -= OnEditorUpdate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -14,20 +14,6 @@ namespace HybridCLR.Editor.ABI
|
||||||
|
|
||||||
public int Index { get; set; }
|
public int Index { get; set; }
|
||||||
|
|
||||||
//public bool IsNative2ManagedByAddress => Type.PorType >= ParamOrReturnType.STRUCT_NOT_PASS_AS_VALUE;
|
|
||||||
public bool IsPassToManagedByAddress => Type.GetParamSlotNum() > 1;
|
|
||||||
|
|
||||||
public bool IsPassToNativeByAddress => Type.PorType == ParamOrReturnType.STRUCTURE_AS_REF_PARAM;
|
|
||||||
|
|
||||||
public string Native2ManagedParamValue(PlatformABI canv)
|
|
||||||
{
|
|
||||||
return IsPassToManagedByAddress ? $"(uint64_t)&__arg{Index}" : $"*(uint64_t*)&__arg{Index}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Managed2NativeParamValue(PlatformABI canv)
|
|
||||||
{
|
|
||||||
return IsPassToNativeByAddress ? $"(uint64_t)(localVarBase+argVarIndexs[{Index}])" : $"*({Type.GetTypeName()}*)(localVarBase+argVarIndexs[{Index}])";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ReturnInfo
|
public class ReturnInfo
|
||||||
|
|
@ -36,11 +22,6 @@ namespace HybridCLR.Editor.ABI
|
||||||
|
|
||||||
public bool IsVoid => Type.PorType == ParamOrReturnType.VOID;
|
public bool IsVoid => Type.PorType == ParamOrReturnType.VOID;
|
||||||
|
|
||||||
public int GetParamSlotNum(PlatformABI canv)
|
|
||||||
{
|
|
||||||
return Type.GetParamSlotNum();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return Type.GetTypeName();
|
return Type.GetTypeName();
|
||||||
|
|
|
||||||
|
|
@ -19,25 +19,9 @@ namespace HybridCLR.Editor.ABI
|
||||||
U8,
|
U8,
|
||||||
R4,
|
R4,
|
||||||
R8,
|
R8,
|
||||||
ARM64_HFA_FLOAT_2,
|
I,
|
||||||
VALUE_TYPE_SIZE_LESS_EQUAL_8,
|
U,
|
||||||
I16, // 8 < size <= 16
|
TYPEDBYREF,
|
||||||
STRUCT_NOT_PASS_AS_VALUE, // struct pass not as value
|
STRUCT,
|
||||||
STRUCTURE_AS_REF_PARAM, // size > 16
|
|
||||||
ARM64_HFA_FLOAT_3,
|
|
||||||
ARM64_HFA_FLOAT_4,
|
|
||||||
ARM64_HFA_DOUBLE_2,
|
|
||||||
ARM64_HFA_DOUBLE_3,
|
|
||||||
ARM64_HFA_DOUBLE_4,
|
|
||||||
ARM64_HVA_8,
|
|
||||||
ARM64_HVA_16,
|
|
||||||
STRUCTURE_ALIGN1, // size > 16
|
|
||||||
STRUCTURE_ALIGN2,
|
|
||||||
STRUCTURE_ALIGN4,
|
|
||||||
STRUCTURE_ALIGN8,
|
|
||||||
SPECIAL_STRUCTURE_ALIGN1,
|
|
||||||
SPECIAL_STRUCTURE_ALIGN2,
|
|
||||||
SPECIAL_STRUCTURE_ALIGN4,
|
|
||||||
SPECIAL_STRUCTURE_ALIGN8,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,102 @@
|
||||||
|
using dnlib.DotNet;
|
||||||
|
using HybridCLR.Editor.Meta;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace HybridCLR.Editor.ABI
|
||||||
|
{
|
||||||
|
public class TypeCreator
|
||||||
|
{
|
||||||
|
private readonly Dictionary<TypeSig, TypeInfo> _typeInfoCache = new Dictionary<TypeSig, TypeInfo>(TypeEqualityComparer.Instance);
|
||||||
|
|
||||||
|
private int _nextStructId = 0;
|
||||||
|
|
||||||
|
public TypeInfo CreateTypeInfo(TypeSig type)
|
||||||
|
{
|
||||||
|
type = type.RemovePinnedAndModifiers();
|
||||||
|
if (!_typeInfoCache.TryGetValue(type, out var typeInfo))
|
||||||
|
{
|
||||||
|
typeInfo = CreateTypeInfo0(type);
|
||||||
|
_typeInfoCache.Add(type, typeInfo);
|
||||||
|
}
|
||||||
|
return typeInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeInfo CreateTypeInfo0(TypeSig type)
|
||||||
|
{
|
||||||
|
type = type.RemovePinnedAndModifiers();
|
||||||
|
if (type.IsByRef)
|
||||||
|
{
|
||||||
|
return TypeInfo.s_u;
|
||||||
|
}
|
||||||
|
switch (type.ElementType)
|
||||||
|
{
|
||||||
|
case ElementType.Void: return TypeInfo.s_void;
|
||||||
|
case ElementType.Boolean: return TypeInfo.s_u1;
|
||||||
|
case ElementType.I1: return TypeInfo.s_i1;
|
||||||
|
case ElementType.U1: return TypeInfo.s_u1;
|
||||||
|
case ElementType.I2: return TypeInfo.s_i2;
|
||||||
|
case ElementType.Char:
|
||||||
|
case ElementType.U2: return TypeInfo.s_u2;
|
||||||
|
case ElementType.I4: return TypeInfo.s_i4;
|
||||||
|
case ElementType.U4: return TypeInfo.s_u4;
|
||||||
|
case ElementType.I8: return TypeInfo.s_i8;
|
||||||
|
case ElementType.U8: return TypeInfo.s_u8;
|
||||||
|
case ElementType.R4: return TypeInfo.s_r4;
|
||||||
|
case ElementType.R8: return TypeInfo.s_r8;
|
||||||
|
case ElementType.I: return TypeInfo.s_i;
|
||||||
|
case ElementType.U:
|
||||||
|
case ElementType.String:
|
||||||
|
case ElementType.Ptr:
|
||||||
|
case ElementType.ByRef:
|
||||||
|
case ElementType.Class:
|
||||||
|
case ElementType.Array:
|
||||||
|
case ElementType.SZArray:
|
||||||
|
case ElementType.FnPtr:
|
||||||
|
case ElementType.Object:
|
||||||
|
case ElementType.Module:
|
||||||
|
case ElementType.Var:
|
||||||
|
case ElementType.MVar:
|
||||||
|
return TypeInfo.s_u;
|
||||||
|
case ElementType.TypedByRef: return TypeInfo.s_typedByRef;
|
||||||
|
case ElementType.ValueType:
|
||||||
|
{
|
||||||
|
TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDef();
|
||||||
|
if (typeDef == null)
|
||||||
|
{
|
||||||
|
throw new Exception($"type:{type} definition could not be found. Please try `HybridCLR/Genergate/LinkXml`, then Build once to generate the AOT dll, and then regenerate the bridge function");
|
||||||
|
}
|
||||||
|
if (typeDef.IsEnum)
|
||||||
|
{
|
||||||
|
return CreateTypeInfo(typeDef.GetEnumUnderlyingType());
|
||||||
|
}
|
||||||
|
return CreateValueType(type);
|
||||||
|
}
|
||||||
|
case ElementType.GenericInst:
|
||||||
|
{
|
||||||
|
GenericInstSig gis = (GenericInstSig)type;
|
||||||
|
if (!gis.GenericType.IsValueType)
|
||||||
|
{
|
||||||
|
return TypeInfo.s_u;
|
||||||
|
}
|
||||||
|
TypeDef typeDef = gis.GenericType.ToTypeDefOrRef().ResolveTypeDef();
|
||||||
|
if (typeDef.IsEnum)
|
||||||
|
{
|
||||||
|
return CreateTypeInfo(typeDef.GetEnumUnderlyingType());
|
||||||
|
}
|
||||||
|
return CreateValueType(type);
|
||||||
|
}
|
||||||
|
default: throw new NotSupportedException($"{type.ElementType}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TypeInfo CreateValueType(TypeSig type)
|
||||||
|
{
|
||||||
|
return new TypeInfo(ParamOrReturnType.STRUCT, type, _nextStructId++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: a22846b73022cb2458d1c40549ab6877
|
guid: 0b1df5760b488fa43a68843c46fda63a
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
using dnlib.DotNet;
|
|
||||||
using HybridCLR.Editor.Meta;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace HybridCLR.Editor.ABI
|
|
||||||
{
|
|
||||||
public class HFATypeInfo
|
|
||||||
{
|
|
||||||
public TypeSig Type { get; set; }
|
|
||||||
|
|
||||||
public int Count { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class TypeCreatorArm64 : TypeCreatorBase
|
|
||||||
{
|
|
||||||
public override bool IsArch32 => false;
|
|
||||||
|
|
||||||
public override bool IsSupportHFA => true;
|
|
||||||
|
|
||||||
protected override TypeInfo OptimizeSigType(TypeInfo type, bool returnType)
|
|
||||||
{
|
|
||||||
if (!type.IsGeneralValueType)
|
|
||||||
{
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
int typeSize = type.Size;
|
|
||||||
if (typeSize <= 8)
|
|
||||||
{
|
|
||||||
return TypeInfo.s_i8;
|
|
||||||
}
|
|
||||||
if (typeSize <= 16)
|
|
||||||
{
|
|
||||||
return TypeInfo.s_i16;
|
|
||||||
}
|
|
||||||
if (returnType)
|
|
||||||
{
|
|
||||||
return type.PorType != ParamOrReturnType.STRUCTURE_ALIGN1 ? new TypeInfo(ParamOrReturnType.STRUCTURE_ALIGN1, typeSize) : type;
|
|
||||||
}
|
|
||||||
return TypeInfo.s_ref;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,320 +0,0 @@
|
||||||
using dnlib.DotNet;
|
|
||||||
using HybridCLR.Editor.Meta;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace HybridCLR.Editor.ABI
|
|
||||||
{
|
|
||||||
public abstract class TypeCreatorBase
|
|
||||||
{
|
|
||||||
public abstract bool IsArch32 { get; }
|
|
||||||
|
|
||||||
public virtual bool IsSupportHFA => false;
|
|
||||||
|
|
||||||
public virtual bool IsSupportWebGLSpecialValueType => false;
|
|
||||||
|
|
||||||
public TypeInfo GetNativeIntTypeInfo() => IsArch32 ? TypeInfo.s_i4 : TypeInfo.s_i8;
|
|
||||||
|
|
||||||
public ValueTypeSizeAligmentCalculator Calculator => IsArch32 ? ValueTypeSizeAligmentCalculator.Caculator32 : ValueTypeSizeAligmentCalculator.Caculator64;
|
|
||||||
|
|
||||||
|
|
||||||
private readonly Dictionary<TypeSig, (int, int)> _typeSizeCache = new Dictionary<TypeSig, (int, int)>(TypeEqualityComparer.Instance);
|
|
||||||
|
|
||||||
public (int Size, int Aligment) ComputeSizeAndAligment(TypeSig t)
|
|
||||||
{
|
|
||||||
if (_typeSizeCache.TryGetValue(t, out var sizeAndAligment))
|
|
||||||
{
|
|
||||||
return sizeAndAligment;
|
|
||||||
}
|
|
||||||
sizeAndAligment = Calculator.SizeAndAligmentOf(t);
|
|
||||||
_typeSizeCache.Add(t, sizeAndAligment);
|
|
||||||
return sizeAndAligment;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TypeInfo CreateTypeInfo(TypeSig type)
|
|
||||||
{
|
|
||||||
type = type.RemovePinnedAndModifiers();
|
|
||||||
if (type.IsByRef)
|
|
||||||
{
|
|
||||||
return GetNativeIntTypeInfo();
|
|
||||||
}
|
|
||||||
switch (type.ElementType)
|
|
||||||
{
|
|
||||||
case ElementType.Void: return TypeInfo.s_void;
|
|
||||||
case ElementType.Boolean: return TypeInfo.s_u1;
|
|
||||||
case ElementType.I1: return TypeInfo.s_i1;
|
|
||||||
case ElementType.U1: return TypeInfo.s_u1;
|
|
||||||
case ElementType.I2: return TypeInfo.s_i2;
|
|
||||||
case ElementType.Char:
|
|
||||||
case ElementType.U2: return TypeInfo.s_u2;
|
|
||||||
case ElementType.I4: return TypeInfo.s_i4;
|
|
||||||
case ElementType.U4: return TypeInfo.s_u4;
|
|
||||||
case ElementType.I8: return TypeInfo.s_i8;
|
|
||||||
case ElementType.U8: return TypeInfo.s_u8;
|
|
||||||
case ElementType.R4: return TypeInfo.s_r4;
|
|
||||||
case ElementType.R8: return TypeInfo.s_r8;
|
|
||||||
case ElementType.U: return IsArch32 ? TypeInfo.s_u4 : TypeInfo.s_u8;
|
|
||||||
case ElementType.I:
|
|
||||||
case ElementType.String:
|
|
||||||
case ElementType.Ptr:
|
|
||||||
case ElementType.ByRef:
|
|
||||||
case ElementType.Class:
|
|
||||||
case ElementType.Array:
|
|
||||||
case ElementType.SZArray:
|
|
||||||
case ElementType.FnPtr:
|
|
||||||
case ElementType.Object:
|
|
||||||
case ElementType.Module:
|
|
||||||
case ElementType.Var:
|
|
||||||
case ElementType.MVar:
|
|
||||||
return GetNativeIntTypeInfo();
|
|
||||||
case ElementType.TypedByRef: return CreateValueType(type);
|
|
||||||
case ElementType.ValueType:
|
|
||||||
{
|
|
||||||
TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDef();
|
|
||||||
if (typeDef == null)
|
|
||||||
{
|
|
||||||
throw new Exception($"type:{type} 未能找到定义。请尝试 `HybridCLR/Genergate/LinkXml`,然后Build一次生成AOT dll,再重新生成桥接函数");
|
|
||||||
}
|
|
||||||
if (typeDef.IsEnum)
|
|
||||||
{
|
|
||||||
return CreateTypeInfo(typeDef.GetEnumUnderlyingType());
|
|
||||||
}
|
|
||||||
return CreateValueType(type);
|
|
||||||
}
|
|
||||||
case ElementType.GenericInst:
|
|
||||||
{
|
|
||||||
GenericInstSig gis = (GenericInstSig)type;
|
|
||||||
if (!gis.GenericType.IsValueType)
|
|
||||||
{
|
|
||||||
return GetNativeIntTypeInfo();
|
|
||||||
}
|
|
||||||
TypeDef typeDef = gis.GenericType.ToTypeDefOrRef().ResolveTypeDef();
|
|
||||||
if (typeDef.IsEnum)
|
|
||||||
{
|
|
||||||
return CreateTypeInfo(typeDef.GetEnumUnderlyingType());
|
|
||||||
}
|
|
||||||
return CreateValueType(type);
|
|
||||||
}
|
|
||||||
default: throw new NotSupportedException($"{type.ElementType}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsNotHFAFastCheck(int typeSize)
|
|
||||||
{
|
|
||||||
return typeSize != 8 && typeSize != 12 && typeSize != 16 && typeSize != 24 && typeSize != 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool ComputHFATypeInfo0(TypeSig type, HFATypeInfo typeInfo)
|
|
||||||
{
|
|
||||||
TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDefThrow();
|
|
||||||
|
|
||||||
List<TypeSig> klassInst = type.ToGenericInstSig()?.GenericArguments?.ToList();
|
|
||||||
GenericArgumentContext ctx = klassInst != null ? new GenericArgumentContext(klassInst, null) : null;
|
|
||||||
|
|
||||||
var fields = typeDef.Fields;// typeDef.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
|
||||||
foreach (FieldDef field in fields)
|
|
||||||
{
|
|
||||||
if (field.IsStatic)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
TypeSig ftype = ctx != null ? MetaUtil.Inflate(field.FieldType, ctx) : field.FieldType;
|
|
||||||
switch (ftype.ElementType)
|
|
||||||
{
|
|
||||||
case ElementType.R4:
|
|
||||||
case ElementType.R8:
|
|
||||||
{
|
|
||||||
if (ftype == typeInfo.Type || typeInfo.Type == null)
|
|
||||||
{
|
|
||||||
typeInfo.Type = ftype;
|
|
||||||
++typeInfo.Count;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ElementType.ValueType:
|
|
||||||
{
|
|
||||||
if (!ComputHFATypeInfo0(ftype, typeInfo))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ElementType.GenericInst:
|
|
||||||
{
|
|
||||||
if (!ftype.IsValueType || !ComputHFATypeInfo0(ftype, typeInfo))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return typeInfo.Count <= 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool ComputHFATypeInfo(TypeSig type, int typeSize, out HFATypeInfo typeInfo)
|
|
||||||
{
|
|
||||||
typeInfo = new HFATypeInfo();
|
|
||||||
if (IsNotHFAFastCheck(typeSize))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool ok = ComputHFATypeInfo0(type, typeInfo);
|
|
||||||
if (ok && typeInfo.Count >= 2 && typeInfo.Count <= 4)
|
|
||||||
{
|
|
||||||
int fieldSize = typeInfo.Type.ElementType == ElementType.R4 ? 4 : 8;
|
|
||||||
return typeSize == fieldSize * typeInfo.Count;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool TryComputSingletonStruct(TypeSig type, out SingletonStruct result)
|
|
||||||
{
|
|
||||||
result = new SingletonStruct();
|
|
||||||
return TryComputSingletonStruct0(type, result) && result.Type != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool TryComputSingletonStruct0(TypeSig type, SingletonStruct result)
|
|
||||||
{
|
|
||||||
TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDefThrow();
|
|
||||||
if (typeDef.IsEnum)
|
|
||||||
{
|
|
||||||
if (result.Type == null)
|
|
||||||
{
|
|
||||||
result.Type = typeDef.GetEnumUnderlyingType();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<TypeSig> klassInst = type.ToGenericInstSig()?.GenericArguments?.ToList();
|
|
||||||
GenericArgumentContext ctx = klassInst != null ? new GenericArgumentContext(klassInst, null) : null;
|
|
||||||
|
|
||||||
var fields = typeDef.Fields;// typeDef.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
|
||||||
foreach (FieldDef field in fields)
|
|
||||||
{
|
|
||||||
if (field.IsStatic)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
TypeSig ftype = ctx != null ? MetaUtil.Inflate(field.FieldType, ctx) : field.FieldType;
|
|
||||||
|
|
||||||
switch (ftype.ElementType)
|
|
||||||
{
|
|
||||||
case ElementType.TypedByRef: return false;
|
|
||||||
case ElementType.ValueType:
|
|
||||||
{
|
|
||||||
if (!TryComputSingletonStruct0(ftype, result))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ElementType.GenericInst:
|
|
||||||
{
|
|
||||||
if (!ftype.IsValueType)
|
|
||||||
{
|
|
||||||
goto default;
|
|
||||||
}
|
|
||||||
if (!TryComputSingletonStruct0(ftype, result))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
if (result.Type != null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
result.Type = ftype;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsWebGLSpeicalValueType(TypeSig type)
|
|
||||||
{
|
|
||||||
TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDefThrow();
|
|
||||||
if (typeDef.IsEnum)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
var fields = typeDef.Fields;// typeDef.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
|
||||||
if (fields.Count == 0)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return fields.All(f => f.IsStatic);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static TypeInfo CreateGeneralValueType(TypeSig type, int size, int aligment)
|
|
||||||
{
|
|
||||||
System.Diagnostics.Debug.Assert(size % aligment == 0);
|
|
||||||
switch (aligment)
|
|
||||||
{
|
|
||||||
case 1: return new TypeInfo(ParamOrReturnType.STRUCTURE_ALIGN1, size);
|
|
||||||
case 2: return new TypeInfo(ParamOrReturnType.STRUCTURE_ALIGN2, size);
|
|
||||||
case 4: return new TypeInfo(ParamOrReturnType.STRUCTURE_ALIGN4, size);
|
|
||||||
case 8: return new TypeInfo(ParamOrReturnType.STRUCTURE_ALIGN8, size);
|
|
||||||
default: throw new NotSupportedException($"type:{type} not support aligment:{aligment}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected TypeInfo CreateValueType(TypeSig type)
|
|
||||||
{
|
|
||||||
(int typeSize, int typeAligment) = ComputeSizeAndAligment(type);
|
|
||||||
if (IsSupportHFA && ComputHFATypeInfo(type, typeSize, out HFATypeInfo hfaTypeInfo))
|
|
||||||
{
|
|
||||||
bool isFloat = hfaTypeInfo.Type.ElementType == ElementType.R4;
|
|
||||||
switch (hfaTypeInfo.Count)
|
|
||||||
{
|
|
||||||
case 2: return isFloat ? TypeInfo.s_vf2 : TypeInfo.s_vd2;
|
|
||||||
case 3: return isFloat ? TypeInfo.s_vf3 : TypeInfo.s_vd3;
|
|
||||||
case 4: return isFloat ? TypeInfo.s_vf4 : TypeInfo.s_vd4;
|
|
||||||
default: throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (IsSupportWebGLSpecialValueType && IsWebGLSpeicalValueType(type))
|
|
||||||
{
|
|
||||||
switch (typeAligment)
|
|
||||||
{
|
|
||||||
case 1: return new TypeInfo(ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN1, typeSize);
|
|
||||||
case 2: return new TypeInfo(ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN2, typeSize);
|
|
||||||
case 4: return new TypeInfo(ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN4, typeSize);
|
|
||||||
case 8: return new TypeInfo(ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN8, typeSize);
|
|
||||||
default: throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 64位下结构体内存对齐规则是一样的
|
|
||||||
return CreateGeneralValueType(type, typeSize, typeAligment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected abstract TypeInfo OptimizeSigType(TypeInfo type, bool returnType);
|
|
||||||
|
|
||||||
public virtual void OptimizeMethod(MethodDesc method)
|
|
||||||
{
|
|
||||||
method.TransfromSigTypes(OptimizeSigType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace HybridCLR.Editor.ABI
|
|
||||||
{
|
|
||||||
public static class TypeCreatorFactory
|
|
||||||
{
|
|
||||||
public static TypeCreatorBase CreateTypeCreator(PlatformABI abi)
|
|
||||||
{
|
|
||||||
switch(abi)
|
|
||||||
{
|
|
||||||
case PlatformABI.Arm64: return new TypeCreatorArm64();
|
|
||||||
case PlatformABI.Universal32: return new TypeCreatorUniversal32();
|
|
||||||
case PlatformABI.Universal64: return new TypeCreatorUniversal64();
|
|
||||||
case PlatformABI.WebGL32: return new TypeCreatorWebGL32();
|
|
||||||
default: throw new NotSupportedException(abi.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace HybridCLR.Editor.ABI
|
|
||||||
{
|
|
||||||
public class TypeCreatorUniversal32 : TypeCreatorBase
|
|
||||||
{
|
|
||||||
public override bool IsArch32 => true;
|
|
||||||
|
|
||||||
public override bool IsSupportHFA => false;
|
|
||||||
|
|
||||||
protected override TypeInfo OptimizeSigType(TypeInfo type, bool returnType)
|
|
||||||
{
|
|
||||||
if (type.PorType > ParamOrReturnType.STRUCTURE_ALIGN1 && type.PorType <= ParamOrReturnType.STRUCTURE_ALIGN4)
|
|
||||||
{
|
|
||||||
return new TypeInfo(ParamOrReturnType.STRUCTURE_ALIGN1, type.Size);
|
|
||||||
}
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 1eb9e19189731a344aad024a43e795bc
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace HybridCLR.Editor.ABI
|
|
||||||
{
|
|
||||||
public class TypeCreatorUniversal64 : TypeCreatorBase
|
|
||||||
{
|
|
||||||
public override bool IsArch32 => false;
|
|
||||||
|
|
||||||
public override bool IsSupportHFA => true;
|
|
||||||
|
|
||||||
protected override TypeInfo OptimizeSigType(TypeInfo type, bool returnType)
|
|
||||||
{
|
|
||||||
if (type.PorType > ParamOrReturnType.STRUCTURE_ALIGN1 && type.PorType <= ParamOrReturnType.STRUCTURE_ALIGN8)
|
|
||||||
{
|
|
||||||
return new TypeInfo(ParamOrReturnType.STRUCTURE_ALIGN1, type.Size);
|
|
||||||
}
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 7867dfe20d27e324e90bc13b9d4f05bb
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
using dnlib.DotNet;
|
|
||||||
using HybridCLR.Editor.Meta;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace HybridCLR.Editor.ABI
|
|
||||||
{
|
|
||||||
public class SingletonStruct
|
|
||||||
{
|
|
||||||
public TypeSig Type { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class TypeCreatorWebGL32 : TypeCreatorBase
|
|
||||||
{
|
|
||||||
public override bool IsArch32 => true;
|
|
||||||
|
|
||||||
public override bool IsSupportHFA => false;
|
|
||||||
|
|
||||||
public override bool IsSupportWebGLSpecialValueType => true;
|
|
||||||
|
|
||||||
|
|
||||||
protected override TypeInfo OptimizeSigType(TypeInfo type, bool returnType)
|
|
||||||
{
|
|
||||||
//if (type.PorType > ParamOrReturnType.STRUCTURE_ALIGN1 && type.PorType <= ParamOrReturnType.STRUCTURE_ALIGN4)
|
|
||||||
//{
|
|
||||||
// return new TypeInfo(ParamOrReturnType.STRUCTURE_ALIGN1, type.Size);
|
|
||||||
//}
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 4790a87aacda1a14d813570e9e0f35ca
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using dnlib.DotNet;
|
using dnlib.DotNet;
|
||||||
|
using HybridCLR.Editor.Meta;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
@ -20,37 +21,34 @@ namespace HybridCLR.Editor.ABI
|
||||||
public static readonly TypeInfo s_u8 = new TypeInfo(ParamOrReturnType.U8);
|
public static readonly TypeInfo s_u8 = new TypeInfo(ParamOrReturnType.U8);
|
||||||
public static readonly TypeInfo s_r4 = new TypeInfo(ParamOrReturnType.R4);
|
public static readonly TypeInfo s_r4 = new TypeInfo(ParamOrReturnType.R4);
|
||||||
public static readonly TypeInfo s_r8 = new TypeInfo(ParamOrReturnType.R8);
|
public static readonly TypeInfo s_r8 = new TypeInfo(ParamOrReturnType.R8);
|
||||||
public static readonly TypeInfo s_i16 = new TypeInfo(ParamOrReturnType.I16);
|
public static readonly TypeInfo s_i = new TypeInfo(ParamOrReturnType.I);
|
||||||
public static readonly TypeInfo s_ref = new TypeInfo(ParamOrReturnType.STRUCTURE_AS_REF_PARAM);
|
public static readonly TypeInfo s_u = new TypeInfo(ParamOrReturnType.U);
|
||||||
|
public static readonly TypeInfo s_typedByRef = new TypeInfo(ParamOrReturnType.TYPEDBYREF);
|
||||||
|
|
||||||
public static readonly TypeInfo s_vf2 = new TypeInfo(ParamOrReturnType.ARM64_HFA_FLOAT_2);
|
public const string strTypedByRef = "typedbyref";
|
||||||
public static readonly TypeInfo s_vf3 = new TypeInfo(ParamOrReturnType.ARM64_HFA_FLOAT_3);
|
|
||||||
public static readonly TypeInfo s_vf4 = new TypeInfo(ParamOrReturnType.ARM64_HFA_FLOAT_4);
|
|
||||||
public static readonly TypeInfo s_vd2 = new TypeInfo(ParamOrReturnType.ARM64_HFA_DOUBLE_2);
|
|
||||||
public static readonly TypeInfo s_vd3 = new TypeInfo(ParamOrReturnType.ARM64_HFA_DOUBLE_3);
|
|
||||||
public static readonly TypeInfo s_vd4 = new TypeInfo(ParamOrReturnType.ARM64_HFA_DOUBLE_4);
|
|
||||||
|
|
||||||
public TypeInfo(ParamOrReturnType portype)
|
public TypeInfo(ParamOrReturnType portype, TypeSig klass = null, int typeId = 0)
|
||||||
{
|
{
|
||||||
PorType = portype;
|
PorType = portype;
|
||||||
Size = 0;
|
Klass = klass;
|
||||||
}
|
_typeId = typeId;
|
||||||
|
|
||||||
public TypeInfo(ParamOrReturnType portype, int size)
|
|
||||||
{
|
|
||||||
PorType = portype;
|
|
||||||
Size = size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ParamOrReturnType PorType { get; }
|
public ParamOrReturnType PorType { get; }
|
||||||
|
|
||||||
public bool IsGeneralValueType => PorType >= ParamOrReturnType.STRUCTURE_ALIGN1 && PorType <= ParamOrReturnType.STRUCTURE_ALIGN8;
|
public TypeSig Klass { get; }
|
||||||
|
|
||||||
public int Size { get; }
|
public bool IsStruct => PorType == ParamOrReturnType.STRUCT;
|
||||||
|
|
||||||
|
public bool IsPrimitiveType => PorType <= ParamOrReturnType.U;
|
||||||
|
|
||||||
|
private readonly int _typeId;
|
||||||
|
|
||||||
|
public int TypeId => _typeId;
|
||||||
|
|
||||||
public bool Equals(TypeInfo other)
|
public bool Equals(TypeInfo other)
|
||||||
{
|
{
|
||||||
return PorType == other.PorType && Size == other.Size;
|
return PorType == other.PorType && TypeEqualityComparer.Instance.Equals(Klass, other.Klass);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public override bool Equals(object obj)
|
||||||
|
|
@ -60,7 +58,12 @@ namespace HybridCLR.Editor.ABI
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
return (int)PorType * 23 + Size;
|
return (int)PorType * 23 + (Klass != null ? TypeEqualityComparer.Instance.GetHashCode(Klass) : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool NeedExpandValue()
|
||||||
|
{
|
||||||
|
return PorType >= ParamOrReturnType.I1 && PorType <= ParamOrReturnType.U2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string CreateSigName()
|
public string CreateSigName()
|
||||||
|
|
@ -78,22 +81,10 @@ namespace HybridCLR.Editor.ABI
|
||||||
case ParamOrReturnType.U8: return "u8";
|
case ParamOrReturnType.U8: return "u8";
|
||||||
case ParamOrReturnType.R4: return "r4";
|
case ParamOrReturnType.R4: return "r4";
|
||||||
case ParamOrReturnType.R8: return "r8";
|
case ParamOrReturnType.R8: return "r8";
|
||||||
case ParamOrReturnType.I16: return "i16";
|
case ParamOrReturnType.I: return "i";
|
||||||
case ParamOrReturnType.STRUCTURE_AS_REF_PARAM: return "sr";
|
case ParamOrReturnType.U: return "u";
|
||||||
case ParamOrReturnType.ARM64_HFA_FLOAT_2: return "vf2";
|
case ParamOrReturnType.TYPEDBYREF: return strTypedByRef;
|
||||||
case ParamOrReturnType.ARM64_HFA_FLOAT_3: return "vf3";
|
case ParamOrReturnType.STRUCT: return $"s{_typeId}";
|
||||||
case ParamOrReturnType.ARM64_HFA_FLOAT_4: return "vf4";
|
|
||||||
case ParamOrReturnType.ARM64_HFA_DOUBLE_2: return "vd2";
|
|
||||||
case ParamOrReturnType.ARM64_HFA_DOUBLE_3: return "vd3";
|
|
||||||
case ParamOrReturnType.ARM64_HFA_DOUBLE_4: return "vd4";
|
|
||||||
case ParamOrReturnType.STRUCTURE_ALIGN1: return "S" + Size;
|
|
||||||
case ParamOrReturnType.STRUCTURE_ALIGN2: return "A" + Size;
|
|
||||||
case ParamOrReturnType.STRUCTURE_ALIGN4: return "B" + Size;
|
|
||||||
case ParamOrReturnType.STRUCTURE_ALIGN8: return "C" + Size;
|
|
||||||
case ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN1: return "X" + Size;
|
|
||||||
case ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN2: return "Y" + Size;
|
|
||||||
case ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN4: return "Z" + Size;
|
|
||||||
case ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN8: return "W" + Size;
|
|
||||||
default: throw new NotSupportedException(PorType.ToString());
|
default: throw new NotSupportedException(PorType.ToString());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -113,55 +104,13 @@ namespace HybridCLR.Editor.ABI
|
||||||
case ParamOrReturnType.U8: return "uint64_t";
|
case ParamOrReturnType.U8: return "uint64_t";
|
||||||
case ParamOrReturnType.R4: return "float";
|
case ParamOrReturnType.R4: return "float";
|
||||||
case ParamOrReturnType.R8: return "double";
|
case ParamOrReturnType.R8: return "double";
|
||||||
case ParamOrReturnType.I16: return "ValueTypeSize16";
|
case ParamOrReturnType.I: return "intptr_t";
|
||||||
case ParamOrReturnType.STRUCTURE_AS_REF_PARAM: return "uint64_t";
|
case ParamOrReturnType.U: return "uintptr_t";
|
||||||
case ParamOrReturnType.ARM64_HFA_FLOAT_2: return "HtVector2f";
|
case ParamOrReturnType.TYPEDBYREF: return "Il2CppTypedRef";
|
||||||
case ParamOrReturnType.ARM64_HFA_FLOAT_3: return "HtVector3f";
|
case ParamOrReturnType.STRUCT: return $"__struct_{_typeId}__";
|
||||||
case ParamOrReturnType.ARM64_HFA_FLOAT_4: return "HtVector4f";
|
|
||||||
case ParamOrReturnType.ARM64_HFA_DOUBLE_2: return "HtVector2d";
|
|
||||||
case ParamOrReturnType.ARM64_HFA_DOUBLE_3: return "HtVector3d";
|
|
||||||
case ParamOrReturnType.ARM64_HFA_DOUBLE_4: return "HtVector4d";
|
|
||||||
case ParamOrReturnType.STRUCTURE_ALIGN1: return $"ValueTypeSize<{Size}>";
|
|
||||||
case ParamOrReturnType.STRUCTURE_ALIGN2: return $"ValueTypeSizeAlign2<{Size}>";
|
|
||||||
case ParamOrReturnType.STRUCTURE_ALIGN4: return $"ValueTypeSizeAlign4<{Size}>";
|
|
||||||
case ParamOrReturnType.STRUCTURE_ALIGN8: return $"ValueTypeSizeAlign8<{Size}>";
|
|
||||||
case ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN1: return $"WebGLSpeicalValueType<{Size}>";
|
|
||||||
case ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN2: return $"WebGLSpeicalValueTypeAlign2<{Size}>";
|
|
||||||
case ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN4: return $"WebGLSpeicalValueTypeAlign4<{Size}>";
|
|
||||||
case ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN8: return $"WebGLSpeicalValueTypeAlign8<{Size}>";
|
|
||||||
default: throw new NotImplementedException(PorType.ToString());
|
default: throw new NotImplementedException(PorType.ToString());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
public int GetParamSlotNum()
|
|
||||||
{
|
|
||||||
switch (PorType)
|
|
||||||
{
|
|
||||||
case ParamOrReturnType.VOID: return 0;
|
|
||||||
case ParamOrReturnType.I16: return 2;
|
|
||||||
case ParamOrReturnType.STRUCTURE_AS_REF_PARAM: return 1;
|
|
||||||
case ParamOrReturnType.ARM64_HFA_FLOAT_3: return 2;
|
|
||||||
case ParamOrReturnType.ARM64_HFA_FLOAT_4: return 2;
|
|
||||||
case ParamOrReturnType.ARM64_HFA_DOUBLE_2: return 2;
|
|
||||||
case ParamOrReturnType.ARM64_HFA_DOUBLE_3: return 3;
|
|
||||||
case ParamOrReturnType.ARM64_HFA_DOUBLE_4: return 4;
|
|
||||||
case ParamOrReturnType.ARM64_HVA_8:
|
|
||||||
case ParamOrReturnType.ARM64_HVA_16: throw new NotSupportedException();
|
|
||||||
case ParamOrReturnType.STRUCTURE_ALIGN1:
|
|
||||||
case ParamOrReturnType.STRUCTURE_ALIGN2:
|
|
||||||
case ParamOrReturnType.STRUCTURE_ALIGN4:
|
|
||||||
case ParamOrReturnType.STRUCTURE_ALIGN8:
|
|
||||||
case ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN1:
|
|
||||||
case ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN2:
|
|
||||||
case ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN4:
|
|
||||||
case ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN8:
|
|
||||||
return (Size + 7) / 8;
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
Debug.Assert(PorType < ParamOrReturnType.STRUCT_NOT_PASS_AS_VALUE);
|
|
||||||
Debug.Assert(Size <= 8);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
using dnlib.DotNet;
|
||||||
|
using dnlib.DotNet.Writer;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace HybridCLR.Editor.AOT
|
||||||
|
{
|
||||||
|
public class AOTAssemblyMetadataStripper
|
||||||
|
{
|
||||||
|
public static byte[] Strip(byte[] assemblyBytes)
|
||||||
|
{
|
||||||
|
var context = ModuleDef.CreateModuleContext();
|
||||||
|
var readerOption = new ModuleCreationOptions(context)
|
||||||
|
{
|
||||||
|
Runtime = CLRRuntimeReaderKind.Mono
|
||||||
|
};
|
||||||
|
var mod = ModuleDefMD.Load(assemblyBytes, readerOption);
|
||||||
|
// remove all resources
|
||||||
|
mod.Resources.Clear();
|
||||||
|
foreach (var type in mod.GetTypes())
|
||||||
|
{
|
||||||
|
if (type.HasGenericParameters)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
foreach (var method in type.Methods)
|
||||||
|
{
|
||||||
|
if (!method.HasBody || method.HasGenericParameters)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
method.Body = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var writer = new System.IO.MemoryStream();
|
||||||
|
var options = new ModuleWriterOptions(mod);
|
||||||
|
options.MetadataOptions.Flags |= MetadataFlags.PreserveRids;
|
||||||
|
mod.Write(writer, options);
|
||||||
|
writer.Flush();
|
||||||
|
return writer.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Strip(string originalAssemblyPath, string strippedAssemblyPath)
|
||||||
|
{
|
||||||
|
byte[] originDllBytes = System.IO.File.ReadAllBytes(originalAssemblyPath);
|
||||||
|
byte[] strippedDllBytes = Strip(originDllBytes);
|
||||||
|
UnityEngine.Debug.Log($"aot dll:{originalAssemblyPath}, length: {originDllBytes.Length} -> {strippedDllBytes.Length}, stripping rate:{(originDllBytes.Length - strippedDllBytes.Length)/(double)originDllBytes.Length} ");
|
||||||
|
Directory.CreateDirectory(System.IO.Path.GetDirectoryName(strippedAssemblyPath));
|
||||||
|
System.IO.File.WriteAllBytes(strippedAssemblyPath, strippedDllBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: b63c5bf995a6d624dbd10d9df6cb6a7a
|
guid: 7e9e6a048682dcb4fab806251411f29f
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
|
|
@ -17,12 +17,16 @@ namespace HybridCLR.Editor.AOT
|
||||||
public AssemblyReferenceDeepCollector Collector { get; set; }
|
public AssemblyReferenceDeepCollector Collector { get; set; }
|
||||||
|
|
||||||
public int MaxIterationCount { get; set; }
|
public int MaxIterationCount { get; set; }
|
||||||
|
|
||||||
|
public bool ComputeAotAssembly { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly int _maxInterationCount;
|
private readonly int _maxInterationCount;
|
||||||
|
|
||||||
private readonly AssemblyReferenceDeepCollector _assemblyCollector;
|
private readonly AssemblyReferenceDeepCollector _assemblyCollector;
|
||||||
|
|
||||||
|
private readonly bool _computeAotAssembly;
|
||||||
|
|
||||||
private readonly HashSet<GenericClass> _genericTypes = new HashSet<GenericClass>();
|
private readonly HashSet<GenericClass> _genericTypes = new HashSet<GenericClass>();
|
||||||
private readonly HashSet<GenericMethod> _genericMethods = new HashSet<GenericMethod>();
|
private readonly HashSet<GenericMethod> _genericMethods = new HashSet<GenericMethod>();
|
||||||
|
|
||||||
|
|
@ -47,6 +51,7 @@ namespace HybridCLR.Editor.AOT
|
||||||
{
|
{
|
||||||
_assemblyCollector = options.Collector;
|
_assemblyCollector = options.Collector;
|
||||||
_maxInterationCount = options.MaxIterationCount;
|
_maxInterationCount = options.MaxIterationCount;
|
||||||
|
_computeAotAssembly = options.ComputeAotAssembly;
|
||||||
_methodReferenceAnalyzer = new MethodReferenceAnalyzer(this.OnNewMethod);
|
_methodReferenceAnalyzer = new MethodReferenceAnalyzer(this.OnNewMethod);
|
||||||
_hotUpdateAssemblyFiles = new HashSet<string>(options.Collector.GetRootAssemblyNames().Select(assName => assName + ".dll"));
|
_hotUpdateAssemblyFiles = new HashSet<string>(options.Collector.GetRootAssemblyNames().Select(assName => assName + ".dll"));
|
||||||
}
|
}
|
||||||
|
|
@ -58,20 +63,20 @@ namespace HybridCLR.Editor.AOT
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
gc = gc.ToGenericShare();
|
gc = gc.ToGenericShare();
|
||||||
if (_genericTypes.Add(gc) && NeedWalk(gc.Type))
|
if (_genericTypes.Add(gc) && NeedWalk(null, gc.Type))
|
||||||
{
|
{
|
||||||
WalkType(gc);
|
WalkType(gc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool NeedWalk(TypeDef type)
|
private bool NeedWalk(MethodDef callFrom, TypeDef type)
|
||||||
{
|
{
|
||||||
return _hotUpdateAssemblyFiles.Contains(type.Module.Name);
|
return _hotUpdateAssemblyFiles.Contains(type.Module.Name) || callFrom == null || callFrom.HasGenericParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsAotType(TypeDef type)
|
private bool IsAotType(TypeDef type)
|
||||||
{
|
{
|
||||||
return !_hotUpdateAssemblyFiles.Contains(type.Module.Name);
|
return _computeAotAssembly || !_hotUpdateAssemblyFiles.Contains(type.Module.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsAotGenericMethod(MethodDef method)
|
private bool IsAotGenericMethod(MethodDef method)
|
||||||
|
|
@ -79,13 +84,13 @@ namespace HybridCLR.Editor.AOT
|
||||||
return IsAotType(method.DeclaringType) && method.HasGenericParameters;
|
return IsAotType(method.DeclaringType) && method.HasGenericParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnNewMethod(GenericMethod method)
|
private void OnNewMethod(MethodDef methodDef, List<TypeSig> klassGenericInst, List<TypeSig> methodGenericInst, GenericMethod method)
|
||||||
{
|
{
|
||||||
if(method == null)
|
if(method == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_genericMethods.Add(method) && NeedWalk(method.Method.DeclaringType))
|
if (NeedWalk(methodDef, method.Method.DeclaringType) && _genericMethods.Add(method))
|
||||||
{
|
{
|
||||||
_newMethods.Add(method);
|
_newMethods.Add(method);
|
||||||
}
|
}
|
||||||
|
|
@ -101,7 +106,7 @@ namespace HybridCLR.Editor.AOT
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_genericMethods.Add(method) && NeedWalk(method.Method.DeclaringType))
|
if (NeedWalk(null, method.Method.DeclaringType) && _genericMethods.Add(method))
|
||||||
{
|
{
|
||||||
_newMethods.Add(method);
|
_newMethods.Add(method);
|
||||||
}
|
}
|
||||||
|
|
@ -157,9 +162,9 @@ namespace HybridCLR.Editor.AOT
|
||||||
for (uint rid = 1, n = ass.Metadata.TablesStream.TypeSpecTable.Rows; rid <= n; rid++)
|
for (uint rid = 1, n = ass.Metadata.TablesStream.TypeSpecTable.Rows; rid <= n; rid++)
|
||||||
{
|
{
|
||||||
var ts = ass.ResolveTypeSpec(rid);
|
var ts = ass.ResolveTypeSpec(rid);
|
||||||
if (!ts.ContainsGenericParameter)
|
var cs = GenericClass.ResolveClass(ts, null)?.ToGenericShare();
|
||||||
|
if (cs != null)
|
||||||
{
|
{
|
||||||
var cs = GenericClass.ResolveClass(ts, null)?.ToGenericShare();
|
|
||||||
TryAddAndWalkGenericType(cs);
|
TryAddAndWalkGenericType(cs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -167,10 +172,6 @@ namespace HybridCLR.Editor.AOT
|
||||||
for (uint rid = 1, n = ass.Metadata.TablesStream.MethodSpecTable.Rows; rid <= n; rid++)
|
for (uint rid = 1, n = ass.Metadata.TablesStream.MethodSpecTable.Rows; rid <= n; rid++)
|
||||||
{
|
{
|
||||||
var ms = ass.ResolveMethodSpec(rid);
|
var ms = ass.ResolveMethodSpec(rid);
|
||||||
if (ms.DeclaringType.ContainsGenericParameter || ms.GenericInstMethodSig.ContainsGenericParameter)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
var gm = GenericMethod.ResolveMethod(ms, null)?.ToGenericShare();
|
var gm = GenericMethod.ResolveMethod(ms, null)?.ToGenericShare();
|
||||||
TryAddMethodNotWalkType(gm);
|
TryAddMethodNotWalkType(gm);
|
||||||
}
|
}
|
||||||
|
|
@ -195,11 +196,29 @@ namespace HybridCLR.Editor.AOT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool IsNotShareableAOTGenericType(TypeDef typeDef)
|
||||||
|
{
|
||||||
|
if (!IsAotType(typeDef))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return typeDef.GenericParameters.Any(c => !c.HasReferenceTypeConstraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsNotShareableAOTGenericMethod(MethodDef method)
|
||||||
|
{
|
||||||
|
if (!IsAotGenericMethod(method))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return method.GenericParameters.Concat(method.DeclaringType.GenericParameters).Any(c => !c.HasReferenceTypeConstraint);
|
||||||
|
}
|
||||||
|
|
||||||
private void FilterAOTGenericTypeAndMethods()
|
private void FilterAOTGenericTypeAndMethods()
|
||||||
{
|
{
|
||||||
ConstraintContext cc = this.ConstraintContext;
|
ConstraintContext cc = this.ConstraintContext;
|
||||||
AotGenericTypes.AddRange(_genericTypes.Where(type => IsAotType(type.Type)).Select(gc => cc.ApplyConstraints(gc)));
|
AotGenericTypes.AddRange(_genericTypes.Where(type => IsNotShareableAOTGenericType(type.Type)).Select(gc => cc.ApplyConstraints(gc)));
|
||||||
AotGenericMethods.AddRange(_genericMethods.Where(method => IsAotGenericMethod(method.Method)).Select(gm => cc.ApplyConstraints(gm)));
|
AotGenericMethods.AddRange(_genericMethods.Where(method => IsNotShareableAOTGenericMethod(method.Method)).Select(gm => cc.ApplyConstraints(gm)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Run()
|
public void Run()
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ namespace HybridCLR.Editor.AOT
|
||||||
{
|
{
|
||||||
_typeSimpleNameMapping.Add(e.Key.FullName, e.Value);
|
_typeSimpleNameMapping.Add(e.Key.FullName, e.Value);
|
||||||
}
|
}
|
||||||
_systemTypePattern = new Regex(string.Join("|", _typeSimpleNameMapping.Keys.Select (k => $@"\b{k}\b")));
|
_systemTypePattern = new Regex(string.Join("|", _typeSimpleNameMapping.Keys.Select (k => $@"\b{Regex.Escape(k)}\b")));
|
||||||
}
|
}
|
||||||
|
|
||||||
public string PrettifyTypeSig(string typeSig)
|
public string PrettifyTypeSig(string typeSig)
|
||||||
|
|
@ -64,18 +64,22 @@ namespace HybridCLR.Editor.AOT
|
||||||
Directory.CreateDirectory(parentDir);
|
Directory.CreateDirectory(parentDir);
|
||||||
|
|
||||||
List<string> codes = new List<string>();
|
List<string> codes = new List<string>();
|
||||||
|
codes.Add("using System.Collections.Generic;");
|
||||||
codes.Add("public class AOTGenericReferences : UnityEngine.MonoBehaviour");
|
codes.Add("public class AOTGenericReferences : UnityEngine.MonoBehaviour");
|
||||||
codes.Add("{");
|
codes.Add("{");
|
||||||
|
|
||||||
codes.Add("");
|
codes.Add("");
|
||||||
codes.Add("\t// {{ AOT assemblies");
|
codes.Add("\t// {{ AOT assemblies");
|
||||||
|
codes.Add("\tpublic static readonly IReadOnlyList<string> PatchedAOTAssemblyList = new List<string>");
|
||||||
|
codes.Add("\t{");
|
||||||
List<dnlib.DotNet.ModuleDef> modules = new HashSet<dnlib.DotNet.ModuleDef>(
|
List<dnlib.DotNet.ModuleDef> modules = new HashSet<dnlib.DotNet.ModuleDef>(
|
||||||
types.Select(t => t.Type.Module).Concat(methods.Select(m => m.Method.Module))).ToList();
|
types.Select(t => t.Type.Module).Concat(methods.Select(m => m.Method.Module))).ToList();
|
||||||
modules.Sort((a, b) => a.Name.CompareTo(b.Name));
|
modules.Sort((a, b) => a.Name.CompareTo(b.Name));
|
||||||
foreach (dnlib.DotNet.ModuleDef module in modules)
|
foreach (dnlib.DotNet.ModuleDef module in modules)
|
||||||
{
|
{
|
||||||
codes.Add($"\t// {module.Name}");
|
codes.Add($"\t\t\"{module.Name}\",");
|
||||||
}
|
}
|
||||||
|
codes.Add("\t};");
|
||||||
codes.Add("\t// }}");
|
codes.Add("\t// }}");
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -87,10 +91,11 @@ namespace HybridCLR.Editor.AOT
|
||||||
codes.Add("");
|
codes.Add("");
|
||||||
codes.Add("\t// {{ AOT generic types");
|
codes.Add("\t// {{ AOT generic types");
|
||||||
|
|
||||||
types.Sort((a, b) => a.Type.FullName.CompareTo(b.Type.FullName));
|
List<string> typeNames = types.Select(t => PrettifyTypeSig(t.ToTypeSig().ToString())).ToList();
|
||||||
foreach(var type in types)
|
typeNames.Sort(string.CompareOrdinal);
|
||||||
|
foreach(var typeName in typeNames)
|
||||||
{
|
{
|
||||||
codes.Add($"\t// {PrettifyTypeSig(type.ToTypeSig().ToString())}");
|
codes.Add($"\t// {typeName}");
|
||||||
}
|
}
|
||||||
|
|
||||||
codes.Add("\t// }}");
|
codes.Add("\t// }}");
|
||||||
|
|
@ -98,27 +103,36 @@ namespace HybridCLR.Editor.AOT
|
||||||
codes.Add("");
|
codes.Add("");
|
||||||
codes.Add("\tpublic void RefMethods()");
|
codes.Add("\tpublic void RefMethods()");
|
||||||
codes.Add("\t{");
|
codes.Add("\t{");
|
||||||
methods.Sort((a, b) =>
|
|
||||||
|
List<(string, string, string)> methodTypeAndNames = methods.Select(m =>
|
||||||
|
(PrettifyTypeSig(m.Method.DeclaringType.ToString()), PrettifyMethodSig(m.Method.Name), PrettifyMethodSig(m.ToMethodSpec().ToString())))
|
||||||
|
.ToList();
|
||||||
|
methodTypeAndNames.Sort((a, b) =>
|
||||||
{
|
{
|
||||||
int c = a.Method.DeclaringType.FullName.CompareTo(b.Method.DeclaringType.FullName);
|
int c = String.Compare(a.Item1, b.Item1, StringComparison.Ordinal);
|
||||||
if (c != 0)
|
if (c != 0)
|
||||||
{
|
{
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
c = a.Method.Name.CompareTo(b.Method.Name);
|
|
||||||
return c;
|
c = String.Compare(a.Item2, b.Item2, StringComparison.Ordinal);
|
||||||
|
if (c != 0)
|
||||||
|
{
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
return String.Compare(a.Item3, b.Item3, StringComparison.Ordinal);
|
||||||
});
|
});
|
||||||
foreach(var method in methods)
|
foreach(var method in methodTypeAndNames)
|
||||||
{
|
{
|
||||||
codes.Add($"\t\t// {PrettifyMethodSig(method.ToMethodSpec().ToString())}");
|
codes.Add($"\t\t// {PrettifyMethodSig(method.Item3)}");
|
||||||
}
|
}
|
||||||
codes.Add("\t}");
|
codes.Add("\t}");
|
||||||
|
|
||||||
codes.Add("}");
|
codes.Add("}");
|
||||||
|
|
||||||
|
|
||||||
var utf8WithoutBOM = new System.Text.UTF8Encoding(false);
|
var utf8WithoutBom = new System.Text.UTF8Encoding(false);
|
||||||
File.WriteAllText(outputFile, string.Join("\n", codes), utf8WithoutBOM);
|
File.WriteAllText(outputFile, string.Join("\n", codes), utf8WithoutBom);
|
||||||
Debug.Log($"[GenericReferenceWriter] write {outputFile}");
|
Debug.Log($"[GenericReferenceWriter] write {outputFile}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,258 @@
|
||||||
|
using System;
|
||||||
|
using HybridCLR.Editor.Installer;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEditor;
|
||||||
|
using System.Reflection;
|
||||||
|
using HybridCLR.Editor.Settings;
|
||||||
|
#if UNITY_2019 && (UNITY_IOS || UNITY_TVOS)
|
||||||
|
using UnityEditor.Build;
|
||||||
|
using UnityEditor.Callbacks;
|
||||||
|
using UnityEditor.iOS.Xcode;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace HybridCLR.Editor.BuildProcessors
|
||||||
|
{
|
||||||
|
public static class AddLil2cppSourceCodeToXcodeproj2019
|
||||||
|
{
|
||||||
|
[PostProcessBuild]
|
||||||
|
public static void OnPostProcessBuild(BuildTarget target, string pathToBuiltProject)
|
||||||
|
{
|
||||||
|
if (!HybridCLRSettings.Instance.enable)
|
||||||
|
return;
|
||||||
|
/*
|
||||||
|
* 1. 生成lump,并且添加到工程
|
||||||
|
3. 将libil2cpp目录复制到 Library/. 删除旧的. search paths里修改 libil2cpp/include为libil2cpp
|
||||||
|
3. Libraries/bdwgc/include -> Libraries/external/bdwgc/include
|
||||||
|
4. 将external目录复制到 Library/external。删除旧目录
|
||||||
|
5. 将Library/external/baselib/Platforms/OSX改名为 IOS 全大写
|
||||||
|
6. 将 external/zlib下c 文件添加到工程
|
||||||
|
7. 移除libil2cpp.a
|
||||||
|
8. Include path add libil2cpp/os/ClassLibraryPAL/brotli/include
|
||||||
|
9. add external/xxHash
|
||||||
|
10. add "#include <stdio.h>" to Classes/Prefix.pch
|
||||||
|
*/
|
||||||
|
|
||||||
|
string pbxprojFile = BuildProcessorUtil.GetXcodeProjectFile(pathToBuiltProject);
|
||||||
|
string srcLibil2cppDir = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp";
|
||||||
|
string dstLibil2cppDir = $"{pathToBuiltProject}/Libraries/libil2cpp";
|
||||||
|
string lumpDir = $"{pathToBuiltProject}/Libraries/lumps";
|
||||||
|
string srcExternalDir = $"{SettingsUtil.LocalIl2CppDir}/external";
|
||||||
|
string dstExternalDir = $"{pathToBuiltProject}/Libraries/external";
|
||||||
|
//RemoveExternalLibil2cppOption(srcExternalDir, dstExternalDir);
|
||||||
|
CopyLibil2cppToXcodeProj(srcLibil2cppDir, dstLibil2cppDir);
|
||||||
|
CopyExternalToXcodeProj(srcExternalDir, dstExternalDir);
|
||||||
|
var lumpFiles = CreateLumps(dstLibil2cppDir, lumpDir);
|
||||||
|
var extraSources = GetExtraSourceFiles(dstExternalDir, dstLibil2cppDir);
|
||||||
|
var cflags = new List<string>()
|
||||||
|
{
|
||||||
|
"-DIL2CPP_MONO_DEBUGGER_DISABLED",
|
||||||
|
};
|
||||||
|
ModifyPBXProject(pathToBuiltProject, pbxprojFile, lumpFiles, extraSources, cflags);
|
||||||
|
AddSystemHeaderToPrefixPch(pathToBuiltProject);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AddSystemHeaderToPrefixPch(string pathToBuiltProject)
|
||||||
|
{
|
||||||
|
// 如果不将 stdio.h 添加到 Prefix.pch, zutil.c会有编译错误
|
||||||
|
string prefixPchFile = $"{pathToBuiltProject}/Classes/Prefix.pch";
|
||||||
|
string fileContent = File.ReadAllText(prefixPchFile, Encoding.UTF8);
|
||||||
|
if (!fileContent.Contains("stdio.h"))
|
||||||
|
{
|
||||||
|
string newFileContent = fileContent + "\n#include <stdio.h>\n";
|
||||||
|
File.WriteAllText(prefixPchFile, newFileContent, Encoding.UTF8);
|
||||||
|
UnityEngine.Debug.Log($"append header to {prefixPchFile}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetRelativePathFromProj(string path)
|
||||||
|
{
|
||||||
|
return path.Substring(path.IndexOf("Libraries", StringComparison.Ordinal)).Replace('\\', '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ModifyPBXProject(string pathToBuiltProject, string pbxprojFile, List<LumpFile> lumpFiles, List<string> extraFiles, List<string> cflags)
|
||||||
|
{
|
||||||
|
var proj = new PBXProject();
|
||||||
|
proj.ReadFromFile(pbxprojFile);
|
||||||
|
string targetGUID = proj.GetUnityFrameworkTargetGuid();
|
||||||
|
// 移除旧的libil2cpp.a
|
||||||
|
var libil2cppGUID = proj.FindFileGuidByProjectPath("Libraries/libil2cpp.a");
|
||||||
|
if (!string.IsNullOrEmpty(libil2cppGUID))
|
||||||
|
{
|
||||||
|
proj.RemoveFileFromBuild(targetGUID, libil2cppGUID);
|
||||||
|
proj.RemoveFile(libil2cppGUID);
|
||||||
|
File.Delete(Path.Combine(pathToBuiltProject, "Libraries", "libil2cpp.a"));
|
||||||
|
}
|
||||||
|
|
||||||
|
//var lumpGroupGuid = proj.AddFile("Lumps", $"Classes/Lumps", PBXSourceTree.Group);
|
||||||
|
|
||||||
|
foreach (var lumpFile in lumpFiles)
|
||||||
|
{
|
||||||
|
string lumpFileName = Path.GetFileName(lumpFile.lumpFile);
|
||||||
|
string projPathOfFile = $"Classes/Lumps/{lumpFileName}";
|
||||||
|
string relativePathOfFile = GetRelativePathFromProj(lumpFile.lumpFile);
|
||||||
|
string lumpGuid = proj.FindFileGuidByProjectPath(projPathOfFile);
|
||||||
|
if (!string.IsNullOrEmpty(lumpGuid))
|
||||||
|
{
|
||||||
|
proj.RemoveFileFromBuild(targetGUID, lumpGuid);
|
||||||
|
proj.RemoveFile(lumpGuid);
|
||||||
|
}
|
||||||
|
lumpGuid = proj.AddFile(relativePathOfFile, projPathOfFile, PBXSourceTree.Source);
|
||||||
|
proj.AddFileToBuild(targetGUID, lumpGuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var extraFile in extraFiles)
|
||||||
|
{
|
||||||
|
string projPathOfFile = $"Classes/Extrals/{Path.GetFileName(extraFile)}";
|
||||||
|
string extraFileGuid = proj.FindFileGuidByProjectPath(projPathOfFile);
|
||||||
|
if (!string.IsNullOrEmpty(extraFileGuid))
|
||||||
|
{
|
||||||
|
proj.RemoveFileFromBuild(targetGUID, extraFileGuid);
|
||||||
|
proj.RemoveFile(extraFileGuid);
|
||||||
|
//Debug.LogWarning($"remove exist extra file:{projPathOfFile} guid:{extraFileGuid}");
|
||||||
|
}
|
||||||
|
var lumpGuid = proj.AddFile(GetRelativePathFromProj(extraFile), projPathOfFile, PBXSourceTree.Source);
|
||||||
|
proj.AddFileToBuild(targetGUID, lumpGuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(var configName in proj.BuildConfigNames())
|
||||||
|
{
|
||||||
|
//Debug.Log($"build config:{bcn}");
|
||||||
|
string configGuid = proj.BuildConfigByName(targetGUID, configName);
|
||||||
|
string headerSearchPaths = "HEADER_SEARCH_PATHS";
|
||||||
|
string hspProp = proj.GetBuildPropertyForConfig(configGuid, headerSearchPaths);
|
||||||
|
//Debug.Log($"config guid:{configGuid} prop:{hspProp}");
|
||||||
|
string newPro = hspProp.Replace("libil2cpp/include", "libil2cpp")
|
||||||
|
.Replace("Libraries/bdwgc", "Libraries/external/bdwgc");
|
||||||
|
|
||||||
|
//if (!newPro.Contains("Libraries/libil2cpp/os/ClassLibraryPAL/brotli/include"))
|
||||||
|
//{
|
||||||
|
// newPro += " $(SRCROOT)/Libraries/libil2cpp/os/ClassLibraryPAL/brotli/include";
|
||||||
|
//}
|
||||||
|
if (!newPro.Contains("Libraries/external/xxHash"))
|
||||||
|
{
|
||||||
|
newPro += " $(SRCROOT)/Libraries/external/xxHash";
|
||||||
|
}
|
||||||
|
newPro += " $(SRCR00T)/Libraries/external/mono";
|
||||||
|
//Debug.Log($"config:{bcn} new prop:{newPro}");
|
||||||
|
proj.SetBuildPropertyForConfig(configGuid, headerSearchPaths, newPro);
|
||||||
|
|
||||||
|
string cflagKey = "OTHER_CFLAGS";
|
||||||
|
string cfProp = proj.GetBuildPropertyForConfig(configGuid, cflagKey);
|
||||||
|
foreach (var flag in cflags)
|
||||||
|
{
|
||||||
|
if (!cfProp.Contains(flag))
|
||||||
|
{
|
||||||
|
cfProp += " " + flag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (configName.Contains("Debug") && !cfProp.Contains("-DIL2CPP_DEBUG="))
|
||||||
|
{
|
||||||
|
cfProp += " -DIL2CPP_DEBUG=1 -DDEBUG=1";
|
||||||
|
}
|
||||||
|
proj.SetBuildPropertyForConfig(configGuid, cflagKey, cfProp);
|
||||||
|
|
||||||
|
}
|
||||||
|
proj.WriteToFile(pbxprojFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CopyLibil2cppToXcodeProj(string srcLibil2cppDir, string dstLibil2cppDir)
|
||||||
|
{
|
||||||
|
BashUtil.RemoveDir(dstLibil2cppDir);
|
||||||
|
BashUtil.CopyDir(srcLibil2cppDir, dstLibil2cppDir, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void CopyExternalToXcodeProj(string srcExternalDir, string dstExternalDir)
|
||||||
|
{
|
||||||
|
BashUtil.RemoveDir(dstExternalDir);
|
||||||
|
BashUtil.CopyDir(srcExternalDir, dstExternalDir, true);
|
||||||
|
|
||||||
|
//string baselibPlatfromsDir = $"{dstExternalDir}/baselib/Platforms";
|
||||||
|
//BashUtil.RemoveDir($"{baselibPlatfromsDir}/IOS");
|
||||||
|
//BashUtil.CopyDir($"{baselibPlatfromsDir}/OSX", $"{baselibPlatfromsDir}/IOS", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
class LumpFile
|
||||||
|
{
|
||||||
|
public List<string> cppFiles = new List<string>();
|
||||||
|
|
||||||
|
public readonly string lumpFile;
|
||||||
|
|
||||||
|
public readonly string il2cppConfigFile;
|
||||||
|
|
||||||
|
public LumpFile(string lumpFile, string il2cppConfigFile)
|
||||||
|
{
|
||||||
|
this.lumpFile = lumpFile;
|
||||||
|
this.il2cppConfigFile = il2cppConfigFile;
|
||||||
|
this.cppFiles.Add(il2cppConfigFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SaveFile()
|
||||||
|
{
|
||||||
|
var lumpFileContent = new List<string>();
|
||||||
|
foreach (var file in cppFiles)
|
||||||
|
{
|
||||||
|
lumpFileContent.Add($"#include \"{GetRelativePathFromProj(file)}\"");
|
||||||
|
}
|
||||||
|
File.WriteAllLines(lumpFile, lumpFileContent, Encoding.UTF8);
|
||||||
|
Debug.Log($"create lump file:{lumpFile}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<LumpFile> CreateLumps(string libil2cppDir, string outputDir)
|
||||||
|
{
|
||||||
|
BashUtil.RecreateDir(outputDir);
|
||||||
|
|
||||||
|
string il2cppConfigFile = $"{libil2cppDir}/il2cpp-config.h";
|
||||||
|
var lumpFiles = new List<LumpFile>();
|
||||||
|
int lumpFileIndex = 0;
|
||||||
|
foreach (var cppDir in Directory.GetDirectories(libil2cppDir, "*", SearchOption.AllDirectories).Concat(new string[] {libil2cppDir}))
|
||||||
|
{
|
||||||
|
var lumpFile = new LumpFile($"{outputDir}/lump_{Path.GetFileName(cppDir)}_{lumpFileIndex}.cpp", il2cppConfigFile);
|
||||||
|
foreach (var file in Directory.GetFiles(cppDir, "*.cpp", SearchOption.TopDirectoryOnly))
|
||||||
|
{
|
||||||
|
lumpFile.cppFiles.Add(file);
|
||||||
|
}
|
||||||
|
lumpFile.SaveFile();
|
||||||
|
lumpFiles.Add(lumpFile);
|
||||||
|
++lumpFileIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
var mmFiles = Directory.GetFiles(libil2cppDir, "*.mm", SearchOption.AllDirectories);
|
||||||
|
if (mmFiles.Length > 0)
|
||||||
|
{
|
||||||
|
var lumpFile = new LumpFile($"{outputDir}/lump_mm.mm", il2cppConfigFile);
|
||||||
|
foreach (var file in mmFiles)
|
||||||
|
{
|
||||||
|
lumpFile.cppFiles.Add(file);
|
||||||
|
}
|
||||||
|
lumpFile.SaveFile();
|
||||||
|
lumpFiles.Add(lumpFile);
|
||||||
|
}
|
||||||
|
return lumpFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<string> GetExtraSourceFiles(string externalDir, string libil2cppDir)
|
||||||
|
{
|
||||||
|
var files = new List<string>();
|
||||||
|
foreach (string extraDir in new string[]
|
||||||
|
{
|
||||||
|
$"{externalDir}/zlib",
|
||||||
|
$"{externalDir}/xxHash",
|
||||||
|
$"{libil2cppDir}/os/ClassLibraryPAL/brotli",
|
||||||
|
})
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(extraDir))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
files.AddRange(Directory.GetFiles(extraDir, "*.c", SearchOption.AllDirectories));
|
||||||
|
}
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: fe1634f74b7ca2e42bd07233b451cd94
|
guid: d2f62ca12f2eb4f2fba8e9cb51279421
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
|
|
@ -0,0 +1,244 @@
|
||||||
|
using System;
|
||||||
|
using HybridCLR.Editor.Installer;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEditor;
|
||||||
|
using System.Reflection;
|
||||||
|
using HybridCLR.Editor.Settings;
|
||||||
|
#if (UNITY_2020 || UNITY_2021) && (UNITY_IOS || UNITY_TVOS)
|
||||||
|
using UnityEditor.Build;
|
||||||
|
using UnityEditor.Callbacks;
|
||||||
|
using UnityEditor.iOS.Xcode;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace HybridCLR.Editor.BuildProcessors
|
||||||
|
{
|
||||||
|
public static class AddLil2cppSourceCodeToXcodeproj2020Or2021
|
||||||
|
{
|
||||||
|
|
||||||
|
[PostProcessBuild]
|
||||||
|
public static void OnPostProcessBuild(BuildTarget target, string pathToBuiltProject)
|
||||||
|
{
|
||||||
|
if (!HybridCLRSettings.Instance.enable)
|
||||||
|
return;
|
||||||
|
/*
|
||||||
|
* 1. 生成lump,并且添加到工程
|
||||||
|
3. 将libil2cpp目录复制到 Library/. 删除旧的. search paths里修改 libil2cpp/include为libil2cpp
|
||||||
|
3. Libraries/bdwgc/include -> Libraries/external/bdwgc/include
|
||||||
|
4. 将external目录复制到 Library/external。删除旧目录
|
||||||
|
5. 将Library/external/baselib/Platforms/OSX改名为 IOS 全大写
|
||||||
|
6. 将 external/zlib下c 文件添加到工程
|
||||||
|
7. 移除libil2cpp.a
|
||||||
|
8. Include path add libil2cpp/os/ClassLibraryPAL/brotli/include
|
||||||
|
9. add external/xxHash
|
||||||
|
*/
|
||||||
|
|
||||||
|
string pbxprojFile = BuildProcessorUtil.GetXcodeProjectFile(pathToBuiltProject);
|
||||||
|
string srcLibil2cppDir = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp";
|
||||||
|
string dstLibil2cppDir = $"{pathToBuiltProject}/Libraries/libil2cpp";
|
||||||
|
string lumpDir = $"{pathToBuiltProject}/Libraries/lumps";
|
||||||
|
string srcExternalDir = $"{SettingsUtil.LocalIl2CppDir}/external";
|
||||||
|
string dstExternalDir = $"{pathToBuiltProject}/Libraries/external";
|
||||||
|
//RemoveExternalLibil2cppOption(srcExternalDir, dstExternalDir);
|
||||||
|
CopyLibil2cppToXcodeProj(srcLibil2cppDir, dstLibil2cppDir);
|
||||||
|
CopyExternalToXcodeProj(srcExternalDir, dstExternalDir);
|
||||||
|
var lumpFiles = CreateLumps(dstLibil2cppDir, lumpDir);
|
||||||
|
var extraSources = GetExtraSourceFiles(dstExternalDir, dstLibil2cppDir);
|
||||||
|
var cflags = new List<string>()
|
||||||
|
{
|
||||||
|
"-DIL2CPP_MONO_DEBUGGER_DISABLED",
|
||||||
|
};
|
||||||
|
ModifyPBXProject(pathToBuiltProject, pbxprojFile, lumpFiles, extraSources, cflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetRelativePathFromProj(string path)
|
||||||
|
{
|
||||||
|
return path.Substring(path.IndexOf("Libraries", StringComparison.Ordinal)).Replace('\\', '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ModifyPBXProject(string pathToBuiltProject, string pbxprojFile, List<LumpFile> lumpFiles, List<string> extraFiles, List<string> cflags)
|
||||||
|
{
|
||||||
|
var proj = new PBXProject();
|
||||||
|
proj.ReadFromFile(pbxprojFile);
|
||||||
|
string targetGUID = proj.GetUnityFrameworkTargetGuid();
|
||||||
|
// 移除旧的libil2cpp.a
|
||||||
|
var libil2cppGUID = proj.FindFileGuidByProjectPath("Libraries/libil2cpp.a");
|
||||||
|
if (!string.IsNullOrEmpty(libil2cppGUID))
|
||||||
|
{
|
||||||
|
proj.RemoveFileFromBuild(targetGUID, libil2cppGUID);
|
||||||
|
proj.RemoveFile(libil2cppGUID);
|
||||||
|
File.Delete(Path.Combine(pathToBuiltProject, "Libraries", "libil2cpp.a"));
|
||||||
|
}
|
||||||
|
|
||||||
|
//var lumpGroupGuid = proj.AddFile("Lumps", $"Classes/Lumps", PBXSourceTree.Group);
|
||||||
|
|
||||||
|
foreach (var lumpFile in lumpFiles)
|
||||||
|
{
|
||||||
|
string lumpFileName = Path.GetFileName(lumpFile.lumpFile);
|
||||||
|
string projPathOfFile = $"Classes/Lumps/{lumpFileName}";
|
||||||
|
string relativePathOfFile = GetRelativePathFromProj(lumpFile.lumpFile);
|
||||||
|
string lumpGuid = proj.FindFileGuidByProjectPath(projPathOfFile);
|
||||||
|
if (!string.IsNullOrEmpty(lumpGuid))
|
||||||
|
{
|
||||||
|
proj.RemoveFileFromBuild(targetGUID, lumpGuid);
|
||||||
|
proj.RemoveFile(lumpGuid);
|
||||||
|
}
|
||||||
|
lumpGuid = proj.AddFile(relativePathOfFile, projPathOfFile, PBXSourceTree.Source);
|
||||||
|
proj.AddFileToBuild(targetGUID, lumpGuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var extraFile in extraFiles)
|
||||||
|
{
|
||||||
|
string projPathOfFile = $"Classes/Extrals/{Path.GetFileName(extraFile)}";
|
||||||
|
string extraFileGuid = proj.FindFileGuidByProjectPath(projPathOfFile);
|
||||||
|
if (!string.IsNullOrEmpty(extraFileGuid))
|
||||||
|
{
|
||||||
|
proj.RemoveFileFromBuild(targetGUID, extraFileGuid);
|
||||||
|
proj.RemoveFile(extraFileGuid);
|
||||||
|
//Debug.LogWarning($"remove exist extra file:{projPathOfFile} guid:{extraFileGuid}");
|
||||||
|
}
|
||||||
|
var lumpGuid = proj.AddFile(GetRelativePathFromProj(extraFile), projPathOfFile, PBXSourceTree.Source);
|
||||||
|
proj.AddFileToBuild(targetGUID, lumpGuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(var configName in proj.BuildConfigNames())
|
||||||
|
{
|
||||||
|
//Debug.Log($"build config:{bcn}");
|
||||||
|
string configGuid = proj.BuildConfigByName(targetGUID, configName);
|
||||||
|
string headerSearchPaths = "HEADER_SEARCH_PATHS";
|
||||||
|
string hspProp = proj.GetBuildPropertyForConfig(configGuid, headerSearchPaths);
|
||||||
|
//Debug.Log($"config guid:{configGuid} prop:{hspProp}");
|
||||||
|
string newPro = hspProp.Replace("libil2cpp/include", "libil2cpp")
|
||||||
|
.Replace("Libraries/bdwgc", "Libraries/external/bdwgc");
|
||||||
|
|
||||||
|
if (!newPro.Contains("Libraries/libil2cpp/os/ClassLibraryPAL/brotli/include"))
|
||||||
|
{
|
||||||
|
newPro += " $(SRCROOT)/Libraries/libil2cpp/os/ClassLibraryPAL/brotli/include";
|
||||||
|
}
|
||||||
|
if (!newPro.Contains("Libraries/external/xxHash"))
|
||||||
|
{
|
||||||
|
newPro += " $(SRCROOT)/Libraries/external/xxHash";
|
||||||
|
}
|
||||||
|
newPro += " $(SRCR00T)/Libraries/external/mono";
|
||||||
|
//Debug.Log($"config:{bcn} new prop:{newPro}");
|
||||||
|
proj.SetBuildPropertyForConfig(configGuid, headerSearchPaths, newPro);
|
||||||
|
|
||||||
|
string cflagKey = "OTHER_CFLAGS";
|
||||||
|
string cfProp = proj.GetBuildPropertyForConfig(configGuid, cflagKey);
|
||||||
|
foreach (var flag in cflags)
|
||||||
|
{
|
||||||
|
if (!cfProp.Contains(flag))
|
||||||
|
{
|
||||||
|
cfProp += " " + flag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (configName.Contains("Debug") && !cfProp.Contains("-DIL2CPP_DEBUG="))
|
||||||
|
{
|
||||||
|
cfProp += " -DIL2CPP_DEBUG=1 -DDEBUG=1";
|
||||||
|
}
|
||||||
|
proj.SetBuildPropertyForConfig(configGuid, cflagKey, cfProp);
|
||||||
|
|
||||||
|
}
|
||||||
|
proj.WriteToFile(pbxprojFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CopyLibil2cppToXcodeProj(string srcLibil2cppDir, string dstLibil2cppDir)
|
||||||
|
{
|
||||||
|
BashUtil.RemoveDir(dstLibil2cppDir);
|
||||||
|
BashUtil.CopyDir(srcLibil2cppDir, dstLibil2cppDir, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void CopyExternalToXcodeProj(string srcExternalDir, string dstExternalDir)
|
||||||
|
{
|
||||||
|
BashUtil.RemoveDir(dstExternalDir);
|
||||||
|
BashUtil.CopyDir(srcExternalDir, dstExternalDir, true);
|
||||||
|
|
||||||
|
string baselibPlatfromsDir = $"{dstExternalDir}/baselib/Platforms";
|
||||||
|
BashUtil.RemoveDir($"{baselibPlatfromsDir}/IOS");
|
||||||
|
BashUtil.CopyDir($"{baselibPlatfromsDir}/OSX", $"{baselibPlatfromsDir}/IOS", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
class LumpFile
|
||||||
|
{
|
||||||
|
public List<string> cppFiles = new List<string>();
|
||||||
|
|
||||||
|
public readonly string lumpFile;
|
||||||
|
|
||||||
|
public readonly string il2cppConfigFile;
|
||||||
|
|
||||||
|
public LumpFile(string lumpFile, string il2cppConfigFile)
|
||||||
|
{
|
||||||
|
this.lumpFile = lumpFile;
|
||||||
|
this.il2cppConfigFile = il2cppConfigFile;
|
||||||
|
this.cppFiles.Add(il2cppConfigFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SaveFile()
|
||||||
|
{
|
||||||
|
var lumpFileContent = new List<string>();
|
||||||
|
foreach (var file in cppFiles)
|
||||||
|
{
|
||||||
|
lumpFileContent.Add($"#include \"{GetRelativePathFromProj(file)}\"");
|
||||||
|
}
|
||||||
|
File.WriteAllLines(lumpFile, lumpFileContent, Encoding.UTF8);
|
||||||
|
Debug.Log($"create lump file:{lumpFile}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<LumpFile> CreateLumps(string libil2cppDir, string outputDir)
|
||||||
|
{
|
||||||
|
BashUtil.RecreateDir(outputDir);
|
||||||
|
|
||||||
|
string il2cppConfigFile = $"{libil2cppDir}/il2cpp-config.h";
|
||||||
|
var lumpFiles = new List<LumpFile>();
|
||||||
|
int lumpFileIndex = 0;
|
||||||
|
foreach (var cppDir in Directory.GetDirectories(libil2cppDir, "*", SearchOption.AllDirectories).Concat(new string[] {libil2cppDir}))
|
||||||
|
{
|
||||||
|
var lumpFile = new LumpFile($"{outputDir}/lump_{Path.GetFileName(cppDir)}_{lumpFileIndex}.cpp", il2cppConfigFile);
|
||||||
|
foreach (var file in Directory.GetFiles(cppDir, "*.cpp", SearchOption.TopDirectoryOnly))
|
||||||
|
{
|
||||||
|
lumpFile.cppFiles.Add(file);
|
||||||
|
}
|
||||||
|
lumpFile.SaveFile();
|
||||||
|
lumpFiles.Add(lumpFile);
|
||||||
|
++lumpFileIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
var mmFiles = Directory.GetFiles(libil2cppDir, "*.mm", SearchOption.AllDirectories);
|
||||||
|
if (mmFiles.Length > 0)
|
||||||
|
{
|
||||||
|
var lumpFile = new LumpFile($"{outputDir}/lump_mm.mm", il2cppConfigFile);
|
||||||
|
foreach (var file in mmFiles)
|
||||||
|
{
|
||||||
|
lumpFile.cppFiles.Add(file);
|
||||||
|
}
|
||||||
|
lumpFile.SaveFile();
|
||||||
|
lumpFiles.Add(lumpFile);
|
||||||
|
}
|
||||||
|
return lumpFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<string> GetExtraSourceFiles(string externalDir, string libil2cppDir)
|
||||||
|
{
|
||||||
|
var files = new List<string>();
|
||||||
|
foreach (string extraDir in new string[]
|
||||||
|
{
|
||||||
|
$"{externalDir}/zlib",
|
||||||
|
$"{externalDir}/xxHash",
|
||||||
|
$"{libil2cppDir}/os/ClassLibraryPAL/brotli",
|
||||||
|
})
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(extraDir))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
files.AddRange(Directory.GetFiles(extraDir, "*.c", SearchOption.AllDirectories));
|
||||||
|
}
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 61948fcb1bc40ba47b8c10b0ae801ebb
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
using HybridCLR.Editor.Installer;
|
||||||
|
using HybridCLR.Editor.Settings;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEditor.Build;
|
||||||
|
using UnityEditor.Callbacks;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
#if UNITY_2022 && (UNITY_IOS || UNITY_TVOS || UNITY_VISIONOS)
|
||||||
|
|
||||||
|
namespace HybridCLR.Editor.BuildProcessors
|
||||||
|
{
|
||||||
|
public static class AddLil2cppSourceCodeToXcodeproj2022OrNewer
|
||||||
|
{
|
||||||
|
|
||||||
|
[PostProcessBuild]
|
||||||
|
public static void OnPostProcessBuild(BuildTarget target, string pathToBuiltProject)
|
||||||
|
{
|
||||||
|
if (!HybridCLRSettings.Instance.enable)
|
||||||
|
return;
|
||||||
|
string pbxprojFile = BuildProcessorUtil.GetXcodeProjectFile(pathToBuiltProject);
|
||||||
|
RemoveExternalLibil2cppOption(pbxprojFile);
|
||||||
|
CopyLibil2cppToXcodeProj(pathToBuiltProject);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string TryRemoveDunplicateShellScriptSegment(string pbxprojFile, string pbxprojContent)
|
||||||
|
{
|
||||||
|
// will appear duplicated Shell Script segment when append to existed xcode project.
|
||||||
|
// This is unity bug.
|
||||||
|
// we remove duplicated Shell Script to avoid build error.
|
||||||
|
string copyFileComment = @"/\* CopyFiles \*/,\s+([A-Z0-9]{24}) /\* ShellScript \*/,\s+([A-Z0-9]{24}) /\* ShellScript \*/,";
|
||||||
|
var m = Regex.Match(pbxprojContent, copyFileComment, RegexOptions.Multiline);
|
||||||
|
if (!m.Success)
|
||||||
|
{
|
||||||
|
return pbxprojContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m.Groups[1].Value != m.Groups[2].Value)
|
||||||
|
{
|
||||||
|
throw new BuildFailedException($"find invalid /* ShellScript */ segment");
|
||||||
|
}
|
||||||
|
|
||||||
|
int startIndexOfDupShellScript = m.Groups[2].Index;
|
||||||
|
int endIndexOfDupShellScript = pbxprojContent.IndexOf(",", startIndexOfDupShellScript);
|
||||||
|
|
||||||
|
pbxprojContent = pbxprojContent.Remove(startIndexOfDupShellScript, endIndexOfDupShellScript + 1 - startIndexOfDupShellScript);
|
||||||
|
Debug.LogWarning($"[AddLil2cppSourceCodeToXcodeproj] remove duplicated '/* ShellScript */' from file '{pbxprojFile}'");
|
||||||
|
return pbxprojContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void RemoveExternalLibil2cppOption(string pbxprojFile)
|
||||||
|
{
|
||||||
|
string pbxprojContent = File.ReadAllText(pbxprojFile, Encoding.UTF8);
|
||||||
|
string removeBuildOption = @"--external-lib-il2-cpp=\""$PROJECT_DIR/Libraries/libil2cpp.a\""";
|
||||||
|
if (pbxprojContent.Contains(removeBuildOption))
|
||||||
|
{
|
||||||
|
pbxprojContent = pbxprojContent.Replace(removeBuildOption, "");
|
||||||
|
Debug.Log($"[AddLil2cppSourceCodeToXcodeproj] remove il2cpp build option '{removeBuildOption}' from file '{pbxprojFile}'");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"[AddLil2cppSourceCodeToXcodeproj] project.pbxproj remove building option:'{removeBuildOption}' fail. This may occur when 'Append' to existing xcode project in building");
|
||||||
|
}
|
||||||
|
|
||||||
|
pbxprojContent = TryRemoveDunplicateShellScriptSegment(pbxprojFile, pbxprojContent);
|
||||||
|
|
||||||
|
|
||||||
|
File.WriteAllText(pbxprojFile, pbxprojContent, Encoding.UTF8);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CopyLibil2cppToXcodeProj(string pathToBuiltProject)
|
||||||
|
{
|
||||||
|
string srcLibil2cppDir = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp";
|
||||||
|
string destLibil2cppDir = $"{pathToBuiltProject}/Il2CppOutputProject/IL2CPP/libil2cpp";
|
||||||
|
BashUtil.RemoveDir(destLibil2cppDir);
|
||||||
|
BashUtil.CopyDir(srcLibil2cppDir, destLibil2cppDir, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a4ce072f7e4a17248a3d9ebfd011356b
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
using HybridCLR.Editor.Installer;
|
||||||
|
using HybridCLR.Editor.Settings;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEditor.Build;
|
||||||
|
using UnityEditor.Callbacks;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
#if UNITY_2023_1_OR_NEWER && (UNITY_IOS || UNITY_TVOS || UNITY_VISIONOS)
|
||||||
|
|
||||||
|
namespace HybridCLR.Editor.BuildProcessors
|
||||||
|
{
|
||||||
|
public static class AddLil2cppSourceCodeToXcodeproj2022OrNewer
|
||||||
|
{
|
||||||
|
|
||||||
|
[PostProcessBuild]
|
||||||
|
public static void OnPostProcessBuild(BuildTarget target, string pathToBuiltProject)
|
||||||
|
{
|
||||||
|
if (!HybridCLRSettings.Instance.enable)
|
||||||
|
return;
|
||||||
|
CopyLibil2cppToXcodeProj(pathToBuiltProject);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CopyLibil2cppToXcodeProj(string pathToBuiltProject)
|
||||||
|
{
|
||||||
|
string srcLibil2cppDir = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp";
|
||||||
|
string destLibil2cppDir = $"{pathToBuiltProject}/Il2CppOutputProject/IL2CPP/libil2cpp";
|
||||||
|
BashUtil.RemoveDir(destLibil2cppDir);
|
||||||
|
BashUtil.CopyDir(srcLibil2cppDir, destLibil2cppDir, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 2fa46135129b046a28014d58fdfd18ca
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using UnityEditor.Build;
|
||||||
|
|
||||||
|
namespace HybridCLR.Editor.BuildProcessors
|
||||||
|
{
|
||||||
|
|
||||||
|
public static class BuildProcessorUtil
|
||||||
|
{
|
||||||
|
|
||||||
|
public static string GetXcodeProjectFile(string pathToBuiltProject)
|
||||||
|
{
|
||||||
|
foreach (string dir in Directory.GetDirectories(pathToBuiltProject, "*.xcodeproj", SearchOption.TopDirectoryOnly))
|
||||||
|
{
|
||||||
|
string pbxprojFile = $"{dir}/project.pbxproj";
|
||||||
|
if (File.Exists(pbxprojFile))
|
||||||
|
{
|
||||||
|
return pbxprojFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new BuildFailedException($"can't find xxxx.xcodeproj/project.pbxproj in {pathToBuiltProject}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c680e56f90f2745298a90803c04f6efc
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -1,11 +1,16 @@
|
||||||
using System;
|
using HybridCLR.Editor.Settings;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using UnityEditor;
|
||||||
using UnityEditor.Build;
|
using UnityEditor.Build;
|
||||||
using UnityEditor.Build.Reporting;
|
using UnityEditor.Build.Reporting;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using static UnityEngine.GraphicsBuffer;
|
||||||
|
|
||||||
namespace HybridCLR.Editor.BuildProcessors
|
namespace HybridCLR.Editor.BuildProcessors
|
||||||
{
|
{
|
||||||
|
|
@ -13,17 +18,18 @@ namespace HybridCLR.Editor.BuildProcessors
|
||||||
{
|
{
|
||||||
public int callbackOrder => 0;
|
public int callbackOrder => 0;
|
||||||
|
|
||||||
|
public static bool DisableMethodBridgeDevelopmentFlagChecking { get; set; }
|
||||||
|
|
||||||
public void OnPreprocessBuild(BuildReport report)
|
public void OnPreprocessBuild(BuildReport report)
|
||||||
{
|
{
|
||||||
HybridCLRSettings globalSettings = SettingsUtil.HybridCLRSettings;
|
HybridCLRSettings globalSettings = SettingsUtil.HybridCLRSettings;
|
||||||
#if !UNITY_2020_1_OR_NEWER || !UNITY_IOS
|
|
||||||
if (!globalSettings.enable || globalSettings.useGlobalIl2cpp)
|
if (!globalSettings.enable || globalSettings.useGlobalIl2cpp)
|
||||||
{
|
{
|
||||||
string oldIl2cppPath = Environment.GetEnvironmentVariable("UNITY_IL2CPP_PATH");
|
string oldIl2cppPath = Environment.GetEnvironmentVariable("UNITY_IL2CPP_PATH");
|
||||||
if (!string.IsNullOrEmpty(oldIl2cppPath))
|
if (!string.IsNullOrEmpty(oldIl2cppPath))
|
||||||
{
|
{
|
||||||
Environment.SetEnvironmentVariable("UNITY_IL2CPP_PATH", "");
|
Environment.SetEnvironmentVariable("UNITY_IL2CPP_PATH", "");
|
||||||
Debug.Log($"[CheckSettings] 清除 UNITY_IL2CPP_PATH, 旧值为:'{oldIl2cppPath}'");
|
Debug.Log($"[CheckSettings] clean process environment variable: UNITY_IL2CPP_PATH, old vlaue:'{oldIl2cppPath}'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -32,32 +38,57 @@ namespace HybridCLR.Editor.BuildProcessors
|
||||||
if (curIl2cppPath != SettingsUtil.LocalIl2CppDir)
|
if (curIl2cppPath != SettingsUtil.LocalIl2CppDir)
|
||||||
{
|
{
|
||||||
Environment.SetEnvironmentVariable("UNITY_IL2CPP_PATH", SettingsUtil.LocalIl2CppDir);
|
Environment.SetEnvironmentVariable("UNITY_IL2CPP_PATH", SettingsUtil.LocalIl2CppDir);
|
||||||
Debug.Log($"[CheckSettings] UNITY_IL2CPP_PATH 当前值为:'{curIl2cppPath}',更新为:'{SettingsUtil.LocalIl2CppDir}'");
|
Debug.Log($"[CheckSettings] UNITY_IL2CPP_PATH old value:'{curIl2cppPath}', new value:'{SettingsUtil.LocalIl2CppDir}'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
if (!globalSettings.enable)
|
if (!globalSettings.enable)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (UnityEditor.PlayerSettings.gcIncremental)
|
BuildTargetGroup buildTargetGroup = BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget);
|
||||||
|
ScriptingImplementation curScriptingImplementation = PlayerSettings.GetScriptingBackend(buildTargetGroup);
|
||||||
|
ScriptingImplementation targetScriptingImplementation = ScriptingImplementation.IL2CPP;
|
||||||
|
if (curScriptingImplementation != targetScriptingImplementation)
|
||||||
{
|
{
|
||||||
Debug.LogError($"[CheckSettings] HybridCLR不支持增量式GC,已经自动将该选项关闭");
|
Debug.LogError($"[CheckSettings] current ScriptingBackend:{curScriptingImplementation},have been switched to:{targetScriptingImplementation} automatically");
|
||||||
UnityEditor.PlayerSettings.gcIncremental = false;
|
PlayerSettings.SetScriptingBackend(buildTargetGroup, targetScriptingImplementation);
|
||||||
}
|
}
|
||||||
|
|
||||||
var installer = new Installer.InstallerController();
|
var installer = new Installer.InstallerController();
|
||||||
if (!installer.HasInstalledHybridCLR())
|
if (!installer.HasInstalledHybridCLR())
|
||||||
{
|
{
|
||||||
throw new Exception($"你没有初始化HybridCLR,请通过菜单'HybridCLR/Installer'安装");
|
throw new BuildFailedException($"You have not initialized HybridCLR, please install it via menu 'HybridCLR/Installer'");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (installer.PackageVersion != installer.InstalledLibil2cppVersion)
|
||||||
|
{
|
||||||
|
throw new BuildFailedException($"You must run `HybridCLR/Installer` after upgrading package");
|
||||||
}
|
}
|
||||||
|
|
||||||
HybridCLRSettings gs = SettingsUtil.HybridCLRSettings;
|
HybridCLRSettings gs = SettingsUtil.HybridCLRSettings;
|
||||||
if (((gs.hotUpdateAssemblies?.Length + gs.hotUpdateAssemblyDefinitions?.Length) ?? 0) == 0)
|
if (((gs.hotUpdateAssemblies?.Length + gs.hotUpdateAssemblyDefinitions?.Length) ?? 0) == 0)
|
||||||
{
|
{
|
||||||
Debug.LogWarning("[CheckSettings] HybridCLRSettings中未配置任何热更新模块");
|
Debug.LogWarning("[CheckSettings] No hot update modules configured in HybridCLRSettings");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!DisableMethodBridgeDevelopmentFlagChecking)
|
||||||
|
{
|
||||||
|
string methodBridgeFile = $"{SettingsUtil.GeneratedCppDir}/MethodBridge.cpp";
|
||||||
|
var match = Regex.Match(File.ReadAllText(methodBridgeFile), @"// DEVELOPMENT=(\d)");
|
||||||
|
if (match.Success)
|
||||||
|
{
|
||||||
|
int developmentFlagInMethodBridge = int.Parse(match.Groups[1].Value);
|
||||||
|
int developmentFlagInEditorSettings = EditorUserBuildSettings.development ? 1 : 0;
|
||||||
|
if (developmentFlagInMethodBridge != developmentFlagInEditorSettings)
|
||||||
|
{
|
||||||
|
Debug.LogError($"[CheckSettings] MethodBridge.cpp DEVELOPMENT flag:{developmentFlagInMethodBridge} is inconsistent with EditorUserBuildSettings.development:{developmentFlagInEditorSettings}. Please run 'HybridCLR/Generate/All' before building.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogError("[CheckSettings] MethodBridge.cpp DEVELOPMENT flag not found. Please run 'HybridCLR/Generate/All' before building.");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using HybridCLR.Editor.Installer;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
@ -7,13 +8,15 @@ using System.Threading.Tasks;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEditor.Build;
|
using UnityEditor.Build;
|
||||||
using UnityEditor.Build.Reporting;
|
using UnityEditor.Build.Reporting;
|
||||||
using UnityEditor.Il2Cpp;
|
|
||||||
using UnityEditor.UnityLinker;
|
using UnityEditor.UnityLinker;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
#if !UNITY_2021_1_OR_NEWER
|
||||||
|
using UnityEditor.Il2Cpp;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace HybridCLR.Editor.BuildProcessors
|
namespace HybridCLR.Editor.BuildProcessors
|
||||||
{
|
{
|
||||||
internal class CopyStrippedAOTAssemblies : IPostprocessBuildWithReport
|
internal class CopyStrippedAOTAssemblies : IPostprocessBuildWithReport, IPreprocessBuildWithReport
|
||||||
#if !UNITY_2021_1_OR_NEWER
|
#if !UNITY_2021_1_OR_NEWER
|
||||||
, IIl2CppProcessor
|
, IIl2CppProcessor
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -25,19 +28,52 @@ namespace HybridCLR.Editor.BuildProcessors
|
||||||
public static string GetStripAssembliesDir2021(BuildTarget target)
|
public static string GetStripAssembliesDir2021(BuildTarget target)
|
||||||
{
|
{
|
||||||
string projectDir = SettingsUtil.ProjectDir;
|
string projectDir = SettingsUtil.ProjectDir;
|
||||||
#if UNITY_STANDALONE_WIN
|
switch (target)
|
||||||
return $"{projectDir}/Library/Bee/artifacts/WinPlayerBuildProgram/ManagedStripped";
|
{
|
||||||
#elif UNITY_ANDROID
|
case BuildTarget.StandaloneWindows:
|
||||||
return $"{projectDir}/Library/Bee/artifacts/Android/ManagedStripped";
|
case BuildTarget.StandaloneWindows64:
|
||||||
#elif UNITY_IOS
|
return $"{projectDir}/Library/Bee/artifacts/WinPlayerBuildProgram/ManagedStripped";
|
||||||
return $"{projectDir}/Temp/StagingArea/Data/Managed/tempStrip";
|
case BuildTarget.StandaloneLinux64:
|
||||||
#elif UNITY_WEBGL
|
return $"{projectDir}/Library/Bee/artifacts/LinuxPlayerBuildProgram/ManagedStripped";
|
||||||
return $"{projectDir}/Library/Bee/artifacts/WebGL/ManagedStripped";
|
case BuildTarget.WSAPlayer:
|
||||||
#elif UNITY_EDITOR_OSX
|
return $"{projectDir}/Library/Bee/artifacts/UWPPlayerBuildProgram/ManagedStripped";
|
||||||
return $"{projectDir}/Library/Bee/artifacts/MacStandalonePlayerBuildProgram/ManagedStripped";
|
case BuildTarget.Android:
|
||||||
#else
|
return $"{projectDir}/Library/Bee/artifacts/Android/ManagedStripped";
|
||||||
throw new NotSupportedException("GetOriginBuildStripAssembliesDir");
|
#if TUANJIE_2022_3_OR_NEWER
|
||||||
|
case BuildTarget.HMIAndroid:
|
||||||
|
return $"{projectDir}/Library/Bee/artifacts/HMIAndroid/ManagedStripped";
|
||||||
#endif
|
#endif
|
||||||
|
case BuildTarget.iOS:
|
||||||
|
#if UNITY_TVOS
|
||||||
|
case BuildTarget.tvOS:
|
||||||
|
#endif
|
||||||
|
return $"{projectDir}/Library/Bee/artifacts/iOS/ManagedStripped";
|
||||||
|
#if UNITY_VISIONOS
|
||||||
|
case BuildTarget.VisionOS:
|
||||||
|
#if UNITY_6000_0_OR_NEWER
|
||||||
|
return $"{projectDir}/Library/Bee/artifacts/VisionOS/ManagedStripped";
|
||||||
|
#else
|
||||||
|
return $"{projectDir}/Library/Bee/artifacts/iOS/ManagedStripped";
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
case BuildTarget.WebGL:
|
||||||
|
return $"{projectDir}/Library/Bee/artifacts/WebGL/ManagedStripped";
|
||||||
|
case BuildTarget.StandaloneOSX:
|
||||||
|
return $"{projectDir}/Library/Bee/artifacts/MacStandalonePlayerBuildProgram/ManagedStripped";
|
||||||
|
case BuildTarget.PS4:
|
||||||
|
return $"{projectDir}/Library/Bee/artifacts/PS4PlayerBuildProgram/ManagedStripped";
|
||||||
|
case BuildTarget.PS5:
|
||||||
|
return $"{projectDir}/Library/Bee/artifacts/PS5PlayerBuildProgram/ManagedStripped";
|
||||||
|
#if UNITY_WEIXINMINIGAME
|
||||||
|
case BuildTarget.WeixinMiniGame:
|
||||||
|
return $"{projectDir}/Library/Bee/artifacts/WeixinMiniGame/ManagedStripped";
|
||||||
|
#endif
|
||||||
|
#if UNITY_OPENHARMONY
|
||||||
|
case BuildTarget.OpenHarmony:
|
||||||
|
return $"{projectDir}/Library/Bee/artifacts/OpenHarmonyPlayerBuildProgram/ManagedStripped";
|
||||||
|
#endif
|
||||||
|
default: return "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
private string GetStripAssembliesDir2020(BuildTarget target)
|
private string GetStripAssembliesDir2020(BuildTarget target)
|
||||||
|
|
@ -50,8 +86,8 @@ namespace HybridCLR.Editor.BuildProcessors
|
||||||
|
|
||||||
public void OnBeforeConvertRun(BuildReport report, Il2CppBuildPipelineData data)
|
public void OnBeforeConvertRun(BuildReport report, Il2CppBuildPipelineData data)
|
||||||
{
|
{
|
||||||
// 此回调只在 2020中调用
|
BuildTarget target = report.summary.platform;
|
||||||
CopyStripDlls(GetStripAssembliesDir2020(data.target), data.target);
|
CopyStripDlls(GetStripAssembliesDir2020(target), target);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -78,10 +114,21 @@ namespace HybridCLR.Editor.BuildProcessors
|
||||||
|
|
||||||
public void OnPostprocessBuild(BuildReport report)
|
public void OnPostprocessBuild(BuildReport report)
|
||||||
{
|
{
|
||||||
#if UNITY_2021_1_OR_NEWER && !UNITY_IOS
|
#if UNITY_2021_1_OR_NEWER
|
||||||
BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
|
BuildTarget target = report.summary.platform;
|
||||||
CopyStripDlls(GetStripAssembliesDir2021(target), target);
|
string srcStripDllPath = GetStripAssembliesDir2021(target);
|
||||||
|
if (!string.IsNullOrEmpty(srcStripDllPath) && Directory.Exists(srcStripDllPath))
|
||||||
|
{
|
||||||
|
CopyStripDlls(srcStripDllPath, target);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void OnPreprocessBuild(BuildReport report)
|
||||||
|
{
|
||||||
|
BuildTarget target = report.summary.platform;
|
||||||
|
var dstPath = SettingsUtil.GetAssembliesPostIl2CppStripDir(target);
|
||||||
|
BashUtil.RecreateDir(dstPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
using HybridCLR.Editor.Meta;
|
using HybridCLR.Editor.Meta;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
@ -25,15 +26,18 @@ namespace HybridCLR.Editor.BuildProcessors
|
||||||
return assemblies;
|
return assemblies;
|
||||||
}
|
}
|
||||||
List<string> allHotUpdateDllNames = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved;
|
List<string> allHotUpdateDllNames = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved;
|
||||||
List<string> allHotupdateDllFiles = SettingsUtil.HotUpdateAssemblyFilesExcludePreserved;
|
|
||||||
|
|
||||||
// 检查是否重复填写
|
// 检查是否重复填写
|
||||||
var hotUpdateDllSet = new HashSet<string>();
|
var hotUpdateDllSet = new HashSet<string>();
|
||||||
foreach(var hotUpdateDll in allHotUpdateDllNames)
|
foreach(var hotUpdateDll in allHotUpdateDllNames)
|
||||||
{
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(hotUpdateDll))
|
||||||
|
{
|
||||||
|
throw new BuildFailedException($"hot update assembly name cann't be empty");
|
||||||
|
}
|
||||||
if (!hotUpdateDllSet.Add(hotUpdateDll))
|
if (!hotUpdateDllSet.Add(hotUpdateDll))
|
||||||
{
|
{
|
||||||
throw new Exception($"热更新 assembly:{hotUpdateDll} 在列表中重复,请除去重复条目");
|
throw new BuildFailedException($"hot update assembly:{hotUpdateDll} is duplicated");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -41,16 +45,24 @@ namespace HybridCLR.Editor.BuildProcessors
|
||||||
// 检查是否填写了正确的dll名称
|
// 检查是否填写了正确的dll名称
|
||||||
foreach (var hotUpdateDllName in allHotUpdateDllNames)
|
foreach (var hotUpdateDllName in allHotUpdateDllNames)
|
||||||
{
|
{
|
||||||
string hotUpdateDllFile = hotUpdateDllName + ".dll";
|
if (assemblies.Select(Path.GetFileNameWithoutExtension).All(ass => ass != hotUpdateDllName)
|
||||||
if (assemblies.All(ass => !ass.EndsWith(hotUpdateDllFile)) && string.IsNullOrEmpty(assResolver.ResolveAssembly(hotUpdateDllName, false)))
|
&& string.IsNullOrEmpty(assResolver.ResolveAssembly(hotUpdateDllName, false)))
|
||||||
{
|
{
|
||||||
throw new Exception($"热更新 assembly:{hotUpdateDllFile} 不存在,请检查拼写错误");
|
throw new BuildFailedException($"hot update assembly:{hotUpdateDllName} doesn't exist");
|
||||||
}
|
}
|
||||||
Debug.Log($"[FilterHotFixAssemblies] 过滤热更新assembly:{hotUpdateDllFile}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 将热更dll从打包列表中移除
|
// 将热更dll从打包列表中移除
|
||||||
return assemblies.Where(ass => allHotupdateDllFiles.All(dll => !ass.EndsWith(dll, StringComparison.OrdinalIgnoreCase))).ToArray();
|
return assemblies.Where(ass =>
|
||||||
|
{
|
||||||
|
string assName = Path.GetFileNameWithoutExtension(ass);
|
||||||
|
bool reserved = allHotUpdateDllNames.All(dll => !assName.Equals(dll, StringComparison.Ordinal));
|
||||||
|
if (!reserved)
|
||||||
|
{
|
||||||
|
Debug.Log($"[FilterHotFixAssemblies] filter assembly:{assName}");
|
||||||
|
}
|
||||||
|
return reserved;
|
||||||
|
}).ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
using System;
|
||||||
|
using UnityEditor.Build;
|
||||||
|
using UnityEditor.Build.Reporting;
|
||||||
|
|
||||||
|
namespace HybridCLR.Editor.BuildProcessors
|
||||||
|
{
|
||||||
|
|
||||||
|
public class MsvcStdextWorkaround : IPreprocessBuildWithReport
|
||||||
|
{
|
||||||
|
const string kWorkaroundFlag = "/D_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS";
|
||||||
|
|
||||||
|
public int callbackOrder => 0;
|
||||||
|
|
||||||
|
public void OnPreprocessBuild(BuildReport report)
|
||||||
|
{
|
||||||
|
var clEnv = Environment.GetEnvironmentVariable("_CL_");
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(clEnv))
|
||||||
|
{
|
||||||
|
Environment.SetEnvironmentVariable("_CL_", kWorkaroundFlag);
|
||||||
|
}
|
||||||
|
else if (!clEnv.Contains(kWorkaroundFlag))
|
||||||
|
{
|
||||||
|
clEnv += " " + kWorkaroundFlag;
|
||||||
|
Environment.SetEnvironmentVariable("_CL_", clEnv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // UNITY_EDITOR
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8bff6cadf0b8db54b87ba51b24d080f6
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -9,21 +9,30 @@ using UnityEditor;
|
||||||
using UnityEditor.Android;
|
using UnityEditor.Android;
|
||||||
using UnityEditor.Build;
|
using UnityEditor.Build;
|
||||||
using UnityEditor.Build.Reporting;
|
using UnityEditor.Build.Reporting;
|
||||||
using UnityEditor.Il2Cpp;
|
|
||||||
using UnityEditor.UnityLinker;
|
using UnityEditor.UnityLinker;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityFS;
|
using UnityFS;
|
||||||
|
#if !UNITY_2023_1_OR_NEWER
|
||||||
|
using UnityEditor.Il2Cpp;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace HybridCLR.Editor.BuildProcessors
|
namespace HybridCLR.Editor.BuildProcessors
|
||||||
{
|
{
|
||||||
public class PatchScriptingAssemblyList :
|
public class PatchScriptingAssemblyList :
|
||||||
#if UNITY_ANDROID
|
#if UNITY_ANDROID
|
||||||
IPostGenerateGradleAndroidProject,
|
IPostGenerateGradleAndroidProject,
|
||||||
|
#elif UNITY_OPENHARMONY
|
||||||
|
UnityEditor.OpenHarmony.IPostGenerateOpenHarmonyProject,
|
||||||
#endif
|
#endif
|
||||||
IPostprocessBuildWithReport
|
IPostprocessBuildWithReport
|
||||||
#if !UNITY_2021_1_OR_NEWER && UNITY_WEBGL
|
#if !UNITY_2021_1_OR_NEWER && UNITY_WEBGL
|
||||||
, IIl2CppProcessor
|
, IIl2CppProcessor
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if UNITY_PS5
|
||||||
|
, IUnityLinkerProcessor
|
||||||
|
#endif
|
||||||
|
|
||||||
{
|
{
|
||||||
public int callbackOrder => 0;
|
public int callbackOrder => 0;
|
||||||
|
|
||||||
|
|
@ -42,16 +51,36 @@ namespace HybridCLR.Editor.BuildProcessors
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if UNITY_OPENHARMONY
|
||||||
|
|
||||||
|
public void OnPostGenerateOpenHarmonyProject(string path)
|
||||||
|
{
|
||||||
|
OnPostGenerateGradleAndroidProject(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
public void OnPostprocessBuild(BuildReport report)
|
public void OnPostprocessBuild(BuildReport report)
|
||||||
{
|
{
|
||||||
// 如果target为Android,由于已经在OnPostGenerateGradelAndroidProject中处理过,
|
// 如果target为Android,由于已经在OnPostGenerateGradelAndroidProject中处理过,
|
||||||
// 这里不再重复处理
|
// 这里不再重复处理
|
||||||
#if !UNITY_ANDROID && !UNITY_WEBGL
|
#if !UNITY_ANDROID && !UNITY_WEBGL && !UNITY_OPENHARMONY
|
||||||
|
|
||||||
PathScriptingAssembilesFile(report.summary.outputPath);
|
PathScriptingAssembilesFile(report.summary.outputPath);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if UNITY_PS5
|
||||||
|
/// <summary>
|
||||||
|
/// 打包模式如果是 Package 需要在这个阶段提前处理 .json , PC Hosted 和 GP5 模式不受影响
|
||||||
|
/// </summary>
|
||||||
|
|
||||||
|
public string GenerateAdditionalLinkXmlFile(UnityEditor.Build.Reporting.BuildReport report, UnityEditor.UnityLinker.UnityLinkerBuildPipelineData data)
|
||||||
|
{
|
||||||
|
string path = $"{SettingsUtil.ProjectDir}/Library/PlayerDataCache/PS5/Data";
|
||||||
|
PathScriptingAssembilesFile(path);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
public void PathScriptingAssembilesFile(string path)
|
public void PathScriptingAssembilesFile(string path)
|
||||||
{
|
{
|
||||||
if (!SettingsUtil.Enable)
|
if (!SettingsUtil.Enable)
|
||||||
|
|
@ -84,7 +113,7 @@ namespace HybridCLR.Editor.BuildProcessors
|
||||||
|
|
||||||
if (jsonFiles.Length == 0)
|
if (jsonFiles.Length == 0)
|
||||||
{
|
{
|
||||||
//Debug.LogError($"can not find file {SettingsUtil.ScriptingAssembliesJsonFile}");
|
Debug.LogWarning($"can not find file {SettingsUtil.ScriptingAssembliesJsonFile}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -96,9 +125,11 @@ namespace HybridCLR.Editor.BuildProcessors
|
||||||
patcher.Save(file);
|
patcher.Save(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddHotFixAssembliesToBinFile(string path)
|
private void AddHotFixAssembliesToBinFile(string path)
|
||||||
{
|
{
|
||||||
|
#if UNITY_STANDALONE_OSX
|
||||||
|
path = Path.GetDirectoryName(path);
|
||||||
|
#endif
|
||||||
if (AddHotFixAssembliesToGlobalgamemanagers(path))
|
if (AddHotFixAssembliesToGlobalgamemanagers(path))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|
@ -148,7 +179,7 @@ namespace HybridCLR.Editor.BuildProcessors
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if UNITY_WEBGL
|
#if UNITY_WEBGL && !UNITY_2022_3_OR_NEWER
|
||||||
public void OnBeforeConvertRun(BuildReport report, Il2CppBuildPipelineData data)
|
public void OnBeforeConvertRun(BuildReport report, Il2CppBuildPipelineData data)
|
||||||
{
|
{
|
||||||
PathScriptingAssembilesFile($"{SettingsUtil.ProjectDir}/Temp/StagingArea/Data");
|
PathScriptingAssembilesFile($"{SettingsUtil.ProjectDir}/Temp/StagingArea/Data");
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace HybridCLR.Editor.BuildProcessors
|
||||||
|
{
|
||||||
|
public class ScriptingAssembliesJsonPatcher
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
private class ScriptingAssemblies
|
||||||
|
{
|
||||||
|
public List<string> names;
|
||||||
|
public List<int> types;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string _file;
|
||||||
|
ScriptingAssemblies _scriptingAssemblies;
|
||||||
|
|
||||||
|
public void Load(string file)
|
||||||
|
{
|
||||||
|
_file = file;
|
||||||
|
string content = File.ReadAllText(file);
|
||||||
|
_scriptingAssemblies = JsonUtility.FromJson<ScriptingAssemblies>(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddScriptingAssemblies(List<string> assemblies)
|
||||||
|
{
|
||||||
|
foreach (string name in assemblies)
|
||||||
|
{
|
||||||
|
if (!_scriptingAssemblies.names.Contains(name))
|
||||||
|
{
|
||||||
|
_scriptingAssemblies.names.Add(name);
|
||||||
|
_scriptingAssemblies.types.Add(16); // user dll type
|
||||||
|
Debug.Log($"[PatchScriptAssembliesJson] add hotfix assembly:{name} to {_file}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Save(string jsonFile)
|
||||||
|
{
|
||||||
|
string content = JsonUtility.ToJson(_scriptingAssemblies);
|
||||||
|
|
||||||
|
File.WriteAllText(jsonFile, content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 4455f7304f8678f408dd6cf21734f55e
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
using HybridCLR.Editor.Meta;
|
using HybridCLR.Editor.Meta;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
@ -10,6 +11,7 @@ using UnityEngine;
|
||||||
|
|
||||||
namespace HybridCLR.Editor.Commands
|
namespace HybridCLR.Editor.Commands
|
||||||
{
|
{
|
||||||
|
using Analyzer = HybridCLR.Editor.AOT.Analyzer;
|
||||||
public static class AOTReferenceGeneratorCommand
|
public static class AOTReferenceGeneratorCommand
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
@ -21,25 +23,110 @@ namespace HybridCLR.Editor.Commands
|
||||||
GenerateAOTGenericReference(target);
|
GenerateAOTGenericReference(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 计算热更代码中的泛型引用
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target"></param>
|
||||||
public static void GenerateAOTGenericReference(BuildTarget target)
|
public static void GenerateAOTGenericReference(BuildTarget target)
|
||||||
{
|
{
|
||||||
var gs = SettingsUtil.HybridCLRSettings;
|
var gs = SettingsUtil.HybridCLRSettings;
|
||||||
List<string> hotUpdateDllNames = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved;
|
List<string> hotUpdateDllNames = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved;
|
||||||
|
|
||||||
using (AssemblyReferenceDeepCollector collector = new AssemblyReferenceDeepCollector(MetaUtil.CreateHotUpdateAndAOTAssemblyResolver(target, hotUpdateDllNames), hotUpdateDllNames))
|
AssemblyReferenceDeepCollector collector = new AssemblyReferenceDeepCollector(MetaUtil.CreateHotUpdateAndAOTAssemblyResolver(target, hotUpdateDllNames), hotUpdateDllNames);
|
||||||
|
var analyzer = new Analyzer(new Analyzer.Options
|
||||||
{
|
{
|
||||||
var analyzer = new Analyzer(new Analyzer.Options
|
MaxIterationCount = Math.Min(20, gs.maxGenericReferenceIteration),
|
||||||
{
|
Collector = collector,
|
||||||
MaxIterationCount = Math.Min(20, gs.maxGenericReferenceIteration),
|
});
|
||||||
Collector = collector,
|
|
||||||
});
|
|
||||||
|
|
||||||
analyzer.Run();
|
analyzer.Run();
|
||||||
|
|
||||||
var writer = new GenericReferenceWriter();
|
var writer = new GenericReferenceWriter();
|
||||||
writer.Write(analyzer.AotGenericTypes.ToList(), analyzer.AotGenericMethods.ToList(), $"{Application.dataPath}/{gs.outputAOTGenericReferenceFile}");
|
writer.Write(analyzer.AotGenericTypes.ToList(), analyzer.AotGenericMethods.ToList(), $"{Application.dataPath}/{gs.outputAOTGenericReferenceFile}");
|
||||||
AssetDatabase.Refresh();
|
AssetDatabase.Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//[MenuItem("HybridCLR/Generate/AOTGenericReference2", priority = 103)]
|
||||||
|
//public static void GeneratedAOTGenericReferenceExcludeExists()
|
||||||
|
//{
|
||||||
|
// GeneratedAOTGenericReferenceExcludeExists(EditorUserBuildSettings.activeBuildTarget);
|
||||||
|
//}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 计算热更新代码中的泛型引用,但排除AOT已经存在的泛型引用
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target"></param>
|
||||||
|
///
|
||||||
|
public static void GeneratedAOTGenericReferenceExcludeExistsAOTClassAndMethods(BuildTarget target)
|
||||||
|
{
|
||||||
|
|
||||||
|
var gs = SettingsUtil.HybridCLRSettings;
|
||||||
|
List<string> hotUpdateDllNames = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved;
|
||||||
|
|
||||||
|
AssemblyReferenceDeepCollector hotUpdateCollector = new AssemblyReferenceDeepCollector(MetaUtil.CreateHotUpdateAndAOTAssemblyResolver(target, hotUpdateDllNames), hotUpdateDllNames);
|
||||||
|
var hotUpdateAnalyzer = new Analyzer(new Analyzer.Options
|
||||||
|
{
|
||||||
|
MaxIterationCount = Math.Min(10, gs.maxGenericReferenceIteration),
|
||||||
|
Collector = hotUpdateCollector,
|
||||||
|
});
|
||||||
|
|
||||||
|
hotUpdateAnalyzer.Run();
|
||||||
|
|
||||||
|
|
||||||
|
string aotDllDir = SettingsUtil.GetAssembliesPostIl2CppStripDir(target);
|
||||||
|
List<string> aotAssemblyNames = Directory.Exists(aotDllDir) ?
|
||||||
|
Directory.GetFiles(aotDllDir, "*.dll", SearchOption.TopDirectoryOnly).Select(Path.GetFileNameWithoutExtension).ToList()
|
||||||
|
: new List<string>();
|
||||||
|
if (aotAssemblyNames.Count == 0)
|
||||||
|
{
|
||||||
|
throw new Exception($"no aot assembly found. please run `HybridCLR/Generate/All` or `HybridCLR/Generate/AotDlls` to generate aot dlls before runing `HybridCLR/Generate/AOTGenericReference`");
|
||||||
}
|
}
|
||||||
|
AssemblyReferenceDeepCollector aotCollector = new AssemblyReferenceDeepCollector(MetaUtil.CreateAOTAssemblyResolver(target), aotAssemblyNames);
|
||||||
|
var aotAnalyzer = new Analyzer(new Analyzer.Options
|
||||||
|
{
|
||||||
|
MaxIterationCount = Math.Min(10, gs.maxGenericReferenceIteration),
|
||||||
|
Collector = aotCollector,
|
||||||
|
ComputeAotAssembly = true,
|
||||||
|
});
|
||||||
|
|
||||||
|
aotAnalyzer.Run();
|
||||||
|
|
||||||
|
var (resultTypes, resultMethods) = ExcludeExistAOTGenericTypeAndMethodss(hotUpdateAnalyzer.AotGenericTypes.ToList(), hotUpdateAnalyzer.AotGenericMethods.ToList(), aotAnalyzer.AotGenericTypes.ToList(), aotAnalyzer.AotGenericMethods.ToList());
|
||||||
|
var writer = new GenericReferenceWriter();
|
||||||
|
writer.Write(resultTypes, resultMethods, $"{Application.dataPath}/{gs.outputAOTGenericReferenceFile}");
|
||||||
|
AssetDatabase.Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static (List<GenericClass>, List<GenericMethod>) ExcludeExistAOTGenericTypeAndMethodss(List<GenericClass> hotUpdateTypes, List<GenericMethod> hotUpdateMethods, List<GenericClass> aotTypes, List<GenericMethod> aotMethods)
|
||||||
|
{
|
||||||
|
var types = new List<GenericClass>();
|
||||||
|
|
||||||
|
var typeSig2Type = hotUpdateTypes.ToDictionary(t => t.Type.DefinitionAssembly.Name + ":" + t.ToTypeSig(), t => t);
|
||||||
|
foreach (var t in aotTypes)
|
||||||
|
{
|
||||||
|
string key = t.Type.DefinitionAssembly.Name + ":" + t.ToTypeSig();
|
||||||
|
if (typeSig2Type.TryGetValue(key, out var removedType))
|
||||||
|
{
|
||||||
|
typeSig2Type.Remove(key);
|
||||||
|
Debug.Log($"remove AOT type:{removedType.ToTypeSig()} ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var methodSig2Method = hotUpdateMethods.ToDictionary(m => m.Method.DeclaringType.DefinitionAssembly.Name + ":" + m.ToMethodSpec().ToString(), m => m);
|
||||||
|
foreach (var m in aotMethods)
|
||||||
|
{
|
||||||
|
string key = m.Method.DeclaringType.DefinitionAssembly.Name + ":" + m.ToMethodSpec().ToString();
|
||||||
|
if (methodSig2Method.TryGetValue(key, out var removedMethod))
|
||||||
|
{
|
||||||
|
methodSig2Method.Remove(key);
|
||||||
|
Debug.Log($"remove AOT method:{removedMethod.ToMethodSpec()} ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (typeSig2Type.Values.ToList(), methodSig2Method.Values.ToList());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,31 +12,48 @@ namespace HybridCLR.Editor.Commands
|
||||||
{
|
{
|
||||||
public class CompileDllCommand
|
public class CompileDllCommand
|
||||||
{
|
{
|
||||||
public static void CompileDll(string buildDir, BuildTarget target)
|
public static void CompileDll(string buildDir, BuildTarget target, bool developmentBuild)
|
||||||
{
|
{
|
||||||
var group = BuildPipeline.GetBuildTargetGroup(target);
|
var group = BuildPipeline.GetBuildTargetGroup(target);
|
||||||
|
|
||||||
ScriptCompilationSettings scriptCompilationSettings = new ScriptCompilationSettings();
|
ScriptCompilationSettings scriptCompilationSettings = new ScriptCompilationSettings();
|
||||||
scriptCompilationSettings.group = group;
|
scriptCompilationSettings.group = group;
|
||||||
scriptCompilationSettings.target = target;
|
scriptCompilationSettings.target = target;
|
||||||
|
scriptCompilationSettings.options = developmentBuild ? ScriptCompilationOptions.DevelopmentBuild : ScriptCompilationOptions.None;
|
||||||
Directory.CreateDirectory(buildDir);
|
Directory.CreateDirectory(buildDir);
|
||||||
ScriptCompilationResult scriptCompilationResult = PlayerBuildInterface.CompilePlayerScripts(scriptCompilationSettings, buildDir);
|
ScriptCompilationResult scriptCompilationResult = PlayerBuildInterface.CompilePlayerScripts(scriptCompilationSettings, buildDir);
|
||||||
foreach (var ass in scriptCompilationResult.assemblies)
|
#if UNITY_2022
|
||||||
{
|
UnityEditor.EditorUtility.ClearProgressBar();
|
||||||
//Debug.LogFormat("compile assemblies:{1}/{0}", ass, buildDir);
|
#endif
|
||||||
}
|
Debug.Log($"compile finish!!! buildDir:{buildDir} target:{target} development:{developmentBuild}");
|
||||||
Debug.Log("compile finish!!!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void CompileDll(BuildTarget target)
|
public static void CompileDll(BuildTarget target)
|
||||||
{
|
{
|
||||||
CompileDll(SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target), target);
|
CompileDll(target, EditorUserBuildSettings.development);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CompileDll(BuildTarget target, bool developmentBuild)
|
||||||
|
{
|
||||||
|
CompileDll(SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target), target, developmentBuild);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MenuItem("HybridCLR/CompileDll/ActiveBuildTarget", priority = 100)]
|
[MenuItem("HybridCLR/CompileDll/ActiveBuildTarget", priority = 100)]
|
||||||
public static void CompileDllActiveBuildTarget()
|
public static void CompileDllActiveBuildTarget()
|
||||||
{
|
{
|
||||||
CompileDll(EditorUserBuildSettings.activeBuildTarget);
|
CompileDll(EditorUserBuildSettings.activeBuildTarget, EditorUserBuildSettings.development);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MenuItem("HybridCLR/CompileDll/ActiveBuildTarget_Release", priority = 102)]
|
||||||
|
public static void CompileDllActiveBuildTargetRelease()
|
||||||
|
{
|
||||||
|
CompileDll(EditorUserBuildSettings.activeBuildTarget, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MenuItem("HybridCLR/CompileDll/ActiveBuildTarget_Development", priority = 104)]
|
||||||
|
public static void CompileDllActiveBuildTargetDevelopment()
|
||||||
|
{
|
||||||
|
CompileDll(EditorUserBuildSettings.activeBuildTarget, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MenuItem("HybridCLR/CompileDll/Win32", priority = 200)]
|
[MenuItem("HybridCLR/CompileDll/Win32", priority = 200)]
|
||||||
|
|
@ -51,16 +68,34 @@ namespace HybridCLR.Editor.Commands
|
||||||
CompileDll(BuildTarget.StandaloneWindows64);
|
CompileDll(BuildTarget.StandaloneWindows64);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MenuItem("HybridCLR/CompileDll/Android", priority = 202)]
|
[MenuItem("HybridCLR/CompileDll/MacOS", priority = 202)]
|
||||||
|
public static void CompileDllMacOS()
|
||||||
|
{
|
||||||
|
CompileDll(BuildTarget.StandaloneOSX);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MenuItem("HybridCLR/CompileDll/Linux", priority = 203)]
|
||||||
|
public static void CompileDllLinux()
|
||||||
|
{
|
||||||
|
CompileDll(BuildTarget.StandaloneLinux64);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MenuItem("HybridCLR/CompileDll/Android", priority = 210)]
|
||||||
public static void CompileDllAndroid()
|
public static void CompileDllAndroid()
|
||||||
{
|
{
|
||||||
CompileDll(BuildTarget.Android);
|
CompileDll(BuildTarget.Android);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MenuItem("HybridCLR/CompileDll/IOS", priority = 203)]
|
[MenuItem("HybridCLR/CompileDll/IOS", priority = 220)]
|
||||||
public static void CompileDllIOS()
|
public static void CompileDllIOS()
|
||||||
{
|
{
|
||||||
CompileDll(BuildTarget.iOS);
|
CompileDll(BuildTarget.iOS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MenuItem("HybridCLR/CompileDll/WebGL", priority = 230)]
|
||||||
|
public static void CompileDllWebGL()
|
||||||
|
{
|
||||||
|
CompileDll(BuildTarget.WebGL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using HybridCLR.Editor.Link;
|
using HybridCLR.Editor.Link;
|
||||||
|
using HybridCLR.Editor.Settings;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
@ -19,8 +20,10 @@ namespace HybridCLR.Editor.Commands
|
||||||
{
|
{
|
||||||
UnityVersion = Application.unityVersion,
|
UnityVersion = Application.unityVersion,
|
||||||
HotUpdateAssemblies = SettingsUtil.HotUpdateAssemblyNamesIncludePreserved,
|
HotUpdateAssemblies = SettingsUtil.HotUpdateAssemblyNamesIncludePreserved,
|
||||||
OutputFile = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp/il2cpp-config.h",
|
UnityVersionTemplateFile = $"{SettingsUtil.TemplatePathInPackage}/UnityVersion.h.tpl",
|
||||||
OutputFile2 = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr/Il2CppCompatibleDef.cpp",
|
UnityVersionOutputFile = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr/generated/UnityVersion.h",
|
||||||
|
AssemblyManifestTemplateFile = $"{SettingsUtil.TemplatePathInPackage}/AssemblyManifest.cpp.tpl",
|
||||||
|
AssemblyManifestOutputFile = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr/generated/AssemblyManifest.cpp",
|
||||||
};
|
};
|
||||||
|
|
||||||
var g = new Il2CppDef.Il2CppDefGenerator(options);
|
var g = new Il2CppDef.Il2CppDefGenerator(options);
|
||||||
|
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
using HybridCLR.Editor.Installer;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace HybridCLR.Editor.Commands
|
|
||||||
{
|
|
||||||
public static class InstallerCommand
|
|
||||||
{
|
|
||||||
|
|
||||||
[MenuItem("HybridCLR/Installer...", false, 0)]
|
|
||||||
private static void Open()
|
|
||||||
{
|
|
||||||
InstallerWindow window = EditorWindow.GetWindow<InstallerWindow>("HybridCLR Installer", true);
|
|
||||||
window.minSize = new Vector2(800f, 500f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: b91d62dfcf14d1241b7654d79d5b98a0
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
|
|
@ -8,6 +8,7 @@ using UnityEngine;
|
||||||
|
|
||||||
namespace HybridCLR.Editor.Commands
|
namespace HybridCLR.Editor.Commands
|
||||||
{
|
{
|
||||||
|
using Analyzer = HybridCLR.Editor.Link.Analyzer;
|
||||||
|
|
||||||
public static class LinkGeneratorCommand
|
public static class LinkGeneratorCommand
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,12 @@ using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
|
using UnityEditor.Build;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace HybridCLR.Editor.Commands
|
namespace HybridCLR.Editor.Commands
|
||||||
{
|
{
|
||||||
|
using Analyzer = HybridCLR.Editor.MethodBridge.Analyzer;
|
||||||
public class MethodBridgeGeneratorCommand
|
public class MethodBridgeGeneratorCommand
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
@ -28,55 +30,67 @@ namespace HybridCLR.Editor.Commands
|
||||||
Directory.Delete(il2cppBuildCachePath, true);
|
Directory.Delete(il2cppBuildCachePath, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GenerateMethodBridgeCppFile(Analyzer analyzer, PlatformABI platform, string templateCode, string outputFile)
|
private static void GenerateMethodBridgeCppFile(IReadOnlyCollection<GenericMethod> genericMethods, List<RawMonoPInvokeCallbackMethodInfo> reversePInvokeMethods, IReadOnlyCollection<CallNativeMethodSignatureInfo> calliMethodSignatures, string tempFile, string outputFile)
|
||||||
{
|
{
|
||||||
|
string templateCode = File.ReadAllText(tempFile, Encoding.UTF8);
|
||||||
var g = new Generator(new Generator.Options()
|
var g = new Generator(new Generator.Options()
|
||||||
{
|
{
|
||||||
PlatformABI = platform,
|
|
||||||
TemplateCode = templateCode,
|
TemplateCode = templateCode,
|
||||||
OutputFile = outputFile,
|
OutputFile = outputFile,
|
||||||
GenericMethods = analyzer.GenericMethods,
|
GenericMethods = genericMethods,
|
||||||
NotGenericMethods = analyzer.NotGenericMethods,
|
ReversePInvokeMethods = reversePInvokeMethods,
|
||||||
|
CalliMethodSignatures = calliMethodSignatures,
|
||||||
|
Development = EditorUserBuildSettings.development,
|
||||||
});
|
});
|
||||||
|
|
||||||
g.PrepareMethods();
|
|
||||||
g.Generate();
|
g.Generate();
|
||||||
Debug.LogFormat("== output:{0} ==", outputFile);
|
Debug.LogFormat("[MethodBridgeGeneratorCommand] output:{0}", outputFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MenuItem("HybridCLR/Generate/MethodBridge", priority = 101)]
|
[MenuItem("HybridCLR/Generate/MethodBridgeAndReversePInvokeWrapper", priority = 101)]
|
||||||
public static void CompileAndGenerateMethodBridge()
|
public static void GenerateMethodBridgeAndReversePInvokeWrapper()
|
||||||
{
|
{
|
||||||
BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
|
BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
|
||||||
CompileDllCommand.CompileDll(target);
|
GenerateMethodBridgeAndReversePInvokeWrapper(target);
|
||||||
GenerateMethodBridge(target);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void GenerateMethodBridge(BuildTarget target)
|
public static void GenerateMethodBridgeAndReversePInvokeWrapper(BuildTarget target)
|
||||||
{
|
{
|
||||||
List<string> hotUpdateDllNames = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved;
|
string aotDllDir = SettingsUtil.GetAssembliesPostIl2CppStripDir(target);
|
||||||
using (AssemblyReferenceDeepCollector collector = new AssemblyReferenceDeepCollector(MetaUtil.CreateHotUpdateAndAOTAssemblyResolver(target, hotUpdateDllNames), hotUpdateDllNames))
|
List<string> aotAssemblyNames = Directory.Exists(aotDllDir) ?
|
||||||
|
Directory.GetFiles(aotDllDir, "*.dll", SearchOption.TopDirectoryOnly).Select(Path.GetFileNameWithoutExtension).ToList()
|
||||||
|
: new List<string>();
|
||||||
|
if (aotAssemblyNames.Count == 0)
|
||||||
{
|
{
|
||||||
var analyzer = new Analyzer(new Analyzer.Options
|
throw new Exception($"no aot assembly found. please run `HybridCLR/Generate/All` or `HybridCLR/Generate/AotDlls` to generate aot dlls before runing `HybridCLR/Generate/MethodBridge`");
|
||||||
{
|
|
||||||
MaxIterationCount = Math.Min(20, SettingsUtil.HybridCLRSettings.maxMethodBridgeGenericIteration),
|
|
||||||
Collector = collector,
|
|
||||||
});
|
|
||||||
|
|
||||||
analyzer.Run();
|
|
||||||
|
|
||||||
var tasks = new List<Task>();
|
|
||||||
string templateCode = File.ReadAllText($"{SettingsUtil.TemplatePathInPackage}/MethodBridgeStub.cpp");
|
|
||||||
foreach (PlatformABI platform in Enum.GetValues(typeof(PlatformABI)))
|
|
||||||
{
|
|
||||||
string outputFile = $"{SettingsUtil.GeneratedCppDir}/MethodBridge_{platform}.cpp";
|
|
||||||
tasks.Add(Task.Run(() =>
|
|
||||||
{
|
|
||||||
GenerateMethodBridgeCppFile(analyzer, platform, templateCode, outputFile);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
Task.WaitAll(tasks.ToArray());
|
|
||||||
}
|
}
|
||||||
|
AssemblyReferenceDeepCollector collector = new AssemblyReferenceDeepCollector(MetaUtil.CreateAOTAssemblyResolver(target), aotAssemblyNames);
|
||||||
|
|
||||||
|
var methodBridgeAnalyzer = new Analyzer(new Analyzer.Options
|
||||||
|
{
|
||||||
|
MaxIterationCount = Math.Min(20, SettingsUtil.HybridCLRSettings.maxMethodBridgeGenericIteration),
|
||||||
|
Collector = collector,
|
||||||
|
});
|
||||||
|
|
||||||
|
methodBridgeAnalyzer.Run();
|
||||||
|
|
||||||
|
List<string> hotUpdateDlls = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved;
|
||||||
|
var cache = new AssemblyCache(MetaUtil.CreateHotUpdateAndAOTAssemblyResolver(target, hotUpdateDlls));
|
||||||
|
|
||||||
|
var reversePInvokeAnalyzer = new MonoPInvokeCallbackAnalyzer(cache, hotUpdateDlls);
|
||||||
|
reversePInvokeAnalyzer.Run();
|
||||||
|
|
||||||
|
var calliAnalyzer = new CalliAnalyzer(cache, hotUpdateDlls);
|
||||||
|
calliAnalyzer.Run();
|
||||||
|
var pinvokeAnalyzer = new PInvokeAnalyzer(cache, hotUpdateDlls);
|
||||||
|
pinvokeAnalyzer.Run();
|
||||||
|
var callPInvokeMethodSignatures = pinvokeAnalyzer.PInvokeMethodSignatures;
|
||||||
|
|
||||||
|
string templateFile = $"{SettingsUtil.TemplatePathInPackage}/MethodBridge.cpp.tpl";
|
||||||
|
string outputFile = $"{SettingsUtil.GeneratedCppDir}/MethodBridge.cpp";
|
||||||
|
|
||||||
|
var callNativeMethodSignatures = calliAnalyzer.CalliMethodSignatures.Concat(pinvokeAnalyzer.PInvokeMethodSignatures).ToList();
|
||||||
|
GenerateMethodBridgeCppFile(methodBridgeAnalyzer.GenericMethods, reversePInvokeAnalyzer.ReversePInvokeMethods, callNativeMethodSignatures, templateFile, outputFile);
|
||||||
|
|
||||||
CleanIl2CppBuildCache();
|
CleanIl2CppBuildCache();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
|
using UnityEditor.Build;
|
||||||
|
|
||||||
namespace HybridCLR.Editor.Commands
|
namespace HybridCLR.Editor.Commands
|
||||||
{
|
{
|
||||||
|
|
@ -15,19 +16,23 @@ namespace HybridCLR.Editor.Commands
|
||||||
[MenuItem("HybridCLR/Generate/All", priority = 200)]
|
[MenuItem("HybridCLR/Generate/All", priority = 200)]
|
||||||
public static void GenerateAll()
|
public static void GenerateAll()
|
||||||
{
|
{
|
||||||
|
var installer = new Installer.InstallerController();
|
||||||
|
if (!installer.HasInstalledHybridCLR())
|
||||||
|
{
|
||||||
|
throw new BuildFailedException($"You have not initialized HybridCLR, please install it via menu 'HybridCLR/Installer'");
|
||||||
|
}
|
||||||
BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
|
BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
|
||||||
CompileDllCommand.CompileDll(target);
|
CompileDllCommand.CompileDll(target, EditorUserBuildSettings.development);
|
||||||
Il2CppDefGeneratorCommand.GenerateIl2CppDef();
|
Il2CppDefGeneratorCommand.GenerateIl2CppDef();
|
||||||
|
|
||||||
// 这几个生成依赖HotUpdateDlls
|
// 这几个生成依赖HotUpdateDlls
|
||||||
LinkGeneratorCommand.GenerateLinkXml(target);
|
LinkGeneratorCommand.GenerateLinkXml(target);
|
||||||
|
|
||||||
// 生成裁剪后的aot dll
|
// 生成裁剪后的aot dll
|
||||||
StripAOTDllCommand.GenerateStripedAOTDlls(target, EditorUserBuildSettings.selectedBuildTargetGroup);
|
StripAOTDllCommand.GenerateStripedAOTDlls(target);
|
||||||
|
|
||||||
// 桥接函数生成依赖于AOT dll,必须保证已经build过,生成AOT dll
|
// 桥接函数生成依赖于AOT dll,必须保证已经build过,生成AOT dll
|
||||||
MethodBridgeGeneratorCommand.GenerateMethodBridge(target);
|
MethodBridgeGeneratorCommand.GenerateMethodBridgeAndReversePInvokeWrapper(target);
|
||||||
ReversePInvokeWrapperGeneratorCommand.GenerateReversePInvokeWrapper(target);
|
|
||||||
AOTReferenceGeneratorCommand.GenerateAOTGenericReference(target);
|
AOTReferenceGeneratorCommand.GenerateAOTGenericReference(target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
using HybridCLR.Editor.ABI;
|
|
||||||
using HybridCLR.Editor.Link;
|
|
||||||
using HybridCLR.Editor.Meta;
|
|
||||||
using HybridCLR.Editor.ReversePInvokeWrap;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace HybridCLR.Editor.Commands
|
|
||||||
{
|
|
||||||
|
|
||||||
public static class ReversePInvokeWrapperGeneratorCommand
|
|
||||||
{
|
|
||||||
|
|
||||||
[MenuItem("HybridCLR/Generate/ReversePInvokeWrapper", priority = 103)]
|
|
||||||
|
|
||||||
public static void CompileAndGenerateReversePInvokeWrapper()
|
|
||||||
{
|
|
||||||
BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
|
|
||||||
CompileDllCommand.CompileDll(target);
|
|
||||||
GenerateReversePInvokeWrapper(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void GenerateReversePInvokeWrapper(BuildTarget target)
|
|
||||||
{
|
|
||||||
List<string> hotUpdateDlls = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved;
|
|
||||||
using (var cache = new AssemblyCache(MetaUtil.CreateHotUpdateAndAOTAssemblyResolver(target, hotUpdateDlls)))
|
|
||||||
{
|
|
||||||
var analyzer = new ReversePInvokeWrap.Analyzer(cache, hotUpdateDlls);
|
|
||||||
analyzer.Run();
|
|
||||||
|
|
||||||
|
|
||||||
string templateCode = File.ReadAllText($"{SettingsUtil.TemplatePathInPackage}/ReversePInvokeMethodStub.cpp");
|
|
||||||
foreach (PlatformABI abi in Enum.GetValues(typeof(PlatformABI)))
|
|
||||||
{
|
|
||||||
string outputFile = $"{SettingsUtil.GeneratedCppDir}/ReversePInvokeMethodStub_{abi}.cpp";
|
|
||||||
|
|
||||||
List<ABIReversePInvokeMethodInfo> methods = analyzer.BuildABIMethods(abi);
|
|
||||||
Debug.Log($"GenerateReversePInvokeWrapper. abi:{abi} wraperCount:{methods.Sum(m => m.Count)} output:{outputFile}");
|
|
||||||
var generator = new Generator();
|
|
||||||
generator.Generate(templateCode, abi, methods, outputFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MethodBridgeGeneratorCommand.CleanIl2CppBuildCache();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 7db18e1736f593c4089c85d764cf8620
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
|
|
@ -1,12 +1,15 @@
|
||||||
using HybridCLR.Editor.Installer;
|
using HybridCLR.Editor.BuildProcessors;
|
||||||
|
using HybridCLR.Editor.Installer;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using static UnityEngine.Networking.UnityWebRequest;
|
||||||
|
|
||||||
namespace HybridCLR.Editor.Commands
|
namespace HybridCLR.Editor.Commands
|
||||||
{
|
{
|
||||||
|
|
@ -15,7 +18,38 @@ namespace HybridCLR.Editor.Commands
|
||||||
[MenuItem("HybridCLR/Generate/AOTDlls", priority = 105)]
|
[MenuItem("HybridCLR/Generate/AOTDlls", priority = 105)]
|
||||||
public static void GenerateStripedAOTDlls()
|
public static void GenerateStripedAOTDlls()
|
||||||
{
|
{
|
||||||
GenerateStripedAOTDlls(EditorUserBuildSettings.activeBuildTarget, EditorUserBuildSettings.selectedBuildTargetGroup);
|
GenerateStripedAOTDlls(EditorUserBuildSettings.activeBuildTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BuildOptions GetBuildPlayerOptions(BuildTarget buildTarget)
|
||||||
|
{
|
||||||
|
BuildOptions options = BuildOptions.None;
|
||||||
|
bool development = EditorUserBuildSettings.development;
|
||||||
|
if (development)
|
||||||
|
{
|
||||||
|
options |= BuildOptions.Development;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EditorUserBuildSettings.allowDebugging && development)
|
||||||
|
{
|
||||||
|
options |= BuildOptions.AllowDebugging;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EditorUserBuildSettings.connectProfiler && (development || buildTarget == BuildTarget.WSAPlayer))
|
||||||
|
{
|
||||||
|
options |= BuildOptions.ConnectWithProfiler;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EditorUserBuildSettings.buildWithDeepProfilingSupport && development)
|
||||||
|
{
|
||||||
|
options |= BuildOptions.EnableDeepProfilingSupport;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if UNITY_2021_2_OR_NEWER
|
||||||
|
options |= BuildOptions.CleanBuildCache;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetLocationPathName(string buildDir, BuildTarget target)
|
private static string GetLocationPathName(string buildDir, BuildTarget target)
|
||||||
|
|
@ -23,100 +57,140 @@ namespace HybridCLR.Editor.Commands
|
||||||
switch(target)
|
switch(target)
|
||||||
{
|
{
|
||||||
case BuildTarget.StandaloneWindows:
|
case BuildTarget.StandaloneWindows:
|
||||||
case BuildTarget.StandaloneWindows64: return $"{buildDir}/{target}";
|
case BuildTarget.StandaloneWindows64: return $"{buildDir}/{PlayerSettings.productName}.exe";
|
||||||
case BuildTarget.StandaloneOSX: return buildDir;
|
case BuildTarget.StandaloneOSX: return buildDir;
|
||||||
case BuildTarget.iOS: return buildDir;
|
case BuildTarget.iOS: return buildDir;
|
||||||
case BuildTarget.Android: return buildDir;
|
case BuildTarget.Android: return buildDir;
|
||||||
case BuildTarget.StandaloneLinux64: return buildDir;
|
case BuildTarget.StandaloneLinux64: return $"{buildDir}/{PlayerSettings.productName}";
|
||||||
default: return buildDir;
|
default: return buildDir;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void GenerateStripedAOTDlls(BuildTarget target, BuildTargetGroup group)
|
public static void GenerateStripedAOTDlls(BuildTarget target)
|
||||||
{
|
{
|
||||||
string outputPath = $"{SettingsUtil.HybridCLRDataDir}/StrippedAOTDllsTempProj/{target}";
|
string outputPath = $"{SettingsUtil.HybridCLRDataDir}/StrippedAOTDllsTempProj/{target}";
|
||||||
BashUtil.RemoveDir(outputPath);
|
BashUtil.RemoveDir(outputPath);
|
||||||
|
|
||||||
var buildOptions = BuildOptions.BuildScriptsOnly;
|
var buildOptions = GetBuildPlayerOptions(target);
|
||||||
#if UNITY_2021_1_OR_NEWER
|
|
||||||
buildOptions |= BuildOptions.CleanBuildCache;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool oldExportAndroidProj = EditorUserBuildSettings.exportAsGoogleAndroidProject;
|
bool oldExportAndroidProj = EditorUserBuildSettings.exportAsGoogleAndroidProject;
|
||||||
#if UNITY_EDITOR_OSX
|
#if UNITY_EDITOR_OSX
|
||||||
bool oldCreateSolution = UnityEditor.OSXStandalone.UserBuildSettings.createXcodeProject;
|
bool oldCreateSolution = UnityEditor.OSXStandalone.UserBuildSettings.createXcodeProject;
|
||||||
#elif UNITY_EDITOR_WIN
|
#elif UNITY_EDITOR_WIN
|
||||||
bool oldCreateSolution = UnityEditor.WindowsStandalone.UserBuildSettings.createSolution;
|
bool oldCreateSolution = UnityEditor.WindowsStandalone.UserBuildSettings.createSolution;
|
||||||
|
#endif
|
||||||
|
#if TUANJIE_2022_3_OR_NEWER
|
||||||
|
bool oldOpenHarmonyProj = EditorUserBuildSettings.exportAsOpenHarmonyProject;
|
||||||
#endif
|
#endif
|
||||||
bool oldBuildScriptsOnly = EditorUserBuildSettings.buildScriptsOnly;
|
bool oldBuildScriptsOnly = EditorUserBuildSettings.buildScriptsOnly;
|
||||||
EditorUserBuildSettings.buildScriptsOnly = true;
|
|
||||||
|
|
||||||
switch (target)
|
string oldBuildLocation = EditorUserBuildSettings.GetBuildLocation(target);
|
||||||
|
try
|
||||||
{
|
{
|
||||||
case BuildTarget.StandaloneWindows:
|
CheckSettings.DisableMethodBridgeDevelopmentFlagChecking = true;
|
||||||
case BuildTarget.StandaloneWindows64:
|
EditorUserBuildSettings.buildScriptsOnly = true;
|
||||||
|
|
||||||
|
string location = GetLocationPathName(outputPath, target);
|
||||||
|
EditorUserBuildSettings.SetBuildLocation(target, location);
|
||||||
|
|
||||||
|
switch (target)
|
||||||
{
|
{
|
||||||
#if UNITY_EDITOR_WIN
|
case BuildTarget.StandaloneWindows:
|
||||||
UnityEditor.WindowsStandalone.UserBuildSettings.createSolution = true;
|
case BuildTarget.StandaloneWindows64:
|
||||||
#endif
|
{
|
||||||
|
#if UNITY_EDITOR_WIN
|
||||||
|
UnityEditor.WindowsStandalone.UserBuildSettings.createSolution = true;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case BuildTarget.StandaloneOSX:
|
||||||
|
{
|
||||||
|
#if UNITY_EDITOR_OSX
|
||||||
|
UnityEditor.OSXStandalone.UserBuildSettings.createXcodeProject = true;
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
#if TUANJIE_2022_3_OR_NEWER
|
||||||
|
case BuildTarget.HMIAndroid:
|
||||||
|
#endif
|
||||||
|
case BuildTarget.Android:
|
||||||
|
{
|
||||||
|
EditorUserBuildSettings.exportAsGoogleAndroidProject = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#if TUANJIE_2022_3_OR_NEWER
|
||||||
|
case BuildTarget.OpenHarmony:
|
||||||
|
{
|
||||||
|
EditorUserBuildSettings.exportAsOpenHarmonyProject = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
case BuildTarget.StandaloneOSX:
|
|
||||||
|
Debug.Log($"GenerateStripedAOTDlls build option:{buildOptions}");
|
||||||
|
|
||||||
|
BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions()
|
||||||
{
|
{
|
||||||
#if UNITY_EDITOR_OSX
|
scenes = EditorBuildSettings.scenes.Where(s => s.enabled).Select(s => s.path).ToArray(),
|
||||||
UnityEditor.OSXStandalone.UserBuildSettings.createXcodeProject = true;
|
locationPathName = location,
|
||||||
|
options = buildOptions,
|
||||||
|
target = target,
|
||||||
|
targetGroup = BuildPipeline.GetBuildTargetGroup(target),
|
||||||
|
#if UNITY_SERVER
|
||||||
|
subtarget = (int)StandaloneBuildSubtarget.Server,
|
||||||
#endif
|
#endif
|
||||||
break;
|
};
|
||||||
}
|
|
||||||
case BuildTarget.Android:
|
var report = BuildPipeline.BuildPlayer(buildPlayerOptions);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (report.summary.result != UnityEditor.Build.Reporting.BuildResult.Succeeded)
|
||||||
{
|
{
|
||||||
EditorUserBuildSettings.exportAsGoogleAndroidProject = true;
|
throw new Exception("GenerateStripedAOTDlls failed");
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions()
|
|
||||||
{
|
{
|
||||||
scenes = EditorBuildSettings.scenes.Where(s => s.enabled).Select(s => s.path).ToArray(),
|
CheckSettings.DisableMethodBridgeDevelopmentFlagChecking = false;
|
||||||
locationPathName = GetLocationPathName(outputPath, target),
|
EditorUserBuildSettings.buildScriptsOnly = oldBuildScriptsOnly;
|
||||||
options = buildOptions,
|
EditorUserBuildSettings.SetBuildLocation(target, oldBuildLocation);
|
||||||
target = target,
|
|
||||||
targetGroup = group,
|
|
||||||
};
|
|
||||||
|
|
||||||
var report = BuildPipeline.BuildPlayer(buildPlayerOptions);
|
switch (target)
|
||||||
|
{
|
||||||
EditorUserBuildSettings.buildScriptsOnly = oldBuildScriptsOnly;
|
case BuildTarget.StandaloneWindows:
|
||||||
switch (target)
|
case BuildTarget.StandaloneWindows64:
|
||||||
{
|
|
||||||
case BuildTarget.StandaloneWindows:
|
|
||||||
case BuildTarget.StandaloneWindows64:
|
|
||||||
{
|
{
|
||||||
#if UNITY_EDITOR_WIN
|
#if UNITY_EDITOR_WIN
|
||||||
UnityEditor.WindowsStandalone.UserBuildSettings.createSolution = oldCreateSolution;
|
UnityEditor.WindowsStandalone.UserBuildSettings.createSolution = oldCreateSolution;
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BuildTarget.StandaloneOSX:
|
case BuildTarget.StandaloneOSX:
|
||||||
{
|
{
|
||||||
#if UNITY_EDITOR_OSX
|
#if UNITY_EDITOR_OSX
|
||||||
UnityEditor.OSXStandalone.UserBuildSettings.createXcodeProject = oldCreateSolution;
|
UnityEditor.OSXStandalone.UserBuildSettings.createXcodeProject = oldCreateSolution;
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BuildTarget.Android:
|
#if TUANJIE_2022_3_OR_NEWER
|
||||||
{
|
case BuildTarget.HMIAndroid:
|
||||||
EditorUserBuildSettings.exportAsGoogleAndroidProject = oldExportAndroidProj;
|
#endif
|
||||||
break;
|
case BuildTarget.Android:
|
||||||
|
{
|
||||||
|
EditorUserBuildSettings.exportAsGoogleAndroidProject = oldExportAndroidProj;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#if TUANJIE_2022_3_OR_NEWER
|
||||||
|
case BuildTarget.OpenHarmony:
|
||||||
|
{
|
||||||
|
EditorUserBuildSettings.exportAsOpenHarmonyProject = oldOpenHarmonyProj;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Debug.Log($"GenerateStripedAOTDlls target:{target} path:{outputPath}");
|
||||||
if (report.summary.result != UnityEditor.Build.Reporting.BuildResult.Succeeded)
|
|
||||||
{
|
|
||||||
Debug.LogError("GenerateStripedAOTDlls 失败");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Debug.Log($"GenerateStripedAOTDlls target:{target} group:{group} path:{outputPath}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 8f2a6638b09b52f4c9dc8906d090b710
|
guid: e60a8b17b0e23a94a8ae875716208030
|
||||||
folderAsset: yes
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
|
|
@ -0,0 +1,109 @@
|
||||||
|
using dnlib.DotNet;
|
||||||
|
using HybridCLR.Editor.Meta;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace HybridCLR.Editor.HotUpdate
|
||||||
|
{
|
||||||
|
public class MissingMetadataChecker
|
||||||
|
{
|
||||||
|
private readonly HashSet<string> _aotAssNames;
|
||||||
|
|
||||||
|
private readonly HashSet<string> _hotUpdateAssNames;
|
||||||
|
|
||||||
|
private readonly AssemblyCache _assCache;
|
||||||
|
|
||||||
|
public MissingMetadataChecker(string aotDllDir, IEnumerable<string> hotUpdateAssNames)
|
||||||
|
{
|
||||||
|
|
||||||
|
_hotUpdateAssNames = new HashSet<string>(hotUpdateAssNames ?? new List<string>());
|
||||||
|
_aotAssNames = new HashSet<string>();
|
||||||
|
foreach (var aotFile in Directory.GetFiles(aotDllDir, "*.dll"))
|
||||||
|
{
|
||||||
|
string aotAssName = Path.GetFileNameWithoutExtension(aotFile);
|
||||||
|
if (_hotUpdateAssNames.Contains(aotAssName))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_aotAssNames.Add(aotAssName);
|
||||||
|
}
|
||||||
|
_assCache = new AssemblyCache(new PathAssemblyResolver(aotDllDir));
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Check(string hotUpdateDllPath)
|
||||||
|
{
|
||||||
|
bool anyMissing = false;
|
||||||
|
|
||||||
|
ModuleDef mod = ModuleDefMD.Load(File.ReadAllBytes(hotUpdateDllPath), _assCache.ModCtx);
|
||||||
|
|
||||||
|
foreach (var refass in mod.GetAssemblyRefs())
|
||||||
|
{
|
||||||
|
string refAssName = refass.Name;
|
||||||
|
if (_aotAssNames.Contains(refAssName))
|
||||||
|
{
|
||||||
|
_assCache.LoadModule(refass.Name, true);
|
||||||
|
}
|
||||||
|
else if (!_hotUpdateAssNames.Contains(refAssName))
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.LogError($"Missing AOT Assembly: {refAssName}");
|
||||||
|
anyMissing = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
foreach (TypeRef typeRef in mod.GetTypeRefs())
|
||||||
|
{
|
||||||
|
string defAssName = typeRef.DefinitionAssembly.Name;
|
||||||
|
if (!_aotAssNames.Contains(defAssName))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (typeRef.ResolveTypeDef() == null)
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.LogError($"Missing Type: {typeRef.FullName}");
|
||||||
|
anyMissing = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (IMethodDefOrRef memberRef in mod.GetMemberRefs())
|
||||||
|
{
|
||||||
|
if (memberRef.DeclaringType.DefinitionAssembly == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
string defAssName = memberRef.DeclaringType.DefinitionAssembly.Name;
|
||||||
|
if (!_aotAssNames.Contains(defAssName))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (memberRef.IsField)
|
||||||
|
{
|
||||||
|
IField field = (IField)memberRef;
|
||||||
|
if (field.ResolveFieldDef() == null)
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.LogError($"Missing Field: {memberRef.FullName}");
|
||||||
|
anyMissing = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (memberRef.IsMethod)
|
||||||
|
{
|
||||||
|
TypeSig declaringTypeSig = memberRef.DeclaringType.ToTypeSig();
|
||||||
|
if (memberRef.ResolveMethodDef() == null)
|
||||||
|
{
|
||||||
|
if (declaringTypeSig.ElementType == ElementType.Array || declaringTypeSig.ElementType == ElementType.SZArray)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
UnityEngine.Debug.LogError($"Missing Method: {memberRef.FullName}");
|
||||||
|
anyMissing = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return !anyMissing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: bdd260aca2a6deb44b20210f01faa86b
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -17,9 +17,13 @@ namespace HybridCLR.Editor.Il2CppDef
|
||||||
{
|
{
|
||||||
public List<string> HotUpdateAssemblies { get; set; }
|
public List<string> HotUpdateAssemblies { get; set; }
|
||||||
|
|
||||||
public string OutputFile { get; set; }
|
public string UnityVersionTemplateFile { get; set; }
|
||||||
|
|
||||||
public string OutputFile2 { get; set; }
|
public string UnityVersionOutputFile { get; set; }
|
||||||
|
|
||||||
|
public string AssemblyManifestTemplateFile { get; set; }
|
||||||
|
|
||||||
|
public string AssemblyManifestOutputFile { get; set; }
|
||||||
|
|
||||||
public string UnityVersion { get; set; }
|
public string UnityVersion { get; set; }
|
||||||
}
|
}
|
||||||
|
|
@ -41,7 +45,7 @@ namespace HybridCLR.Editor.Il2CppDef
|
||||||
|
|
||||||
private void GenerateIl2CppConfig()
|
private void GenerateIl2CppConfig()
|
||||||
{
|
{
|
||||||
var frr = new FileRegionReplace(File.ReadAllText(_options.OutputFile));
|
var frr = new FileRegionReplace(File.ReadAllText(_options.UnityVersionTemplateFile));
|
||||||
|
|
||||||
List<string> lines = new List<string>();
|
List<string> lines = new List<string>();
|
||||||
|
|
||||||
|
|
@ -52,7 +56,14 @@ namespace HybridCLR.Editor.Il2CppDef
|
||||||
|
|
||||||
lines.Add($"#define HYBRIDCLR_UNITY_VERSION {majorVer}{minorVer1.ToString("D2")}{minorVer2.ToString("D2")}");
|
lines.Add($"#define HYBRIDCLR_UNITY_VERSION {majorVer}{minorVer1.ToString("D2")}{minorVer2.ToString("D2")}");
|
||||||
lines.Add($"#define HYBRIDCLR_UNITY_{majorVer} 1");
|
lines.Add($"#define HYBRIDCLR_UNITY_{majorVer} 1");
|
||||||
for (int ver = 2019; ver <= 2024; ver++)
|
for (int ver = 2019; ver <= 2023; ver++)
|
||||||
|
{
|
||||||
|
if (majorVer >= ver)
|
||||||
|
{
|
||||||
|
lines.Add($"#define HYBRIDCLR_UNITY_{ver}_OR_NEW 1");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int ver = 6000; ver <= 6100; ver++)
|
||||||
{
|
{
|
||||||
if (majorVer >= ver)
|
if (majorVer >= ver)
|
||||||
{
|
{
|
||||||
|
|
@ -60,15 +71,25 @@ namespace HybridCLR.Editor.Il2CppDef
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if TUANJIE_1_1_OR_NEWER
|
||||||
|
var tuanjieMatch = Regex.Matches(Application.tuanjieVersion, @"(\d+)\.(\d+)\.(\d+)");
|
||||||
|
int tuanjieMajorVer = int.Parse(tuanjieMatch[0].Groups[1].Value);
|
||||||
|
int tuanjieMinorVer1 = int.Parse(tuanjieMatch[0].Groups[2].Value);
|
||||||
|
int tuanjieMinorVer2 = int.Parse(tuanjieMatch[0].Groups[3].Value);
|
||||||
|
lines.Add($"#define HYBRIDCLR_TUANJIE_VERSION {tuanjieMajorVer}{tuanjieMinorVer1.ToString("D2")}{tuanjieMinorVer2.ToString("D2")}");
|
||||||
|
#elif TUANJIE_2022_3_OR_NEWER
|
||||||
|
lines.Add($"#define HYBRIDCLR_TUANJIE_VERSION 10000");
|
||||||
|
#endif
|
||||||
|
|
||||||
frr.Replace("UNITY_VERSION", string.Join("\n", lines));
|
frr.Replace("UNITY_VERSION", string.Join("\n", lines));
|
||||||
|
|
||||||
frr.Commit(_options.OutputFile);
|
frr.Commit(_options.UnityVersionOutputFile);
|
||||||
Debug.Log($"[HybridCLR.Editor.Il2CppDef.Generator] output:{_options.OutputFile}");
|
Debug.Log($"[HybridCLR.Editor.Il2CppDef.Generator] output:{_options.UnityVersionOutputFile}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GeneratePlaceHolderAssemblies()
|
private void GeneratePlaceHolderAssemblies()
|
||||||
{
|
{
|
||||||
var frr = new FileRegionReplace(File.ReadAllText(_options.OutputFile2));
|
var frr = new FileRegionReplace(File.ReadAllText(_options.AssemblyManifestTemplateFile));
|
||||||
|
|
||||||
List<string> lines = new List<string>();
|
List<string> lines = new List<string>();
|
||||||
|
|
||||||
|
|
@ -79,8 +100,8 @@ namespace HybridCLR.Editor.Il2CppDef
|
||||||
|
|
||||||
frr.Replace("PLACE_HOLDER", string.Join("\n", lines));
|
frr.Replace("PLACE_HOLDER", string.Join("\n", lines));
|
||||||
|
|
||||||
frr.Commit(_options.OutputFile2);
|
frr.Commit(_options.AssemblyManifestOutputFile);
|
||||||
Debug.Log($"[HybridCLR.Editor.Il2CppDef.Generator] output:{_options.OutputFile2}");
|
Debug.Log($"[HybridCLR.Editor.Il2CppDef.Generator] output:{_options.AssemblyManifestOutputFile}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace HybridCLR.Editor.Installer
|
namespace HybridCLR.Editor.Installer
|
||||||
|
|
@ -63,20 +64,34 @@ namespace HybridCLR.Editor.Installer
|
||||||
{
|
{
|
||||||
UnityEngine.Debug.Log($"[BashUtil] RemoveDir dir:{dir}");
|
UnityEngine.Debug.Log($"[BashUtil] RemoveDir dir:{dir}");
|
||||||
}
|
}
|
||||||
if (!Directory.Exists(dir))
|
|
||||||
|
int maxTryCount = 5;
|
||||||
|
for (int i = 0; i < maxTryCount; ++i)
|
||||||
{
|
{
|
||||||
return;
|
try
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(dir))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
foreach (var file in Directory.GetFiles(dir))
|
||||||
|
{
|
||||||
|
File.SetAttributes(file, FileAttributes.Normal);
|
||||||
|
File.Delete(file);
|
||||||
|
}
|
||||||
|
foreach (var subDir in Directory.GetDirectories(dir))
|
||||||
|
{
|
||||||
|
RemoveDir(subDir);
|
||||||
|
}
|
||||||
|
Directory.Delete(dir, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.LogError($"[BashUtil] RemoveDir:{dir} with exception:{e}. try count:{i}");
|
||||||
|
Thread.Sleep(100);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
foreach (var file in Directory.GetFiles(dir))
|
|
||||||
{
|
|
||||||
File.SetAttributes(file, FileAttributes.Normal);
|
|
||||||
File.Delete(file);
|
|
||||||
}
|
|
||||||
foreach (var subDir in Directory.GetDirectories(dir))
|
|
||||||
{
|
|
||||||
RemoveDir(subDir);
|
|
||||||
}
|
|
||||||
Directory.Delete(dir);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RecreateDir(string dir)
|
public static void RecreateDir(string dir)
|
||||||
|
|
@ -87,23 +102,23 @@ namespace HybridCLR.Editor.Installer
|
||||||
}
|
}
|
||||||
Directory.CreateDirectory(dir);
|
Directory.CreateDirectory(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void CopyDir(string src, string dst, bool log = false)
|
public static void CopyDir(string src, string dst, bool log = false)
|
||||||
{
|
{
|
||||||
if (log)
|
if (log)
|
||||||
{
|
{
|
||||||
UnityEngine.Debug.Log($"[BashUtil] CopyDir {src} => {dst}");
|
UnityEngine.Debug.Log($"[BashUtil] CopyDir {src} => {dst}");
|
||||||
}
|
}
|
||||||
RemoveDir(dst);
|
if (Directory.Exists(dst))
|
||||||
Directory.CreateDirectory(dst);
|
|
||||||
foreach(var file in Directory.GetFiles(src))
|
|
||||||
{
|
{
|
||||||
File.Copy(file, $"{dst}/{Path.GetFileName(file)}");
|
RemoveDir(dst);
|
||||||
}
|
}
|
||||||
foreach(var subDir in Directory.GetDirectories(src))
|
else
|
||||||
{
|
{
|
||||||
CopyDir(subDir, $"{dst}/{Path.GetFileName(subDir)}");
|
string parentDir = Path.GetDirectoryName(Path.GetFullPath(dst));
|
||||||
|
Directory.CreateDirectory(parentDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UnityEditor.FileUtil.CopyFileOrDirectory(src, dst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,16 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
using Debug = UnityEngine.Debug;
|
using Debug = UnityEngine.Debug;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Linq;
|
||||||
|
using HybridCLR.Editor.Settings;
|
||||||
|
|
||||||
namespace HybridCLR.Editor.Installer
|
namespace HybridCLR.Editor.Installer
|
||||||
{
|
{
|
||||||
public enum InstallErrorCode
|
|
||||||
{
|
|
||||||
Ok,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public class InstallerController
|
public class InstallerController
|
||||||
{
|
{
|
||||||
|
|
@ -36,11 +25,17 @@ namespace HybridCLR.Editor.Installer
|
||||||
private readonly HybridclrVersionManifest _versionManifest;
|
private readonly HybridclrVersionManifest _versionManifest;
|
||||||
private readonly HybridclrVersionInfo _curDefaultVersion;
|
private readonly HybridclrVersionInfo _curDefaultVersion;
|
||||||
|
|
||||||
|
public string PackageVersion { get; private set; }
|
||||||
|
|
||||||
|
public string InstalledLibil2cppVersion { get; private set; }
|
||||||
|
|
||||||
public InstallerController()
|
public InstallerController()
|
||||||
{
|
{
|
||||||
_curVersion = ParseUnityVersion(Application.unityVersion);
|
_curVersion = ParseUnityVersion(Application.unityVersion);
|
||||||
_versionManifest = GetHybridCLRVersionManifest();
|
_versionManifest = GetHybridCLRVersionManifest();
|
||||||
_curDefaultVersion = _versionManifest.versions.Find(v => v.unity_version == _curVersion.major.ToString());
|
_curDefaultVersion = _versionManifest.versions.FirstOrDefault(v => _curVersion.isTuanjieEngine ? v.unity_version == $"{_curVersion.major}-tuanjie" : v.unity_version == _curVersion.major.ToString());
|
||||||
|
PackageVersion = LoadPackageInfo().version;
|
||||||
|
InstalledLibil2cppVersion = ReadLocalVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
private HybridclrVersionManifest GetHybridCLRVersionManifest()
|
private HybridclrVersionManifest GetHybridCLRVersionManifest()
|
||||||
|
|
@ -49,6 +44,21 @@ namespace HybridCLR.Editor.Installer
|
||||||
return JsonUtility.FromJson<HybridclrVersionManifest>(File.ReadAllText(versionFile, Encoding.UTF8));
|
return JsonUtility.FromJson<HybridclrVersionManifest>(File.ReadAllText(versionFile, Encoding.UTF8));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private PackageInfo LoadPackageInfo()
|
||||||
|
{
|
||||||
|
string packageJson = $"{SettingsUtil.ProjectDir}/Packages/{SettingsUtil.PackageName}/package.json";
|
||||||
|
return JsonUtility.FromJson<PackageInfo>(File.ReadAllText(packageJson, Encoding.UTF8));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
class PackageInfo
|
||||||
|
{
|
||||||
|
public string name;
|
||||||
|
|
||||||
|
public string version;
|
||||||
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
class VersionDesc
|
class VersionDesc
|
||||||
{
|
{
|
||||||
|
|
@ -78,6 +88,7 @@ namespace HybridCLR.Editor.Installer
|
||||||
public int major;
|
public int major;
|
||||||
public int minor1;
|
public int minor1;
|
||||||
public int minor2;
|
public int minor2;
|
||||||
|
public bool isTuanjieEngine;
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
|
|
@ -87,10 +98,6 @@ namespace HybridCLR.Editor.Installer
|
||||||
|
|
||||||
private static readonly Regex s_unityVersionPat = new Regex(@"(\d+)\.(\d+)\.(\d+)");
|
private static readonly Regex s_unityVersionPat = new Regex(@"(\d+)\.(\d+)\.(\d+)");
|
||||||
|
|
||||||
public const int min2019_4_CompatibleMinorVersion = 40;
|
|
||||||
public const int min2020_3_CompatibleMinorVersion = 21;
|
|
||||||
public const int min2021_3_CompatibleMinorVersion = 0;
|
|
||||||
|
|
||||||
private UnityVersion ParseUnityVersion(string versionStr)
|
private UnityVersion ParseUnityVersion(string versionStr)
|
||||||
{
|
{
|
||||||
var matches = s_unityVersionPat.Matches(versionStr);
|
var matches = s_unityVersionPat.Matches(versionStr);
|
||||||
|
|
@ -98,13 +105,12 @@ namespace HybridCLR.Editor.Installer
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// 找最后一个匹配的
|
|
||||||
Match match = matches[matches.Count - 1];
|
Match match = matches[matches.Count - 1];
|
||||||
// Debug.Log($"capture count:{match.Groups.Count} {match.Groups[1].Value} {match.Groups[2].Value}");
|
|
||||||
int major = int.Parse(match.Groups[1].Value);
|
int major = int.Parse(match.Groups[1].Value);
|
||||||
int minor1 = int.Parse(match.Groups[2].Value);
|
int minor1 = int.Parse(match.Groups[2].Value);
|
||||||
int minor2 = int.Parse(match.Groups[3].Value);
|
int minor2 = int.Parse(match.Groups[3].Value);
|
||||||
return new UnityVersion { major = major, minor1 = minor1, minor2 = minor2 };
|
bool isTuanjieEngine = versionStr.Contains("t");
|
||||||
|
return new UnityVersion { major = major, minor1 = minor1, minor2 = minor2, isTuanjieEngine = isTuanjieEngine };
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetCurrentUnityVersionMinCompatibleVersionStr()
|
public string GetCurrentUnityVersionMinCompatibleVersionStr()
|
||||||
|
|
@ -116,49 +122,41 @@ namespace HybridCLR.Editor.Installer
|
||||||
{
|
{
|
||||||
switch(majorVersion)
|
switch(majorVersion)
|
||||||
{
|
{
|
||||||
case 2019: return $"2019.4.{min2019_4_CompatibleMinorVersion}";
|
case 2019: return "2019.4.0";
|
||||||
case 2020: return $"2020.3.{min2020_3_CompatibleMinorVersion}";
|
case 2020: return "2020.3.0";
|
||||||
case 2021: return $"2021.3.{min2021_3_CompatibleMinorVersion}";
|
case 2021: return "2021.3.0";
|
||||||
default: throw new Exception($"not support version:{majorVersion}");
|
case 2022: return "2022.3.0";
|
||||||
|
case 2023: return "2023.2.0";
|
||||||
|
case 6000: return "6000.0.0";
|
||||||
|
default: return $"2020.3.0";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsComaptibleVersion()
|
public enum CompatibleType
|
||||||
|
{
|
||||||
|
Compatible,
|
||||||
|
MaybeIncompatible,
|
||||||
|
Incompatible,
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompatibleType GetCompatibleType()
|
||||||
{
|
{
|
||||||
UnityVersion version = _curVersion;
|
UnityVersion version = _curVersion;
|
||||||
switch (version.major)
|
if (version == null)
|
||||||
{
|
{
|
||||||
case 2019:
|
return CompatibleType.Incompatible;
|
||||||
{
|
|
||||||
if (version.major != 2019 || version.minor1 != 4)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return version.minor2 >= min2019_4_CompatibleMinorVersion;
|
|
||||||
}
|
|
||||||
case 2020:
|
|
||||||
{
|
|
||||||
if (version.major != 2020 || version.minor1 != 3)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return version.minor2 >= min2020_3_CompatibleMinorVersion;
|
|
||||||
}
|
|
||||||
case 2021:
|
|
||||||
{
|
|
||||||
if (version.major != 2021 || version.minor1 != 3)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return version.minor2 >= min2021_3_CompatibleMinorVersion;
|
|
||||||
}
|
|
||||||
default: throw new Exception($"not support il2cpp_plus branch:{version.major}");
|
|
||||||
}
|
}
|
||||||
|
if ((version.major == 2019 && version.minor1 < 4)
|
||||||
|
|| (version.major >= 2020 && version.major <= 2022 && version.minor1 < 3))
|
||||||
|
{
|
||||||
|
return CompatibleType.MaybeIncompatible;
|
||||||
|
}
|
||||||
|
return CompatibleType.Compatible;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string HybridclrLocalVersion => _curDefaultVersion.hybridclr.branch;
|
public string HybridclrLocalVersion => _curDefaultVersion?.hybridclr?.branch;
|
||||||
|
|
||||||
public string Il2cppPlusLocalVersion => _curDefaultVersion.il2cpp_plus.branch;
|
public string Il2cppPlusLocalVersion => _curDefaultVersion?.il2cpp_plus?.branch;
|
||||||
|
|
||||||
|
|
||||||
private string GetIl2CppPathByContentPath(string contentPath)
|
private string GetIl2CppPathByContentPath(string contentPath)
|
||||||
|
|
@ -166,10 +164,29 @@ namespace HybridCLR.Editor.Installer
|
||||||
return $"{contentPath}/il2cpp";
|
return $"{contentPath}/il2cpp";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string ApplicationIl2cppPath => GetIl2CppPathByContentPath(EditorApplication.applicationContentsPath);
|
||||||
|
|
||||||
|
public string LocalVersionFile => $"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr/generated/libil2cpp-version.txt";
|
||||||
|
|
||||||
|
private string ReadLocalVersion()
|
||||||
|
{
|
||||||
|
if (!File.Exists(LocalVersionFile))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return File.ReadAllText(LocalVersionFile, Encoding.UTF8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteLocalVersion()
|
||||||
|
{
|
||||||
|
InstalledLibil2cppVersion = PackageVersion;
|
||||||
|
File.WriteAllText(LocalVersionFile, PackageVersion, Encoding.UTF8);
|
||||||
|
Debug.Log($"Write installed version:'{PackageVersion}' to {LocalVersionFile}");
|
||||||
|
}
|
||||||
|
|
||||||
public void InstallDefaultHybridCLR()
|
public void InstallDefaultHybridCLR()
|
||||||
{
|
{
|
||||||
RunInitLocalIl2CppData(GetIl2CppPathByContentPath(EditorApplication.applicationContentsPath), _curVersion);
|
InstallFromLocal(PrepareLibil2cppWithHybridclrFromGitRepo());
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasInstalledHybridCLR()
|
public bool HasInstalledHybridCLR()
|
||||||
|
|
@ -177,7 +194,6 @@ namespace HybridCLR.Editor.Installer
|
||||||
return Directory.Exists($"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr");
|
return Directory.Exists($"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private string GetUnityIl2CppDllInstallLocation()
|
private string GetUnityIl2CppDllInstallLocation()
|
||||||
{
|
{
|
||||||
#if UNITY_EDITOR_WIN
|
#if UNITY_EDITOR_WIN
|
||||||
|
|
@ -190,9 +206,9 @@ namespace HybridCLR.Editor.Installer
|
||||||
private string GetUnityIl2CppDllModifiedPath(string curVersionStr)
|
private string GetUnityIl2CppDllModifiedPath(string curVersionStr)
|
||||||
{
|
{
|
||||||
#if UNITY_EDITOR_WIN
|
#if UNITY_EDITOR_WIN
|
||||||
return $"{SettingsUtil.ProjectDir}/{SettingsUtil.HybridCLRDataPathInPackage}/ModifiedUnityAssemblies/{curVersionStr}/Unity.IL2CPP-Win.dll.bytes";
|
return $"{SettingsUtil.ProjectDir}/{SettingsUtil.HybridCLRDataPathInPackage}/ModifiedUnityAssemblies/{curVersionStr}/Unity.IL2CPP-Win.dll";
|
||||||
#else
|
#else
|
||||||
return $"{SettingsUtil.ProjectDir}/{SettingsUtil.HybridCLRDataPathInPackage}/ModifiedUnityAssemblies/{curVersionStr}/Unity.IL2CPP-Mac.dll.bytes";
|
return $"{SettingsUtil.ProjectDir}/{SettingsUtil.HybridCLRDataPathInPackage}/ModifiedUnityAssemblies/{curVersionStr}/Unity.IL2CPP-Mac.dll";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -202,31 +218,51 @@ namespace HybridCLR.Editor.Installer
|
||||||
BashUtil.RunCommand(workDir, "git", new string[] {"clone", "-b", branch, "--depth", "1", repoUrl, repoDir});
|
BashUtil.RunCommand(workDir, "git", new string[] {"clone", "-b", branch, "--depth", "1", repoUrl, repoDir});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RunInitLocalIl2CppData(string editorIl2cppPath, UnityVersion version)
|
private string PrepareLibil2cppWithHybridclrFromGitRepo()
|
||||||
{
|
{
|
||||||
if (!IsComaptibleVersion())
|
|
||||||
{
|
|
||||||
Debug.LogError($"il2cpp 版本不兼容,最小版本为 {GetCurrentUnityVersionMinCompatibleVersionStr()}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
string workDir = SettingsUtil.HybridCLRDataDir;
|
string workDir = SettingsUtil.HybridCLRDataDir;
|
||||||
Directory.CreateDirectory(workDir);
|
Directory.CreateDirectory(workDir);
|
||||||
//BashUtil.RecreateDir(workDir);
|
//BashUtil.RecreateDir(workDir);
|
||||||
|
|
||||||
string buildiOSDir = $"{workDir}/iOSBuild";
|
|
||||||
BashUtil.RemoveDir(buildiOSDir);
|
|
||||||
BashUtil.CopyDir($"{SettingsUtil.HybridCLRDataPathInPackage}/iOSBuild", buildiOSDir, true);
|
|
||||||
|
|
||||||
// clone hybridclr
|
// clone hybridclr
|
||||||
string hybridclrRepoURL = HybridCLRSettings.Instance.hybridclrRepoURL;
|
string hybridclrRepoURL = HybridCLRSettings.Instance.hybridclrRepoURL;
|
||||||
string hybridclrRepoDir = $"{workDir}/{hybridclr_repo_path}";
|
string hybridclrRepoDir = $"{workDir}/{hybridclr_repo_path}";
|
||||||
CloneBranch(workDir, hybridclrRepoURL, _curDefaultVersion.hybridclr.branch, hybridclrRepoDir);
|
CloneBranch(workDir, hybridclrRepoURL, _curDefaultVersion.hybridclr.branch, hybridclrRepoDir);
|
||||||
|
|
||||||
|
if (!Directory.Exists(hybridclrRepoDir))
|
||||||
|
{
|
||||||
|
throw new Exception($"clone hybridclr fail. url: {hybridclrRepoURL}");
|
||||||
|
}
|
||||||
|
|
||||||
// clone il2cpp_plus
|
// clone il2cpp_plus
|
||||||
string il2cppPlusRepoURL = HybridCLRSettings.Instance.il2cppPlusRepoURL;
|
string il2cppPlusRepoURL = HybridCLRSettings.Instance.il2cppPlusRepoURL;
|
||||||
string il2cppPlusRepoDir = $"{workDir}/{il2cpp_plus_repo_path}";
|
string il2cppPlusRepoDir = $"{workDir}/{il2cpp_plus_repo_path}";
|
||||||
CloneBranch(workDir, il2cppPlusRepoURL, _curDefaultVersion.il2cpp_plus.branch, il2cppPlusRepoDir);
|
CloneBranch(workDir, il2cppPlusRepoURL, _curDefaultVersion.il2cpp_plus.branch, il2cppPlusRepoDir);
|
||||||
|
|
||||||
|
if (!Directory.Exists(il2cppPlusRepoDir))
|
||||||
|
{
|
||||||
|
throw new Exception($"clone il2cpp_plus fail. url: {il2cppPlusRepoDir}");
|
||||||
|
}
|
||||||
|
|
||||||
|
Directory.Move($"{hybridclrRepoDir}/hybridclr", $"{il2cppPlusRepoDir}/libil2cpp/hybridclr");
|
||||||
|
return $"{il2cppPlusRepoDir}/libil2cpp";
|
||||||
|
}
|
||||||
|
|
||||||
|
public void InstallFromLocal(string libil2cppWithHybridclrSourceDir)
|
||||||
|
{
|
||||||
|
RunInitLocalIl2CppData(ApplicationIl2cppPath, libil2cppWithHybridclrSourceDir, _curVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RunInitLocalIl2CppData(string editorIl2cppPath, string libil2cppWithHybridclrSourceDir, UnityVersion version)
|
||||||
|
{
|
||||||
|
if (GetCompatibleType() == CompatibleType.Incompatible)
|
||||||
|
{
|
||||||
|
Debug.LogError($"Incompatible with current version, minimum compatible version: {GetCurrentUnityVersionMinCompatibleVersionStr()}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
string workDir = SettingsUtil.HybridCLRDataDir;
|
||||||
|
Directory.CreateDirectory(workDir);
|
||||||
|
|
||||||
// create LocalIl2Cpp
|
// create LocalIl2Cpp
|
||||||
string localUnityDataDir = SettingsUtil.LocalUnityDataDir;
|
string localUnityDataDir = SettingsUtil.LocalUnityDataDir;
|
||||||
BashUtil.RecreateDir(localUnityDataDir);
|
BashUtil.RecreateDir(localUnityDataDir);
|
||||||
|
|
@ -239,12 +275,10 @@ namespace HybridCLR.Editor.Installer
|
||||||
|
|
||||||
// replace libil2cpp
|
// replace libil2cpp
|
||||||
string dstLibil2cppDir = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp";
|
string dstLibil2cppDir = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp";
|
||||||
BashUtil.CopyDir($"{il2cppPlusRepoDir}/libil2cpp", dstLibil2cppDir, true);
|
BashUtil.CopyDir($"{libil2cppWithHybridclrSourceDir}", dstLibil2cppDir, true);
|
||||||
BashUtil.CopyDir($"{hybridclrRepoDir}/hybridclr", $"{dstLibil2cppDir}/hybridclr", true);
|
|
||||||
|
|
||||||
// clean Il2cppBuildCache
|
// clean Il2cppBuildCache
|
||||||
BashUtil.RemoveDir($"{SettingsUtil.ProjectDir}/Library/Il2cppBuildCache", true);
|
BashUtil.RemoveDir($"{SettingsUtil.ProjectDir}/Library/Il2cppBuildCache", true);
|
||||||
|
|
||||||
if (version.major == 2019)
|
if (version.major == 2019)
|
||||||
{
|
{
|
||||||
string curVersionStr = version.ToString();
|
string curVersionStr = version.ToString();
|
||||||
|
|
@ -257,16 +291,17 @@ namespace HybridCLR.Editor.Installer
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogError($"未找到当前版本:{curVersionStr} 对应的改造过的 Unity.IL2CPP.dll,打包出的程序将会崩溃");
|
throw new Exception($"the modified Unity.IL2CPP.dll of {curVersionStr} isn't found. please install hybridclr in 2019.4.40 first, then switch to your unity version");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (HasInstalledHybridCLR())
|
if (HasInstalledHybridCLR())
|
||||||
{
|
{
|
||||||
Debug.Log("安装成功");
|
WriteLocalVersion();
|
||||||
|
Debug.Log("Install Sucessfully");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogError("安装失败");
|
Debug.LogError("Installation failed!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
@ -10,6 +11,10 @@ namespace HybridCLR.Editor.Installer
|
||||||
{
|
{
|
||||||
private InstallerController _controller;
|
private InstallerController _controller;
|
||||||
|
|
||||||
|
private bool _installFromDir;
|
||||||
|
|
||||||
|
private string _installLibil2cppWithHybridclrSourceDir;
|
||||||
|
|
||||||
private void OnEnable()
|
private void OnEnable()
|
||||||
{
|
{
|
||||||
_controller = new InstallerController();
|
_controller = new InstallerController();
|
||||||
|
|
@ -25,7 +30,7 @@ namespace HybridCLR.Editor.Installer
|
||||||
height = 24
|
height = 24
|
||||||
};
|
};
|
||||||
var content = EditorGUIUtility.IconContent("Settings");
|
var content = EditorGUIUtility.IconContent("Settings");
|
||||||
content.tooltip = "点击打开HybridCLR Settings";
|
content.tooltip = "HybridCLR Settings";
|
||||||
if (GUI.Button(rect, content, GUI.skin.GetStyle("IconButton")))
|
if (GUI.Button(rect, content, GUI.skin.GetStyle("IconButton")))
|
||||||
{
|
{
|
||||||
SettingsService.OpenProjectSettings("Project/HybridCLR Settings");
|
SettingsService.OpenProjectSettings("Project/HybridCLR Settings");
|
||||||
|
|
@ -36,50 +41,73 @@ namespace HybridCLR.Editor.Installer
|
||||||
GUILayout.Space(10f);
|
GUILayout.Space(10f);
|
||||||
|
|
||||||
EditorGUILayout.BeginVertical("box");
|
EditorGUILayout.BeginVertical("box");
|
||||||
EditorGUILayout.LabelField($"安装状态:{(hasInstall ? "已安装" : "未安装")}", EditorStyles.boldLabel);
|
EditorGUILayout.LabelField($"Installed: {hasInstall}", EditorStyles.boldLabel);
|
||||||
GUILayout.Space(10f);
|
GUILayout.Space(10f);
|
||||||
|
|
||||||
EditorGUILayout.LabelField($"HybridCLR 版本: {_controller.HybridclrLocalVersion}");
|
EditorGUILayout.LabelField($"Package Version: v{_controller.PackageVersion}");
|
||||||
GUILayout.Space(5f);
|
GUILayout.Space(5f);
|
||||||
EditorGUILayout.LabelField($"il2cpp_plus 版本: {_controller.Il2cppPlusLocalVersion}");
|
EditorGUILayout.LabelField($"Installed Version: v{_controller.InstalledLibil2cppVersion ?? " Unknown"}");
|
||||||
GUILayout.Space(5f);
|
GUILayout.Space(5f);
|
||||||
//GUIInstallButton("检查更新", "检查", UpdateHybridCLR);
|
|
||||||
//GUILayout.Space(40f);
|
|
||||||
|
|
||||||
GUILayout.Space(10f);
|
GUILayout.Space(10f);
|
||||||
|
|
||||||
|
InstallerController.CompatibleType compatibleType = _controller.GetCompatibleType();
|
||||||
//EditorGUILayout.BeginHorizontal();
|
if (compatibleType != InstallerController.CompatibleType.Incompatible)
|
||||||
//EditorGUILayout.LabelField("待安装的 hybridclr 仓库版本号(或branch或tag)(默认取最新版本):", GUILayout.MaxWidth(400));
|
|
||||||
//_hybridclrVersion = EditorGUILayout.TextField(_hybridclrVersion);
|
|
||||||
//EditorGUILayout.EndHorizontal();
|
|
||||||
|
|
||||||
//EditorGUILayout.BeginHorizontal();
|
|
||||||
//EditorGUILayout.LabelField($"待安装的 il2cpp_plus 仓库版本号(或branch或tag)(默认取{_controller.MajorVersion}-main分支最新版本):", GUILayout.MaxWidth(400));
|
|
||||||
//_il2cppPlusVersion = EditorGUILayout.TextField(_il2cppPlusVersion);
|
|
||||||
//EditorGUILayout.EndHorizontal();
|
|
||||||
|
|
||||||
|
|
||||||
GUIInstallButton("安装hybridclr+il2cpp_plus代码到本地目录", "安装");
|
|
||||||
EditorGUILayout.EndVertical();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GUIInstallButton(string content, string button)
|
|
||||||
{
|
|
||||||
EditorGUILayout.BeginHorizontal();
|
|
||||||
EditorGUILayout.LabelField(content);
|
|
||||||
if (GUILayout.Button(button, GUILayout.Width(100)))
|
|
||||||
{
|
{
|
||||||
InstallLocalHybridCLR();
|
if (compatibleType == InstallerController.CompatibleType.MaybeIncompatible)
|
||||||
GUIUtility.ExitGUI();
|
{
|
||||||
}
|
EditorGUILayout.HelpBox($"Maybe incompatible with current version, recommend minimum compatible version:{_controller.GetCurrentUnityVersionMinCompatibleVersionStr()}", MessageType.Warning);
|
||||||
EditorGUILayout.EndHorizontal();
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
_installFromDir = EditorGUILayout.Toggle("Copy libil2cpp from local", _installFromDir, GUILayout.MinWidth(100));
|
||||||
|
EditorGUI.BeginDisabledGroup(!_installFromDir);
|
||||||
|
EditorGUILayout.TextField(_installLibil2cppWithHybridclrSourceDir, GUILayout.Width(400));
|
||||||
|
if (GUILayout.Button("Choose", GUILayout.Width(100)))
|
||||||
|
{
|
||||||
|
_installLibil2cppWithHybridclrSourceDir = EditorUtility.OpenFolderPanel("Select libil2cpp", Application.dataPath, "libil2cpp");
|
||||||
|
}
|
||||||
|
EditorGUI.EndDisabledGroup();
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
GUILayout.Space(20f);
|
||||||
|
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
if (GUILayout.Button("Install", GUILayout.Width(100)))
|
||||||
|
{
|
||||||
|
InstallLocalHybridCLR();
|
||||||
|
GUIUtility.ExitGUI();
|
||||||
|
}
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox($"Incompatible with current version, minimum compatible version:{_controller.GetCurrentUnityVersionMinCompatibleVersionStr()}", MessageType.Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.EndVertical();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InstallLocalHybridCLR()
|
private void InstallLocalHybridCLR()
|
||||||
{
|
{
|
||||||
_controller.InstallDefaultHybridCLR();
|
if (_installFromDir)
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(_installLibil2cppWithHybridclrSourceDir))
|
||||||
|
{
|
||||||
|
Debug.LogError($"Source libil2cpp:'{_installLibil2cppWithHybridclrSourceDir}' doesn't exist.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!File.Exists($"{_installLibil2cppWithHybridclrSourceDir}/il2cpp-config.h") || !File.Exists($"{_installLibil2cppWithHybridclrSourceDir}/hybridclr/RuntimeApi.cpp"))
|
||||||
|
{
|
||||||
|
Debug.LogError($"Source libil2cpp:' {_installLibil2cppWithHybridclrSourceDir} ' is invalid");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_controller.InstallFromLocal(_installLibil2cppWithHybridclrSourceDir);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_controller.InstallDefaultHybridCLR();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ using System.Threading.Tasks;
|
||||||
using dnlib.DotNet;
|
using dnlib.DotNet;
|
||||||
using HybridCLR.Editor.Meta;
|
using HybridCLR.Editor.Meta;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
using IAssemblyResolver = HybridCLR.Editor.Meta.IAssemblyResolver;
|
using IAssemblyResolver = HybridCLR.Editor.Meta.IAssemblyResolver;
|
||||||
|
|
||||||
namespace HybridCLR.Editor.Link
|
namespace HybridCLR.Editor.Link
|
||||||
|
|
@ -22,26 +23,27 @@ namespace HybridCLR.Editor.Link
|
||||||
|
|
||||||
public HashSet<TypeRef> CollectRefs(List<string> rootAssemblies)
|
public HashSet<TypeRef> CollectRefs(List<string> rootAssemblies)
|
||||||
{
|
{
|
||||||
using (var assCollector = new AssemblyCache(_resolver))
|
var assCollector = new AssemblyCache(_resolver);
|
||||||
{
|
var rootAssemblyNames = new HashSet<string>(rootAssemblies);
|
||||||
var rootAssemblyNames = new HashSet<string>(rootAssemblies);
|
|
||||||
|
|
||||||
var typeRefs = new HashSet<TypeRef>(TypeEqualityComparer.Instance);
|
var typeRefs = new HashSet<TypeRef>(TypeEqualityComparer.Instance);
|
||||||
foreach (var rootAss in rootAssemblies)
|
foreach (var rootAss in rootAssemblies)
|
||||||
|
{
|
||||||
|
var dnAss = assCollector.LoadModule(rootAss, false);
|
||||||
|
foreach (var type in dnAss.GetTypeRefs())
|
||||||
{
|
{
|
||||||
var dnAss = assCollector.LoadModule(rootAss, false);
|
if (type.DefinitionAssembly == null)
|
||||||
foreach (var type in dnAss.GetTypeRefs())
|
|
||||||
{
|
{
|
||||||
if (!rootAssemblyNames.Contains(type.DefinitionAssembly.Name.ToString()))
|
Debug.LogWarning($"assembly:{dnAss.Name} TypeRef {type.FullName} has no DefinitionAssembly");
|
||||||
{
|
continue;
|
||||||
typeRefs.Add(type);
|
}
|
||||||
}
|
if (!rootAssemblyNames.Contains(type.DefinitionAssembly.Name.ToString()))
|
||||||
|
{
|
||||||
|
typeRefs.Add(type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assCollector.Dispose();
|
|
||||||
return typeRefs;
|
|
||||||
}
|
}
|
||||||
|
return typeRefs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace HybridCLR.Editor.Link
|
namespace HybridCLR.Editor.Link
|
||||||
{
|
{
|
||||||
internal class LinkXmlWriter
|
public class LinkXmlWriter
|
||||||
{
|
{
|
||||||
public void Write(string outputLinkXmlFile, HashSet<TypeRef> refTypes)
|
public void Write(string outputLinkXmlFile, HashSet<TypeRef> refTypes)
|
||||||
{
|
{
|
||||||
|
|
@ -22,18 +22,24 @@ namespace HybridCLR.Editor.Link
|
||||||
writer.WriteStartElement("linker");
|
writer.WriteStartElement("linker");
|
||||||
|
|
||||||
var typesByAssembly = refTypes.GroupBy(t => t.DefinitionAssembly.Name.String).ToList();
|
var typesByAssembly = refTypes.GroupBy(t => t.DefinitionAssembly.Name.String).ToList();
|
||||||
typesByAssembly.Sort((a, b) => a.Key.CompareTo(b.Key));
|
typesByAssembly.Sort((a, b) => String.Compare(a.Key, b.Key, StringComparison.Ordinal));
|
||||||
|
|
||||||
foreach(var assembly in typesByAssembly)
|
foreach(var assembly in typesByAssembly)
|
||||||
{
|
{
|
||||||
writer.WriteStartElement("assembly");
|
writer.WriteStartElement("assembly");
|
||||||
writer.WriteAttributeString("fullname", assembly.Key);
|
writer.WriteAttributeString("fullname", assembly.Key);
|
||||||
List<TypeRef> assTypes = assembly.ToList();
|
List<string> assTypeNames = assembly.Select(t => t.FullName).ToList();
|
||||||
assTypes.Sort((a, b) => a.FullName.CompareTo(b.FullName));
|
assTypeNames.Sort(string.CompareOrdinal);
|
||||||
foreach(var type in assTypes)
|
foreach(var typeName in assTypeNames)
|
||||||
{
|
{
|
||||||
|
#if UNITY_2023_1_OR_NEWER
|
||||||
|
if (typeName == "UnityEngine.Debug")
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
writer.WriteStartElement("type");
|
writer.WriteStartElement("type");
|
||||||
writer.WriteAttributeString("fullname", type.FullName);
|
writer.WriteAttributeString("fullname", typeName);
|
||||||
writer.WriteAttributeString("preserve", "all");
|
writer.WriteAttributeString("preserve", "all");
|
||||||
writer.WriteEndElement();
|
writer.WriteEndElement();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,73 +9,12 @@ using UnityEngine;
|
||||||
|
|
||||||
namespace HybridCLR.Editor.Meta
|
namespace HybridCLR.Editor.Meta
|
||||||
{
|
{
|
||||||
public class AssemblyCache : IDisposable
|
public class AssemblyCache : AssemblyCacheBase
|
||||||
{
|
{
|
||||||
private readonly IAssemblyResolver _assemblyPathResolver;
|
|
||||||
private readonly ModuleContext _modCtx;
|
|
||||||
private readonly AssemblyResolver _asmResolver;
|
|
||||||
private bool disposedValue;
|
|
||||||
|
|
||||||
public Dictionary<string, ModuleDefMD> LoadedModules { get; } = new Dictionary<string, ModuleDefMD>();
|
public AssemblyCache(IAssemblyResolver assemblyResolver) : base(assemblyResolver)
|
||||||
|
|
||||||
public AssemblyCache(IAssemblyResolver assemblyResolver)
|
|
||||||
{
|
{
|
||||||
_assemblyPathResolver = assemblyResolver;
|
|
||||||
_modCtx = ModuleDef.CreateModuleContext();
|
|
||||||
_asmResolver = (AssemblyResolver)_modCtx.AssemblyResolver;
|
|
||||||
_asmResolver.EnableTypeDefCache = true;
|
|
||||||
_asmResolver.UseGAC = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ModuleDefMD LoadModule(string moduleName, bool loadReferenceAssemblies = true)
|
|
||||||
{
|
|
||||||
// Debug.Log($"load module:{moduleName}");
|
|
||||||
if (LoadedModules.TryGetValue(moduleName, out var mod))
|
|
||||||
{
|
|
||||||
return mod;
|
|
||||||
}
|
|
||||||
mod = DoLoadModule(_assemblyPathResolver.ResolveAssembly(moduleName, true));
|
|
||||||
LoadedModules.Add(moduleName, mod);
|
|
||||||
|
|
||||||
if (loadReferenceAssemblies)
|
|
||||||
{
|
|
||||||
foreach (var refAsm in mod.GetAssemblyRefs())
|
|
||||||
{
|
|
||||||
LoadModule(refAsm.Name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return mod;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ModuleDefMD DoLoadModule(string dllPath)
|
|
||||||
{
|
|
||||||
//Debug.Log($"do load module:{dllPath}");
|
|
||||||
ModuleDefMD mod = ModuleDefMD.Load(dllPath, _modCtx);
|
|
||||||
_asmResolver.AddToCache(mod);
|
|
||||||
return mod;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (!disposedValue)
|
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
foreach(var mod in LoadedModules.Values)
|
|
||||||
{
|
|
||||||
mod.Dispose();
|
|
||||||
}
|
|
||||||
LoadedModules.Clear();
|
|
||||||
}
|
|
||||||
disposedValue = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Dispose(disposing: true);
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
using dnlib.DotNet;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace HybridCLR.Editor.Meta
|
||||||
|
{
|
||||||
|
public abstract class AssemblyCacheBase
|
||||||
|
{
|
||||||
|
private readonly IAssemblyResolver _assemblyPathResolver;
|
||||||
|
private readonly ModuleContext _modCtx;
|
||||||
|
private readonly AssemblyResolver _asmResolver;
|
||||||
|
private bool _loadedNetstandard;
|
||||||
|
|
||||||
|
|
||||||
|
public ModuleContext ModCtx => _modCtx;
|
||||||
|
|
||||||
|
public Dictionary<string, ModuleDefMD> LoadedModules { get; } = new Dictionary<string, ModuleDefMD>();
|
||||||
|
|
||||||
|
private readonly List<ModuleDefMD> _loadedModulesIncludeNetstandard = new List<ModuleDefMD>();
|
||||||
|
|
||||||
|
protected AssemblyCacheBase(IAssemblyResolver assemblyResolver)
|
||||||
|
{
|
||||||
|
_assemblyPathResolver = assemblyResolver;
|
||||||
|
_modCtx = ModuleDef.CreateModuleContext();
|
||||||
|
_asmResolver = (AssemblyResolver)_modCtx.AssemblyResolver;
|
||||||
|
_asmResolver.EnableTypeDefCache = true;
|
||||||
|
_asmResolver.UseGAC = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ModuleDefMD TryLoadModule(string moduleName, bool loadReferenceAssemblies = true)
|
||||||
|
{
|
||||||
|
string dllPath = _assemblyPathResolver.ResolveAssembly(moduleName, false);
|
||||||
|
if (string.IsNullOrEmpty(dllPath))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return LoadModule(moduleName, loadReferenceAssemblies);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModuleDefMD LoadModule(string moduleName, bool loadReferenceAssemblies = true)
|
||||||
|
{
|
||||||
|
// Debug.Log($"load module:{moduleName}");
|
||||||
|
if (LoadedModules.TryGetValue(moduleName, out var mod))
|
||||||
|
{
|
||||||
|
return mod;
|
||||||
|
}
|
||||||
|
if (moduleName == "netstandard")
|
||||||
|
{
|
||||||
|
if (!_loadedNetstandard)
|
||||||
|
{
|
||||||
|
LoadNetStandard();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
mod = DoLoadModule(_assemblyPathResolver.ResolveAssembly(moduleName, true));
|
||||||
|
LoadedModules.Add(moduleName, mod);
|
||||||
|
|
||||||
|
if (loadReferenceAssemblies)
|
||||||
|
{
|
||||||
|
foreach (var refAsm in mod.GetAssemblyRefs())
|
||||||
|
{
|
||||||
|
LoadModule(refAsm.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mod;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadNetStandard()
|
||||||
|
{
|
||||||
|
string netstandardDllPath = _assemblyPathResolver.ResolveAssembly("netstandard", false);
|
||||||
|
if (!string.IsNullOrEmpty(netstandardDllPath))
|
||||||
|
{
|
||||||
|
DoLoadModule(netstandardDllPath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DoLoadModule(MetaUtil.ResolveNetStandardAssemblyPath("netstandard2.0"));
|
||||||
|
DoLoadModule(MetaUtil.ResolveNetStandardAssemblyPath("netstandard2.1"));
|
||||||
|
}
|
||||||
|
_loadedNetstandard = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ModuleDefMD DoLoadModule(string dllPath)
|
||||||
|
{
|
||||||
|
//Debug.Log($"do load module:{dllPath}");
|
||||||
|
ModuleDefMD mod = ModuleDefMD.Load(File.ReadAllBytes(dllPath), _modCtx);
|
||||||
|
mod.EnableTypeDefFindCache = true;
|
||||||
|
_asmResolver.AddToCache(mod);
|
||||||
|
_loadedModulesIncludeNetstandard.Add(mod);
|
||||||
|
return mod;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3b01fa99119e72141bfee5628c0ffce1
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -9,17 +9,10 @@ using UnityEngine;
|
||||||
|
|
||||||
namespace HybridCLR.Editor.Meta
|
namespace HybridCLR.Editor.Meta
|
||||||
{
|
{
|
||||||
public class AssemblyReferenceDeepCollector : IDisposable
|
public class AssemblyReferenceDeepCollector : AssemblyCacheBase
|
||||||
{
|
{
|
||||||
private readonly IAssemblyResolver _assemblyPathResolver;
|
|
||||||
private readonly List<string> _rootAssemblies;
|
private readonly List<string> _rootAssemblies;
|
||||||
|
|
||||||
private readonly ModuleContext _modCtx;
|
|
||||||
private readonly AssemblyResolver _asmResolver;
|
|
||||||
private bool disposedValue;
|
|
||||||
|
|
||||||
public Dictionary<string, ModuleDefMD> LoadedModules { get; } = new Dictionary<string, ModuleDefMD>();
|
|
||||||
|
|
||||||
public IReadOnlyList<string> GetRootAssemblyNames()
|
public IReadOnlyList<string> GetRootAssemblyNames()
|
||||||
{
|
{
|
||||||
return _rootAssemblies;
|
return _rootAssemblies;
|
||||||
|
|
@ -30,19 +23,19 @@ namespace HybridCLR.Editor.Meta
|
||||||
return LoadedModules.Where(e => !_rootAssemblies.Contains(e.Key)).Select(e => e.Value).ToList();
|
return LoadedModules.Where(e => !_rootAssemblies.Contains(e.Key)).Select(e => e.Value).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<ModuleDefMD> GetLoadedModules()
|
||||||
|
{
|
||||||
|
return LoadedModules.Select(e => e.Value).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
public List<ModuleDefMD> GetLoadedModulesOfRootAssemblies()
|
public List<ModuleDefMD> GetLoadedModulesOfRootAssemblies()
|
||||||
{
|
{
|
||||||
return _rootAssemblies.Select(ass => LoadedModules[ass]).ToList();
|
return _rootAssemblies.Select(ass => LoadedModules[ass]).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public AssemblyReferenceDeepCollector(IAssemblyResolver assemblyResolver, List<string> rootAssemblies)
|
public AssemblyReferenceDeepCollector(IAssemblyResolver assemblyResolver, List<string> rootAssemblies) : base(assemblyResolver)
|
||||||
{
|
{
|
||||||
_assemblyPathResolver = assemblyResolver;
|
|
||||||
_rootAssemblies = rootAssemblies;
|
_rootAssemblies = rootAssemblies;
|
||||||
_modCtx = ModuleDef.CreateModuleContext();
|
|
||||||
_asmResolver = (AssemblyResolver)_modCtx.AssemblyResolver;
|
|
||||||
_asmResolver.EnableTypeDefCache = true;
|
|
||||||
_asmResolver.UseGAC = false;
|
|
||||||
LoadAllAssembiles();
|
LoadAllAssembiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -53,52 +46,5 @@ namespace HybridCLR.Editor.Meta
|
||||||
LoadModule(asm);
|
LoadModule(asm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ModuleDefMD LoadModule(string moduleName)
|
|
||||||
{
|
|
||||||
// Debug.Log($"load module:{moduleName}");
|
|
||||||
if (LoadedModules.TryGetValue(moduleName, out var mod))
|
|
||||||
{
|
|
||||||
return mod;
|
|
||||||
}
|
|
||||||
mod = DoLoadModule(_assemblyPathResolver.ResolveAssembly(moduleName, true));
|
|
||||||
LoadedModules.Add(moduleName, mod);
|
|
||||||
|
|
||||||
foreach (var refAsm in mod.GetAssemblyRefs())
|
|
||||||
{
|
|
||||||
LoadModule(refAsm.Name);
|
|
||||||
}
|
|
||||||
return mod;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ModuleDefMD DoLoadModule(string dllPath)
|
|
||||||
{
|
|
||||||
//Debug.Log($"do load module:{dllPath}");
|
|
||||||
ModuleDefMD mod = ModuleDefMD.Load(dllPath, _modCtx);
|
|
||||||
_asmResolver.AddToCache(mod);
|
|
||||||
return mod;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (!disposedValue)
|
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
foreach(var mod in LoadedModules.Values)
|
|
||||||
{
|
|
||||||
mod.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LoadedModules.Clear();
|
|
||||||
disposedValue = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Dispose(disposing: true);
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,14 @@ namespace HybridCLR.Editor.Meta
|
||||||
}
|
}
|
||||||
if (throwExIfNotFind)
|
if (throwExIfNotFind)
|
||||||
{
|
{
|
||||||
#if UNITY_2021_1_OR_NEWER && UNITY_IOS
|
if (SettingsUtil.HotUpdateAssemblyNamesIncludePreserved.Contains(assemblyName))
|
||||||
throw new Exception($"resolve assembly:{assemblyName} 失败! 请按照Install文档正确替换了UnityEditor.CoreModule.dll或者升级hybridclr_unity到2.0.1及更高版本");
|
{
|
||||||
#else
|
throw new Exception($"resolve Hot update dll:{assemblyName} failed! Please make sure that this hot update dll exists or the search path is configured in the external hot update path.");
|
||||||
throw new Exception($"resolve assembly:{assemblyName} 失败! 请参阅常见错误文档");
|
}
|
||||||
#endif
|
else
|
||||||
|
{
|
||||||
|
throw new Exception($"resolve AOT dll:{assemblyName} failed! Please make sure that the AOT project has referenced the dll and generated the trimmed AOT dll correctly.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,105 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace HybridCLR.Editor.Meta
|
||||||
|
{
|
||||||
|
|
||||||
|
public class AssemblySorter
|
||||||
|
{
|
||||||
|
class Node
|
||||||
|
{
|
||||||
|
public string Name;
|
||||||
|
public List<Node> Dependencies = new List<Node>();
|
||||||
|
|
||||||
|
public Node(string name)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TopologicalSorter
|
||||||
|
{
|
||||||
|
|
||||||
|
public static List<Node> Sort(List<Node> nodes)
|
||||||
|
{
|
||||||
|
List<Node> sorted = new List<Node>();
|
||||||
|
HashSet<Node> visited = new HashSet<Node>();
|
||||||
|
HashSet<Node> tempMarks = new HashSet<Node>();
|
||||||
|
|
||||||
|
foreach (var node in nodes)
|
||||||
|
{
|
||||||
|
if (!visited.Contains(node))
|
||||||
|
{
|
||||||
|
Visit(node, visited, tempMarks, sorted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sorted;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Visit(Node node, HashSet<Node> visited, HashSet<Node> tempMarks, List<Node> sorted)
|
||||||
|
{
|
||||||
|
if (tempMarks.Contains(node))
|
||||||
|
{
|
||||||
|
throw new Exception("Detected cyclic dependency!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!visited.Contains(node))
|
||||||
|
{
|
||||||
|
tempMarks.Add(node);
|
||||||
|
foreach (var dependency in node.Dependencies)
|
||||||
|
{
|
||||||
|
Visit(dependency, visited, tempMarks, sorted);
|
||||||
|
}
|
||||||
|
tempMarks.Remove(node);
|
||||||
|
visited.Add(node);
|
||||||
|
sorted.Add(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<string> SortAssemblyByReferenceOrder(IEnumerable<string> assemblies, Dictionary<string, HashSet<string>> refs)
|
||||||
|
{
|
||||||
|
var nodes = new List<Node>();
|
||||||
|
var nodeMap = new Dictionary<string, Node>();
|
||||||
|
foreach (var assembly in assemblies)
|
||||||
|
{
|
||||||
|
var node = new Node(assembly);
|
||||||
|
nodes.Add(node);
|
||||||
|
nodeMap.Add(assembly, node);
|
||||||
|
}
|
||||||
|
foreach (var assembly in assemblies)
|
||||||
|
{
|
||||||
|
var node = nodeMap[assembly];
|
||||||
|
foreach (var refAssembly in refs[assembly])
|
||||||
|
{
|
||||||
|
node.Dependencies.Add(nodeMap[refAssembly]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var sortedNodes = TopologicalSorter.Sort(nodes);
|
||||||
|
return sortedNodes.Select(node => node.Name).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<string> SortAssemblyByReferenceOrder(IEnumerable<string> assemblies, IAssemblyResolver assemblyResolver)
|
||||||
|
{
|
||||||
|
var assCache = new AssemblyCache(assemblyResolver);
|
||||||
|
var assRefAssemblies = new Dictionary<string, HashSet<string>>();
|
||||||
|
foreach (var assName in assemblies)
|
||||||
|
{
|
||||||
|
var refAssemblies = new HashSet<string>();
|
||||||
|
var mod = assCache.LoadModule(assName, false);
|
||||||
|
foreach (var refAss in mod.GetAssemblyRefs())
|
||||||
|
{
|
||||||
|
if (assemblies.Contains(refAss.Name.ToString()))
|
||||||
|
{
|
||||||
|
refAssemblies.Add(refAss.Name.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assRefAssemblies.Add(assName, refAssemblies);
|
||||||
|
}
|
||||||
|
return SortAssemblyByReferenceOrder(assemblies, assRefAssemblies);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b9b8eb45398fa344daa8c6e9b9fbf291
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -29,6 +29,12 @@ namespace HybridCLR.Editor.Meta
|
||||||
Debug.Log($"[FixedSetAssemblyResolver] resolve:{assemblyName} path:{assemblyPath}");
|
Debug.Log($"[FixedSetAssemblyResolver] resolve:{assemblyName} path:{assemblyPath}");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
assemblyPath = $"{_rootDir}/{assemblyName}.dll.bytes";
|
||||||
|
if (File.Exists(assemblyPath))
|
||||||
|
{
|
||||||
|
Debug.Log($"[FixedSetAssemblyResolver] resolve:{assemblyName} path:{assemblyPath}");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
assemblyPath = null;
|
assemblyPath = null;
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,11 @@ using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace HybridCLR.Editor.Meta
|
namespace HybridCLR.Editor.Meta
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Replaces generic type/method var with its generic argument
|
public class GenericArgumentContext
|
||||||
/// </summary>
|
|
||||||
public sealed class GenericArgumentContext
|
|
||||||
{
|
{
|
||||||
List<TypeSig> typeArgsStack = new List<TypeSig>();
|
private readonly List<TypeSig> typeArgsStack;
|
||||||
List<TypeSig> methodArgsStack = new List<TypeSig>();
|
private readonly List<TypeSig> methodArgsStack;
|
||||||
|
|
||||||
public GenericArgumentContext(List<TypeSig> typeArgsStack, List<TypeSig> methodArgsStack)
|
public GenericArgumentContext(List<TypeSig> typeArgsStack, List<TypeSig> methodArgsStack)
|
||||||
{
|
{
|
||||||
|
|
@ -21,16 +19,6 @@ namespace HybridCLR.Editor.Meta
|
||||||
this.methodArgsStack = methodArgsStack;
|
this.methodArgsStack = methodArgsStack;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Replaces a generic type/method var with its generic argument (if any). If
|
|
||||||
/// <paramref name="typeSig"/> isn't a generic type/method var or if it can't
|
|
||||||
/// be resolved, it itself is returned. Else the resolved type is returned.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="typeSig">Type signature</param>
|
|
||||||
/// <returns>New <see cref="TypeSig"/> which is never <c>null</c> unless
|
|
||||||
/// <paramref name="typeSig"/> is <c>null</c></returns>
|
|
||||||
public TypeSig Resolve(TypeSig typeSig)
|
public TypeSig Resolve(TypeSig typeSig)
|
||||||
{
|
{
|
||||||
if (!typeSig.ContainsGenericParameter)
|
if (!typeSig.ContainsGenericParameter)
|
||||||
|
|
@ -41,9 +29,9 @@ namespace HybridCLR.Editor.Meta
|
||||||
switch (typeSig.ElementType)
|
switch (typeSig.ElementType)
|
||||||
{
|
{
|
||||||
case ElementType.Ptr: return new PtrSig(Resolve(typeSig.Next));
|
case ElementType.Ptr: return new PtrSig(Resolve(typeSig.Next));
|
||||||
case ElementType.ByRef: return new PtrSig(Resolve(typeSig.Next));
|
case ElementType.ByRef: return new ByRefSig(Resolve(typeSig.Next));
|
||||||
|
|
||||||
case ElementType.SZArray: return new PtrSig(Resolve(typeSig.Next));
|
case ElementType.SZArray: return new SZArraySig(Resolve(typeSig.Next));
|
||||||
case ElementType.Array:
|
case ElementType.Array:
|
||||||
{
|
{
|
||||||
var ara = (ArraySig)typeSig;
|
var ara = (ArraySig)typeSig;
|
||||||
|
|
@ -53,7 +41,7 @@ namespace HybridCLR.Editor.Meta
|
||||||
case ElementType.Var:
|
case ElementType.Var:
|
||||||
{
|
{
|
||||||
GenericVar genericVar = (GenericVar)typeSig;
|
GenericVar genericVar = (GenericVar)typeSig;
|
||||||
var newSig = Resolve(typeArgsStack, genericVar.Number, true);
|
var newSig = Resolve(typeArgsStack, genericVar.Number);
|
||||||
if (newSig == null)
|
if (newSig == null)
|
||||||
{
|
{
|
||||||
throw new Exception();
|
throw new Exception();
|
||||||
|
|
@ -64,7 +52,7 @@ namespace HybridCLR.Editor.Meta
|
||||||
case ElementType.MVar:
|
case ElementType.MVar:
|
||||||
{
|
{
|
||||||
GenericMVar genericVar = (GenericMVar)typeSig;
|
GenericMVar genericVar = (GenericMVar)typeSig;
|
||||||
var newSig = Resolve(methodArgsStack, genericVar.Number, true);
|
var newSig = Resolve(methodArgsStack, genericVar.Number);
|
||||||
if (newSig == null)
|
if (newSig == null)
|
||||||
{
|
{
|
||||||
throw new Exception();
|
throw new Exception();
|
||||||
|
|
@ -79,7 +67,29 @@ namespace HybridCLR.Editor.Meta
|
||||||
|
|
||||||
case ElementType.FnPtr:
|
case ElementType.FnPtr:
|
||||||
{
|
{
|
||||||
throw new NotSupportedException(typeSig.ToString());
|
var fptr = (FnPtrSig)typeSig;
|
||||||
|
var cs = fptr.Signature;
|
||||||
|
CallingConventionSig ccs;
|
||||||
|
switch (cs)
|
||||||
|
{
|
||||||
|
case MethodSig ms:
|
||||||
|
{
|
||||||
|
ccs = new MethodSig(ms.GetCallingConvention(), ms.GenParamCount, Resolve(ms.RetType), ms.Params.Select(p => Resolve(p)).ToList());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PropertySig ps:
|
||||||
|
{
|
||||||
|
ccs = new PropertySig(ps.HasThis, Resolve(ps.RetType));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GenericInstMethodSig gims:
|
||||||
|
{
|
||||||
|
ccs = new GenericInstMethodSig(gims.GenericArguments.Select(ga => Resolve(ga)).ToArray());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: throw new NotSupportedException(cs.ToString());
|
||||||
|
}
|
||||||
|
return new FnPtrSig(ccs);
|
||||||
}
|
}
|
||||||
|
|
||||||
case ElementType.ValueArray:
|
case ElementType.ValueArray:
|
||||||
|
|
@ -91,13 +101,9 @@ namespace HybridCLR.Editor.Meta
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private TypeSig Resolve(List<TypeSig> args, uint number, bool isTypeVar)
|
private TypeSig Resolve(List<TypeSig> args, uint number)
|
||||||
{
|
{
|
||||||
var typeSig = args[(int)number];
|
return args[(int)number];
|
||||||
var gvar = typeSig as GenericSig;
|
|
||||||
if (gvar is null || gvar.IsTypeVar != isTypeVar)
|
|
||||||
return typeSig;
|
|
||||||
return gvar;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ namespace HybridCLR.Editor.Meta
|
||||||
|
|
||||||
public GenericClass ToGenericShare()
|
public GenericClass ToGenericShare()
|
||||||
{
|
{
|
||||||
return new GenericClass(Type, MetaUtil.ToShareTypeSigs(KlassInst));
|
return new GenericClass(Type, MetaUtil.ToShareTypeSigs(Type.Module.CorLibTypes, KlassInst));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public override bool Equals(object obj)
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,8 @@ namespace HybridCLR.Editor.Meta
|
||||||
|
|
||||||
public GenericMethod ToGenericShare()
|
public GenericMethod ToGenericShare()
|
||||||
{
|
{
|
||||||
return new GenericMethod(Method, MetaUtil.ToShareTypeSigs(KlassInst), MetaUtil.ToShareTypeSigs(MethodInst));
|
ICorLibTypes corLibTypes = Method.Module.CorLibTypes;
|
||||||
|
return new GenericMethod(Method, MetaUtil.ToShareTypeSigs(corLibTypes, KlassInst), MetaUtil.ToShareTypeSigs(corLibTypes, MethodInst));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public override bool Equals(object obj)
|
||||||
|
|
@ -93,7 +94,7 @@ namespace HybridCLR.Editor.Meta
|
||||||
methodDef = method.ResolveMethodDef();
|
methodDef = method.ResolveMethodDef();
|
||||||
if (methodDef == null)
|
if (methodDef == null)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"method:{method} ResolveMethodDef() == null");
|
//Debug.LogWarning($"method:{method} ResolveMethodDef() == null");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (method is MethodSpec methodSpec)
|
if (method is MethodSpec methodSpec)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
using dnlib.DotNet;
|
using dnlib.DotNet;
|
||||||
using HybridCLR.Editor.Meta;
|
using HybridCLR.Editor.Meta;
|
||||||
|
using HybridCLR.Editor.Settings;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
@ -59,13 +60,8 @@ namespace HybridCLR.Editor.Meta
|
||||||
return ctx.Resolve(sig);
|
return ctx.Resolve(sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TypeSig ToShareTypeSig(TypeSig typeSig)
|
public static TypeSig ToShareTypeSig(ICorLibTypes corTypes, TypeSig typeSig)
|
||||||
{
|
{
|
||||||
var corTypes = typeSig?.Module?.CorLibTypes;
|
|
||||||
if (corTypes == null)
|
|
||||||
{
|
|
||||||
return typeSig;
|
|
||||||
}
|
|
||||||
var a = typeSig.RemovePinnedAndModifiers();
|
var a = typeSig.RemovePinnedAndModifiers();
|
||||||
switch (a.ElementType)
|
switch (a.ElementType)
|
||||||
{
|
{
|
||||||
|
|
@ -88,22 +84,45 @@ namespace HybridCLR.Editor.Meta
|
||||||
case ElementType.U: return corTypes.UIntPtr;
|
case ElementType.U: return corTypes.UIntPtr;
|
||||||
case ElementType.Object: return corTypes.Object;
|
case ElementType.Object: return corTypes.Object;
|
||||||
case ElementType.Sentinel: return typeSig;
|
case ElementType.Sentinel: return typeSig;
|
||||||
case ElementType.Ptr: return corTypes.IntPtr;
|
case ElementType.Ptr: return corTypes.UIntPtr;
|
||||||
case ElementType.ByRef: return corTypes.IntPtr;
|
case ElementType.ByRef: return corTypes.UIntPtr;
|
||||||
case ElementType.SZArray: return corTypes.Object;
|
case ElementType.SZArray: return corTypes.Object;
|
||||||
case ElementType.Array: return corTypes.Object;
|
case ElementType.Array: return corTypes.Object;
|
||||||
case ElementType.ValueType: return typeSig;
|
case ElementType.ValueType:
|
||||||
|
{
|
||||||
|
TypeDef typeDef = a.ToTypeDefOrRef().ResolveTypeDef();
|
||||||
|
if (typeDef == null)
|
||||||
|
{
|
||||||
|
throw new Exception($"type:{a} definition could not be found");
|
||||||
|
}
|
||||||
|
if (typeDef.IsEnum)
|
||||||
|
{
|
||||||
|
return ToShareTypeSig(corTypes, typeDef.GetEnumUnderlyingType());
|
||||||
|
}
|
||||||
|
return typeSig;
|
||||||
|
}
|
||||||
|
case ElementType.Var:
|
||||||
|
case ElementType.MVar:
|
||||||
case ElementType.Class: return corTypes.Object;
|
case ElementType.Class: return corTypes.Object;
|
||||||
case ElementType.GenericInst:
|
case ElementType.GenericInst:
|
||||||
{
|
{
|
||||||
var gia = (GenericInstSig)a;
|
var gia = (GenericInstSig)a;
|
||||||
if (gia.GenericType.IsClassSig)
|
TypeDef typeDef = gia.GenericType.ToTypeDefOrRef().ResolveTypeDef();
|
||||||
{
|
if (typeDef == null)
|
||||||
return corTypes.Object;
|
{
|
||||||
}
|
throw new Exception($"type:{a} definition could not be found");
|
||||||
return new GenericInstSig(gia.GenericType, gia.GenericArguments.Select(ga => ToShareTypeSig(ga)).ToList());
|
}
|
||||||
|
if (typeDef.IsEnum)
|
||||||
|
{
|
||||||
|
return ToShareTypeSig(corTypes, typeDef.GetEnumUnderlyingType());
|
||||||
|
}
|
||||||
|
if (!typeDef.IsValueType)
|
||||||
|
{
|
||||||
|
return corTypes.Object;
|
||||||
|
}
|
||||||
|
return new GenericInstSig(gia.GenericType, gia.GenericArguments.Select(ga => ToShareTypeSig(corTypes, ga)).ToList());
|
||||||
}
|
}
|
||||||
case ElementType.FnPtr: return corTypes.IntPtr;
|
case ElementType.FnPtr: return corTypes.UIntPtr;
|
||||||
case ElementType.ValueArray: return typeSig;
|
case ElementType.ValueArray: return typeSig;
|
||||||
case ElementType.Module: return typeSig;
|
case ElementType.Module: return typeSig;
|
||||||
default:
|
default:
|
||||||
|
|
@ -111,13 +130,13 @@ namespace HybridCLR.Editor.Meta
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<TypeSig> ToShareTypeSigs(IList<TypeSig> typeSigs)
|
public static List<TypeSig> ToShareTypeSigs(ICorLibTypes corTypes, IList<TypeSig> typeSigs)
|
||||||
{
|
{
|
||||||
if (typeSigs == null)
|
if (typeSigs == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return typeSigs.Select(s => ToShareTypeSig(s)).ToList();
|
return typeSigs.Select(s => ToShareTypeSig(corTypes, s)).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IAssemblyResolver CreateHotUpdateAssemblyResolver(BuildTarget target, List<string> hotUpdateDlls)
|
public static IAssemblyResolver CreateHotUpdateAssemblyResolver(BuildTarget target, List<string> hotUpdateDlls)
|
||||||
|
|
@ -153,6 +172,46 @@ namespace HybridCLR.Editor.Meta
|
||||||
CreateHotUpdateAssemblyResolver(target, hotUpdateDlls),
|
CreateHotUpdateAssemblyResolver(target, hotUpdateDlls),
|
||||||
CreateAOTAssemblyResolver(target)
|
CreateAOTAssemblyResolver(target)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ResolveNetStandardAssemblyPath(string assemblyName)
|
||||||
|
{
|
||||||
|
return $"{SettingsUtil.HybridCLRDataPathInPackage}/NetStandard/{assemblyName}.dll";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static List<TypeSig> CreateDefaultGenericParams(ModuleDef module, int genericParamCount)
|
||||||
|
{
|
||||||
|
var methodGenericParams = new List<TypeSig>();
|
||||||
|
for (int i = 0; i < genericParamCount; i++)
|
||||||
|
{
|
||||||
|
methodGenericParams.Add(module.CorLibTypes.Object);
|
||||||
|
}
|
||||||
|
return methodGenericParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsSupportedPInvokeTypeSig(TypeSig typeSig)
|
||||||
|
{
|
||||||
|
typeSig = typeSig.RemovePinnedAndModifiers();
|
||||||
|
if (typeSig.IsByRef)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
switch (typeSig.ElementType)
|
||||||
|
{
|
||||||
|
case ElementType.SZArray:
|
||||||
|
case ElementType.Array:
|
||||||
|
//case ElementType.Class:
|
||||||
|
case ElementType.String:
|
||||||
|
//case ElementType.Object:
|
||||||
|
return false;
|
||||||
|
default: return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsSupportedPInvokeMethodSignature(MethodSig methodSig)
|
||||||
|
{
|
||||||
|
return IsSupportedPInvokeTypeSig(methodSig.RetType) && methodSig.Params.All(p => IsSupportedPInvokeTypeSig(p));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using dnlib.DotNet;
|
using dnlib.DotNet;
|
||||||
|
using HybridCLR.Editor.ABI;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
@ -10,26 +11,17 @@ namespace HybridCLR.Editor.Meta
|
||||||
{
|
{
|
||||||
public class MethodReferenceAnalyzer
|
public class MethodReferenceAnalyzer
|
||||||
{
|
{
|
||||||
private readonly Action<GenericMethod> _onNewMethod;
|
private readonly Action<MethodDef, List<TypeSig>, List<TypeSig>, GenericMethod> _onNewMethod;
|
||||||
|
|
||||||
private readonly ConcurrentDictionary<MethodDef, List<IMethod>> _methodEffectInsts = new ConcurrentDictionary<MethodDef, List<IMethod>>();
|
private readonly ConcurrentDictionary<MethodDef, List<IMethod>> _methodEffectInsts = new ConcurrentDictionary<MethodDef, List<IMethod>>();
|
||||||
|
|
||||||
public MethodReferenceAnalyzer(Action<GenericMethod> onNewMethod)
|
public MethodReferenceAnalyzer(Action<MethodDef, List<TypeSig>, List<TypeSig>, GenericMethod> onNewMethod)
|
||||||
{
|
{
|
||||||
_onNewMethod = onNewMethod;
|
_onNewMethod = onNewMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WalkMethod(MethodDef method, List<TypeSig> klassGenericInst, List<TypeSig> methodGenericInst)
|
public void WalkMethod(MethodDef method, List<TypeSig> klassGenericInst, List<TypeSig> methodGenericInst)
|
||||||
{
|
{
|
||||||
if (klassGenericInst != null || methodGenericInst != null)
|
|
||||||
{
|
|
||||||
//var typeSig = klassGenericInst != null ? new GenericInstSig(method.DeclaringType.ToTypeSig().ToClassOrValueTypeSig(), klassGenericInst) : method.DeclaringType?.ToTypeSig();
|
|
||||||
//Debug.Log($"== walk generic method {typeSig}::{method.Name} {method.MethodSig}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//Debug.Log($"== walk not geneeric method:{method}");
|
|
||||||
}
|
|
||||||
var ctx = new GenericArgumentContext(klassGenericInst, methodGenericInst);
|
var ctx = new GenericArgumentContext(klassGenericInst, methodGenericInst);
|
||||||
|
|
||||||
if (_methodEffectInsts.TryGetValue(method, out var effectInsts))
|
if (_methodEffectInsts.TryGetValue(method, out var effectInsts))
|
||||||
|
|
@ -37,7 +29,7 @@ namespace HybridCLR.Editor.Meta
|
||||||
foreach (var met in effectInsts)
|
foreach (var met in effectInsts)
|
||||||
{
|
{
|
||||||
var resolveMet = GenericMethod.ResolveMethod(met, ctx)?.ToGenericShare();
|
var resolveMet = GenericMethod.ResolveMethod(met, ctx)?.ToGenericShare();
|
||||||
_onNewMethod(resolveMet);
|
_onNewMethod(method, klassGenericInst, methodGenericInst, resolveMet);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -69,7 +61,7 @@ namespace HybridCLR.Editor.Meta
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
effectInsts.Add(met);
|
effectInsts.Add(met);
|
||||||
_onNewMethod(resolveMet);
|
_onNewMethod(method, klassGenericInst, methodGenericInst, resolveMet);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ITokenOperand token:
|
case ITokenOperand token:
|
||||||
|
|
|
||||||
|
|
@ -20,11 +20,16 @@ namespace HybridCLR.Editor.Meta
|
||||||
{
|
{
|
||||||
foreach(var path in _searchPaths)
|
foreach(var path in _searchPaths)
|
||||||
{
|
{
|
||||||
string assPath = Path.Combine(path, assemblyName + ".dll");
|
assemblyPath = Path.Combine(path, $"{assemblyName}.dll");
|
||||||
if (File.Exists(assPath))
|
if (File.Exists(assemblyPath))
|
||||||
{
|
{
|
||||||
Debug.Log($"resolve {assemblyName} at {assPath}");
|
Debug.Log($"resolve {assemblyName} at {assemblyPath}");
|
||||||
assemblyPath = assPath;
|
return true;
|
||||||
|
}
|
||||||
|
assemblyPath = Path.Combine(path, $"{assemblyName}.dll.bytes");
|
||||||
|
if (File.Exists(assemblyPath))
|
||||||
|
{
|
||||||
|
Debug.Log($"resolve {assemblyName} at {assemblyPath}");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using dnlib.DotNet;
|
using dnlib.DotNet;
|
||||||
|
using HybridCLR.Editor.ABI;
|
||||||
using HybridCLR.Editor.Meta;
|
using HybridCLR.Editor.Meta;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
@ -25,7 +26,6 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
private readonly object _lock = new object();
|
private readonly object _lock = new object();
|
||||||
|
|
||||||
private readonly List<TypeDef> _typeDefs = new List<TypeDef>();
|
private readonly List<TypeDef> _typeDefs = new List<TypeDef>();
|
||||||
private readonly List<MethodDef> _notGenericMethods = new List<MethodDef>();
|
|
||||||
|
|
||||||
private readonly HashSet<GenericClass> _genericTypes = new HashSet<GenericClass>();
|
private readonly HashSet<GenericClass> _genericTypes = new HashSet<GenericClass>();
|
||||||
private readonly HashSet<GenericMethod> _genericMethods = new HashSet<GenericMethod>();
|
private readonly HashSet<GenericMethod> _genericMethods = new HashSet<GenericMethod>();
|
||||||
|
|
@ -35,8 +35,6 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
|
|
||||||
public IReadOnlyList<TypeDef> TypeDefs => _typeDefs;
|
public IReadOnlyList<TypeDef> TypeDefs => _typeDefs;
|
||||||
|
|
||||||
public IReadOnlyList<MethodDef> NotGenericMethods => _notGenericMethods;
|
|
||||||
|
|
||||||
public IReadOnlyCollection<GenericClass> GenericTypes => _genericTypes;
|
public IReadOnlyCollection<GenericClass> GenericTypes => _genericTypes;
|
||||||
|
|
||||||
public IReadOnlyCollection<GenericMethod> GenericMethods => _genericMethods;
|
public IReadOnlyCollection<GenericMethod> GenericMethods => _genericMethods;
|
||||||
|
|
@ -59,7 +57,7 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
}
|
}
|
||||||
lock(_lock)
|
lock(_lock)
|
||||||
{
|
{
|
||||||
gc = gc.ToGenericShare();
|
gc = StandardizeClass(gc);
|
||||||
if (_genericTypes.Add(gc))
|
if (_genericTypes.Add(gc))
|
||||||
{
|
{
|
||||||
WalkType(gc);
|
WalkType(gc);
|
||||||
|
|
@ -67,10 +65,28 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnNewMethod(GenericMethod method)
|
private GenericClass StandardizeClass(GenericClass gc)
|
||||||
|
{
|
||||||
|
TypeDef typeDef = gc.Type;
|
||||||
|
ICorLibTypes corLibTypes = typeDef.Module.CorLibTypes;
|
||||||
|
List<TypeSig> klassGenericParams = gc.KlassInst != null ? MetaUtil.ToShareTypeSigs(corLibTypes, gc.KlassInst) : (typeDef.GenericParameters.Count > 0 ? MetaUtil.CreateDefaultGenericParams(typeDef.Module, typeDef.GenericParameters.Count) : null);
|
||||||
|
return new GenericClass(typeDef, klassGenericParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GenericMethod StandardizeMethod(GenericMethod gm)
|
||||||
|
{
|
||||||
|
TypeDef typeDef = gm.Method.DeclaringType;
|
||||||
|
ICorLibTypes corLibTypes = typeDef.Module.CorLibTypes;
|
||||||
|
List<TypeSig> klassGenericParams = gm.KlassInst != null ? MetaUtil.ToShareTypeSigs(corLibTypes, gm.KlassInst) : (typeDef.GenericParameters.Count > 0 ? MetaUtil.CreateDefaultGenericParams(typeDef.Module, typeDef.GenericParameters.Count) : null);
|
||||||
|
List<TypeSig> methodGenericParams = gm.MethodInst != null ? MetaUtil.ToShareTypeSigs(corLibTypes, gm.MethodInst) : (gm.Method.GenericParameters.Count > 0 ? MetaUtil.CreateDefaultGenericParams(typeDef.Module, gm.Method.GenericParameters.Count) : null);
|
||||||
|
return new GenericMethod(gm.Method, klassGenericParams, methodGenericParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnNewMethod(MethodDef methodDef, List<TypeSig> klassGenericInst, List<TypeSig> methodGenericInst, GenericMethod method)
|
||||||
{
|
{
|
||||||
lock(_lock)
|
lock(_lock)
|
||||||
{
|
{
|
||||||
|
method = StandardizeMethod(method);
|
||||||
if (_genericMethods.Add(method))
|
if (_genericMethods.Add(method))
|
||||||
{
|
{
|
||||||
_newMethods.Add(method);
|
_newMethods.Add(method);
|
||||||
|
|
@ -94,11 +110,7 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
}
|
}
|
||||||
foreach (var method in gc.Type.Methods)
|
foreach (var method in gc.Type.Methods)
|
||||||
{
|
{
|
||||||
if (method.HasGenericParameters)
|
var gm = StandardizeMethod(new GenericMethod(method, gc.KlassInst, null));
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
var gm = new GenericMethod(method, gc.KlassInst, null).ToGenericShare();
|
|
||||||
//Debug.Log($"add method:{gm.Method} {gm.KlassInst}");
|
//Debug.Log($"add method:{gm.Method} {gm.KlassInst}");
|
||||||
|
|
||||||
if (_genericMethods.Add(gm))
|
if (_genericMethods.Add(gm))
|
||||||
|
|
@ -123,7 +135,8 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
foreach (var method in typeDef.Methods)
|
foreach (var method in typeDef.Methods)
|
||||||
{
|
{
|
||||||
// 对于带泛型的参数,统一泛型共享为object
|
// 对于带泛型的参数,统一泛型共享为object
|
||||||
_notGenericMethods.Add(method);
|
var gm = StandardizeMethod(new GenericMethod(method, null, null));
|
||||||
|
_genericMethods.Add(gm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -131,7 +144,7 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
{
|
{
|
||||||
// 将所有非泛型函数全部加入函数列表,同时立马walk这些method。
|
// 将所有非泛型函数全部加入函数列表,同时立马walk这些method。
|
||||||
// 后续迭代中将只遍历MethodSpec
|
// 后续迭代中将只遍历MethodSpec
|
||||||
foreach (var ass in _assemblyCollector.GetLoadedModulesExcludeRootAssemblies())
|
foreach (var ass in _assemblyCollector.GetLoadedModules())
|
||||||
{
|
{
|
||||||
foreach (TypeDef typeDef in ass.GetTypes())
|
foreach (TypeDef typeDef in ass.GetTypes())
|
||||||
{
|
{
|
||||||
|
|
@ -141,40 +154,29 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
for (uint rid = 1, n = ass.Metadata.TablesStream.TypeSpecTable.Rows; rid <= n; rid++)
|
for (uint rid = 1, n = ass.Metadata.TablesStream.TypeSpecTable.Rows; rid <= n; rid++)
|
||||||
{
|
{
|
||||||
var ts = ass.ResolveTypeSpec(rid);
|
var ts = ass.ResolveTypeSpec(rid);
|
||||||
if (!ts.ContainsGenericParameter)
|
var cs = GenericClass.ResolveClass(ts, null);
|
||||||
|
if (cs != null)
|
||||||
{
|
{
|
||||||
var cs = GenericClass.ResolveClass(ts, null)?.ToGenericShare();
|
TryAddAndWalkGenericType(cs);
|
||||||
if (cs != null)
|
|
||||||
{
|
|
||||||
TryAddAndWalkGenericType(cs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint rid = 1, n = ass.Metadata.TablesStream.MethodSpecTable.Rows; rid <= n; rid++)
|
for (uint rid = 1, n = ass.Metadata.TablesStream.MethodSpecTable.Rows; rid <= n; rid++)
|
||||||
{
|
{
|
||||||
var ms = ass.ResolveMethodSpec(rid);
|
var ms = ass.ResolveMethodSpec(rid);
|
||||||
if(ms.DeclaringType.ContainsGenericParameter || ms.GenericInstMethodSig.ContainsGenericParameter)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
var gm = GenericMethod.ResolveMethod(ms, null)?.ToGenericShare();
|
var gm = GenericMethod.ResolveMethod(ms, null)?.ToGenericShare();
|
||||||
if (gm == null)
|
if (gm == null)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
gm = StandardizeMethod(gm);
|
||||||
if (_genericMethods.Add(gm))
|
if (_genericMethods.Add(gm))
|
||||||
{
|
{
|
||||||
_newMethods.Add(gm);
|
_newMethods.Add(gm);
|
||||||
}
|
}
|
||||||
//if (gm.KlassInst != null)
|
|
||||||
//{
|
|
||||||
// TryAddAndWalkGenericType(new GenericClass(gm.Method.DeclaringType, gm.KlassInst));
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Debug.Log($"PostPrepare allMethods:{_notGenericMethods.Count} newMethods:{_newMethods.Count}");
|
Debug.Log($"PostPrepare allMethods:{_genericMethods.Count} newMethods:{_newMethods.Count}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RecursiveCollect()
|
private void RecursiveCollect()
|
||||||
|
|
@ -190,7 +192,7 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
{
|
{
|
||||||
_methodReferenceAnalyzer.WalkMethod(method.Method, method.KlassInst, method.MethodInst);
|
_methodReferenceAnalyzer.WalkMethod(method.Method, method.KlassInst, method.MethodInst);
|
||||||
})).ToArray());
|
})).ToArray());
|
||||||
Debug.Log($"iteration:[{i}] allMethods:{_notGenericMethods.Count} genericClass:{_genericTypes.Count} genericMethods:{_genericMethods.Count} newMethods:{_newMethods.Count}");
|
Debug.Log($"iteration:[{i}] genericClass:{_genericTypes.Count} genericMethods:{_genericMethods.Count} newMethods:{_newMethods.Count}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
using dnlib.DotNet;
|
||||||
|
|
||||||
|
namespace HybridCLR.Editor.MethodBridge
|
||||||
|
{
|
||||||
|
public class CallNativeMethodSignatureInfo
|
||||||
|
{
|
||||||
|
public MethodSig MethodSig { get; set; }
|
||||||
|
|
||||||
|
public CallingConvention? Callvention { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue