Compare commits
279 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 |
|
|
@ -1,7 +0,0 @@
|
||||||
# change logs
|
|
||||||
|
|
||||||
- 2023.04.29 Installer支持从本地目录复制改造后的libil2cpp
|
|
||||||
- 2023.03.28 `HybridCLR/Generate/Il2CppDef`生成的代码位置移到`hybridclr/generated`下
|
|
||||||
- 2022.08.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.1.0"},
|
"hybridclr" : { "branch":"v8.6.0"},
|
||||||
"il2cpp_plus": { "branch":"v2019-2.1.0"}
|
"il2cpp_plus": { "branch":"v2019-8.1.0"}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"unity_version":"2020",
|
"unity_version":"2020",
|
||||||
"hybridclr" : { "branch":"v2.2.0"},
|
"hybridclr" : { "branch":"v8.6.0"},
|
||||||
"il2cpp_plus": { "branch":"v2020-2.2.0"}
|
"il2cpp_plus": { "branch":"v2020-8.1.0"}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"unity_version":"2021",
|
"unity_version":"2021",
|
||||||
"hybridclr" : { "branch":"v2.2.0"},
|
"hybridclr" : { "branch":"v8.6.0"},
|
||||||
"il2cpp_plus": { "branch":"v2021-2.2.0"}
|
"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);
|
||||||
|
|
|
||||||
|
|
@ -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: a22846b73022cb2458d1c40549ab6877
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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: b63c5bf995a6d624dbd10d9df6cb6a7a
|
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,328 +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;
|
|
||||||
}
|
|
||||||
if (fields.All(f => f.IsStatic))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (typeDef.IsExplicitLayout && fields.Count(f => !f.IsStatic) > 1)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
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,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: fe1634f74b7ca2e42bd07233b451cd94
|
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// }}");
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -86,11 +90,12 @@ 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: 1eb9e19189731a344aad024a43e795bc
|
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)
|
||||||
|
|
@ -49,9 +85,9 @@ 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/hybridclr/generated/UnityVersion.h",
|
UnityVersionTemplateFile = $"{SettingsUtil.TemplatePathInPackage}/UnityVersion.h.tpl",
|
||||||
OutputFile2 = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr/generated/AssemblyManifest.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,99 +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)
|
|
||||||
{
|
|
||||||
throw new Exception("GenerateStripedAOTDlls 失败");
|
|
||||||
}
|
|
||||||
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,38 +102,23 @@ namespace HybridCLR.Editor.Installer
|
||||||
}
|
}
|
||||||
Directory.CreateDirectory(dir);
|
Directory.CreateDirectory(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CopyWithCheckLongFile(string srcFile, string dstFile)
|
|
||||||
{
|
|
||||||
if (srcFile.Length > 255)
|
|
||||||
{
|
|
||||||
UnityEngine.Debug.LogError($"srcFile:{srcFile} path is too long. copy ignore!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (dstFile.Length > 255)
|
|
||||||
{
|
|
||||||
UnityEngine.Debug.LogError($"dstFile:{dstFile} path is too long. copy ignore!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
File.Copy(srcFile, dstFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
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))
|
|
||||||
{
|
{
|
||||||
CopyWithCheckLongFile(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)
|
||||||
|
|
@ -168,6 +166,24 @@ namespace HybridCLR.Editor.Installer
|
||||||
|
|
||||||
public string ApplicationIl2cppPath => GetIl2CppPathByContentPath(EditorApplication.applicationContentsPath);
|
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()
|
||||||
{
|
{
|
||||||
InstallFromLocal(PrepareLibil2cppWithHybridclrFromGitRepo());
|
InstallFromLocal(PrepareLibil2cppWithHybridclrFromGitRepo());
|
||||||
|
|
@ -178,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
|
||||||
|
|
@ -191,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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -240,19 +255,13 @@ namespace HybridCLR.Editor.Installer
|
||||||
|
|
||||||
private void RunInitLocalIl2CppData(string editorIl2cppPath, string libil2cppWithHybridclrSourceDir, UnityVersion version)
|
private void RunInitLocalIl2CppData(string editorIl2cppPath, string libil2cppWithHybridclrSourceDir, UnityVersion version)
|
||||||
{
|
{
|
||||||
if (!IsComaptibleVersion())
|
if (GetCompatibleType() == CompatibleType.Incompatible)
|
||||||
{
|
{
|
||||||
Debug.LogError($"il2cpp 版本不兼容,最小版本为 {GetCurrentUnityVersionMinCompatibleVersionStr()}");
|
Debug.LogError($"Incompatible with current version, minimum compatible version: {GetCurrentUnityVersionMinCompatibleVersionStr()}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
string workDir = SettingsUtil.HybridCLRDataDir;
|
string workDir = SettingsUtil.HybridCLRDataDir;
|
||||||
Directory.CreateDirectory(workDir);
|
Directory.CreateDirectory(workDir);
|
||||||
//BashUtil.RecreateDir(workDir);
|
|
||||||
|
|
||||||
string buildiOSDir = $"{workDir}/iOSBuild";
|
|
||||||
BashUtil.RemoveDir(buildiOSDir);
|
|
||||||
BashUtil.CopyDir($"{SettingsUtil.HybridCLRDataPathInPackage}/iOSBuild", buildiOSDir, true);
|
|
||||||
|
|
||||||
|
|
||||||
// create LocalIl2Cpp
|
// create LocalIl2Cpp
|
||||||
string localUnityDataDir = SettingsUtil.LocalUnityDataDir;
|
string localUnityDataDir = SettingsUtil.LocalUnityDataDir;
|
||||||
|
|
@ -270,7 +279,6 @@ namespace HybridCLR.Editor.Installer
|
||||||
|
|
||||||
// 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();
|
||||||
|
|
@ -283,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!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,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");
|
||||||
|
|
@ -41,75 +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();
|
||||||
|
if (compatibleType != InstallerController.CompatibleType.Incompatible)
|
||||||
|
{
|
||||||
|
if (compatibleType == InstallerController.CompatibleType.MaybeIncompatible)
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox($"Maybe incompatible with current version, recommend minimum compatible version:{_controller.GetCurrentUnityVersionMinCompatibleVersionStr()}", MessageType.Warning);
|
||||||
|
}
|
||||||
|
|
||||||
//EditorGUILayout.BeginHorizontal();
|
EditorGUILayout.BeginHorizontal();
|
||||||
//EditorGUILayout.LabelField("待安装的 hybridclr 仓库版本号(或branch或tag)(默认取最新版本):", GUILayout.MaxWidth(400));
|
_installFromDir = EditorGUILayout.Toggle("Copy libil2cpp from local", _installFromDir, GUILayout.MinWidth(100));
|
||||||
//_hybridclrVersion = EditorGUILayout.TextField(_hybridclrVersion);
|
EditorGUI.BeginDisabledGroup(!_installFromDir);
|
||||||
//EditorGUILayout.EndHorizontal();
|
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();
|
||||||
|
|
||||||
//EditorGUILayout.BeginHorizontal();
|
GUILayout.Space(20f);
|
||||||
//EditorGUILayout.LabelField($"待安装的 il2cpp_plus 仓库版本号(或branch或tag)(默认取{_controller.MajorVersion}-main分支最新版本):", GUILayout.MaxWidth(400));
|
|
||||||
//_il2cppPlusVersion = EditorGUILayout.TextField(_il2cppPlusVersion);
|
|
||||||
//EditorGUILayout.EndHorizontal();
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
GUIInstallButton("安装hybridclr+il2cpp_plus代码到本地目录", "安装");
|
|
||||||
EditorGUILayout.EndVertical();
|
EditorGUILayout.EndVertical();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GUIInstallButton(string content, string button)
|
|
||||||
{
|
|
||||||
EditorGUILayout.BeginHorizontal();
|
|
||||||
_installFromDir = EditorGUILayout.Toggle("从本地复制libil2cpp", _installFromDir);
|
|
||||||
EditorGUI.BeginDisabledGroup(!_installFromDir);
|
|
||||||
EditorGUILayout.TextField(_installLibil2cppWithHybridclrSourceDir, GUILayout.Width(400));
|
|
||||||
if (GUILayout.Button("选择目录", GUILayout.Width(100)))
|
|
||||||
{
|
|
||||||
_installLibil2cppWithHybridclrSourceDir = EditorUtility.OpenFolderPanel("选择libil2cpp目录", Application.dataPath, "libil2cpp");
|
|
||||||
}
|
|
||||||
EditorGUI.EndDisabledGroup();
|
|
||||||
EditorGUILayout.EndHorizontal();
|
|
||||||
|
|
||||||
EditorGUILayout.BeginHorizontal();
|
|
||||||
EditorGUILayout.LabelField(content);
|
|
||||||
if (GUILayout.Button(button, GUILayout.Width(100)))
|
|
||||||
{
|
|
||||||
InstallLocalHybridCLR();
|
|
||||||
GUIUtility.ExitGUI();
|
|
||||||
}
|
|
||||||
EditorGUILayout.EndHorizontal();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InstallLocalHybridCLR()
|
private void InstallLocalHybridCLR()
|
||||||
{
|
{
|
||||||
if (_installFromDir)
|
if (_installFromDir)
|
||||||
{
|
{
|
||||||
if (!Directory.Exists(_installLibil2cppWithHybridclrSourceDir))
|
if (!Directory.Exists(_installLibil2cppWithHybridclrSourceDir))
|
||||||
{
|
{
|
||||||
Debug.LogError($"本地libil2cpp复制目录不存在. '{_installLibil2cppWithHybridclrSourceDir}'");
|
Debug.LogError($"Source libil2cpp:'{_installLibil2cppWithHybridclrSourceDir}' doesn't exist.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!File.Exists($"{_installLibil2cppWithHybridclrSourceDir}/il2cpp-config.h") || !File.Exists($"{_installLibil2cppWithHybridclrSourceDir}/hybridclr/RuntimeApi.cpp"))
|
if (!File.Exists($"{_installLibil2cppWithHybridclrSourceDir}/il2cpp-config.h") || !File.Exists($"{_installLibil2cppWithHybridclrSourceDir}/hybridclr/RuntimeApi.cpp"))
|
||||||
{
|
{
|
||||||
Debug.LogError($"本地libil2cpp不是合法有效的源码目录. '{_installLibil2cppWithHybridclrSourceDir}'");
|
Debug.LogError($"Source libil2cpp:' {_installLibil2cppWithHybridclrSourceDir} ' is invalid");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
_controller.InstallFromLocal(_installLibil2cppWithHybridclrSourceDir);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_controller.InstallDefaultHybridCLR();
|
||||||
}
|
}
|
||||||
_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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,11 +18,11 @@ namespace HybridCLR.Editor.Meta
|
||||||
{
|
{
|
||||||
if (SettingsUtil.HotUpdateAssemblyNamesIncludePreserved.Contains(assemblyName))
|
if (SettingsUtil.HotUpdateAssemblyNamesIncludePreserved.Contains(assemblyName))
|
||||||
{
|
{
|
||||||
throw new Exception($"resolve 热更新 dll:{assemblyName} 失败!请确保已经编译了热更新dll或者外部热更新路径中配置了正确的值。更多请参阅常见错误文档");
|
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.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new Exception($"resolve AOT dll:{assemblyName} 失败! 请确保主工程已经引用了该dll并且正确生成了裁剪后的AOT dll。更多请参阅常见错误文档");
|
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; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d2e4ca0a49975a84a8a72dbc70ec7795
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
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.MethodBridge
|
||||||
|
{
|
||||||
|
|
||||||
|
public class CalliAnalyzer
|
||||||
|
{
|
||||||
|
private readonly List<ModuleDefMD> _rootModules = new List<ModuleDefMD>();
|
||||||
|
|
||||||
|
private readonly List<CallNativeMethodSignatureInfo> _calliMethodSignatures = new List<CallNativeMethodSignatureInfo>();
|
||||||
|
|
||||||
|
public List<CallNativeMethodSignatureInfo> CalliMethodSignatures => _calliMethodSignatures;
|
||||||
|
|
||||||
|
public CalliAnalyzer(AssemblyCache cache, List<string> assemblyNames)
|
||||||
|
{
|
||||||
|
foreach (var assemblyName in assemblyNames)
|
||||||
|
{
|
||||||
|
_rootModules.Add(cache.LoadModule(assemblyName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CollectCalli()
|
||||||
|
{
|
||||||
|
foreach (var mod in _rootModules)
|
||||||
|
{
|
||||||
|
Debug.Log($"ass:{mod.FullName} methodcount:{mod.Metadata.TablesStream.MethodTable.Rows}");
|
||||||
|
for (uint rid = 1, n = mod.Metadata.TablesStream.MethodTable.Rows; rid <= n; rid++)
|
||||||
|
{
|
||||||
|
var method = mod.ResolveMethod(rid);
|
||||||
|
//Debug.Log($"method:{method}");
|
||||||
|
if (!method.HasBody)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var il in method.Body.Instructions)
|
||||||
|
{
|
||||||
|
if (il.OpCode.Code == dnlib.DotNet.Emit.Code.Calli)
|
||||||
|
{
|
||||||
|
MethodSig methodSig = (MethodSig)il.Operand;
|
||||||
|
|
||||||
|
_calliMethodSignatures.Add(new CallNativeMethodSignatureInfo()
|
||||||
|
{
|
||||||
|
MethodSig = methodSig,
|
||||||
|
});
|
||||||
|
Debug.Log($"method:{method} calli method signature:{methodSig}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Run()
|
||||||
|
{
|
||||||
|
CollectCalli();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6ce33c8e48da5a649b261ba3a60fd3b9
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue