Compare commits
292 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
434160afa8 | |
|
|
01754c8fb4 | |
|
|
1934d90f27 | |
|
|
814572e1a1 | |
|
|
d505624c78 | |
|
|
e36bbb9022 | |
|
|
0642726469 | |
|
|
d86572db37 | |
|
|
b5944ea834 | |
|
|
73654e76d2 | |
|
|
1537690bb5 | |
|
|
7f158f814a | |
|
|
ee7af5c592 | |
|
|
ab41cd0144 | |
|
|
59a3c3974a | |
|
|
c9ff293dfe | |
|
|
56486b8a76 | |
|
|
8e27e8d41b | |
|
|
fca130bbfa | |
|
|
c21dbcc60a | |
|
|
7f2fa52f37 | |
|
|
da46e71534 | |
|
|
804418fddb | |
|
|
7a0032934b | |
|
|
b301b44cd3 | |
|
|
ddc3332958 | |
|
|
52f25bdb2a | |
|
|
31be818bb6 | |
|
|
213a11ff25 | |
|
|
585be97be9 | |
|
|
361873803f | |
|
|
46f308ed5e | |
|
|
34406b1c13 | |
|
|
e5b52922f7 | |
|
|
e44fa663db | |
|
|
903cf9faa2 | |
|
|
3fe41a8cba | |
|
|
603b0ccb24 | |
|
|
9429a4d24d | |
|
|
ea592ba20c | |
|
|
8d1280a1bd | |
|
|
528240b52b | |
|
|
4768c039d2 | |
|
|
10dc749d7a | |
|
|
0c5ef00c12 | |
|
|
1553582ec1 | |
|
|
756b906a21 | |
|
|
355e24fbe8 | |
|
|
9e4946aa45 | |
|
|
8e571d594d | |
|
|
b8dd2be1e4 | |
|
|
de7b60695a | |
|
|
a11ebecf93 | |
|
|
019412fa81 | |
|
|
84bf6d59db | |
|
|
82163d2e50 | |
|
|
208372e6af | |
|
|
dd8d812641 | |
|
|
c19b34542e | |
|
|
e30306d7e1 | |
|
|
20f34c9b14 | |
|
|
45749ffb5c | |
|
|
b176d63d93 | |
|
|
0c99afd58e | |
|
|
2458c9a9ba | |
|
|
4d0fef095b | |
|
|
642d2cd644 | |
|
|
e54ce36b0e | |
|
|
ac8b649d50 | |
|
|
9ca9cd5aa7 | |
|
|
37dafd7b3c | |
|
|
f58d12c2cb | |
|
|
d5eaa350c5 | |
|
|
1f0053a3c9 | |
|
|
15dccc7427 | |
|
|
7d287a2293 | |
|
|
f19ba3eb30 | |
|
|
4e172129d8 | |
|
|
2414e77fef | |
|
|
77517a9814 | |
|
|
162f21f6a5 | |
|
|
bd7c3293bc | |
|
|
e25be945c7 | |
|
|
925921c27c | |
|
|
64a6d26fa3 | |
|
|
c24617d864 | |
|
|
59bc259cc8 | |
|
|
c413cd6143 | |
|
|
c614cdcf4e | |
|
|
08f493ab3e | |
|
|
3705ca6e1f | |
|
|
34df279943 | |
|
|
b85ed1aa92 | |
|
|
faf4a328af | |
|
|
53f4f33bf0 | |
|
|
48c91f497b | |
|
|
9afbe3bd84 | |
|
|
2d5f71f6b7 | |
|
|
5747458bf2 | |
|
|
0b455eb882 | |
|
|
e086228d90 | |
|
|
909e96ca7c | |
|
|
75b24345f6 | |
|
|
88e20505f8 | |
|
|
b4b486944c | |
|
|
360ba38805 | |
|
|
e5a6952777 | |
|
|
9330cf682c | |
|
|
16a7d5d529 | |
|
|
303c6c7b35 | |
|
|
e4cf9e9086 | |
|
|
b977a85b23 | |
|
|
0fcb51a369 | |
|
|
d61511924d | |
|
|
aca7dd0a67 | |
|
|
fc685a99ca | |
|
|
d431aeb019 | |
|
|
63d0aaa6e6 | |
|
|
d45974c6b4 | |
|
|
3de931a3af | |
|
|
b96d6fc10d | |
|
|
ef1b78caae | |
|
|
47622bf49c | |
|
|
846d7103a3 | |
|
|
170f13082e | |
|
|
60016d7481 | |
|
|
97dae7fed2 | |
|
|
f935127cd3 | |
|
|
ec5f2ef05e | |
|
|
6d0ceaa4f5 | |
|
|
95922aec1e | |
|
|
3259c11828 | |
|
|
74bab1d935 | |
|
|
fd81edb495 | |
|
|
12bafb897f | |
|
|
a6befb1312 | |
|
|
a36e3fe72d | |
|
|
d9776d1793 | |
|
|
2697eb5a90 | |
|
|
4879bb7f44 | |
|
|
24f85780a2 | |
|
|
6c679cc3ab | |
|
|
20a06f1ec5 | |
|
|
5446bd937c | |
|
|
ae88dd0eec | |
|
|
a5c006d67c | |
|
|
67c487f521 | |
|
|
6ffb977ef3 | |
|
|
f59ba2623a | |
|
|
4b57138935 | |
|
|
276cd0a4a8 | |
|
|
22a9793b9d | |
|
|
1b7947b196 | |
|
|
188fdc9430 | |
|
|
ff0f225423 | |
|
|
36ca398543 | |
|
|
f30e2f5b33 | |
|
|
a531a213c2 | |
|
|
2b42376505 | |
|
|
ef103d8351 | |
|
|
db87b92f78 | |
|
|
51da1d4c43 | |
|
|
71ad34d7ac | |
|
|
7c29ab804b | |
|
|
9b269ea4c2 | |
|
|
c9ad6880cb | |
|
|
372fa9e06e | |
|
|
3df95d138d | |
|
|
410bb9b542 | |
|
|
15155b9a46 | |
|
|
f810ede6d7 | |
|
|
63d9e7f4c3 | |
|
|
3cea936aa4 | |
|
|
d90faed922 | |
|
|
febff1c658 | |
|
|
94a329a522 | |
|
|
84ed2e6b9d | |
|
|
47fbd443c1 | |
|
|
d5b52cc8db | |
|
|
d9ed27abfb | |
|
|
f51c2803c1 | |
|
|
05a34d4d12 | |
|
|
216d09f7b6 | |
|
|
8d441a02d2 | |
|
|
de2bc21f20 | |
|
|
4aba5c2a5e | |
|
|
b573e61504 | |
|
|
69de3d733d | |
|
|
a77ed7369a | |
|
|
1bd27a3e22 | |
|
|
4da7c1a524 | |
|
|
5c750e9c02 | |
|
|
cc09487671 | |
|
|
b024a18ba1 | |
|
|
4587cb7c19 | |
|
|
beec0b73e6 | |
|
|
61fb0cfe34 | |
|
|
260909bd4b | |
|
|
06a250b9fa | |
|
|
dc884d36b8 | |
|
|
1168d51e93 | |
|
|
7270e9194d | |
|
|
1d50dfcb6e | |
|
|
1eaaf44c97 | |
|
|
9cf8f19517 | |
|
|
22760c6c7c | |
|
|
47e43b0afa | |
|
|
58c7073073 | |
|
|
9dafabd1ee | |
|
|
5857696b56 | |
|
|
f2807f4838 | |
|
|
f46c180181 | |
|
|
1e14a5f30f | |
|
|
dfa11d11c3 | |
|
|
69d3303f3d | |
|
|
9eb6dda71b | |
|
|
10e0568251 | |
|
|
1f9faf49a3 | |
|
|
3f1b34682d | |
|
|
c3f6325e4a | |
|
|
a9f5608ecf | |
|
|
8a95fd57f5 | |
|
|
679c21da43 | |
|
|
52bab856ed | |
|
|
844b2fb62f | |
|
|
88404cbbfc | |
|
|
9b4aa904ef | |
|
|
a71153d414 | |
|
|
bec8c84c56 | |
|
|
79bab0459c | |
|
|
1d09f72460 | |
|
|
058270c658 | |
|
|
210c781fad | |
|
|
6757f6df5b | |
|
|
41c73fe35b | |
|
|
4d487fa4c4 | |
|
|
2f71bb515d | |
|
|
0d8b001dd2 | |
|
|
3d68dc4db3 | |
|
|
2988aef85a | |
|
|
768512bcfa | |
|
|
4492449b73 | |
|
|
be113567ba | |
|
|
e45a789569 | |
|
|
0a82b0d339 | |
|
|
c8cd323bb0 | |
|
|
2f09f88ca2 | |
|
|
8e178c0e37 | |
|
|
40711cbf38 | |
|
|
7749b6448e | |
|
|
1459992ec4 | |
|
|
c09dad4ae1 | |
|
|
271dc70626 | |
|
|
c462aeb2ef | |
|
|
adbdbf3a00 | |
|
|
10684d29cd | |
|
|
7d58454fdd | |
|
|
21b85aa2d3 | |
|
|
8439e4176d | |
|
|
4b43870ff2 | |
|
|
b49b94521e | |
|
|
49873ba6ed | |
|
|
97f083f07d | |
|
|
941bbc723a | |
|
|
18def7886d | |
|
|
f1336c56d4 | |
|
|
8f89651d10 | |
|
|
8d0634620a | |
|
|
f5afc43625 | |
|
|
f8eee2ba49 | |
|
|
07b52bed05 | |
|
|
3139fbefa6 | |
|
|
fbeeb3d959 | |
|
|
1f4e754adb | |
|
|
f63bbc8a52 | |
|
|
b17751b8a8 | |
|
|
05e721cf02 | |
|
|
29646f1294 | |
|
|
3702411ac8 | |
|
|
d205f00a1b | |
|
|
2894701063 | |
|
|
1045538b40 | |
|
|
8fd9b2ec82 | |
|
|
0ccdd424ab | |
|
|
c083e4ada4 | |
|
|
4c6dd1249a | |
|
|
b8b990bfc1 | |
|
|
252e6add67 | |
|
|
6e76b96f97 | |
|
|
dd18ecdba5 | |
|
|
2ff3e276d2 | |
|
|
1d5f2a953c |
|
|
@ -1,5 +0,0 @@
|
|||
# change logs
|
||||
|
||||
- 2022.8.30 创建
|
||||
|
||||
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 94322e93a1f61b340bdc1d5042dab659
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d104ab5da8136154899a40116dc88731
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,12 @@
|
|||
#include "../Il2CppCompatibleDef.h"
|
||||
|
||||
namespace hybridclr
|
||||
{
|
||||
const char* g_placeHolderAssemblies[] =
|
||||
{
|
||||
//!!!{{PLACE_HOLDER
|
||||
|
||||
//!!!}}PLACE_HOLDER
|
||||
nullptr,
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
#include <codegen/il2cpp-codegen-metadata.h>
|
||||
#if HYBRIDCLR_UNITY_2023_OR_NEW
|
||||
#include <codegen/il2cpp-codegen.h>
|
||||
#elif HYBRIDCLR_UNITY_2022
|
||||
#include <codegen/il2cpp-codegen-il2cpp.h>
|
||||
#elif HYBRIDCLR_UNITY_2020 || HYBRIDCLR_UNITY_2021
|
||||
#include <codegen/il2cpp-codegen-common-big.h>
|
||||
#else
|
||||
#include <codegen/il2cpp-codegen-common.h>
|
||||
#endif
|
||||
|
||||
#include "vm/ClassInlines.h"
|
||||
#include "vm/Object.h"
|
||||
#include "vm/Class.h"
|
||||
#include "vm/ScopedThreadAttacher.h"
|
||||
|
||||
#include "../metadata/MetadataUtil.h"
|
||||
|
||||
|
||||
#include "../interpreter/InterpreterModule.h"
|
||||
#include "../interpreter/MethodBridge.h"
|
||||
#include "../interpreter/Interpreter.h"
|
||||
#include "../interpreter/MemoryUtil.h"
|
||||
#include "../interpreter/InstrinctDef.h"
|
||||
|
||||
using namespace hybridclr::interpreter;
|
||||
using namespace hybridclr::metadata;
|
||||
|
||||
//!!!{{CODE
|
||||
|
||||
|
||||
//!!!}}CODE
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
#include <codegen/il2cpp-codegen-metadata.h>
|
||||
#include "vm/ClassInlines.h"
|
||||
#include "vm/Object.h"
|
||||
#include "vm/Class.h"
|
||||
|
||||
#include "../metadata/MetadataModule.h"
|
||||
#include "../metadata/MetadataUtil.h"
|
||||
|
||||
#include "../interpreter/MethodBridge.h"
|
||||
#include "../interpreter/Interpreter.h"
|
||||
#include "../interpreter/MemoryUtil.h"
|
||||
#include "../interpreter/InstrinctDef.h"
|
||||
|
||||
using namespace hybridclr::interpreter;
|
||||
|
||||
#if {PLATFORM_ABI}
|
||||
//!!!{{CODE
|
||||
|
||||
//!!!}}CODE
|
||||
#endif
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
#include "../metadata/ReversePInvokeMethodStub.h"
|
||||
#include "../metadata/MetadataModule.h"
|
||||
|
||||
namespace hybridclr
|
||||
{
|
||||
namespace metadata
|
||||
{
|
||||
#if {PLATFORM_ABI}
|
||||
|
||||
//!!!{{CODE
|
||||
|
||||
void __ReversePInvokeMethod_0(void* xState)
|
||||
{
|
||||
CallLuaFunction(xState, 0);
|
||||
}
|
||||
|
||||
void __ReversePInvokeMethod_1(void* xState)
|
||||
{
|
||||
CallLuaFunction(xState, 1);
|
||||
}
|
||||
|
||||
Il2CppMethodPointer s_ReversePInvokeMethodStub[]
|
||||
{
|
||||
(Il2CppMethodPointer)__ReversePInvokeMethod_0,
|
||||
(Il2CppMethodPointer)__ReversePInvokeMethod_1,
|
||||
nullptr,
|
||||
};
|
||||
|
||||
//!!!}}CODE
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
//!!!{{UNITY_VERSION
|
||||
|
||||
|
||||
//!!!}}UNITY_VERSION
|
||||
|
|
@ -2,18 +2,38 @@
|
|||
"versions": [
|
||||
{
|
||||
"unity_version":"2019",
|
||||
"hybridclr" : { "branch":"v2.0.3"},
|
||||
"il2cpp_plus": { "branch":"v2019-2.0.1"}
|
||||
"hybridclr" : { "branch":"v8.6.0"},
|
||||
"il2cpp_plus": { "branch":"v2019-8.1.0"}
|
||||
},
|
||||
{
|
||||
"unity_version":"2020",
|
||||
"hybridclr" : { "branch":"v2.0.3"},
|
||||
"il2cpp_plus": { "branch":"v2020-2.0.2"}
|
||||
"hybridclr" : { "branch":"v8.6.0"},
|
||||
"il2cpp_plus": { "branch":"v2020-8.1.0"}
|
||||
},
|
||||
{
|
||||
"unity_version":"2021",
|
||||
"hybridclr" : { "branch":"v2.0.3"},
|
||||
"il2cpp_plus": { "branch":"v2021-2.0.2"}
|
||||
"hybridclr" : { "branch":"v8.6.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
|
||||
guid: 4455f7304f8678f408dd6cf21734f55e
|
||||
guid: 8f2dd29d56a640d4ebd1c2fd374b7638
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -116,8 +116,8 @@ namespace MonoHook
|
|||
|
||||
static void SetupFlushICacheFunc()
|
||||
{
|
||||
string processorType = SystemInfo.processorType;
|
||||
if (processorType.Contains("Intel") || processorType.Contains("AMD"))
|
||||
string processorType = SystemInfo.processorType.ToLowerInvariant();
|
||||
if (processorType.Contains("intel") || processorType.Contains("amd"))
|
||||
return;
|
||||
|
||||
if (IntPtr.Size == 4)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,11 @@ namespace MonoHook
|
|||
|
||||
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");
|
||||
if (p_SystemPageSize == null)
|
||||
|
|
@ -35,6 +39,16 @@ namespace MonoHook
|
|||
|
||||
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])
|
||||
{
|
||||
memcpy_jit(new IntPtr(pDst), new IntPtr(p), src.Length);
|
||||
|
|
|
|||
|
|
@ -1,277 +0,0 @@
|
|||
#if ENABLE_HOOK_TEST_CASE
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Callbacks;
|
||||
using UnityEngine;
|
||||
using System.Linq;
|
||||
|
||||
namespace MonoHook.Test
|
||||
{
|
||||
// 有需求时可以打开,也可以手动按需注册Hook
|
||||
[InitializeOnLoad]
|
||||
public class BuildPipeline_StripDll_HookTest
|
||||
{
|
||||
/// <summary>
|
||||
/// 裁剪执行完毕的回调,可能会被调用多次,一般而言同一次打包只需要处理第一次回调
|
||||
/// </summary>
|
||||
public static Action<string, BuildPostProcessArgs, BeeDriverResult> OnAssemblyStripped;
|
||||
|
||||
// 尝试 Hook 4个函数,至少一个被调用就可以达到要求
|
||||
private static MethodHook _hook_PostprocessBuildPlayer_CompleteBuild;
|
||||
private static MethodHook _hook_Default_PostProcess;
|
||||
private static MethodHook _hook_ReportBuildResults;
|
||||
private static MethodHook _hook_StripAssembliesTo;
|
||||
|
||||
#region Fake Internal Structures
|
||||
public struct BuildPostProcessArgs
|
||||
{
|
||||
public BuildTarget target;
|
||||
public int subTarget;
|
||||
public string stagingArea;
|
||||
public string stagingAreaData;
|
||||
public string stagingAreaDataManaged;
|
||||
public string playerPackage;
|
||||
public string installPath;
|
||||
public string companyName;
|
||||
public string productName;
|
||||
public Guid productGUID;
|
||||
public BuildOptions options;
|
||||
public UnityEditor.Build.Reporting.BuildReport report;
|
||||
internal /*RuntimeClassRegistry*/object usedClassRegistry;
|
||||
}
|
||||
|
||||
public sealed class BeeDriverResult
|
||||
{
|
||||
public /*NodeResult*/object[] NodeResults { get; set; }
|
||||
public bool Success { get; set; }
|
||||
public /*Message*/object[] BeeDriverMessages { get; set; }
|
||||
public override string ToString() => Success.ToString();
|
||||
}
|
||||
#endregion
|
||||
|
||||
static BuildPipeline_StripDll_HookTest()
|
||||
{
|
||||
InstallHook();
|
||||
#if ENABLE_HOOK_TEST_CASE
|
||||
OnAssemblyStripped = DemoStripCallback;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 示例裁剪回调函数
|
||||
/// </summary>
|
||||
/// <param name="outputFolder"></param>
|
||||
/// <param name="args"></param>
|
||||
/// <param name="result"></param>
|
||||
static void DemoStripCallback(string outputFolder, BuildPostProcessArgs args, BeeDriverResult result)
|
||||
{
|
||||
if (outputFolder != null)
|
||||
Debug.Log($"stripped outputFolder is:{outputFolder}");
|
||||
else if (args.stagingAreaDataManaged != null)
|
||||
Debug.Log($"stripped staging folder is:{args.stagingAreaDataManaged}");
|
||||
else if (result != null)
|
||||
Debug.Log($"stripped result is: {result.Success}");
|
||||
else
|
||||
Debug.Log("stripped test called");
|
||||
}
|
||||
|
||||
public static void InstallHook()
|
||||
{
|
||||
do
|
||||
{
|
||||
Type type = Type.GetType("UnityEditor.PostprocessBuildPlayer,UnityEditor, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
|
||||
if (type == null)
|
||||
{
|
||||
Debug.LogError($"can not find type: UnityEditor.PostprocessBuildPlayer");
|
||||
break;
|
||||
}
|
||||
|
||||
MethodInfo miTarget = type.GetMethod("PostProcessCompletedBuild", BindingFlags.Static | BindingFlags.Public);
|
||||
|
||||
if (miTarget == null)
|
||||
{
|
||||
Debug.LogError($"can not find method: UnityEditor.PostprocessBuildPlayer.PostProcessCompletedBuild");
|
||||
break;
|
||||
}
|
||||
|
||||
MethodInfo miReplace = typeof(BuildPipeline_StripDll_HookTest).GetMethod(nameof(PostprocessBuildPlayer_CompleteBuild_Replace), BindingFlags.Static | BindingFlags.NonPublic);
|
||||
MethodInfo miProxy = typeof(BuildPipeline_StripDll_HookTest).GetMethod(nameof(PostprocessBuildPlayer_CompleteBuild_Proxy), BindingFlags.Static | BindingFlags.NonPublic);
|
||||
|
||||
_hook_PostprocessBuildPlayer_CompleteBuild = new MethodHook(miTarget, miReplace, miProxy);
|
||||
_hook_PostprocessBuildPlayer_CompleteBuild.Install();
|
||||
|
||||
Debug.Log("Hook BuildPipeline_StripDll_HookTest.PostprocessBuildPlayer_CompleteBuild installed");
|
||||
} while (false);
|
||||
|
||||
do
|
||||
{
|
||||
Type type = Type.GetType("UnityEditor.Modules.DefaultBuildPostprocessor,UnityEditor.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
|
||||
if (type == null)
|
||||
{
|
||||
Debug.LogError($"can not find type: UnityEditor.Modules.DefaultBuildPostprocessor");
|
||||
break;
|
||||
}
|
||||
|
||||
MethodInfo[] miTargets = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);
|
||||
MethodInfo miTarget = (from mi in miTargets where mi.Name == "PostProcess" && mi.GetParameters().Length == 2 select mi).FirstOrDefault();
|
||||
|
||||
if (miTarget == null)
|
||||
{
|
||||
Debug.LogError($"can not find method: UnityEditor.Modules.DefaultBuildPostprocessor.PostProcess");
|
||||
break;
|
||||
}
|
||||
|
||||
MethodInfo miReplace = typeof(BuildPipeline_StripDll_HookTest).GetMethod(nameof(Default_PostProcess_Replace), BindingFlags.Static | BindingFlags.NonPublic);
|
||||
MethodInfo miProxy = typeof(BuildPipeline_StripDll_HookTest).GetMethod(nameof(Default_PostProcess_Proxy), BindingFlags.Static | BindingFlags.NonPublic);
|
||||
|
||||
_hook_Default_PostProcess = new MethodHook(miTarget, miReplace, miProxy);
|
||||
_hook_Default_PostProcess.Install();
|
||||
|
||||
Debug.Log("Hook BuildPipeline_StripDll_HookTest.PostProcess installed");
|
||||
} while (false);
|
||||
|
||||
do
|
||||
{
|
||||
Type type = Type.GetType("UnityEditor.Modules.BeeBuildPostprocessor,UnityEditor.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
|
||||
if (type == null)
|
||||
{
|
||||
Debug.LogError($"can not find type: UnityEditor.Modules.BeeBuildPostprocessor");
|
||||
break;
|
||||
}
|
||||
|
||||
MethodInfo miTarget = type.GetMethod("ReportBuildResults", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
if (miTarget == null)
|
||||
{
|
||||
Debug.LogError($"can not find method: UnityEditor.Modules.BeeBuildPostprocessor.ReportBuildResults");
|
||||
break;
|
||||
}
|
||||
|
||||
MethodInfo miReplace = typeof(BuildPipeline_StripDll_HookTest).GetMethod(nameof(ReportBuildResults_Replace), BindingFlags.Static | BindingFlags.NonPublic);
|
||||
MethodInfo miProxy = typeof(BuildPipeline_StripDll_HookTest).GetMethod(nameof(ReportBuildResults_Proxy), BindingFlags.Static | BindingFlags.NonPublic);
|
||||
|
||||
_hook_ReportBuildResults = new MethodHook(miTarget, miReplace, miProxy);
|
||||
_hook_ReportBuildResults.Install();
|
||||
|
||||
Debug.Log("Hook BuildPipeline_StripDll_HookTest.ReportBuildResults installed");
|
||||
} while (false);
|
||||
|
||||
do
|
||||
{
|
||||
Type type = Type.GetType("UnityEditorInternal.AssemblyStripper,UnityEditor.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
|
||||
if (type == null)
|
||||
{
|
||||
Debug.LogError($"can not find type: UnityEditorInternal.AssemblyStripper");
|
||||
break;
|
||||
}
|
||||
|
||||
MethodInfo miTarget = type.GetMethod("StripAssembliesTo", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
if (miTarget == null)
|
||||
{
|
||||
Debug.LogError($"can not find method: UnityEditorInternal.AssemblyStripper.StripAssembliesTo");
|
||||
break;
|
||||
}
|
||||
|
||||
MethodInfo miReplace = typeof(BuildPipeline_StripDll_HookTest).GetMethod(nameof(StripAssembliesTo_Replace), BindingFlags.Static | BindingFlags.NonPublic);
|
||||
MethodInfo miProxy = typeof(BuildPipeline_StripDll_HookTest).GetMethod(nameof(StripAssembliesTo_Proxy), BindingFlags.Static | BindingFlags.NonPublic);
|
||||
|
||||
_hook_StripAssembliesTo = new MethodHook(miTarget, miReplace, miProxy);
|
||||
_hook_StripAssembliesTo.Install();
|
||||
|
||||
Debug.Log("Hook BuildPipeline_StripDll_HookTest.StripAssembliesTo installed");
|
||||
} while (false);
|
||||
}
|
||||
|
||||
public static void UninstallHook()
|
||||
{
|
||||
_hook_PostprocessBuildPlayer_CompleteBuild?.Uninstall();
|
||||
_hook_Default_PostProcess?.Uninstall();
|
||||
_hook_ReportBuildResults?.Uninstall();
|
||||
_hook_StripAssembliesTo?.Uninstall();
|
||||
}
|
||||
|
||||
static void PostprocessBuildPlayer_CompleteBuild_Replace(BuildPostProcessArgs args)
|
||||
{
|
||||
Debug.Log("PostprocessBuildPlayer_CompleteBuild_Replace called");
|
||||
|
||||
OnAssemblyStripped?.Invoke(null, args, null);
|
||||
PostprocessBuildPlayer_CompleteBuild_Proxy(args);
|
||||
}
|
||||
|
||||
static void Default_PostProcess_Replace(object obj, BuildPostProcessArgs args, out /*BuildProperties*/ object outProperties)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 注意:此函数中途可能会被 Unity throw Exception
|
||||
Default_PostProcess_Proxy(obj, args, out outProperties);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
throw ex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Debug.Log("PostProcess_Replace called");
|
||||
OnAssemblyStripped?.Invoke(null, args, null);
|
||||
}
|
||||
}
|
||||
|
||||
static void ReportBuildResults_Replace(object obj, BeeDriverResult result)
|
||||
{
|
||||
// TODO: 可以在这里把 Library\Bee\artifacts\WinPlayerBuildProgram\ManagedStripped 目录下的文件复制出来
|
||||
Debug.Log("ReportBuildResults_Replace called");
|
||||
|
||||
OnAssemblyStripped?.Invoke(null, default(BuildPostProcessArgs), result);
|
||||
ReportBuildResults_Proxy(obj, result);
|
||||
}
|
||||
|
||||
static bool StripAssembliesTo_Replace(string outputFolder, out string output, out string error, IEnumerable<string> linkXmlFiles, /*UnityLinkerRunInformation*/ object runInformation)
|
||||
{
|
||||
bool ret = StripAssembliesTo_Proxy(outputFolder, out output, out error, linkXmlFiles, runInformation);
|
||||
|
||||
// TODO: 可以在这里把 Temp\StagingArea\Data\Managed\tempStrip 目录下的文件复制出来
|
||||
Debug.Log("StripAssembliesTo_Replace called");
|
||||
|
||||
OnAssemblyStripped?.Invoke(outputFolder, default(BuildPostProcessArgs), null);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#region Proxy Methods
|
||||
[MethodImpl(MethodImplOptions.NoOptimization)]
|
||||
static void PostprocessBuildPlayer_CompleteBuild_Proxy(BuildPostProcessArgs args)
|
||||
{
|
||||
Debug.Log("dummy code" + 200);
|
||||
Debug.Log(args.companyName);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoOptimization)]
|
||||
static void Default_PostProcess_Proxy(object obj, BuildPostProcessArgs args, out /*BuildProperties*/ object outProperties)
|
||||
{
|
||||
Debug.Log("dummy code" + 100);
|
||||
outProperties = null;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoOptimization)]
|
||||
static void ReportBuildResults_Proxy(object obj, /*BeeDriverResult*/ object result)
|
||||
{
|
||||
// dummy code
|
||||
Debug.Log("something" + obj.ToString() + result.ToString() + 2);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoOptimization)]
|
||||
static bool StripAssembliesTo_Proxy(string outputFolder, out string output, out string error, IEnumerable<string> linkXmlFiles, /*UnityLinkerRunInformation*/ object runInformation)
|
||||
{
|
||||
Debug.Log("StripAssembliesTo_Proxy called");
|
||||
output = null;
|
||||
error = null;
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -12,7 +12,7 @@ using System.IO;
|
|||
|
||||
namespace HybridCLR.MonoHook
|
||||
{
|
||||
#if UNITY_2021_1_OR_NEWER && UNITY_IOS
|
||||
#if UNITY_2021_1_OR_NEWER && !UNITY_2023_1_OR_NEWER
|
||||
[InitializeOnLoad]
|
||||
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
|
||||
guid: ed8859610137d404e87f332b7082c19b
|
||||
guid: 96c2bc28db69e1644892219abef3d4b5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
@ -12,7 +12,7 @@ using System.IO;
|
|||
|
||||
namespace HybridCLR.MonoHook
|
||||
{
|
||||
#if UNITY_2021_1_OR_NEWER && UNITY_WEBGL
|
||||
#if UNITY_2021_1_OR_NEWER && (UNITY_WEBGL || UNITY_WEIXINMINIGAME)
|
||||
[InitializeOnLoad]
|
||||
public class PatchScriptingAssembliesJsonHook
|
||||
{
|
||||
|
|
@ -35,12 +35,29 @@ namespace HybridCLR.MonoHook
|
|||
|
||||
private static string BuildMainWindowTitle()
|
||||
{
|
||||
string tempJsonPath = $"{Application.dataPath}/../Library/PlayerDataCache/WebGL/Data/ScriptingAssemblies.json";
|
||||
if (File.Exists(tempJsonPath))
|
||||
var cacheDir = $"{Application.dataPath}/../Library/PlayerDataCache";
|
||||
if (Directory.Exists(cacheDir))
|
||||
{
|
||||
var patcher = new PatchScriptingAssemblyList();
|
||||
patcher.PathScriptingAssembilesFile(Path.GetDirectoryName(tempJsonPath));
|
||||
foreach (var tempJsonPath in Directory.GetDirectories(cacheDir, "*", SearchOption.TopDirectoryOnly))
|
||||
{
|
||||
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();
|
||||
return newTitle;
|
||||
}
|
||||
|
|
@ -48,6 +65,8 @@ namespace HybridCLR.MonoHook
|
|||
[MethodImpl(MethodImplOptions.NoOptimization)]
|
||||
private static string BuildMainWindowTitleProxy()
|
||||
{
|
||||
// 为满足MonoHook要求的最小代码长度而特地加入的无用填充代码,
|
||||
UnityEngine.Debug.Log(12345.ToString());
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace DotNetDetour
|
||||
{
|
||||
|
|
@ -641,15 +642,8 @@ namespace DotNetDetour
|
|||
if(s_isArm.HasValue)
|
||||
return s_isArm.Value;
|
||||
|
||||
string processorType = UnityEngine.SystemInfo.processorType;
|
||||
|
||||
/*
|
||||
* appple M 系列
|
||||
* SystemInfo.processorType 返回值为: Apple M1 Max, Apple M2 等
|
||||
* SystemInfo.operatingSystem 返回值为: Mac OS X xx.x.x
|
||||
*
|
||||
*/
|
||||
s_isArm = processorType.Contains("ARM") || processorType.Contains("Apple M");
|
||||
var arch = RuntimeInformation.ProcessArchitecture;
|
||||
s_isArm = arch == Architecture.Arm || arch == Architecture.Arm64;
|
||||
|
||||
return s_isArm.Value;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/*
|
||||
/*
|
||||
Desc: 一个可以运行时 Hook Mono 方法的工具,让你可以无需修改 UnityEditor.dll 等文件就可以重写其函数功能
|
||||
Author: Misaka Mikoto
|
||||
Github: https://github.com/Misaka-Mikoto-Tech/MonoHook
|
||||
|
|
@ -85,7 +85,7 @@ namespace MonoHook
|
|||
|
||||
private CodePatcher _codePatcher;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
#if UNITY_EDITOR && !UNITY_2020_3_OR_NEWER
|
||||
/// <summary>
|
||||
/// call `MethodInfo.MethodHandle.GetFunctionPointer()`
|
||||
/// will visit static class `UnityEditor.IMGUI.Controls.TreeViewGUI.Styles` and invoke its static constructor,
|
||||
|
|
@ -97,7 +97,7 @@ namespace MonoHook
|
|||
|
||||
static MethodHook()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
#if UNITY_EDITOR && !UNITY_2020_3_OR_NEWER
|
||||
s_fi_GUISkin_current = typeof(GUISkin).GetField("current", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
#endif
|
||||
}
|
||||
|
|
@ -126,7 +126,7 @@ namespace MonoHook
|
|||
if (isHooked)
|
||||
return;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
#if UNITY_EDITOR && !UNITY_2020_3_OR_NEWER
|
||||
if (s_fi_GUISkin_current.GetValue(null) != null)
|
||||
DoInstall();
|
||||
else
|
||||
|
|
@ -191,7 +191,7 @@ namespace MonoHook
|
|||
if (targetMethod.IsAbstract)
|
||||
throw new Exception($"WRANING: you can not hook abstract method [{methodName}]");
|
||||
|
||||
#if UNITY_EDITOR
|
||||
#if UNITY_EDITOR && !UNITY_2020_3_OR_NEWER
|
||||
int minMethodBodySize = 10;
|
||||
|
||||
{
|
||||
|
|
@ -358,13 +358,19 @@ namespace MonoHook
|
|||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
#if UNITY_EDITOR && !UNITY_2020_3_OR_NEWER
|
||||
private void OnEditorUpdate()
|
||||
{
|
||||
if (s_fi_GUISkin_current.GetValue(null) != null)
|
||||
{
|
||||
DoInstall();
|
||||
EditorApplication.update -= OnEditorUpdate;
|
||||
try
|
||||
{
|
||||
DoInstall();
|
||||
}
|
||||
finally
|
||||
{
|
||||
EditorApplication.update -= OnEditorUpdate;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -14,20 +14,6 @@ namespace HybridCLR.Editor.ABI
|
|||
|
||||
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
|
||||
|
|
@ -36,11 +22,6 @@ namespace HybridCLR.Editor.ABI
|
|||
|
||||
public bool IsVoid => Type.PorType == ParamOrReturnType.VOID;
|
||||
|
||||
public int GetParamSlotNum(PlatformABI canv)
|
||||
{
|
||||
return Type.GetParamSlotNum();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Type.GetTypeName();
|
||||
|
|
|
|||
|
|
@ -19,25 +19,9 @@ namespace HybridCLR.Editor.ABI
|
|||
U8,
|
||||
R4,
|
||||
R8,
|
||||
ARM64_HFA_FLOAT_2,
|
||||
VALUE_TYPE_SIZE_LESS_EQUAL_8,
|
||||
I16, // 8 < size <= 16
|
||||
STRUCT_NOT_PASS_AS_VALUE, // struct pass not as value
|
||||
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,
|
||||
I,
|
||||
U,
|
||||
TYPEDBYREF,
|
||||
STRUCT,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
guid: a22846b73022cb2458d1c40549ab6877
|
||||
guid: 0b1df5760b488fa43a68843c46fda63a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
using dnlib.DotNet;
|
||||
using HybridCLR.Editor.Meta;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HybridCLR.Editor.ABI
|
||||
{
|
||||
public class HFATypeInfo
|
||||
{
|
||||
public TypeSig Type { get; set; }
|
||||
|
||||
public int Count { get; set; }
|
||||
}
|
||||
|
||||
public class TypeCreatorArm64 : TypeCreatorBase
|
||||
{
|
||||
public override bool IsArch32 => false;
|
||||
|
||||
public override bool IsSupportHFA => true;
|
||||
|
||||
protected override TypeInfo OptimizeSigType(TypeInfo type, bool returnType)
|
||||
{
|
||||
if (!type.IsGeneralValueType)
|
||||
{
|
||||
return type;
|
||||
}
|
||||
int typeSize = type.Size;
|
||||
if (typeSize <= 8)
|
||||
{
|
||||
return TypeInfo.s_i8;
|
||||
}
|
||||
if (typeSize <= 16)
|
||||
{
|
||||
return TypeInfo.s_i16;
|
||||
}
|
||||
if (returnType)
|
||||
{
|
||||
return type.PorType != ParamOrReturnType.STRUCTURE_ALIGN1 ? new TypeInfo(ParamOrReturnType.STRUCTURE_ALIGN1, typeSize) : type;
|
||||
}
|
||||
return TypeInfo.s_ref;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,320 +0,0 @@
|
|||
using dnlib.DotNet;
|
||||
using HybridCLR.Editor.Meta;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HybridCLR.Editor.ABI
|
||||
{
|
||||
public abstract class TypeCreatorBase
|
||||
{
|
||||
public abstract bool IsArch32 { get; }
|
||||
|
||||
public virtual bool IsSupportHFA => false;
|
||||
|
||||
public virtual bool IsSupportWebGLSpecialValueType => false;
|
||||
|
||||
public TypeInfo GetNativeIntTypeInfo() => IsArch32 ? TypeInfo.s_i4 : TypeInfo.s_i8;
|
||||
|
||||
public ValueTypeSizeAligmentCalculator Calculator => IsArch32 ? ValueTypeSizeAligmentCalculator.Caculator32 : ValueTypeSizeAligmentCalculator.Caculator64;
|
||||
|
||||
|
||||
private readonly Dictionary<TypeSig, (int, int)> _typeSizeCache = new Dictionary<TypeSig, (int, int)>(TypeEqualityComparer.Instance);
|
||||
|
||||
public (int Size, int Aligment) ComputeSizeAndAligment(TypeSig t)
|
||||
{
|
||||
if (_typeSizeCache.TryGetValue(t, out var sizeAndAligment))
|
||||
{
|
||||
return sizeAndAligment;
|
||||
}
|
||||
sizeAndAligment = Calculator.SizeAndAligmentOf(t);
|
||||
_typeSizeCache.Add(t, sizeAndAligment);
|
||||
return sizeAndAligment;
|
||||
}
|
||||
|
||||
public TypeInfo CreateTypeInfo(TypeSig type)
|
||||
{
|
||||
type = type.RemovePinnedAndModifiers();
|
||||
if (type.IsByRef)
|
||||
{
|
||||
return GetNativeIntTypeInfo();
|
||||
}
|
||||
switch (type.ElementType)
|
||||
{
|
||||
case ElementType.Void: return TypeInfo.s_void;
|
||||
case ElementType.Boolean: return TypeInfo.s_u1;
|
||||
case ElementType.I1: return TypeInfo.s_i1;
|
||||
case ElementType.U1: return TypeInfo.s_u1;
|
||||
case ElementType.I2: return TypeInfo.s_i2;
|
||||
case ElementType.Char:
|
||||
case ElementType.U2: return TypeInfo.s_u2;
|
||||
case ElementType.I4: return TypeInfo.s_i4;
|
||||
case ElementType.U4: return TypeInfo.s_u4;
|
||||
case ElementType.I8: return TypeInfo.s_i8;
|
||||
case ElementType.U8: return TypeInfo.s_u8;
|
||||
case ElementType.R4: return TypeInfo.s_r4;
|
||||
case ElementType.R8: return TypeInfo.s_r8;
|
||||
case ElementType.U: return IsArch32 ? TypeInfo.s_u4 : TypeInfo.s_u8;
|
||||
case ElementType.I:
|
||||
case ElementType.String:
|
||||
case ElementType.Ptr:
|
||||
case ElementType.ByRef:
|
||||
case ElementType.Class:
|
||||
case ElementType.Array:
|
||||
case ElementType.SZArray:
|
||||
case ElementType.FnPtr:
|
||||
case ElementType.Object:
|
||||
case ElementType.Module:
|
||||
case ElementType.Var:
|
||||
case ElementType.MVar:
|
||||
return GetNativeIntTypeInfo();
|
||||
case ElementType.TypedByRef: return CreateValueType(type);
|
||||
case ElementType.ValueType:
|
||||
{
|
||||
TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDef();
|
||||
if (typeDef == null)
|
||||
{
|
||||
throw new Exception($"type:{type} 未能找到定义。请尝试 `HybridCLR/Genergate/LinkXml`,然后Build一次生成AOT dll,再重新生成桥接函数");
|
||||
}
|
||||
if (typeDef.IsEnum)
|
||||
{
|
||||
return CreateTypeInfo(typeDef.GetEnumUnderlyingType());
|
||||
}
|
||||
return CreateValueType(type);
|
||||
}
|
||||
case ElementType.GenericInst:
|
||||
{
|
||||
GenericInstSig gis = (GenericInstSig)type;
|
||||
if (!gis.GenericType.IsValueType)
|
||||
{
|
||||
return GetNativeIntTypeInfo();
|
||||
}
|
||||
TypeDef typeDef = gis.GenericType.ToTypeDefOrRef().ResolveTypeDef();
|
||||
if (typeDef.IsEnum)
|
||||
{
|
||||
return CreateTypeInfo(typeDef.GetEnumUnderlyingType());
|
||||
}
|
||||
return CreateValueType(type);
|
||||
}
|
||||
default: throw new NotSupportedException($"{type.ElementType}");
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsNotHFAFastCheck(int typeSize)
|
||||
{
|
||||
return typeSize != 8 && typeSize != 12 && typeSize != 16 && typeSize != 24 && typeSize != 32;
|
||||
}
|
||||
|
||||
private static bool ComputHFATypeInfo0(TypeSig type, HFATypeInfo typeInfo)
|
||||
{
|
||||
TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDefThrow();
|
||||
|
||||
List<TypeSig> klassInst = type.ToGenericInstSig()?.GenericArguments?.ToList();
|
||||
GenericArgumentContext ctx = klassInst != null ? new GenericArgumentContext(klassInst, null) : null;
|
||||
|
||||
var fields = typeDef.Fields;// typeDef.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
foreach (FieldDef field in fields)
|
||||
{
|
||||
if (field.IsStatic)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
TypeSig ftype = ctx != null ? MetaUtil.Inflate(field.FieldType, ctx) : field.FieldType;
|
||||
switch (ftype.ElementType)
|
||||
{
|
||||
case ElementType.R4:
|
||||
case ElementType.R8:
|
||||
{
|
||||
if (ftype == typeInfo.Type || typeInfo.Type == null)
|
||||
{
|
||||
typeInfo.Type = ftype;
|
||||
++typeInfo.Count;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ElementType.ValueType:
|
||||
{
|
||||
if (!ComputHFATypeInfo0(ftype, typeInfo))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ElementType.GenericInst:
|
||||
{
|
||||
if (!ftype.IsValueType || !ComputHFATypeInfo0(ftype, typeInfo))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
return typeInfo.Count <= 4;
|
||||
}
|
||||
|
||||
private static bool ComputHFATypeInfo(TypeSig type, int typeSize, out HFATypeInfo typeInfo)
|
||||
{
|
||||
typeInfo = new HFATypeInfo();
|
||||
if (IsNotHFAFastCheck(typeSize))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool ok = ComputHFATypeInfo0(type, typeInfo);
|
||||
if (ok && typeInfo.Count >= 2 && typeInfo.Count <= 4)
|
||||
{
|
||||
int fieldSize = typeInfo.Type.ElementType == ElementType.R4 ? 4 : 8;
|
||||
return typeSize == fieldSize * typeInfo.Count;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool TryComputSingletonStruct(TypeSig type, out SingletonStruct result)
|
||||
{
|
||||
result = new SingletonStruct();
|
||||
return TryComputSingletonStruct0(type, result) && result.Type != null;
|
||||
}
|
||||
|
||||
public static bool TryComputSingletonStruct0(TypeSig type, SingletonStruct result)
|
||||
{
|
||||
TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDefThrow();
|
||||
if (typeDef.IsEnum)
|
||||
{
|
||||
if (result.Type == null)
|
||||
{
|
||||
result.Type = typeDef.GetEnumUnderlyingType();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
List<TypeSig> klassInst = type.ToGenericInstSig()?.GenericArguments?.ToList();
|
||||
GenericArgumentContext ctx = klassInst != null ? new GenericArgumentContext(klassInst, null) : null;
|
||||
|
||||
var fields = typeDef.Fields;// typeDef.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
foreach (FieldDef field in fields)
|
||||
{
|
||||
if (field.IsStatic)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
TypeSig ftype = ctx != null ? MetaUtil.Inflate(field.FieldType, ctx) : field.FieldType;
|
||||
|
||||
switch (ftype.ElementType)
|
||||
{
|
||||
case ElementType.TypedByRef: return false;
|
||||
case ElementType.ValueType:
|
||||
{
|
||||
if (!TryComputSingletonStruct0(ftype, result))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ElementType.GenericInst:
|
||||
{
|
||||
if (!ftype.IsValueType)
|
||||
{
|
||||
goto default;
|
||||
}
|
||||
if (!TryComputSingletonStruct0(ftype, result))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
if (result.Type != null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
result.Type = ftype;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool IsWebGLSpeicalValueType(TypeSig type)
|
||||
{
|
||||
TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDefThrow();
|
||||
if (typeDef.IsEnum)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var fields = typeDef.Fields;// typeDef.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
if (fields.Count == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return fields.All(f => f.IsStatic);
|
||||
}
|
||||
|
||||
protected static TypeInfo CreateGeneralValueType(TypeSig type, int size, int aligment)
|
||||
{
|
||||
System.Diagnostics.Debug.Assert(size % aligment == 0);
|
||||
switch (aligment)
|
||||
{
|
||||
case 1: return new TypeInfo(ParamOrReturnType.STRUCTURE_ALIGN1, size);
|
||||
case 2: return new TypeInfo(ParamOrReturnType.STRUCTURE_ALIGN2, size);
|
||||
case 4: return new TypeInfo(ParamOrReturnType.STRUCTURE_ALIGN4, size);
|
||||
case 8: return new TypeInfo(ParamOrReturnType.STRUCTURE_ALIGN8, size);
|
||||
default: throw new NotSupportedException($"type:{type} not support aligment:{aligment}");
|
||||
}
|
||||
}
|
||||
|
||||
protected TypeInfo CreateValueType(TypeSig type)
|
||||
{
|
||||
(int typeSize, int typeAligment) = ComputeSizeAndAligment(type);
|
||||
if (IsSupportHFA && ComputHFATypeInfo(type, typeSize, out HFATypeInfo hfaTypeInfo))
|
||||
{
|
||||
bool isFloat = hfaTypeInfo.Type.ElementType == ElementType.R4;
|
||||
switch (hfaTypeInfo.Count)
|
||||
{
|
||||
case 2: return isFloat ? TypeInfo.s_vf2 : TypeInfo.s_vd2;
|
||||
case 3: return isFloat ? TypeInfo.s_vf3 : TypeInfo.s_vd3;
|
||||
case 4: return isFloat ? TypeInfo.s_vf4 : TypeInfo.s_vd4;
|
||||
default: throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
if (IsSupportWebGLSpecialValueType && IsWebGLSpeicalValueType(type))
|
||||
{
|
||||
switch (typeAligment)
|
||||
{
|
||||
case 1: return new TypeInfo(ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN1, typeSize);
|
||||
case 2: return new TypeInfo(ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN2, typeSize);
|
||||
case 4: return new TypeInfo(ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN4, typeSize);
|
||||
case 8: return new TypeInfo(ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN8, typeSize);
|
||||
default: throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 64位下结构体内存对齐规则是一样的
|
||||
return CreateGeneralValueType(type, typeSize, typeAligment);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected abstract TypeInfo OptimizeSigType(TypeInfo type, bool returnType);
|
||||
|
||||
public virtual void OptimizeMethod(MethodDesc method)
|
||||
{
|
||||
method.TransfromSigTypes(OptimizeSigType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HybridCLR.Editor.ABI
|
||||
{
|
||||
public static class TypeCreatorFactory
|
||||
{
|
||||
public static TypeCreatorBase CreateTypeCreator(PlatformABI abi)
|
||||
{
|
||||
switch(abi)
|
||||
{
|
||||
case PlatformABI.Arm64: return new TypeCreatorArm64();
|
||||
case PlatformABI.Universal32: return new TypeCreatorUniversal32();
|
||||
case PlatformABI.Universal64: return new TypeCreatorUniversal64();
|
||||
case PlatformABI.WebGL32: return new TypeCreatorWebGL32();
|
||||
default: throw new NotSupportedException(abi.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HybridCLR.Editor.ABI
|
||||
{
|
||||
public class TypeCreatorUniversal32 : TypeCreatorBase
|
||||
{
|
||||
public override bool IsArch32 => true;
|
||||
|
||||
public override bool IsSupportHFA => false;
|
||||
|
||||
protected override TypeInfo OptimizeSigType(TypeInfo type, bool returnType)
|
||||
{
|
||||
if (type.PorType > ParamOrReturnType.STRUCTURE_ALIGN1 && type.PorType <= ParamOrReturnType.STRUCTURE_ALIGN4)
|
||||
{
|
||||
return new TypeInfo(ParamOrReturnType.STRUCTURE_ALIGN1, type.Size);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1eb9e19189731a344aad024a43e795bc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HybridCLR.Editor.ABI
|
||||
{
|
||||
public class TypeCreatorUniversal64 : TypeCreatorBase
|
||||
{
|
||||
public override bool IsArch32 => false;
|
||||
|
||||
public override bool IsSupportHFA => true;
|
||||
|
||||
protected override TypeInfo OptimizeSigType(TypeInfo type, bool returnType)
|
||||
{
|
||||
if (type.PorType > ParamOrReturnType.STRUCTURE_ALIGN1 && type.PorType <= ParamOrReturnType.STRUCTURE_ALIGN8)
|
||||
{
|
||||
return new TypeInfo(ParamOrReturnType.STRUCTURE_ALIGN1, type.Size);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7867dfe20d27e324e90bc13b9d4f05bb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
using dnlib.DotNet;
|
||||
using HybridCLR.Editor.Meta;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HybridCLR.Editor.ABI
|
||||
{
|
||||
public class SingletonStruct
|
||||
{
|
||||
public TypeSig Type { get; set; }
|
||||
}
|
||||
|
||||
public class TypeCreatorWebGL32 : TypeCreatorBase
|
||||
{
|
||||
public override bool IsArch32 => true;
|
||||
|
||||
public override bool IsSupportHFA => false;
|
||||
|
||||
public override bool IsSupportWebGLSpecialValueType => true;
|
||||
|
||||
|
||||
protected override TypeInfo OptimizeSigType(TypeInfo type, bool returnType)
|
||||
{
|
||||
//if (type.PorType > ParamOrReturnType.STRUCTURE_ALIGN1 && type.PorType <= ParamOrReturnType.STRUCTURE_ALIGN4)
|
||||
//{
|
||||
// return new TypeInfo(ParamOrReturnType.STRUCTURE_ALIGN1, type.Size);
|
||||
//}
|
||||
return type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4790a87aacda1a14d813570e9e0f35ca
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
using dnlib.DotNet;
|
||||
using HybridCLR.Editor.Meta;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
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_r4 = new TypeInfo(ParamOrReturnType.R4);
|
||||
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_ref = new TypeInfo(ParamOrReturnType.STRUCTURE_AS_REF_PARAM);
|
||||
public static readonly TypeInfo s_i = new TypeInfo(ParamOrReturnType.I);
|
||||
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 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 const string strTypedByRef = "typedbyref";
|
||||
|
||||
public TypeInfo(ParamOrReturnType portype)
|
||||
public TypeInfo(ParamOrReturnType portype, TypeSig klass = null, int typeId = 0)
|
||||
{
|
||||
PorType = portype;
|
||||
Size = 0;
|
||||
}
|
||||
|
||||
public TypeInfo(ParamOrReturnType portype, int size)
|
||||
{
|
||||
PorType = portype;
|
||||
Size = size;
|
||||
Klass = klass;
|
||||
_typeId = typeId;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return PorType == other.PorType && Size == other.Size;
|
||||
return PorType == other.PorType && TypeEqualityComparer.Instance.Equals(Klass, other.Klass);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
|
|
@ -60,7 +58,12 @@ namespace HybridCLR.Editor.ABI
|
|||
|
||||
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()
|
||||
|
|
@ -78,22 +81,10 @@ namespace HybridCLR.Editor.ABI
|
|||
case ParamOrReturnType.U8: return "u8";
|
||||
case ParamOrReturnType.R4: return "r4";
|
||||
case ParamOrReturnType.R8: return "r8";
|
||||
case ParamOrReturnType.I16: return "i16";
|
||||
case ParamOrReturnType.STRUCTURE_AS_REF_PARAM: return "sr";
|
||||
case ParamOrReturnType.ARM64_HFA_FLOAT_2: return "vf2";
|
||||
case ParamOrReturnType.ARM64_HFA_FLOAT_3: return "vf3";
|
||||
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;
|
||||
case ParamOrReturnType.I: return "i";
|
||||
case ParamOrReturnType.U: return "u";
|
||||
case ParamOrReturnType.TYPEDBYREF: return strTypedByRef;
|
||||
case ParamOrReturnType.STRUCT: return $"s{_typeId}";
|
||||
default: throw new NotSupportedException(PorType.ToString());
|
||||
};
|
||||
}
|
||||
|
|
@ -113,55 +104,13 @@ namespace HybridCLR.Editor.ABI
|
|||
case ParamOrReturnType.U8: return "uint64_t";
|
||||
case ParamOrReturnType.R4: return "float";
|
||||
case ParamOrReturnType.R8: return "double";
|
||||
case ParamOrReturnType.I16: return "ValueTypeSize16";
|
||||
case ParamOrReturnType.STRUCTURE_AS_REF_PARAM: return "uint64_t";
|
||||
case ParamOrReturnType.ARM64_HFA_FLOAT_2: return "HtVector2f";
|
||||
case ParamOrReturnType.ARM64_HFA_FLOAT_3: return "HtVector3f";
|
||||
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}>";
|
||||
case ParamOrReturnType.I: return "intptr_t";
|
||||
case ParamOrReturnType.U: return "uintptr_t";
|
||||
case ParamOrReturnType.TYPEDBYREF: return "Il2CppTypedRef";
|
||||
case ParamOrReturnType.STRUCT: return $"__struct_{_typeId}__";
|
||||
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
|
||||
guid: b63c5bf995a6d624dbd10d9df6cb6a7a
|
||||
guid: 7e9e6a048682dcb4fab806251411f29f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
@ -17,12 +17,16 @@ namespace HybridCLR.Editor.AOT
|
|||
public AssemblyReferenceDeepCollector Collector { get; set; }
|
||||
|
||||
public int MaxIterationCount { get; set; }
|
||||
|
||||
public bool ComputeAotAssembly { get; set; }
|
||||
}
|
||||
|
||||
private readonly int _maxInterationCount;
|
||||
|
||||
private readonly AssemblyReferenceDeepCollector _assemblyCollector;
|
||||
|
||||
private readonly bool _computeAotAssembly;
|
||||
|
||||
private readonly HashSet<GenericClass> _genericTypes = new HashSet<GenericClass>();
|
||||
private readonly HashSet<GenericMethod> _genericMethods = new HashSet<GenericMethod>();
|
||||
|
||||
|
|
@ -47,6 +51,7 @@ namespace HybridCLR.Editor.AOT
|
|||
{
|
||||
_assemblyCollector = options.Collector;
|
||||
_maxInterationCount = options.MaxIterationCount;
|
||||
_computeAotAssembly = options.ComputeAotAssembly;
|
||||
_methodReferenceAnalyzer = new MethodReferenceAnalyzer(this.OnNewMethod);
|
||||
_hotUpdateAssemblyFiles = new HashSet<string>(options.Collector.GetRootAssemblyNames().Select(assName => assName + ".dll"));
|
||||
}
|
||||
|
|
@ -58,20 +63,20 @@ namespace HybridCLR.Editor.AOT
|
|||
return;
|
||||
}
|
||||
gc = gc.ToGenericShare();
|
||||
if (_genericTypes.Add(gc) && NeedWalk(gc.Type))
|
||||
if (_genericTypes.Add(gc) && NeedWalk(null, gc.Type))
|
||||
{
|
||||
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)
|
||||
{
|
||||
return !_hotUpdateAssemblyFiles.Contains(type.Module.Name);
|
||||
return _computeAotAssembly || !_hotUpdateAssemblyFiles.Contains(type.Module.Name);
|
||||
}
|
||||
|
||||
private bool IsAotGenericMethod(MethodDef method)
|
||||
|
|
@ -79,13 +84,13 @@ namespace HybridCLR.Editor.AOT
|
|||
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)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (_genericMethods.Add(method) && NeedWalk(method.Method.DeclaringType))
|
||||
if (NeedWalk(methodDef, method.Method.DeclaringType) && _genericMethods.Add(method))
|
||||
{
|
||||
_newMethods.Add(method);
|
||||
}
|
||||
|
|
@ -101,7 +106,7 @@ namespace HybridCLR.Editor.AOT
|
|||
{
|
||||
return;
|
||||
}
|
||||
if (_genericMethods.Add(method) && NeedWalk(method.Method.DeclaringType))
|
||||
if (NeedWalk(null, method.Method.DeclaringType) && _genericMethods.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++)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -167,10 +172,6 @@ namespace HybridCLR.Editor.AOT
|
|||
for (uint rid = 1, n = ass.Metadata.TablesStream.MethodSpecTable.Rows; rid <= n; rid++)
|
||||
{
|
||||
var ms = ass.ResolveMethodSpec(rid);
|
||||
if (ms.DeclaringType.ContainsGenericParameter || ms.GenericInstMethodSig.ContainsGenericParameter)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var gm = GenericMethod.ResolveMethod(ms, null)?.ToGenericShare();
|
||||
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()
|
||||
{
|
||||
ConstraintContext cc = this.ConstraintContext;
|
||||
AotGenericTypes.AddRange(_genericTypes.Where(type => IsAotType(type.Type)).Select(gc => cc.ApplyConstraints(gc)));
|
||||
AotGenericMethods.AddRange(_genericMethods.Where(method => IsAotGenericMethod(method.Method)).Select(gm => cc.ApplyConstraints(gm)));
|
||||
AotGenericTypes.AddRange(_genericTypes.Where(type => IsNotShareableAOTGenericType(type.Type)).Select(gc => cc.ApplyConstraints(gc)));
|
||||
AotGenericMethods.AddRange(_genericMethods.Where(method => IsNotShareableAOTGenericMethod(method.Method)).Select(gm => cc.ApplyConstraints(gm)));
|
||||
}
|
||||
|
||||
public void Run()
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ namespace HybridCLR.Editor.AOT
|
|||
{
|
||||
_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)
|
||||
|
|
@ -64,18 +64,22 @@ namespace HybridCLR.Editor.AOT
|
|||
Directory.CreateDirectory(parentDir);
|
||||
|
||||
List<string> codes = new List<string>();
|
||||
codes.Add("using System.Collections.Generic;");
|
||||
codes.Add("public class AOTGenericReferences : UnityEngine.MonoBehaviour");
|
||||
codes.Add("{");
|
||||
|
||||
codes.Add("");
|
||||
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>(
|
||||
types.Select(t => t.Type.Module).Concat(methods.Select(m => m.Method.Module))).ToList();
|
||||
modules.Sort((a, b) => a.Name.CompareTo(b.Name));
|
||||
foreach (dnlib.DotNet.ModuleDef module in modules)
|
||||
{
|
||||
codes.Add($"\t// {module.Name}");
|
||||
codes.Add($"\t\t\"{module.Name}\",");
|
||||
}
|
||||
codes.Add("\t};");
|
||||
codes.Add("\t// }}");
|
||||
|
||||
|
||||
|
|
@ -86,11 +90,12 @@ namespace HybridCLR.Editor.AOT
|
|||
|
||||
codes.Add("");
|
||||
codes.Add("\t// {{ AOT generic types");
|
||||
|
||||
types.Sort((a, b) => a.Type.FullName.CompareTo(b.Type.FullName));
|
||||
foreach(var type in types)
|
||||
|
||||
List<string> typeNames = types.Select(t => PrettifyTypeSig(t.ToTypeSig().ToString())).ToList();
|
||||
typeNames.Sort(string.CompareOrdinal);
|
||||
foreach(var typeName in typeNames)
|
||||
{
|
||||
codes.Add($"\t// {PrettifyTypeSig(type.ToTypeSig().ToString())}");
|
||||
codes.Add($"\t// {typeName}");
|
||||
}
|
||||
|
||||
codes.Add("\t// }}");
|
||||
|
|
@ -98,27 +103,36 @@ namespace HybridCLR.Editor.AOT
|
|||
codes.Add("");
|
||||
codes.Add("\tpublic void RefMethods()");
|
||||
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)
|
||||
{
|
||||
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("}");
|
||||
|
||||
|
||||
var utf8WithoutBOM = new System.Text.UTF8Encoding(false);
|
||||
File.WriteAllText(outputFile, string.Join("\n", codes), utf8WithoutBOM);
|
||||
var utf8WithoutBom = new System.Text.UTF8Encoding(false);
|
||||
File.WriteAllText(outputFile, string.Join("\n", codes), utf8WithoutBom);
|
||||
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
|
||||
guid: fe1634f74b7ca2e42bd07233b451cd94
|
||||
guid: d2f62ca12f2eb4f2fba8e9cb51279421
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
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.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Build;
|
||||
using UnityEditor.Build.Reporting;
|
||||
using UnityEngine;
|
||||
using static UnityEngine.GraphicsBuffer;
|
||||
|
||||
namespace HybridCLR.Editor.BuildProcessors
|
||||
{
|
||||
|
|
@ -13,17 +18,18 @@ namespace HybridCLR.Editor.BuildProcessors
|
|||
{
|
||||
public int callbackOrder => 0;
|
||||
|
||||
public static bool DisableMethodBridgeDevelopmentFlagChecking { get; set; }
|
||||
|
||||
public void OnPreprocessBuild(BuildReport report)
|
||||
{
|
||||
HybridCLRSettings globalSettings = SettingsUtil.HybridCLRSettings;
|
||||
#if !UNITY_2020_1_OR_NEWER || !UNITY_IOS
|
||||
if (!globalSettings.enable || globalSettings.useGlobalIl2cpp)
|
||||
{
|
||||
string oldIl2cppPath = Environment.GetEnvironmentVariable("UNITY_IL2CPP_PATH");
|
||||
if (!string.IsNullOrEmpty(oldIl2cppPath))
|
||||
{
|
||||
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
|
||||
|
|
@ -32,32 +38,57 @@ namespace HybridCLR.Editor.BuildProcessors
|
|||
if (curIl2cppPath != 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)
|
||||
{
|
||||
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,已经自动将该选项关闭");
|
||||
UnityEditor.PlayerSettings.gcIncremental = false;
|
||||
Debug.LogError($"[CheckSettings] current ScriptingBackend:{curScriptingImplementation},have been switched to:{targetScriptingImplementation} automatically");
|
||||
PlayerSettings.SetScriptingBackend(buildTargetGroup, targetScriptingImplementation);
|
||||
}
|
||||
|
||||
var installer = new Installer.InstallerController();
|
||||
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;
|
||||
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.IO;
|
||||
using System.Linq;
|
||||
|
|
@ -7,13 +8,15 @@ using System.Threading.Tasks;
|
|||
using UnityEditor;
|
||||
using UnityEditor.Build;
|
||||
using UnityEditor.Build.Reporting;
|
||||
using UnityEditor.Il2Cpp;
|
||||
using UnityEditor.UnityLinker;
|
||||
using UnityEngine;
|
||||
#if !UNITY_2021_1_OR_NEWER
|
||||
using UnityEditor.Il2Cpp;
|
||||
#endif
|
||||
|
||||
namespace HybridCLR.Editor.BuildProcessors
|
||||
{
|
||||
internal class CopyStrippedAOTAssemblies : IPostprocessBuildWithReport
|
||||
internal class CopyStrippedAOTAssemblies : IPostprocessBuildWithReport, IPreprocessBuildWithReport
|
||||
#if !UNITY_2021_1_OR_NEWER
|
||||
, IIl2CppProcessor
|
||||
#endif
|
||||
|
|
@ -25,19 +28,52 @@ namespace HybridCLR.Editor.BuildProcessors
|
|||
public static string GetStripAssembliesDir2021(BuildTarget target)
|
||||
{
|
||||
string projectDir = SettingsUtil.ProjectDir;
|
||||
#if UNITY_STANDALONE_WIN
|
||||
return $"{projectDir}/Library/Bee/artifacts/WinPlayerBuildProgram/ManagedStripped";
|
||||
#elif UNITY_ANDROID
|
||||
return $"{projectDir}/Library/Bee/artifacts/Android/ManagedStripped";
|
||||
#elif UNITY_IOS
|
||||
return $"{projectDir}/Temp/StagingArea/Data/Managed/tempStrip";
|
||||
#elif UNITY_WEBGL
|
||||
return $"{projectDir}/Library/Bee/artifacts/WebGL/ManagedStripped";
|
||||
#elif UNITY_EDITOR_OSX
|
||||
return $"{projectDir}/Library/Bee/artifacts/MacStandalonePlayerBuildProgram/ManagedStripped";
|
||||
#else
|
||||
throw new NotSupportedException("GetOriginBuildStripAssembliesDir");
|
||||
switch (target)
|
||||
{
|
||||
case BuildTarget.StandaloneWindows:
|
||||
case BuildTarget.StandaloneWindows64:
|
||||
return $"{projectDir}/Library/Bee/artifacts/WinPlayerBuildProgram/ManagedStripped";
|
||||
case BuildTarget.StandaloneLinux64:
|
||||
return $"{projectDir}/Library/Bee/artifacts/LinuxPlayerBuildProgram/ManagedStripped";
|
||||
case BuildTarget.WSAPlayer:
|
||||
return $"{projectDir}/Library/Bee/artifacts/UWPPlayerBuildProgram/ManagedStripped";
|
||||
case BuildTarget.Android:
|
||||
return $"{projectDir}/Library/Bee/artifacts/Android/ManagedStripped";
|
||||
#if TUANJIE_2022_3_OR_NEWER
|
||||
case BuildTarget.HMIAndroid:
|
||||
return $"{projectDir}/Library/Bee/artifacts/HMIAndroid/ManagedStripped";
|
||||
#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
|
||||
private string GetStripAssembliesDir2020(BuildTarget target)
|
||||
|
|
@ -49,9 +85,9 @@ namespace HybridCLR.Editor.BuildProcessors
|
|||
}
|
||||
|
||||
public void OnBeforeConvertRun(BuildReport report, Il2CppBuildPipelineData data)
|
||||
{
|
||||
// 此回调只在 2020中调用
|
||||
CopyStripDlls(GetStripAssembliesDir2020(data.target), data.target);
|
||||
{
|
||||
BuildTarget target = report.summary.platform;
|
||||
CopyStripDlls(GetStripAssembliesDir2020(target), target);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -78,10 +114,21 @@ namespace HybridCLR.Editor.BuildProcessors
|
|||
|
||||
public void OnPostprocessBuild(BuildReport report)
|
||||
{
|
||||
#if UNITY_2021_1_OR_NEWER && !UNITY_IOS
|
||||
BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
|
||||
CopyStripDlls(GetStripAssembliesDir2021(target), target);
|
||||
#if UNITY_2021_1_OR_NEWER
|
||||
BuildTarget target = report.summary.platform;
|
||||
string srcStripDllPath = GetStripAssembliesDir2021(target);
|
||||
if (!string.IsNullOrEmpty(srcStripDllPath) && Directory.Exists(srcStripDllPath))
|
||||
{
|
||||
CopyStripDlls(srcStripDllPath, target);
|
||||
}
|
||||
#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 System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
|
@ -25,15 +26,18 @@ namespace HybridCLR.Editor.BuildProcessors
|
|||
return assemblies;
|
||||
}
|
||||
List<string> allHotUpdateDllNames = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved;
|
||||
List<string> allHotupdateDllFiles = SettingsUtil.HotUpdateAssemblyFilesExcludePreserved;
|
||||
|
||||
// 检查是否重复填写
|
||||
var hotUpdateDllSet = new HashSet<string>();
|
||||
foreach(var hotUpdateDll in allHotUpdateDllNames)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(hotUpdateDll))
|
||||
{
|
||||
throw new BuildFailedException($"hot update assembly name cann't be empty");
|
||||
}
|
||||
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名称
|
||||
foreach (var hotUpdateDllName in allHotUpdateDllNames)
|
||||
{
|
||||
string hotUpdateDllFile = hotUpdateDllName + ".dll";
|
||||
if (assemblies.All(ass => !ass.EndsWith(hotUpdateDllFile)) && string.IsNullOrEmpty(assResolver.ResolveAssembly(hotUpdateDllName, false)))
|
||||
if (assemblies.Select(Path.GetFileNameWithoutExtension).All(ass => ass != hotUpdateDllName)
|
||||
&& 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从打包列表中移除
|
||||
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.Build;
|
||||
using UnityEditor.Build.Reporting;
|
||||
using UnityEditor.Il2Cpp;
|
||||
using UnityEditor.UnityLinker;
|
||||
using UnityEngine;
|
||||
using UnityFS;
|
||||
#if !UNITY_2023_1_OR_NEWER
|
||||
using UnityEditor.Il2Cpp;
|
||||
#endif
|
||||
|
||||
namespace HybridCLR.Editor.BuildProcessors
|
||||
{
|
||||
public class PatchScriptingAssemblyList :
|
||||
#if UNITY_ANDROID
|
||||
IPostGenerateGradleAndroidProject,
|
||||
#elif UNITY_OPENHARMONY
|
||||
UnityEditor.OpenHarmony.IPostGenerateOpenHarmonyProject,
|
||||
#endif
|
||||
IPostprocessBuildWithReport
|
||||
#if !UNITY_2021_1_OR_NEWER && UNITY_WEBGL
|
||||
, IIl2CppProcessor
|
||||
, IIl2CppProcessor
|
||||
#endif
|
||||
|
||||
#if UNITY_PS5
|
||||
, IUnityLinkerProcessor
|
||||
#endif
|
||||
|
||||
{
|
||||
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)
|
||||
{
|
||||
// 如果target为Android,由于已经在OnPostGenerateGradelAndroidProject中处理过,
|
||||
// 这里不再重复处理
|
||||
#if !UNITY_ANDROID && !UNITY_WEBGL
|
||||
|
||||
#if !UNITY_ANDROID && !UNITY_WEBGL && !UNITY_OPENHARMONY
|
||||
PathScriptingAssembilesFile(report.summary.outputPath);
|
||||
#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)
|
||||
{
|
||||
if (!SettingsUtil.Enable)
|
||||
|
|
@ -84,7 +113,7 @@ namespace HybridCLR.Editor.BuildProcessors
|
|||
|
||||
if (jsonFiles.Length == 0)
|
||||
{
|
||||
//Debug.LogError($"can not find file {SettingsUtil.ScriptingAssembliesJsonFile}");
|
||||
Debug.LogWarning($"can not find file {SettingsUtil.ScriptingAssembliesJsonFile}");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -96,9 +125,11 @@ namespace HybridCLR.Editor.BuildProcessors
|
|||
patcher.Save(file);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddHotFixAssembliesToBinFile(string path)
|
||||
{
|
||||
#if UNITY_STANDALONE_OSX
|
||||
path = Path.GetDirectoryName(path);
|
||||
#endif
|
||||
if (AddHotFixAssembliesToGlobalgamemanagers(path))
|
||||
{
|
||||
return;
|
||||
|
|
@ -148,7 +179,7 @@ namespace HybridCLR.Editor.BuildProcessors
|
|||
return true;
|
||||
}
|
||||
|
||||
#if UNITY_WEBGL
|
||||
#if UNITY_WEBGL && !UNITY_2022_3_OR_NEWER
|
||||
public void OnBeforeConvertRun(BuildReport report, Il2CppBuildPipelineData 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 System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
|
@ -10,6 +11,7 @@ using UnityEngine;
|
|||
|
||||
namespace HybridCLR.Editor.Commands
|
||||
{
|
||||
using Analyzer = HybridCLR.Editor.AOT.Analyzer;
|
||||
public static class AOTReferenceGeneratorCommand
|
||||
{
|
||||
|
||||
|
|
@ -21,25 +23,110 @@ namespace HybridCLR.Editor.Commands
|
|||
GenerateAOTGenericReference(target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算热更代码中的泛型引用
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
public static void GenerateAOTGenericReference(BuildTarget target)
|
||||
{
|
||||
var gs = SettingsUtil.HybridCLRSettings;
|
||||
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();
|
||||
writer.Write(analyzer.AotGenericTypes.ToList(), analyzer.AotGenericMethods.ToList(), $"{Application.dataPath}/{gs.outputAOTGenericReferenceFile}");
|
||||
AssetDatabase.Refresh();
|
||||
var writer = new GenericReferenceWriter();
|
||||
writer.Write(analyzer.AotGenericTypes.ToList(), analyzer.AotGenericMethods.ToList(), $"{Application.dataPath}/{gs.outputAOTGenericReferenceFile}");
|
||||
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 static void CompileDll(string buildDir, BuildTarget target)
|
||||
public static void CompileDll(string buildDir, BuildTarget target, bool developmentBuild)
|
||||
{
|
||||
var group = BuildPipeline.GetBuildTargetGroup(target);
|
||||
|
||||
ScriptCompilationSettings scriptCompilationSettings = new ScriptCompilationSettings();
|
||||
scriptCompilationSettings.group = group;
|
||||
scriptCompilationSettings.target = target;
|
||||
scriptCompilationSettings.options = developmentBuild ? ScriptCompilationOptions.DevelopmentBuild : ScriptCompilationOptions.None;
|
||||
Directory.CreateDirectory(buildDir);
|
||||
ScriptCompilationResult scriptCompilationResult = PlayerBuildInterface.CompilePlayerScripts(scriptCompilationSettings, buildDir);
|
||||
foreach (var ass in scriptCompilationResult.assemblies)
|
||||
{
|
||||
//Debug.LogFormat("compile assemblies:{1}/{0}", ass, buildDir);
|
||||
}
|
||||
Debug.Log("compile finish!!!");
|
||||
#if UNITY_2022
|
||||
UnityEditor.EditorUtility.ClearProgressBar();
|
||||
#endif
|
||||
Debug.Log($"compile finish!!! buildDir:{buildDir} target:{target} development:{developmentBuild}");
|
||||
}
|
||||
|
||||
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)]
|
||||
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)]
|
||||
|
|
@ -51,16 +68,34 @@ namespace HybridCLR.Editor.Commands
|
|||
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()
|
||||
{
|
||||
CompileDll(BuildTarget.Android);
|
||||
}
|
||||
|
||||
[MenuItem("HybridCLR/CompileDll/IOS", priority = 203)]
|
||||
[MenuItem("HybridCLR/CompileDll/IOS", priority = 220)]
|
||||
public static void CompileDllIOS()
|
||||
{
|
||||
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.Settings;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
|
@ -19,8 +20,10 @@ namespace HybridCLR.Editor.Commands
|
|||
{
|
||||
UnityVersion = Application.unityVersion,
|
||||
HotUpdateAssemblies = SettingsUtil.HotUpdateAssemblyNamesIncludePreserved,
|
||||
OutputFile = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp/il2cpp-config.h",
|
||||
OutputFile2 = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr/Il2CppCompatibleDef.cpp",
|
||||
UnityVersionTemplateFile = $"{SettingsUtil.TemplatePathInPackage}/UnityVersion.h.tpl",
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
using Analyzer = HybridCLR.Editor.Link.Analyzer;
|
||||
|
||||
public static class LinkGeneratorCommand
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,10 +10,12 @@ using System.Reflection;
|
|||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Build;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HybridCLR.Editor.Commands
|
||||
{
|
||||
using Analyzer = HybridCLR.Editor.MethodBridge.Analyzer;
|
||||
public class MethodBridgeGeneratorCommand
|
||||
{
|
||||
|
||||
|
|
@ -28,55 +30,67 @@ namespace HybridCLR.Editor.Commands
|
|||
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()
|
||||
{
|
||||
PlatformABI = platform,
|
||||
TemplateCode = templateCode,
|
||||
OutputFile = outputFile,
|
||||
GenericMethods = analyzer.GenericMethods,
|
||||
NotGenericMethods = analyzer.NotGenericMethods,
|
||||
GenericMethods = genericMethods,
|
||||
ReversePInvokeMethods = reversePInvokeMethods,
|
||||
CalliMethodSignatures = calliMethodSignatures,
|
||||
Development = EditorUserBuildSettings.development,
|
||||
});
|
||||
|
||||
g.PrepareMethods();
|
||||
g.Generate();
|
||||
Debug.LogFormat("== output:{0} ==", outputFile);
|
||||
Debug.LogFormat("[MethodBridgeGeneratorCommand] output:{0}", outputFile);
|
||||
}
|
||||
|
||||
[MenuItem("HybridCLR/Generate/MethodBridge", priority = 101)]
|
||||
public static void CompileAndGenerateMethodBridge()
|
||||
[MenuItem("HybridCLR/Generate/MethodBridgeAndReversePInvokeWrapper", priority = 101)]
|
||||
public static void GenerateMethodBridgeAndReversePInvokeWrapper()
|
||||
{
|
||||
BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
|
||||
CompileDllCommand.CompileDll(target);
|
||||
GenerateMethodBridge(target);
|
||||
GenerateMethodBridgeAndReversePInvokeWrapper(target);
|
||||
}
|
||||
|
||||
public static void GenerateMethodBridge(BuildTarget target)
|
||||
public static void GenerateMethodBridgeAndReversePInvokeWrapper(BuildTarget target)
|
||||
{
|
||||
List<string> hotUpdateDllNames = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved;
|
||||
using (AssemblyReferenceDeepCollector collector = new AssemblyReferenceDeepCollector(MetaUtil.CreateHotUpdateAndAOTAssemblyResolver(target, hotUpdateDllNames), hotUpdateDllNames))
|
||||
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)
|
||||
{
|
||||
var analyzer = new Analyzer(new Analyzer.Options
|
||||
{
|
||||
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());
|
||||
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`");
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ using System.Linq;
|
|||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Build;
|
||||
|
||||
namespace HybridCLR.Editor.Commands
|
||||
{
|
||||
|
|
@ -15,19 +16,23 @@ namespace HybridCLR.Editor.Commands
|
|||
[MenuItem("HybridCLR/Generate/All", priority = 200)]
|
||||
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;
|
||||
CompileDllCommand.CompileDll(target);
|
||||
CompileDllCommand.CompileDll(target, EditorUserBuildSettings.development);
|
||||
Il2CppDefGeneratorCommand.GenerateIl2CppDef();
|
||||
|
||||
// 这几个生成依赖HotUpdateDlls
|
||||
LinkGeneratorCommand.GenerateLinkXml(target);
|
||||
|
||||
// 生成裁剪后的aot dll
|
||||
StripAOTDllCommand.GenerateStripedAOTDlls(target, EditorUserBuildSettings.selectedBuildTargetGroup);
|
||||
StripAOTDllCommand.GenerateStripedAOTDlls(target);
|
||||
|
||||
// 桥接函数生成依赖于AOT dll,必须保证已经build过,生成AOT dll
|
||||
MethodBridgeGeneratorCommand.GenerateMethodBridge(target);
|
||||
ReversePInvokeWrapperGeneratorCommand.GenerateReversePInvokeWrapper(target);
|
||||
MethodBridgeGeneratorCommand.GenerateMethodBridgeAndReversePInvokeWrapper(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.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using static UnityEngine.Networking.UnityWebRequest;
|
||||
|
||||
namespace HybridCLR.Editor.Commands
|
||||
{
|
||||
|
|
@ -15,7 +18,38 @@ namespace HybridCLR.Editor.Commands
|
|||
[MenuItem("HybridCLR/Generate/AOTDlls", priority = 105)]
|
||||
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)
|
||||
|
|
@ -23,100 +57,140 @@ namespace HybridCLR.Editor.Commands
|
|||
switch(target)
|
||||
{
|
||||
case BuildTarget.StandaloneWindows:
|
||||
case BuildTarget.StandaloneWindows64: return $"{buildDir}/{target}";
|
||||
case BuildTarget.StandaloneWindows64: return $"{buildDir}/{PlayerSettings.productName}.exe";
|
||||
case BuildTarget.StandaloneOSX: return buildDir;
|
||||
case BuildTarget.iOS: return buildDir;
|
||||
case BuildTarget.Android: return buildDir;
|
||||
case BuildTarget.StandaloneLinux64: return buildDir;
|
||||
case BuildTarget.StandaloneLinux64: return $"{buildDir}/{PlayerSettings.productName}";
|
||||
default: return buildDir;
|
||||
}
|
||||
}
|
||||
|
||||
public static void GenerateStripedAOTDlls(BuildTarget target, BuildTargetGroup group)
|
||||
public static void GenerateStripedAOTDlls(BuildTarget target)
|
||||
{
|
||||
string outputPath = $"{SettingsUtil.HybridCLRDataDir}/StrippedAOTDllsTempProj/{target}";
|
||||
BashUtil.RemoveDir(outputPath);
|
||||
|
||||
var buildOptions = BuildOptions.BuildScriptsOnly;
|
||||
#if UNITY_2021_1_OR_NEWER
|
||||
buildOptions |= BuildOptions.CleanBuildCache;
|
||||
#endif
|
||||
var buildOptions = GetBuildPlayerOptions(target);
|
||||
|
||||
bool oldExportAndroidProj = EditorUserBuildSettings.exportAsGoogleAndroidProject;
|
||||
#if UNITY_EDITOR_OSX
|
||||
bool oldCreateSolution = UnityEditor.OSXStandalone.UserBuildSettings.createXcodeProject;
|
||||
#elif UNITY_EDITOR_WIN
|
||||
bool oldCreateSolution = UnityEditor.WindowsStandalone.UserBuildSettings.createSolution;
|
||||
#endif
|
||||
#if TUANJIE_2022_3_OR_NEWER
|
||||
bool oldOpenHarmonyProj = EditorUserBuildSettings.exportAsOpenHarmonyProject;
|
||||
#endif
|
||||
bool oldBuildScriptsOnly = EditorUserBuildSettings.buildScriptsOnly;
|
||||
EditorUserBuildSettings.buildScriptsOnly = true;
|
||||
|
||||
switch (target)
|
||||
string oldBuildLocation = EditorUserBuildSettings.GetBuildLocation(target);
|
||||
try
|
||||
{
|
||||
case BuildTarget.StandaloneWindows:
|
||||
case BuildTarget.StandaloneWindows64:
|
||||
CheckSettings.DisableMethodBridgeDevelopmentFlagChecking = true;
|
||||
EditorUserBuildSettings.buildScriptsOnly = true;
|
||||
|
||||
string location = GetLocationPathName(outputPath, target);
|
||||
EditorUserBuildSettings.SetBuildLocation(target, location);
|
||||
|
||||
switch (target)
|
||||
{
|
||||
#if UNITY_EDITOR_WIN
|
||||
UnityEditor.WindowsStandalone.UserBuildSettings.createSolution = true;
|
||||
#endif
|
||||
case BuildTarget.StandaloneWindows:
|
||||
case BuildTarget.StandaloneWindows64:
|
||||
{
|
||||
#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;
|
||||
}
|
||||
#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
|
||||
UnityEditor.OSXStandalone.UserBuildSettings.createXcodeProject = true;
|
||||
scenes = EditorBuildSettings.scenes.Where(s => s.enabled).Select(s => s.path).ToArray(),
|
||||
locationPathName = location,
|
||||
options = buildOptions,
|
||||
target = target,
|
||||
targetGroup = BuildPipeline.GetBuildTargetGroup(target),
|
||||
#if UNITY_SERVER
|
||||
subtarget = (int)StandaloneBuildSubtarget.Server,
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case BuildTarget.Android:
|
||||
};
|
||||
|
||||
var report = BuildPipeline.BuildPlayer(buildPlayerOptions);
|
||||
|
||||
|
||||
|
||||
if (report.summary.result != UnityEditor.Build.Reporting.BuildResult.Succeeded)
|
||||
{
|
||||
EditorUserBuildSettings.exportAsGoogleAndroidProject = true;
|
||||
break;
|
||||
throw new Exception("GenerateStripedAOTDlls failed");
|
||||
}
|
||||
}
|
||||
|
||||
BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions()
|
||||
finally
|
||||
{
|
||||
scenes = EditorBuildSettings.scenes.Where(s => s.enabled).Select(s => s.path).ToArray(),
|
||||
locationPathName = GetLocationPathName(outputPath, target),
|
||||
options = buildOptions,
|
||||
target = target,
|
||||
targetGroup = group,
|
||||
};
|
||||
CheckSettings.DisableMethodBridgeDevelopmentFlagChecking = false;
|
||||
EditorUserBuildSettings.buildScriptsOnly = oldBuildScriptsOnly;
|
||||
EditorUserBuildSettings.SetBuildLocation(target, oldBuildLocation);
|
||||
|
||||
var report = BuildPipeline.BuildPlayer(buildPlayerOptions);
|
||||
|
||||
EditorUserBuildSettings.buildScriptsOnly = oldBuildScriptsOnly;
|
||||
switch (target)
|
||||
{
|
||||
case BuildTarget.StandaloneWindows:
|
||||
case BuildTarget.StandaloneWindows64:
|
||||
switch (target)
|
||||
{
|
||||
case BuildTarget.StandaloneWindows:
|
||||
case BuildTarget.StandaloneWindows64:
|
||||
{
|
||||
#if UNITY_EDITOR_WIN
|
||||
UnityEditor.WindowsStandalone.UserBuildSettings.createSolution = oldCreateSolution;
|
||||
UnityEditor.WindowsStandalone.UserBuildSettings.createSolution = oldCreateSolution;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case BuildTarget.StandaloneOSX:
|
||||
case BuildTarget.StandaloneOSX:
|
||||
{
|
||||
#if UNITY_EDITOR_OSX
|
||||
UnityEditor.OSXStandalone.UserBuildSettings.createXcodeProject = oldCreateSolution;
|
||||
UnityEditor.OSXStandalone.UserBuildSettings.createXcodeProject = oldCreateSolution;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case BuildTarget.Android:
|
||||
{
|
||||
EditorUserBuildSettings.exportAsGoogleAndroidProject = oldExportAndroidProj;
|
||||
break;
|
||||
#if TUANJIE_2022_3_OR_NEWER
|
||||
case BuildTarget.HMIAndroid:
|
||||
#endif
|
||||
case BuildTarget.Android:
|
||||
{
|
||||
EditorUserBuildSettings.exportAsGoogleAndroidProject = oldExportAndroidProj;
|
||||
break;
|
||||
}
|
||||
#if TUANJIE_2022_3_OR_NEWER
|
||||
case BuildTarget.OpenHarmony:
|
||||
{
|
||||
EditorUserBuildSettings.exportAsOpenHarmonyProject = oldOpenHarmonyProj;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (report.summary.result != UnityEditor.Build.Reporting.BuildResult.Succeeded)
|
||||
{
|
||||
Debug.LogError("GenerateStripedAOTDlls 失败");
|
||||
return;
|
||||
}
|
||||
Debug.Log($"GenerateStripedAOTDlls target:{target} group:{group} path:{outputPath}");
|
||||
Debug.Log($"GenerateStripedAOTDlls target:{target} path:{outputPath}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8f2a6638b09b52f4c9dc8906d090b710
|
||||
guid: e60a8b17b0e23a94a8ae875716208030
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
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 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; }
|
||||
}
|
||||
|
|
@ -41,7 +45,7 @@ namespace HybridCLR.Editor.Il2CppDef
|
|||
|
||||
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>();
|
||||
|
||||
|
|
@ -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_{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)
|
||||
{
|
||||
|
|
@ -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.Commit(_options.OutputFile);
|
||||
Debug.Log($"[HybridCLR.Editor.Il2CppDef.Generator] output:{_options.OutputFile}");
|
||||
frr.Commit(_options.UnityVersionOutputFile);
|
||||
Debug.Log($"[HybridCLR.Editor.Il2CppDef.Generator] output:{_options.UnityVersionOutputFile}");
|
||||
}
|
||||
|
||||
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>();
|
||||
|
||||
|
|
@ -79,8 +100,8 @@ namespace HybridCLR.Editor.Il2CppDef
|
|||
|
||||
frr.Replace("PLACE_HOLDER", string.Join("\n", lines));
|
||||
|
||||
frr.Commit(_options.OutputFile2);
|
||||
Debug.Log($"[HybridCLR.Editor.Il2CppDef.Generator] output:{_options.OutputFile2}");
|
||||
frr.Commit(_options.AssemblyManifestOutputFile);
|
||||
Debug.Log($"[HybridCLR.Editor.Il2CppDef.Generator] output:{_options.AssemblyManifestOutputFile}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ using System.Diagnostics;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HybridCLR.Editor.Installer
|
||||
|
|
@ -63,20 +64,34 @@ namespace HybridCLR.Editor.Installer
|
|||
{
|
||||
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)
|
||||
|
|
@ -87,23 +102,23 @@ namespace HybridCLR.Editor.Installer
|
|||
}
|
||||
Directory.CreateDirectory(dir);
|
||||
}
|
||||
|
||||
public static void CopyDir(string src, string dst, bool log = false)
|
||||
{
|
||||
if (log)
|
||||
{
|
||||
UnityEngine.Debug.Log($"[BashUtil] CopyDir {src} => {dst}");
|
||||
}
|
||||
RemoveDir(dst);
|
||||
Directory.CreateDirectory(dst);
|
||||
foreach(var file in Directory.GetFiles(src))
|
||||
if (Directory.Exists(dst))
|
||||
{
|
||||
File.Copy(file, $"{dst}/{Path.GetFileName(file)}");
|
||||
RemoveDir(dst);
|
||||
}
|
||||
foreach(var subDir in Directory.GetDirectories(src))
|
||||
else
|
||||
{
|
||||
CopyDir(subDir, $"{dst}/{Path.GetFileName(subDir)}");
|
||||
string parentDir = Path.GetDirectoryName(Path.GetFullPath(dst));
|
||||
Directory.CreateDirectory(parentDir);
|
||||
}
|
||||
|
||||
UnityEditor.FileUtil.CopyFileOrDirectory(src, dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,27 +1,16 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Diagnostics;
|
||||
|
||||
using Debug = UnityEngine.Debug;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Linq;
|
||||
using HybridCLR.Editor.Settings;
|
||||
|
||||
namespace HybridCLR.Editor.Installer
|
||||
{
|
||||
public enum InstallErrorCode
|
||||
{
|
||||
Ok,
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public class InstallerController
|
||||
{
|
||||
|
|
@ -36,11 +25,17 @@ namespace HybridCLR.Editor.Installer
|
|||
private readonly HybridclrVersionManifest _versionManifest;
|
||||
private readonly HybridclrVersionInfo _curDefaultVersion;
|
||||
|
||||
public string PackageVersion { get; private set; }
|
||||
|
||||
public string InstalledLibil2cppVersion { get; private set; }
|
||||
|
||||
public InstallerController()
|
||||
{
|
||||
_curVersion = ParseUnityVersion(Application.unityVersion);
|
||||
_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()
|
||||
|
|
@ -49,6 +44,21 @@ namespace HybridCLR.Editor.Installer
|
|||
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]
|
||||
class VersionDesc
|
||||
{
|
||||
|
|
@ -78,6 +88,7 @@ namespace HybridCLR.Editor.Installer
|
|||
public int major;
|
||||
public int minor1;
|
||||
public int minor2;
|
||||
public bool isTuanjieEngine;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
|
|
@ -87,10 +98,6 @@ namespace HybridCLR.Editor.Installer
|
|||
|
||||
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)
|
||||
{
|
||||
var matches = s_unityVersionPat.Matches(versionStr);
|
||||
|
|
@ -98,13 +105,12 @@ namespace HybridCLR.Editor.Installer
|
|||
{
|
||||
return null;
|
||||
}
|
||||
// 找最后一个匹配的
|
||||
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 minor1 = int.Parse(match.Groups[2].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()
|
||||
|
|
@ -116,49 +122,41 @@ namespace HybridCLR.Editor.Installer
|
|||
{
|
||||
switch(majorVersion)
|
||||
{
|
||||
case 2019: return $"2019.4.{min2019_4_CompatibleMinorVersion}";
|
||||
case 2020: return $"2020.3.{min2020_3_CompatibleMinorVersion}";
|
||||
case 2021: return $"2021.3.{min2021_3_CompatibleMinorVersion}";
|
||||
default: throw new Exception($"not support version:{majorVersion}");
|
||||
case 2019: return "2019.4.0";
|
||||
case 2020: return "2020.3.0";
|
||||
case 2021: return "2021.3.0";
|
||||
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;
|
||||
switch (version.major)
|
||||
if (version == null)
|
||||
{
|
||||
case 2019:
|
||||
{
|
||||
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}");
|
||||
return CompatibleType.Incompatible;
|
||||
}
|
||||
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)
|
||||
|
|
@ -166,10 +164,29 @@ namespace HybridCLR.Editor.Installer
|
|||
return $"{contentPath}/il2cpp";
|
||||
}
|
||||
|
||||
public string ApplicationIl2cppPath => GetIl2CppPathByContentPath(EditorApplication.applicationContentsPath);
|
||||
|
||||
public string LocalVersionFile => $"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr/generated/libil2cpp-version.txt";
|
||||
|
||||
private string ReadLocalVersion()
|
||||
{
|
||||
if (!File.Exists(LocalVersionFile))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return File.ReadAllText(LocalVersionFile, Encoding.UTF8);
|
||||
}
|
||||
|
||||
public void WriteLocalVersion()
|
||||
{
|
||||
InstalledLibil2cppVersion = PackageVersion;
|
||||
File.WriteAllText(LocalVersionFile, PackageVersion, Encoding.UTF8);
|
||||
Debug.Log($"Write installed version:'{PackageVersion}' to {LocalVersionFile}");
|
||||
}
|
||||
|
||||
public void InstallDefaultHybridCLR()
|
||||
{
|
||||
RunInitLocalIl2CppData(GetIl2CppPathByContentPath(EditorApplication.applicationContentsPath), _curVersion);
|
||||
InstallFromLocal(PrepareLibil2cppWithHybridclrFromGitRepo());
|
||||
}
|
||||
|
||||
public bool HasInstalledHybridCLR()
|
||||
|
|
@ -177,7 +194,6 @@ namespace HybridCLR.Editor.Installer
|
|||
return Directory.Exists($"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr");
|
||||
}
|
||||
|
||||
|
||||
private string GetUnityIl2CppDllInstallLocation()
|
||||
{
|
||||
#if UNITY_EDITOR_WIN
|
||||
|
|
@ -190,9 +206,9 @@ namespace HybridCLR.Editor.Installer
|
|||
private string GetUnityIl2CppDllModifiedPath(string curVersionStr)
|
||||
{
|
||||
#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
|
||||
return $"{SettingsUtil.ProjectDir}/{SettingsUtil.HybridCLRDataPathInPackage}/ModifiedUnityAssemblies/{curVersionStr}/Unity.IL2CPP-Mac.dll.bytes";
|
||||
return $"{SettingsUtil.ProjectDir}/{SettingsUtil.HybridCLRDataPathInPackage}/ModifiedUnityAssemblies/{curVersionStr}/Unity.IL2CPP-Mac.dll";
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -202,31 +218,51 @@ namespace HybridCLR.Editor.Installer
|
|||
BashUtil.RunCommand(workDir, "git", new string[] {"clone", "-b", branch, "--depth", "1", repoUrl, repoDir});
|
||||
}
|
||||
|
||||
private void RunInitLocalIl2CppData(string editorIl2cppPath, UnityVersion version)
|
||||
private string PrepareLibil2cppWithHybridclrFromGitRepo()
|
||||
{
|
||||
if (!IsComaptibleVersion())
|
||||
{
|
||||
Debug.LogError($"il2cpp 版本不兼容,最小版本为 {GetCurrentUnityVersionMinCompatibleVersionStr()}");
|
||||
return;
|
||||
}
|
||||
string workDir = SettingsUtil.HybridCLRDataDir;
|
||||
Directory.CreateDirectory(workDir);
|
||||
//BashUtil.RecreateDir(workDir);
|
||||
|
||||
string buildiOSDir = $"{workDir}/iOSBuild";
|
||||
BashUtil.RemoveDir(buildiOSDir);
|
||||
BashUtil.CopyDir($"{SettingsUtil.HybridCLRDataPathInPackage}/iOSBuild", buildiOSDir, true);
|
||||
|
||||
// clone hybridclr
|
||||
string hybridclrRepoURL = HybridCLRSettings.Instance.hybridclrRepoURL;
|
||||
string hybridclrRepoDir = $"{workDir}/{hybridclr_repo_path}";
|
||||
CloneBranch(workDir, hybridclrRepoURL, _curDefaultVersion.hybridclr.branch, hybridclrRepoDir);
|
||||
|
||||
if (!Directory.Exists(hybridclrRepoDir))
|
||||
{
|
||||
throw new Exception($"clone hybridclr fail. url: {hybridclrRepoURL}");
|
||||
}
|
||||
|
||||
// clone il2cpp_plus
|
||||
string il2cppPlusRepoURL = HybridCLRSettings.Instance.il2cppPlusRepoURL;
|
||||
string il2cppPlusRepoDir = $"{workDir}/{il2cpp_plus_repo_path}";
|
||||
CloneBranch(workDir, il2cppPlusRepoURL, _curDefaultVersion.il2cpp_plus.branch, il2cppPlusRepoDir);
|
||||
|
||||
if (!Directory.Exists(il2cppPlusRepoDir))
|
||||
{
|
||||
throw new Exception($"clone il2cpp_plus fail. url: {il2cppPlusRepoDir}");
|
||||
}
|
||||
|
||||
Directory.Move($"{hybridclrRepoDir}/hybridclr", $"{il2cppPlusRepoDir}/libil2cpp/hybridclr");
|
||||
return $"{il2cppPlusRepoDir}/libil2cpp";
|
||||
}
|
||||
|
||||
public void InstallFromLocal(string libil2cppWithHybridclrSourceDir)
|
||||
{
|
||||
RunInitLocalIl2CppData(ApplicationIl2cppPath, libil2cppWithHybridclrSourceDir, _curVersion);
|
||||
}
|
||||
|
||||
private void RunInitLocalIl2CppData(string editorIl2cppPath, string libil2cppWithHybridclrSourceDir, UnityVersion version)
|
||||
{
|
||||
if (GetCompatibleType() == CompatibleType.Incompatible)
|
||||
{
|
||||
Debug.LogError($"Incompatible with current version, minimum compatible version: {GetCurrentUnityVersionMinCompatibleVersionStr()}");
|
||||
return;
|
||||
}
|
||||
string workDir = SettingsUtil.HybridCLRDataDir;
|
||||
Directory.CreateDirectory(workDir);
|
||||
|
||||
// create LocalIl2Cpp
|
||||
string localUnityDataDir = SettingsUtil.LocalUnityDataDir;
|
||||
BashUtil.RecreateDir(localUnityDataDir);
|
||||
|
|
@ -239,12 +275,10 @@ namespace HybridCLR.Editor.Installer
|
|||
|
||||
// replace libil2cpp
|
||||
string dstLibil2cppDir = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp";
|
||||
BashUtil.CopyDir($"{il2cppPlusRepoDir}/libil2cpp", dstLibil2cppDir, true);
|
||||
BashUtil.CopyDir($"{hybridclrRepoDir}/hybridclr", $"{dstLibil2cppDir}/hybridclr", true);
|
||||
BashUtil.CopyDir($"{libil2cppWithHybridclrSourceDir}", dstLibil2cppDir, true);
|
||||
|
||||
// clean Il2cppBuildCache
|
||||
BashUtil.RemoveDir($"{SettingsUtil.ProjectDir}/Library/Il2cppBuildCache", true);
|
||||
|
||||
if (version.major == 2019)
|
||||
{
|
||||
string curVersionStr = version.ToString();
|
||||
|
|
@ -257,16 +291,17 @@ namespace HybridCLR.Editor.Installer
|
|||
}
|
||||
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())
|
||||
{
|
||||
Debug.Log("安装成功");
|
||||
WriteLocalVersion();
|
||||
Debug.Log("Install Sucessfully");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("安装失败");
|
||||
Debug.LogError("Installation failed!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
|
@ -10,6 +11,10 @@ namespace HybridCLR.Editor.Installer
|
|||
{
|
||||
private InstallerController _controller;
|
||||
|
||||
private bool _installFromDir;
|
||||
|
||||
private string _installLibil2cppWithHybridclrSourceDir;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
_controller = new InstallerController();
|
||||
|
|
@ -25,7 +30,7 @@ namespace HybridCLR.Editor.Installer
|
|||
height = 24
|
||||
};
|
||||
var content = EditorGUIUtility.IconContent("Settings");
|
||||
content.tooltip = "点击打开HybridCLR Settings";
|
||||
content.tooltip = "HybridCLR Settings";
|
||||
if (GUI.Button(rect, content, GUI.skin.GetStyle("IconButton")))
|
||||
{
|
||||
SettingsService.OpenProjectSettings("Project/HybridCLR Settings");
|
||||
|
|
@ -36,50 +41,73 @@ namespace HybridCLR.Editor.Installer
|
|||
GUILayout.Space(10f);
|
||||
|
||||
EditorGUILayout.BeginVertical("box");
|
||||
EditorGUILayout.LabelField($"安装状态:{(hasInstall ? "已安装" : "未安装")}", EditorStyles.boldLabel);
|
||||
EditorGUILayout.LabelField($"Installed: {hasInstall}", EditorStyles.boldLabel);
|
||||
GUILayout.Space(10f);
|
||||
|
||||
EditorGUILayout.LabelField($"HybridCLR 版本: {_controller.HybridclrLocalVersion}");
|
||||
EditorGUILayout.LabelField($"Package Version: v{_controller.PackageVersion}");
|
||||
GUILayout.Space(5f);
|
||||
EditorGUILayout.LabelField($"il2cpp_plus 版本: {_controller.Il2cppPlusLocalVersion}");
|
||||
EditorGUILayout.LabelField($"Installed Version: v{_controller.InstalledLibil2cppVersion ?? " Unknown"}");
|
||||
GUILayout.Space(5f);
|
||||
//GUIInstallButton("检查更新", "检查", UpdateHybridCLR);
|
||||
//GUILayout.Space(40f);
|
||||
|
||||
|
||||
GUILayout.Space(10f);
|
||||
|
||||
|
||||
//EditorGUILayout.BeginHorizontal();
|
||||
//EditorGUILayout.LabelField("待安装的 hybridclr 仓库版本号(或branch或tag)(默认取最新版本):", GUILayout.MaxWidth(400));
|
||||
//_hybridclrVersion = EditorGUILayout.TextField(_hybridclrVersion);
|
||||
//EditorGUILayout.EndHorizontal();
|
||||
|
||||
//EditorGUILayout.BeginHorizontal();
|
||||
//EditorGUILayout.LabelField($"待安装的 il2cpp_plus 仓库版本号(或branch或tag)(默认取{_controller.MajorVersion}-main分支最新版本):", GUILayout.MaxWidth(400));
|
||||
//_il2cppPlusVersion = EditorGUILayout.TextField(_il2cppPlusVersion);
|
||||
//EditorGUILayout.EndHorizontal();
|
||||
|
||||
|
||||
GUIInstallButton("安装hybridclr+il2cpp_plus代码到本地目录", "安装");
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
private void GUIInstallButton(string content, string button)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.LabelField(content);
|
||||
if (GUILayout.Button(button, GUILayout.Width(100)))
|
||||
InstallerController.CompatibleType compatibleType = _controller.GetCompatibleType();
|
||||
if (compatibleType != InstallerController.CompatibleType.Incompatible)
|
||||
{
|
||||
InstallLocalHybridCLR();
|
||||
GUIUtility.ExitGUI();
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
if (compatibleType == InstallerController.CompatibleType.MaybeIncompatible)
|
||||
{
|
||||
EditorGUILayout.HelpBox($"Maybe incompatible with current version, recommend minimum compatible version:{_controller.GetCurrentUnityVersionMinCompatibleVersionStr()}", MessageType.Warning);
|
||||
}
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
_installFromDir = EditorGUILayout.Toggle("Copy libil2cpp from local", _installFromDir, GUILayout.MinWidth(100));
|
||||
EditorGUI.BeginDisabledGroup(!_installFromDir);
|
||||
EditorGUILayout.TextField(_installLibil2cppWithHybridclrSourceDir, GUILayout.Width(400));
|
||||
if (GUILayout.Button("Choose", GUILayout.Width(100)))
|
||||
{
|
||||
_installLibil2cppWithHybridclrSourceDir = EditorUtility.OpenFolderPanel("Select libil2cpp", Application.dataPath, "libil2cpp");
|
||||
}
|
||||
EditorGUI.EndDisabledGroup();
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
GUILayout.Space(20f);
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
if (GUILayout.Button("Install", GUILayout.Width(100)))
|
||||
{
|
||||
InstallLocalHybridCLR();
|
||||
GUIUtility.ExitGUI();
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUILayout.HelpBox($"Incompatible with current version, minimum compatible version:{_controller.GetCurrentUnityVersionMinCompatibleVersionStr()}", MessageType.Error);
|
||||
}
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
private void InstallLocalHybridCLR()
|
||||
{
|
||||
_controller.InstallDefaultHybridCLR();
|
||||
if (_installFromDir)
|
||||
{
|
||||
if (!Directory.Exists(_installLibil2cppWithHybridclrSourceDir))
|
||||
{
|
||||
Debug.LogError($"Source libil2cpp:'{_installLibil2cppWithHybridclrSourceDir}' doesn't exist.");
|
||||
return;
|
||||
}
|
||||
if (!File.Exists($"{_installLibil2cppWithHybridclrSourceDir}/il2cpp-config.h") || !File.Exists($"{_installLibil2cppWithHybridclrSourceDir}/hybridclr/RuntimeApi.cpp"))
|
||||
{
|
||||
Debug.LogError($"Source libil2cpp:' {_installLibil2cppWithHybridclrSourceDir} ' is invalid");
|
||||
return;
|
||||
}
|
||||
_controller.InstallFromLocal(_installLibil2cppWithHybridclrSourceDir);
|
||||
}
|
||||
else
|
||||
{
|
||||
_controller.InstallDefaultHybridCLR();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ using System.Threading.Tasks;
|
|||
using dnlib.DotNet;
|
||||
using HybridCLR.Editor.Meta;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using IAssemblyResolver = HybridCLR.Editor.Meta.IAssemblyResolver;
|
||||
|
||||
namespace HybridCLR.Editor.Link
|
||||
|
|
@ -22,26 +23,27 @@ namespace HybridCLR.Editor.Link
|
|||
|
||||
public HashSet<TypeRef> CollectRefs(List<string> rootAssemblies)
|
||||
{
|
||||
using (var assCollector = new AssemblyCache(_resolver))
|
||||
{
|
||||
var rootAssemblyNames = new HashSet<string>(rootAssemblies);
|
||||
var assCollector = new AssemblyCache(_resolver);
|
||||
var rootAssemblyNames = new HashSet<string>(rootAssemblies);
|
||||
|
||||
var typeRefs = new HashSet<TypeRef>(TypeEqualityComparer.Instance);
|
||||
foreach (var rootAss in rootAssemblies)
|
||||
var typeRefs = new HashSet<TypeRef>(TypeEqualityComparer.Instance);
|
||||
foreach (var rootAss in rootAssemblies)
|
||||
{
|
||||
var dnAss = assCollector.LoadModule(rootAss, false);
|
||||
foreach (var type in dnAss.GetTypeRefs())
|
||||
{
|
||||
var dnAss = assCollector.LoadModule(rootAss, false);
|
||||
foreach (var type in dnAss.GetTypeRefs())
|
||||
if (type.DefinitionAssembly == null)
|
||||
{
|
||||
if (!rootAssemblyNames.Contains(type.DefinitionAssembly.Name.ToString()))
|
||||
{
|
||||
typeRefs.Add(type);
|
||||
}
|
||||
Debug.LogWarning($"assembly:{dnAss.Name} TypeRef {type.FullName} has no DefinitionAssembly");
|
||||
continue;
|
||||
}
|
||||
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
|
||||
{
|
||||
internal class LinkXmlWriter
|
||||
public class LinkXmlWriter
|
||||
{
|
||||
public void Write(string outputLinkXmlFile, HashSet<TypeRef> refTypes)
|
||||
{
|
||||
|
|
@ -22,18 +22,24 @@ namespace HybridCLR.Editor.Link
|
|||
writer.WriteStartElement("linker");
|
||||
|
||||
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)
|
||||
{
|
||||
writer.WriteStartElement("assembly");
|
||||
writer.WriteAttributeString("fullname", assembly.Key);
|
||||
List<TypeRef> assTypes = assembly.ToList();
|
||||
assTypes.Sort((a, b) => a.FullName.CompareTo(b.FullName));
|
||||
foreach(var type in assTypes)
|
||||
List<string> assTypeNames = assembly.Select(t => t.FullName).ToList();
|
||||
assTypeNames.Sort(string.CompareOrdinal);
|
||||
foreach(var typeName in assTypeNames)
|
||||
{
|
||||
#if UNITY_2023_1_OR_NEWER
|
||||
if (typeName == "UnityEngine.Debug")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
writer.WriteStartElement("type");
|
||||
writer.WriteAttributeString("fullname", type.FullName);
|
||||
writer.WriteAttributeString("fullname", typeName);
|
||||
writer.WriteAttributeString("preserve", "all");
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,73 +9,12 @@ using UnityEngine;
|
|||
|
||||
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)
|
||||
public AssemblyCache(IAssemblyResolver assemblyResolver) : base(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
|
||||
{
|
||||
public class AssemblyReferenceDeepCollector : IDisposable
|
||||
public class AssemblyReferenceDeepCollector : AssemblyCacheBase
|
||||
{
|
||||
private readonly IAssemblyResolver _assemblyPathResolver;
|
||||
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()
|
||||
{
|
||||
return _rootAssemblies;
|
||||
|
|
@ -30,19 +23,19 @@ namespace HybridCLR.Editor.Meta
|
|||
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()
|
||||
{
|
||||
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;
|
||||
_modCtx = ModuleDef.CreateModuleContext();
|
||||
_asmResolver = (AssemblyResolver)_modCtx.AssemblyResolver;
|
||||
_asmResolver.EnableTypeDefCache = true;
|
||||
_asmResolver.UseGAC = false;
|
||||
LoadAllAssembiles();
|
||||
}
|
||||
|
||||
|
|
@ -53,52 +46,5 @@ namespace HybridCLR.Editor.Meta
|
|||
LoadModule(asm);
|
||||
}
|
||||
}
|
||||
|
||||
private ModuleDefMD LoadModule(string moduleName)
|
||||
{
|
||||
// Debug.Log($"load module:{moduleName}");
|
||||
if (LoadedModules.TryGetValue(moduleName, out var mod))
|
||||
{
|
||||
return mod;
|
||||
}
|
||||
mod = DoLoadModule(_assemblyPathResolver.ResolveAssembly(moduleName, true));
|
||||
LoadedModules.Add(moduleName, mod);
|
||||
|
||||
foreach (var refAsm in mod.GetAssemblyRefs())
|
||||
{
|
||||
LoadModule(refAsm.Name);
|
||||
}
|
||||
return mod;
|
||||
}
|
||||
|
||||
private ModuleDefMD DoLoadModule(string dllPath)
|
||||
{
|
||||
//Debug.Log($"do load module:{dllPath}");
|
||||
ModuleDefMD mod = ModuleDefMD.Load(dllPath, _modCtx);
|
||||
_asmResolver.AddToCache(mod);
|
||||
return mod;
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposedValue)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
foreach(var mod in LoadedModules.Values)
|
||||
{
|
||||
mod.Dispose();
|
||||
}
|
||||
}
|
||||
LoadedModules.Clear();
|
||||
disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,11 +16,14 @@ namespace HybridCLR.Editor.Meta
|
|||
}
|
||||
if (throwExIfNotFind)
|
||||
{
|
||||
#if UNITY_2021_1_OR_NEWER && UNITY_IOS
|
||||
throw new Exception($"resolve assembly:{assemblyName} 失败! 请按照Install文档正确替换了UnityEditor.CoreModule.dll或者升级hybridclr_unity到2.0.1及更高版本");
|
||||
#else
|
||||
throw new Exception($"resolve assembly:{assemblyName} 失败! 请参阅常见错误文档");
|
||||
#endif
|
||||
if (SettingsUtil.HotUpdateAssemblyNamesIncludePreserved.Contains(assemblyName))
|
||||
{
|
||||
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
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}");
|
||||
return true;
|
||||
}
|
||||
assemblyPath = $"{_rootDir}/{assemblyName}.dll.bytes";
|
||||
if (File.Exists(assemblyPath))
|
||||
{
|
||||
Debug.Log($"[FixedSetAssemblyResolver] resolve:{assemblyName} path:{assemblyPath}");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
assemblyPath = null;
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -7,13 +7,11 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace HybridCLR.Editor.Meta
|
||||
{
|
||||
/// <summary>
|
||||
/// Replaces generic type/method var with its generic argument
|
||||
/// </summary>
|
||||
public sealed class GenericArgumentContext
|
||||
|
||||
public class GenericArgumentContext
|
||||
{
|
||||
List<TypeSig> typeArgsStack = new List<TypeSig>();
|
||||
List<TypeSig> methodArgsStack = new List<TypeSig>();
|
||||
private readonly List<TypeSig> typeArgsStack;
|
||||
private readonly List<TypeSig> methodArgsStack;
|
||||
|
||||
public GenericArgumentContext(List<TypeSig> typeArgsStack, List<TypeSig> methodArgsStack)
|
||||
{
|
||||
|
|
@ -21,16 +19,6 @@ namespace HybridCLR.Editor.Meta
|
|||
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)
|
||||
{
|
||||
if (!typeSig.ContainsGenericParameter)
|
||||
|
|
@ -41,9 +29,9 @@ namespace HybridCLR.Editor.Meta
|
|||
switch (typeSig.ElementType)
|
||||
{
|
||||
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:
|
||||
{
|
||||
var ara = (ArraySig)typeSig;
|
||||
|
|
@ -53,7 +41,7 @@ namespace HybridCLR.Editor.Meta
|
|||
case ElementType.Var:
|
||||
{
|
||||
GenericVar genericVar = (GenericVar)typeSig;
|
||||
var newSig = Resolve(typeArgsStack, genericVar.Number, true);
|
||||
var newSig = Resolve(typeArgsStack, genericVar.Number);
|
||||
if (newSig == null)
|
||||
{
|
||||
throw new Exception();
|
||||
|
|
@ -64,7 +52,7 @@ namespace HybridCLR.Editor.Meta
|
|||
case ElementType.MVar:
|
||||
{
|
||||
GenericMVar genericVar = (GenericMVar)typeSig;
|
||||
var newSig = Resolve(methodArgsStack, genericVar.Number, true);
|
||||
var newSig = Resolve(methodArgsStack, genericVar.Number);
|
||||
if (newSig == null)
|
||||
{
|
||||
throw new Exception();
|
||||
|
|
@ -79,7 +67,29 @@ namespace HybridCLR.Editor.Meta
|
|||
|
||||
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:
|
||||
|
|
@ -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];
|
||||
var gvar = typeSig as GenericSig;
|
||||
if (gvar is null || gvar.IsTypeVar != isTypeVar)
|
||||
return typeSig;
|
||||
return gvar;
|
||||
return args[(int)number];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace HybridCLR.Editor.Meta
|
|||
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -26,7 +26,8 @@ namespace HybridCLR.Editor.Meta
|
|||
|
||||
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)
|
||||
|
|
@ -93,7 +94,7 @@ namespace HybridCLR.Editor.Meta
|
|||
methodDef = method.ResolveMethodDef();
|
||||
if (methodDef == null)
|
||||
{
|
||||
Debug.LogWarning($"method:{method} ResolveMethodDef() == null");
|
||||
//Debug.LogWarning($"method:{method} ResolveMethodDef() == null");
|
||||
return null;
|
||||
}
|
||||
if (method is MethodSpec methodSpec)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using dnlib.DotNet;
|
||||
using HybridCLR.Editor.Meta;
|
||||
using HybridCLR.Editor.Settings;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
|
@ -59,13 +60,8 @@ namespace HybridCLR.Editor.Meta
|
|||
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();
|
||||
switch (a.ElementType)
|
||||
{
|
||||
|
|
@ -88,22 +84,45 @@ namespace HybridCLR.Editor.Meta
|
|||
case ElementType.U: return corTypes.UIntPtr;
|
||||
case ElementType.Object: return corTypes.Object;
|
||||
case ElementType.Sentinel: return typeSig;
|
||||
case ElementType.Ptr: return corTypes.IntPtr;
|
||||
case ElementType.ByRef: return corTypes.IntPtr;
|
||||
case ElementType.Ptr: return corTypes.UIntPtr;
|
||||
case ElementType.ByRef: return corTypes.UIntPtr;
|
||||
case ElementType.SZArray: 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.GenericInst:
|
||||
{
|
||||
var gia = (GenericInstSig)a;
|
||||
if (gia.GenericType.IsClassSig)
|
||||
{
|
||||
return corTypes.Object;
|
||||
}
|
||||
return new GenericInstSig(gia.GenericType, gia.GenericArguments.Select(ga => ToShareTypeSig(ga)).ToList());
|
||||
TypeDef typeDef = gia.GenericType.ToTypeDefOrRef().ResolveTypeDef();
|
||||
if (typeDef == null)
|
||||
{
|
||||
throw new Exception($"type:{a} definition could not be found");
|
||||
}
|
||||
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.Module: return typeSig;
|
||||
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)
|
||||
{
|
||||
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)
|
||||
|
|
@ -153,6 +172,46 @@ namespace HybridCLR.Editor.Meta
|
|||
CreateHotUpdateAssemblyResolver(target, hotUpdateDlls),
|
||||
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 HybridCLR.Editor.ABI;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
|
|
@ -10,26 +11,17 @@ namespace HybridCLR.Editor.Meta
|
|||
{
|
||||
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>>();
|
||||
|
||||
public MethodReferenceAnalyzer(Action<GenericMethod> onNewMethod)
|
||||
public MethodReferenceAnalyzer(Action<MethodDef, List<TypeSig>, List<TypeSig>, GenericMethod> onNewMethod)
|
||||
{
|
||||
_onNewMethod = onNewMethod;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (_methodEffectInsts.TryGetValue(method, out var effectInsts))
|
||||
|
|
@ -37,7 +29,7 @@ namespace HybridCLR.Editor.Meta
|
|||
foreach (var met in effectInsts)
|
||||
{
|
||||
var resolveMet = GenericMethod.ResolveMethod(met, ctx)?.ToGenericShare();
|
||||
_onNewMethod(resolveMet);
|
||||
_onNewMethod(method, klassGenericInst, methodGenericInst, resolveMet);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -69,7 +61,7 @@ namespace HybridCLR.Editor.Meta
|
|||
continue;
|
||||
}
|
||||
effectInsts.Add(met);
|
||||
_onNewMethod(resolveMet);
|
||||
_onNewMethod(method, klassGenericInst, methodGenericInst, resolveMet);
|
||||
break;
|
||||
}
|
||||
case ITokenOperand token:
|
||||
|
|
|
|||
|
|
@ -20,11 +20,16 @@ namespace HybridCLR.Editor.Meta
|
|||
{
|
||||
foreach(var path in _searchPaths)
|
||||
{
|
||||
string assPath = Path.Combine(path, assemblyName + ".dll");
|
||||
if (File.Exists(assPath))
|
||||
assemblyPath = Path.Combine(path, $"{assemblyName}.dll");
|
||||
if (File.Exists(assemblyPath))
|
||||
{
|
||||
Debug.Log($"resolve {assemblyName} at {assPath}");
|
||||
assemblyPath = assPath;
|
||||
Debug.Log($"resolve {assemblyName} at {assemblyPath}");
|
||||
return true;
|
||||
}
|
||||
assemblyPath = Path.Combine(path, $"{assemblyName}.dll.bytes");
|
||||
if (File.Exists(assemblyPath))
|
||||
{
|
||||
Debug.Log($"resolve {assemblyName} at {assemblyPath}");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using dnlib.DotNet;
|
||||
using HybridCLR.Editor.ABI;
|
||||
using HybridCLR.Editor.Meta;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
|
@ -25,7 +26,6 @@ namespace HybridCLR.Editor.MethodBridge
|
|||
private readonly object _lock = new object();
|
||||
|
||||
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<GenericMethod> _genericMethods = new HashSet<GenericMethod>();
|
||||
|
|
@ -35,8 +35,6 @@ namespace HybridCLR.Editor.MethodBridge
|
|||
|
||||
public IReadOnlyList<TypeDef> TypeDefs => _typeDefs;
|
||||
|
||||
public IReadOnlyList<MethodDef> NotGenericMethods => _notGenericMethods;
|
||||
|
||||
public IReadOnlyCollection<GenericClass> GenericTypes => _genericTypes;
|
||||
|
||||
public IReadOnlyCollection<GenericMethod> GenericMethods => _genericMethods;
|
||||
|
|
@ -59,7 +57,7 @@ namespace HybridCLR.Editor.MethodBridge
|
|||
}
|
||||
lock(_lock)
|
||||
{
|
||||
gc = gc.ToGenericShare();
|
||||
gc = StandardizeClass(gc);
|
||||
if (_genericTypes.Add(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)
|
||||
{
|
||||
method = StandardizeMethod(method);
|
||||
if (_genericMethods.Add(method))
|
||||
{
|
||||
_newMethods.Add(method);
|
||||
|
|
@ -94,11 +110,7 @@ namespace HybridCLR.Editor.MethodBridge
|
|||
}
|
||||
foreach (var method in gc.Type.Methods)
|
||||
{
|
||||
if (method.HasGenericParameters)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var gm = new GenericMethod(method, gc.KlassInst, null).ToGenericShare();
|
||||
var gm = StandardizeMethod(new GenericMethod(method, gc.KlassInst, null));
|
||||
//Debug.Log($"add method:{gm.Method} {gm.KlassInst}");
|
||||
|
||||
if (_genericMethods.Add(gm))
|
||||
|
|
@ -123,7 +135,8 @@ namespace HybridCLR.Editor.MethodBridge
|
|||
foreach (var method in typeDef.Methods)
|
||||
{
|
||||
// 对于带泛型的参数,统一泛型共享为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。
|
||||
// 后续迭代中将只遍历MethodSpec
|
||||
foreach (var ass in _assemblyCollector.GetLoadedModulesExcludeRootAssemblies())
|
||||
foreach (var ass in _assemblyCollector.GetLoadedModules())
|
||||
{
|
||||
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++)
|
||||
{
|
||||
var ts = ass.ResolveTypeSpec(rid);
|
||||
if (!ts.ContainsGenericParameter)
|
||||
var cs = GenericClass.ResolveClass(ts, null);
|
||||
if (cs != null)
|
||||
{
|
||||
var cs = GenericClass.ResolveClass(ts, null)?.ToGenericShare();
|
||||
if (cs != null)
|
||||
{
|
||||
TryAddAndWalkGenericType(cs);
|
||||
}
|
||||
TryAddAndWalkGenericType(cs);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint rid = 1, n = ass.Metadata.TablesStream.MethodSpecTable.Rows; rid <= n; rid++)
|
||||
{
|
||||
var ms = ass.ResolveMethodSpec(rid);
|
||||
if(ms.DeclaringType.ContainsGenericParameter || ms.GenericInstMethodSig.ContainsGenericParameter)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var gm = GenericMethod.ResolveMethod(ms, null)?.ToGenericShare();
|
||||
if (gm == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
gm = StandardizeMethod(gm);
|
||||
if (_genericMethods.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()
|
||||
|
|
@ -190,7 +192,7 @@ namespace HybridCLR.Editor.MethodBridge
|
|||
{
|
||||
_methodReferenceAnalyzer.WalkMethod(method.Method, method.KlassInst, method.MethodInst);
|
||||
})).ToArray());
|
||||
Debug.Log($"iteration:[{i}] allMethods:{_notGenericMethods.Count} genericClass:{_genericTypes.Count} genericMethods:{_genericMethods.Count} newMethods:{_newMethods.Count}");
|
||||
Debug.Log($"iteration:[{i}] genericClass:{_genericTypes.Count} genericMethods:{_genericMethods.Count} newMethods:{_newMethods.Count}");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
using dnlib.DotNet;
|
||||
|
||||
namespace HybridCLR.Editor.MethodBridge
|
||||
{
|
||||
public class CallNativeMethodSignatureInfo
|
||||
{
|
||||
public MethodSig MethodSig { get; set; }
|
||||
|
||||
public CallingConvention? Callvention { get; set; }
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue