Compare commits

..

No commits in common. "main" and "v2.0.7" have entirely different histories.
main ... v2.0.7

146 changed files with 2816 additions and 5526 deletions

5
CHANGELOG.md Normal file
View File

@ -0,0 +1,5 @@
# change logs
- 2022.8.30 创建

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: c9e34f237251ef44193538977db6b15f guid: 7b2d5d0a85ef3bf44be6cbe94ed5ed2a
TextScriptImporter: TextScriptImporter:
externalObjects: {} externalObjects: {}
userData: userData:

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 8e53ce54bd8e88c4785c625555308dba guid: 22f11da50eb60c245b40028549937af6
TextScriptImporter: TextScriptImporter:
externalObjects: {} externalObjects: {}
userData: userData:

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 94322e93a1f61b340bdc1d5042dab659
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: e60a8b17b0e23a94a8ae875716208030 guid: 8f2a6638b09b52f4c9dc8906d090b710
folderAsset: yes folderAsset: yes
DefaultImporter: DefaultImporter:
externalObjects: {} externalObjects: {}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d104ab5da8136154899a40116dc88731
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

Binary file not shown.

View File

@ -1,12 +0,0 @@
#include "../Il2CppCompatibleDef.h"
namespace hybridclr
{
const char* g_placeHolderAssemblies[] =
{
//!!!{{PLACE_HOLDER
//!!!}}PLACE_HOLDER
nullptr,
};
}

View File

@ -1,32 +0,0 @@
#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

View File

@ -0,0 +1,20 @@
#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

View File

@ -0,0 +1,32 @@
#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
}
}

View File

@ -1,6 +0,0 @@
#pragma once
//!!!{{UNITY_VERSION
//!!!}}UNITY_VERSION

View File

@ -2,38 +2,18 @@
"versions": [ "versions": [
{ {
"unity_version":"2019", "unity_version":"2019",
"hybridclr" : { "branch":"v8.6.0"}, "hybridclr" : { "branch":"v2.0.2"},
"il2cpp_plus": { "branch":"v2019-8.1.0"} "il2cpp_plus": { "branch":"v2019-2.0.1"}
}, },
{ {
"unity_version":"2020", "unity_version":"2020",
"hybridclr" : { "branch":"v8.6.0"}, "hybridclr" : { "branch":"v2.0.2"},
"il2cpp_plus": { "branch":"v2020-8.1.0"} "il2cpp_plus": { "branch":"v2020-2.0.2"}
}, },
{ {
"unity_version":"2021", "unity_version":"2021",
"hybridclr" : { "branch":"v8.6.0"}, "hybridclr" : { "branch":"v2.0.2"},
"il2cpp_plus": { "branch":"v2021-8.1.0"} "il2cpp_plus": { "branch":"v2021-2.0.2"}
},
{
"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"}
} }
] ]
} }

View File

@ -0,0 +1,88 @@
# 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"
)

View File

@ -0,0 +1,19 @@
#!/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

47
Data~/iOSBuild/external/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,47 @@
# 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})

View File

@ -0,0 +1,64 @@
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 " "

View File

@ -0,0 +1,62 @@
# 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})

View File

@ -42,11 +42,11 @@ namespace HybridCLR.Editor.UnityBinFileReader
writer.Write(new EndianBinaryWriter(output)); writer.Write(new EndianBinaryWriter(output));
Debug.Log($"patch file:{dataunity3dFile} size:{output.Length}"); Debug.Log($"patch file:{dataunity3dFile} size:{output.Length}");
//string bakFile = dataunity3dFile + ".bak"; string bakFile = dataunity3dFile + ".bak";
//if (!File.Exists(bakFile)) if (!File.Exists(bakFile))
//{ {
// File.Copy(dataunity3dFile, bakFile); File.Copy(dataunity3dFile, bakFile);
//} }
File.WriteAllBytes(dataunity3dFile, output.ToArray()); File.WriteAllBytes(dataunity3dFile, output.ToArray());
} }
} }

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 8f2dd29d56a640d4ebd1c2fd374b7638 guid: 4455f7304f8678f408dd6cf21734f55e
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2

View File

@ -116,8 +116,8 @@ namespace MonoHook
static void SetupFlushICacheFunc() static void SetupFlushICacheFunc()
{ {
string processorType = SystemInfo.processorType.ToLowerInvariant(); string processorType = SystemInfo.processorType;
if (processorType.Contains("intel") || processorType.Contains("amd")) if (processorType.Contains("Intel") || processorType.Contains("AMD"))
return; return;
if (IntPtr.Size == 4) if (IntPtr.Size == 4)

View File

@ -15,12 +15,8 @@ namespace MonoHook
static HookUtils() static HookUtils()
{
try
{ {
jit_write_protect_supported = pthread_jit_write_protect_supported_np() != 0; jit_write_protect_supported = pthread_jit_write_protect_supported_np() != 0;
}
catch { }
PropertyInfo p_SystemPageSize = typeof(Environment).GetProperty("SystemPageSize"); PropertyInfo p_SystemPageSize = typeof(Environment).GetProperty("SystemPageSize");
if (p_SystemPageSize == null) if (p_SystemPageSize == null)
@ -39,16 +35,6 @@ namespace MonoHook
public static void MemCpy_Jit(void* pDst, byte[] src) public static void MemCpy_Jit(void* pDst, byte[] src)
{ {
if (!jit_write_protect_supported)
{
fixed(void * pSrc = &src[0])
{
MemCpy(pDst, pSrc, src.Length);
}
return;
}
fixed(void * p = &src[0]) fixed(void * p = &src[0])
{ {
memcpy_jit(new IntPtr(pDst), new IntPtr(p), src.Length); memcpy_jit(new IntPtr(pDst), new IntPtr(p), src.Length);

View File

@ -12,7 +12,7 @@ using System.IO;
namespace HybridCLR.MonoHook namespace HybridCLR.MonoHook
{ {
#if UNITY_2021_1_OR_NEWER && !UNITY_2023_1_OR_NEWER #if UNITY_2021_1_OR_NEWER && UNITY_IOS
[InitializeOnLoad] [InitializeOnLoad]
public class CopyStrippedAOTAssembliesHook public class CopyStrippedAOTAssembliesHook
{ {

View File

@ -1,56 +0,0 @@

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
}

View File

@ -1,74 +0,0 @@

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_2021_1_OR_NEWER && (UNITY_WEBGL || UNITY_WEIXINMINIGAME)
[InitializeOnLoad]
public class PatchScriptingAssembliesJsonHook
{
private static MethodHook _hook;
static PatchScriptingAssembliesJsonHook()
{
if (_hook == null)
{
Type type = typeof(UnityEditor.EditorApplication);
MethodInfo miTarget = type.GetMethod("BuildMainWindowTitle", BindingFlags.Static | BindingFlags.NonPublic);
MethodInfo miReplacement = new Func<string>(BuildMainWindowTitle).Method;
MethodInfo miProxy = new Func<string>(BuildMainWindowTitleProxy).Method;
_hook = new MethodHook(miTarget, miReplacement, miProxy);
_hook.Install();
}
}
private static string BuildMainWindowTitle()
{
var cacheDir = $"{Application.dataPath}/../Library/PlayerDataCache";
if (Directory.Exists(cacheDir))
{
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;
}
[MethodImpl(MethodImplOptions.NoOptimization)]
private static string BuildMainWindowTitleProxy()
{
// 为满足MonoHook要求的最小代码长度而特地加入的无用填充代码
UnityEngine.Debug.Log(12345.ToString());
return string.Empty;
}
}
#endif
}

View File

@ -1,4 +1,4 @@
/* /*
Desc: Hook Mono UnityEditor.dll Desc: Hook Mono UnityEditor.dll
Author: Misaka Mikoto Author: Misaka Mikoto
Github: https://github.com/Misaka-Mikoto-Tech/MonoHook Github: https://github.com/Misaka-Mikoto-Tech/MonoHook
@ -85,7 +85,7 @@ namespace MonoHook
private CodePatcher _codePatcher; private CodePatcher _codePatcher;
#if UNITY_EDITOR && !UNITY_2020_3_OR_NEWER #if UNITY_EDITOR
/// <summary> /// <summary>
/// call `MethodInfo.MethodHandle.GetFunctionPointer()` /// call `MethodInfo.MethodHandle.GetFunctionPointer()`
/// will visit static class `UnityEditor.IMGUI.Controls.TreeViewGUI.Styles` and invoke its static constructor, /// will visit static class `UnityEditor.IMGUI.Controls.TreeViewGUI.Styles` and invoke its static constructor,
@ -97,7 +97,7 @@ namespace MonoHook
static MethodHook() static MethodHook()
{ {
#if UNITY_EDITOR && !UNITY_2020_3_OR_NEWER #if UNITY_EDITOR
s_fi_GUISkin_current = typeof(GUISkin).GetField("current", BindingFlags.Static | BindingFlags.NonPublic); s_fi_GUISkin_current = typeof(GUISkin).GetField("current", BindingFlags.Static | BindingFlags.NonPublic);
#endif #endif
} }
@ -126,7 +126,7 @@ namespace MonoHook
if (isHooked) if (isHooked)
return; return;
#if UNITY_EDITOR && !UNITY_2020_3_OR_NEWER #if UNITY_EDITOR
if (s_fi_GUISkin_current.GetValue(null) != null) if (s_fi_GUISkin_current.GetValue(null) != null)
DoInstall(); DoInstall();
else else
@ -191,7 +191,7 @@ namespace MonoHook
if (targetMethod.IsAbstract) if (targetMethod.IsAbstract)
throw new Exception($"WRANING: you can not hook abstract method [{methodName}]"); throw new Exception($"WRANING: you can not hook abstract method [{methodName}]");
#if UNITY_EDITOR && !UNITY_2020_3_OR_NEWER #if UNITY_EDITOR
int minMethodBodySize = 10; int minMethodBodySize = 10;
{ {
@ -358,7 +358,7 @@ namespace MonoHook
} }
} }
#if UNITY_EDITOR && !UNITY_2020_3_OR_NEWER #if UNITY_EDITOR
private void OnEditorUpdate() private void OnEditorUpdate()
{ {
if (s_fi_GUISkin_current.GetValue(null) != null) if (s_fi_GUISkin_current.GetValue(null) != null)

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 16b9dc031f67b4fe5ad79c230f75768c guid: 82346623158bae349a8347ae74662b12
folderAsset: yes folderAsset: yes
DefaultImporter: DefaultImporter:
externalObjects: {} externalObjects: {}

View File

@ -14,6 +14,20 @@ namespace HybridCLR.Editor.ABI
public int Index { get; set; } public int Index { get; set; }
//public bool IsNative2ManagedByAddress => Type.PorType >= ParamOrReturnType.STRUCT_NOT_PASS_AS_VALUE;
public bool IsPassToManagedByAddress => Type.GetParamSlotNum() > 1;
public bool IsPassToNativeByAddress => Type.PorType == ParamOrReturnType.STRUCTURE_AS_REF_PARAM;
public string Native2ManagedParamValue(PlatformABI canv)
{
return IsPassToManagedByAddress ? $"(uint64_t)&__arg{Index}" : $"*(uint64_t*)&__arg{Index}";
}
public string Managed2NativeParamValue(PlatformABI canv)
{
return IsPassToNativeByAddress ? $"(uint64_t)(localVarBase+argVarIndexs[{Index}])" : $"*({Type.GetTypeName()}*)(localVarBase+argVarIndexs[{Index}])";
}
} }
public class ReturnInfo public class ReturnInfo
@ -22,6 +36,11 @@ namespace HybridCLR.Editor.ABI
public bool IsVoid => Type.PorType == ParamOrReturnType.VOID; public bool IsVoid => Type.PorType == ParamOrReturnType.VOID;
public int GetParamSlotNum(PlatformABI canv)
{
return Type.GetParamSlotNum();
}
public override string ToString() public override string ToString()
{ {
return Type.GetTypeName(); return Type.GetTypeName();

View File

@ -19,9 +19,25 @@ namespace HybridCLR.Editor.ABI
U8, U8,
R4, R4,
R8, R8,
I, ARM64_HFA_FLOAT_2,
U, VALUE_TYPE_SIZE_LESS_EQUAL_8,
TYPEDBYREF, I16, // 8 < size <= 16
STRUCT, 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,
} }
} }

View File

@ -1,102 +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 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++);
}
}
}

View File

@ -0,0 +1,46 @@
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;
}
}
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 96c2bc28db69e1644892219abef3d4b5 guid: a22846b73022cb2458d1c40549ab6877
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2

View File

@ -0,0 +1,320 @@
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);
}
}
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: cc89a9041ab48ac41975fbd1e00b9b98 guid: b63c5bf995a6d624dbd10d9df6cb6a7a
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2

View File

@ -0,0 +1,23 @@
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());
}
}
}
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 0b1df5760b488fa43a68843c46fda63a guid: fe1634f74b7ca2e42bd07233b451cd94
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2

View File

@ -0,0 +1,24 @@
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;
}
}
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 7e9e6a048682dcb4fab806251411f29f guid: 1eb9e19189731a344aad024a43e795bc
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2

View File

@ -0,0 +1,24 @@
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;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7867dfe20d27e324e90bc13b9d4f05bb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,34 @@
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;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4790a87aacda1a14d813570e9e0f35ca
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,5 +1,4 @@
using dnlib.DotNet; using dnlib.DotNet;
using HybridCLR.Editor.Meta;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
@ -21,34 +20,37 @@ namespace HybridCLR.Editor.ABI
public static readonly TypeInfo s_u8 = new TypeInfo(ParamOrReturnType.U8); public static readonly TypeInfo s_u8 = new TypeInfo(ParamOrReturnType.U8);
public static readonly TypeInfo s_r4 = new TypeInfo(ParamOrReturnType.R4); public static readonly TypeInfo s_r4 = new TypeInfo(ParamOrReturnType.R4);
public static readonly TypeInfo s_r8 = new TypeInfo(ParamOrReturnType.R8); public static readonly TypeInfo s_r8 = new TypeInfo(ParamOrReturnType.R8);
public static readonly TypeInfo s_i = new TypeInfo(ParamOrReturnType.I); public static readonly TypeInfo s_i16 = new TypeInfo(ParamOrReturnType.I16);
public static readonly TypeInfo s_u = new TypeInfo(ParamOrReturnType.U); public static readonly TypeInfo s_ref = new TypeInfo(ParamOrReturnType.STRUCTURE_AS_REF_PARAM);
public static readonly TypeInfo s_typedByRef = new TypeInfo(ParamOrReturnType.TYPEDBYREF);
public const string strTypedByRef = "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 TypeInfo(ParamOrReturnType portype, TypeSig klass = null, int typeId = 0) public TypeInfo(ParamOrReturnType portype)
{ {
PorType = portype; PorType = portype;
Klass = klass; Size = 0;
_typeId = typeId; }
public TypeInfo(ParamOrReturnType portype, int size)
{
PorType = portype;
Size = size;
} }
public ParamOrReturnType PorType { get; } public ParamOrReturnType PorType { get; }
public TypeSig Klass { get; } public bool IsGeneralValueType => PorType >= ParamOrReturnType.STRUCTURE_ALIGN1 && PorType <= ParamOrReturnType.STRUCTURE_ALIGN8;
public bool IsStruct => PorType == ParamOrReturnType.STRUCT; public int Size { get; }
public bool IsPrimitiveType => PorType <= ParamOrReturnType.U;
private readonly int _typeId;
public int TypeId => _typeId;
public bool Equals(TypeInfo other) public bool Equals(TypeInfo other)
{ {
return PorType == other.PorType && TypeEqualityComparer.Instance.Equals(Klass, other.Klass); return PorType == other.PorType && Size == other.Size;
} }
public override bool Equals(object obj) public override bool Equals(object obj)
@ -58,12 +60,7 @@ namespace HybridCLR.Editor.ABI
public override int GetHashCode() public override int GetHashCode()
{ {
return (int)PorType * 23 + (Klass != null ? TypeEqualityComparer.Instance.GetHashCode(Klass) : 0); return (int)PorType * 23 + Size;
}
public bool NeedExpandValue()
{
return PorType >= ParamOrReturnType.I1 && PorType <= ParamOrReturnType.U2;
} }
public string CreateSigName() public string CreateSigName()
@ -81,10 +78,22 @@ namespace HybridCLR.Editor.ABI
case ParamOrReturnType.U8: return "u8"; case ParamOrReturnType.U8: return "u8";
case ParamOrReturnType.R4: return "r4"; case ParamOrReturnType.R4: return "r4";
case ParamOrReturnType.R8: return "r8"; case ParamOrReturnType.R8: return "r8";
case ParamOrReturnType.I: return "i"; case ParamOrReturnType.I16: return "i16";
case ParamOrReturnType.U: return "u"; case ParamOrReturnType.STRUCTURE_AS_REF_PARAM: return "sr";
case ParamOrReturnType.TYPEDBYREF: return strTypedByRef; case ParamOrReturnType.ARM64_HFA_FLOAT_2: return "vf2";
case ParamOrReturnType.STRUCT: return $"s{_typeId}"; 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;
default: throw new NotSupportedException(PorType.ToString()); default: throw new NotSupportedException(PorType.ToString());
}; };
} }
@ -104,13 +113,55 @@ namespace HybridCLR.Editor.ABI
case ParamOrReturnType.U8: return "uint64_t"; case ParamOrReturnType.U8: return "uint64_t";
case ParamOrReturnType.R4: return "float"; case ParamOrReturnType.R4: return "float";
case ParamOrReturnType.R8: return "double"; case ParamOrReturnType.R8: return "double";
case ParamOrReturnType.I: return "intptr_t"; case ParamOrReturnType.I16: return "ValueTypeSize16";
case ParamOrReturnType.U: return "uintptr_t"; case ParamOrReturnType.STRUCTURE_AS_REF_PARAM: return "uint64_t";
case ParamOrReturnType.TYPEDBYREF: return "Il2CppTypedRef"; case ParamOrReturnType.ARM64_HFA_FLOAT_2: return "HtVector2f";
case ParamOrReturnType.STRUCT: return $"__struct_{_typeId}__"; 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}>";
default: throw new NotImplementedException(PorType.ToString()); default: throw new NotImplementedException(PorType.ToString());
}; };
} }
public int GetParamSlotNum()
{
switch (PorType)
{
case ParamOrReturnType.VOID: return 0;
case ParamOrReturnType.I16: return 2;
case ParamOrReturnType.STRUCTURE_AS_REF_PARAM: return 1;
case ParamOrReturnType.ARM64_HFA_FLOAT_3: return 2;
case ParamOrReturnType.ARM64_HFA_FLOAT_4: return 2;
case ParamOrReturnType.ARM64_HFA_DOUBLE_2: return 2;
case ParamOrReturnType.ARM64_HFA_DOUBLE_3: return 3;
case ParamOrReturnType.ARM64_HFA_DOUBLE_4: return 4;
case ParamOrReturnType.ARM64_HVA_8:
case ParamOrReturnType.ARM64_HVA_16: throw new NotSupportedException();
case ParamOrReturnType.STRUCTURE_ALIGN1:
case ParamOrReturnType.STRUCTURE_ALIGN2:
case ParamOrReturnType.STRUCTURE_ALIGN4:
case ParamOrReturnType.STRUCTURE_ALIGN8:
case ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN1:
case ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN2:
case ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN4:
case ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN8:
return (Size + 7) / 8;
default:
{
Debug.Assert(PorType < ParamOrReturnType.STRUCT_NOT_PASS_AS_VALUE);
Debug.Assert(Size <= 8);
return 1;
}
}
}
} }
} }

View File

@ -1,56 +0,0 @@
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);
}
}
}

View File

@ -17,16 +17,12 @@ namespace HybridCLR.Editor.AOT
public AssemblyReferenceDeepCollector Collector { get; set; } public AssemblyReferenceDeepCollector Collector { get; set; }
public int MaxIterationCount { get; set; } public int MaxIterationCount { get; set; }
public bool ComputeAotAssembly { get; set; }
} }
private readonly int _maxInterationCount; private readonly int _maxInterationCount;
private readonly AssemblyReferenceDeepCollector _assemblyCollector; private readonly AssemblyReferenceDeepCollector _assemblyCollector;
private readonly bool _computeAotAssembly;
private readonly HashSet<GenericClass> _genericTypes = new HashSet<GenericClass>(); private readonly HashSet<GenericClass> _genericTypes = new HashSet<GenericClass>();
private readonly HashSet<GenericMethod> _genericMethods = new HashSet<GenericMethod>(); private readonly HashSet<GenericMethod> _genericMethods = new HashSet<GenericMethod>();
@ -51,7 +47,6 @@ namespace HybridCLR.Editor.AOT
{ {
_assemblyCollector = options.Collector; _assemblyCollector = options.Collector;
_maxInterationCount = options.MaxIterationCount; _maxInterationCount = options.MaxIterationCount;
_computeAotAssembly = options.ComputeAotAssembly;
_methodReferenceAnalyzer = new MethodReferenceAnalyzer(this.OnNewMethod); _methodReferenceAnalyzer = new MethodReferenceAnalyzer(this.OnNewMethod);
_hotUpdateAssemblyFiles = new HashSet<string>(options.Collector.GetRootAssemblyNames().Select(assName => assName + ".dll")); _hotUpdateAssemblyFiles = new HashSet<string>(options.Collector.GetRootAssemblyNames().Select(assName => assName + ".dll"));
} }
@ -63,20 +58,20 @@ namespace HybridCLR.Editor.AOT
return; return;
} }
gc = gc.ToGenericShare(); gc = gc.ToGenericShare();
if (_genericTypes.Add(gc) && NeedWalk(null, gc.Type)) if (_genericTypes.Add(gc) && NeedWalk(gc.Type))
{ {
WalkType(gc); WalkType(gc);
} }
} }
private bool NeedWalk(MethodDef callFrom, TypeDef type) private bool NeedWalk(TypeDef type)
{ {
return _hotUpdateAssemblyFiles.Contains(type.Module.Name) || callFrom == null || callFrom.HasGenericParameters; return _hotUpdateAssemblyFiles.Contains(type.Module.Name);
} }
private bool IsAotType(TypeDef type) private bool IsAotType(TypeDef type)
{ {
return _computeAotAssembly || !_hotUpdateAssemblyFiles.Contains(type.Module.Name); return !_hotUpdateAssemblyFiles.Contains(type.Module.Name);
} }
private bool IsAotGenericMethod(MethodDef method) private bool IsAotGenericMethod(MethodDef method)
@ -84,13 +79,13 @@ namespace HybridCLR.Editor.AOT
return IsAotType(method.DeclaringType) && method.HasGenericParameters; return IsAotType(method.DeclaringType) && method.HasGenericParameters;
} }
private void OnNewMethod(MethodDef methodDef, List<TypeSig> klassGenericInst, List<TypeSig> methodGenericInst, GenericMethod method) private void OnNewMethod(GenericMethod method)
{ {
if(method == null) if(method == null)
{ {
return; return;
} }
if (NeedWalk(methodDef, method.Method.DeclaringType) && _genericMethods.Add(method)) if (_genericMethods.Add(method) && NeedWalk(method.Method.DeclaringType))
{ {
_newMethods.Add(method); _newMethods.Add(method);
} }
@ -106,7 +101,7 @@ namespace HybridCLR.Editor.AOT
{ {
return; return;
} }
if (NeedWalk(null, method.Method.DeclaringType) && _genericMethods.Add(method)) if (_genericMethods.Add(method) && NeedWalk(method.Method.DeclaringType))
{ {
_newMethods.Add(method); _newMethods.Add(method);
} }
@ -162,9 +157,9 @@ namespace HybridCLR.Editor.AOT
for (uint rid = 1, n = ass.Metadata.TablesStream.TypeSpecTable.Rows; rid <= n; rid++) for (uint rid = 1, n = ass.Metadata.TablesStream.TypeSpecTable.Rows; rid <= n; rid++)
{ {
var ts = ass.ResolveTypeSpec(rid); var ts = ass.ResolveTypeSpec(rid);
var cs = GenericClass.ResolveClass(ts, null)?.ToGenericShare(); if (!ts.ContainsGenericParameter)
if (cs != null)
{ {
var cs = GenericClass.ResolveClass(ts, null)?.ToGenericShare();
TryAddAndWalkGenericType(cs); TryAddAndWalkGenericType(cs);
} }
} }
@ -172,6 +167,10 @@ namespace HybridCLR.Editor.AOT
for (uint rid = 1, n = ass.Metadata.TablesStream.MethodSpecTable.Rows; rid <= n; rid++) for (uint rid = 1, n = ass.Metadata.TablesStream.MethodSpecTable.Rows; rid <= n; rid++)
{ {
var ms = ass.ResolveMethodSpec(rid); var ms = ass.ResolveMethodSpec(rid);
if (ms.DeclaringType.ContainsGenericParameter || ms.GenericInstMethodSig.ContainsGenericParameter)
{
continue;
}
var gm = GenericMethod.ResolveMethod(ms, null)?.ToGenericShare(); var gm = GenericMethod.ResolveMethod(ms, null)?.ToGenericShare();
TryAddMethodNotWalkType(gm); TryAddMethodNotWalkType(gm);
} }
@ -196,29 +195,11 @@ namespace HybridCLR.Editor.AOT
} }
} }
private bool IsNotShareableAOTGenericType(TypeDef typeDef)
{
if (!IsAotType(typeDef))
{
return false;
}
return typeDef.GenericParameters.Any(c => !c.HasReferenceTypeConstraint);
}
private bool IsNotShareableAOTGenericMethod(MethodDef method)
{
if (!IsAotGenericMethod(method))
{
return false;
}
return method.GenericParameters.Concat(method.DeclaringType.GenericParameters).Any(c => !c.HasReferenceTypeConstraint);
}
private void FilterAOTGenericTypeAndMethods() private void FilterAOTGenericTypeAndMethods()
{ {
ConstraintContext cc = this.ConstraintContext; ConstraintContext cc = this.ConstraintContext;
AotGenericTypes.AddRange(_genericTypes.Where(type => IsNotShareableAOTGenericType(type.Type)).Select(gc => cc.ApplyConstraints(gc))); AotGenericTypes.AddRange(_genericTypes.Where(type => IsAotType(type.Type)).Select(gc => cc.ApplyConstraints(gc)));
AotGenericMethods.AddRange(_genericMethods.Where(method => IsNotShareableAOTGenericMethod(method.Method)).Select(gm => cc.ApplyConstraints(gm))); AotGenericMethods.AddRange(_genericMethods.Where(method => IsAotGenericMethod(method.Method)).Select(gm => cc.ApplyConstraints(gm)));
} }
public void Run() public void Run()

View File

@ -4,7 +4,6 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using UnityEngine; using UnityEngine;
@ -12,90 +11,27 @@ namespace HybridCLR.Editor.AOT
{ {
public class GenericReferenceWriter public class GenericReferenceWriter
{ {
private static readonly Dictionary<Type, string> _typeNameMapping = new Dictionary<Type, string>
{
{typeof(bool), "bool" },
{typeof(byte), "byte" },
{typeof(sbyte), "sbyte" },
{typeof(short), "short" },
{typeof(ushort), "ushort" },
{typeof(int), "int" },
{typeof(uint), "uint" },
{typeof(long), "long" },
{typeof(ulong), "ulong" },
{typeof(float), "float" },
{typeof(double), "double" },
{typeof(object), "object" },
{typeof(string), "string" },
};
private readonly Dictionary<string, string> _typeSimpleNameMapping = new Dictionary<string, string>();
private readonly Regex _systemTypePattern;
private readonly Regex _genericPattern = new Regex(@"`\d+");
public GenericReferenceWriter()
{
foreach (var e in _typeNameMapping)
{
_typeSimpleNameMapping.Add(e.Key.FullName, e.Value);
}
_systemTypePattern = new Regex(string.Join("|", _typeSimpleNameMapping.Keys.Select (k => $@"\b{Regex.Escape(k)}\b")));
}
public string PrettifyTypeSig(string typeSig)
{
string s = _genericPattern.Replace(typeSig, "").Replace('/', '.');
return _systemTypePattern.Replace(s, m => _typeSimpleNameMapping[m.Groups[0].Value]);
}
public string PrettifyMethodSig(string methodSig)
{
string s = PrettifyTypeSig(methodSig).Replace("::", ".");
if (s.Contains(".ctor("))
{
s = "new " + s.Replace(".ctor(", "(");
}
return s;
}
public void Write(List<GenericClass> types, List<GenericMethod> methods, string outputFile) public void Write(List<GenericClass> types, List<GenericMethod> methods, string outputFile)
{ {
string parentDir = Directory.GetParent(outputFile).FullName; string parentDir = Directory.GetParent(outputFile).FullName;
Directory.CreateDirectory(parentDir); Directory.CreateDirectory(parentDir);
List<string> codes = new List<string>(); List<string> codes = new List<string>();
codes.Add("using System.Collections.Generic;");
codes.Add("public class AOTGenericReferences : UnityEngine.MonoBehaviour"); codes.Add("public class AOTGenericReferences : UnityEngine.MonoBehaviour");
codes.Add("{"); codes.Add("{");
codes.Add("");
codes.Add("\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\t\"{module.Name}\",");
}
codes.Add("\t};");
codes.Add("\t// }}");
codes.Add(""); codes.Add("");
codes.Add("\t// {{ constraint implement type"); codes.Add("\t// {{ constraint implement type");
codes.Add("\t// }} "); codes.Add("\t// }} ");
codes.Add(""); codes.Add("");
codes.Add("\t// {{ AOT generic types"); codes.Add("\t// {{ AOT generic type");
List<string> typeNames = types.Select(t => PrettifyTypeSig(t.ToTypeSig().ToString())).ToList(); types.Sort((a, b) => a.Type.FullName.CompareTo(b.Type.FullName));
typeNames.Sort(string.CompareOrdinal); foreach(var type in types)
foreach(var typeName in typeNames)
{ {
codes.Add($"\t// {typeName}"); codes.Add($"\t//{type.ToTypeSig()}");
} }
codes.Add("\t// }}"); codes.Add("\t// }}");
@ -103,36 +39,27 @@ namespace HybridCLR.Editor.AOT
codes.Add(""); codes.Add("");
codes.Add("\tpublic void RefMethods()"); codes.Add("\tpublic void RefMethods()");
codes.Add("\t{"); codes.Add("\t{");
methods.Sort((a, b) =>
List<(string, string, string)> methodTypeAndNames = methods.Select(m =>
(PrettifyTypeSig(m.Method.DeclaringType.ToString()), PrettifyMethodSig(m.Method.Name), PrettifyMethodSig(m.ToMethodSpec().ToString())))
.ToList();
methodTypeAndNames.Sort((a, b) =>
{ {
int c = String.Compare(a.Item1, b.Item1, StringComparison.Ordinal); int c = a.Method.DeclaringType.FullName.CompareTo(b.Method.DeclaringType.FullName);
if (c != 0) if (c != 0)
{ {
return c; return c;
} }
c = a.Method.Name.CompareTo(b.Method.Name);
c = String.Compare(a.Item2, b.Item2, StringComparison.Ordinal);
if (c != 0)
{
return c; return c;
}
return String.Compare(a.Item3, b.Item3, StringComparison.Ordinal);
}); });
foreach(var method in methodTypeAndNames) foreach(var method in methods)
{ {
codes.Add($"\t\t// {PrettifyMethodSig(method.Item3)}"); codes.Add($"\t\t// {method.ToMethodSpec()}");
} }
codes.Add("\t}"); codes.Add("\t}");
codes.Add("}"); codes.Add("}");
var utf8WithoutBom = new System.Text.UTF8Encoding(false); var utf8WithoutBOM = new System.Text.UTF8Encoding(false);
File.WriteAllText(outputFile, string.Join("\n", codes), utf8WithoutBom); File.WriteAllText(outputFile, string.Join("\n", codes), utf8WithoutBOM);
Debug.Log($"[GenericReferenceWriter] write {outputFile}"); Debug.Log($"[GenericReferenceWriter] write {outputFile}");
} }
} }

View File

@ -1,258 +0,0 @@
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/includelibil2cpp
3. Libraries/bdwgc/include -> Libraries/external/bdwgc/include
4. external Library/external
5. Library/external/baselib/Platforms/OSX IOS
6. external/zlibc
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

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: d2f62ca12f2eb4f2fba8e9cb51279421
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,244 +0,0 @@
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/includelibil2cpp
3. Libraries/bdwgc/include -> Libraries/external/bdwgc/include
4. external Library/external
5. Library/external/baselib/Platforms/OSX IOS
6. external/zlibc
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

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 61948fcb1bc40ba47b8c10b0ae801ebb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,82 +0,0 @@
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

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: a4ce072f7e4a17248a3d9ebfd011356b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,34 +0,0 @@
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

View File

@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: 2fa46135129b046a28014d58fdfd18ca

View File

@ -1,25 +0,0 @@
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}");
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: c680e56f90f2745298a90803c04f6efc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,16 +1,11 @@
using HybridCLR.Editor.Settings; using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using UnityEditor;
using UnityEditor.Build; using UnityEditor.Build;
using UnityEditor.Build.Reporting; using UnityEditor.Build.Reporting;
using UnityEngine; using UnityEngine;
using static UnityEngine.GraphicsBuffer;
namespace HybridCLR.Editor.BuildProcessors namespace HybridCLR.Editor.BuildProcessors
{ {
@ -18,18 +13,17 @@ namespace HybridCLR.Editor.BuildProcessors
{ {
public int callbackOrder => 0; public int callbackOrder => 0;
public static bool DisableMethodBridgeDevelopmentFlagChecking { get; set; }
public void OnPreprocessBuild(BuildReport report) public void OnPreprocessBuild(BuildReport report)
{ {
HybridCLRSettings globalSettings = SettingsUtil.HybridCLRSettings; HybridCLRSettings globalSettings = SettingsUtil.HybridCLRSettings;
#if !UNITY_2020_1_OR_NEWER || !UNITY_IOS
if (!globalSettings.enable || globalSettings.useGlobalIl2cpp) if (!globalSettings.enable || globalSettings.useGlobalIl2cpp)
{ {
string oldIl2cppPath = Environment.GetEnvironmentVariable("UNITY_IL2CPP_PATH"); string oldIl2cppPath = Environment.GetEnvironmentVariable("UNITY_IL2CPP_PATH");
if (!string.IsNullOrEmpty(oldIl2cppPath)) if (!string.IsNullOrEmpty(oldIl2cppPath))
{ {
Environment.SetEnvironmentVariable("UNITY_IL2CPP_PATH", ""); Environment.SetEnvironmentVariable("UNITY_IL2CPP_PATH", "");
Debug.Log($"[CheckSettings] clean process environment variable: UNITY_IL2CPP_PATH, old vlaue:'{oldIl2cppPath}'"); Debug.Log($"[CheckSettings] 清除 UNITY_IL2CPP_PATH, 旧值为:'{oldIl2cppPath}'");
} }
} }
else else
@ -38,57 +32,32 @@ namespace HybridCLR.Editor.BuildProcessors
if (curIl2cppPath != SettingsUtil.LocalIl2CppDir) if (curIl2cppPath != SettingsUtil.LocalIl2CppDir)
{ {
Environment.SetEnvironmentVariable("UNITY_IL2CPP_PATH", SettingsUtil.LocalIl2CppDir); Environment.SetEnvironmentVariable("UNITY_IL2CPP_PATH", SettingsUtil.LocalIl2CppDir);
Debug.Log($"[CheckSettings] UNITY_IL2CPP_PATH old value:'{curIl2cppPath}' new value:'{SettingsUtil.LocalIl2CppDir}'"); Debug.Log($"[CheckSettings] UNITY_IL2CPP_PATH 当前值为:'{curIl2cppPath}',更新为:'{SettingsUtil.LocalIl2CppDir}'");
} }
} }
#endif
if (!globalSettings.enable) if (!globalSettings.enable)
{ {
return; return;
} }
BuildTargetGroup buildTargetGroup = BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget); if (UnityEditor.PlayerSettings.gcIncremental)
ScriptingImplementation curScriptingImplementation = PlayerSettings.GetScriptingBackend(buildTargetGroup);
ScriptingImplementation targetScriptingImplementation = ScriptingImplementation.IL2CPP;
if (curScriptingImplementation != targetScriptingImplementation)
{ {
Debug.LogError($"[CheckSettings] current ScriptingBackend:{curScriptingImplementation}have been switched to:{targetScriptingImplementation} automatically"); Debug.LogError($"[CheckSettings] HybridCLR不支持增量式GC已经自动将该选项关闭");
PlayerSettings.SetScriptingBackend(buildTargetGroup, targetScriptingImplementation); UnityEditor.PlayerSettings.gcIncremental = false;
} }
var installer = new Installer.InstallerController(); var installer = new Installer.InstallerController();
if (!installer.HasInstalledHybridCLR()) if (!installer.HasInstalledHybridCLR())
{ {
throw new BuildFailedException($"You have not initialized HybridCLR, please install it via menu 'HybridCLR/Installer'"); throw new Exception($"你没有初始化HybridCLR请通过菜单'HybridCLR/Installer'安装");
}
if (installer.PackageVersion != installer.InstalledLibil2cppVersion)
{
throw new BuildFailedException($"You must run `HybridCLR/Installer` after upgrading package");
} }
HybridCLRSettings gs = SettingsUtil.HybridCLRSettings; HybridCLRSettings gs = SettingsUtil.HybridCLRSettings;
if (((gs.hotUpdateAssemblies?.Length + gs.hotUpdateAssemblyDefinitions?.Length) ?? 0) == 0) if (((gs.hotUpdateAssemblies?.Length + gs.hotUpdateAssemblyDefinitions?.Length) ?? 0) == 0)
{ {
Debug.LogWarning("[CheckSettings] No hot update modules configured in HybridCLRSettings"); Debug.LogWarning("[CheckSettings] 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.");
}
}
} }
} }
} }

View File

@ -1,5 +1,4 @@
using HybridCLR.Editor.Installer; using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -8,15 +7,13 @@ using System.Threading.Tasks;
using UnityEditor; using UnityEditor;
using UnityEditor.Build; using UnityEditor.Build;
using UnityEditor.Build.Reporting; using UnityEditor.Build.Reporting;
using UnityEditor.Il2Cpp;
using UnityEditor.UnityLinker; using UnityEditor.UnityLinker;
using UnityEngine; using UnityEngine;
#if !UNITY_2021_1_OR_NEWER
using UnityEditor.Il2Cpp;
#endif
namespace HybridCLR.Editor.BuildProcessors namespace HybridCLR.Editor.BuildProcessors
{ {
internal class CopyStrippedAOTAssemblies : IPostprocessBuildWithReport, IPreprocessBuildWithReport internal class CopyStrippedAOTAssemblies : IPostprocessBuildWithReport
#if !UNITY_2021_1_OR_NEWER #if !UNITY_2021_1_OR_NEWER
, IIl2CppProcessor , IIl2CppProcessor
#endif #endif
@ -28,52 +25,19 @@ namespace HybridCLR.Editor.BuildProcessors
public static string GetStripAssembliesDir2021(BuildTarget target) public static string GetStripAssembliesDir2021(BuildTarget target)
{ {
string projectDir = SettingsUtil.ProjectDir; string projectDir = SettingsUtil.ProjectDir;
switch (target) #if UNITY_STANDALONE_WIN
{
case BuildTarget.StandaloneWindows:
case BuildTarget.StandaloneWindows64:
return $"{projectDir}/Library/Bee/artifacts/WinPlayerBuildProgram/ManagedStripped"; return $"{projectDir}/Library/Bee/artifacts/WinPlayerBuildProgram/ManagedStripped";
case BuildTarget.StandaloneLinux64: #elif UNITY_ANDROID
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"; return $"{projectDir}/Library/Bee/artifacts/Android/ManagedStripped";
#if TUANJIE_2022_3_OR_NEWER #elif UNITY_IOS
case BuildTarget.HMIAndroid: return $"{projectDir}/Temp/StagingArea/Data/Managed/tempStrip";
return $"{projectDir}/Library/Bee/artifacts/HMIAndroid/ManagedStripped"; #elif UNITY_WEBGL
#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"; return $"{projectDir}/Library/Bee/artifacts/WebGL/ManagedStripped";
case BuildTarget.StandaloneOSX: #elif UNITY_EDITOR_OSX
return $"{projectDir}/Library/Bee/artifacts/MacStandalonePlayerBuildProgram/ManagedStripped"; return $"{projectDir}/Library/Bee/artifacts/MacStandalonePlayerBuildProgram/ManagedStripped";
case BuildTarget.PS4: #else
return $"{projectDir}/Library/Bee/artifacts/PS4PlayerBuildProgram/ManagedStripped"; throw new NotSupportedException("GetOriginBuildStripAssembliesDir");
case BuildTarget.PS5:
return $"{projectDir}/Library/Bee/artifacts/PS5PlayerBuildProgram/ManagedStripped";
#if UNITY_WEIXINMINIGAME
case BuildTarget.WeixinMiniGame:
return $"{projectDir}/Library/Bee/artifacts/WeixinMiniGame/ManagedStripped";
#endif #endif
#if UNITY_OPENHARMONY
case BuildTarget.OpenHarmony:
return $"{projectDir}/Library/Bee/artifacts/OpenHarmonyPlayerBuildProgram/ManagedStripped";
#endif
default: return "";
}
} }
#else #else
private string GetStripAssembliesDir2020(BuildTarget target) private string GetStripAssembliesDir2020(BuildTarget target)
@ -86,8 +50,8 @@ namespace HybridCLR.Editor.BuildProcessors
public void OnBeforeConvertRun(BuildReport report, Il2CppBuildPipelineData data) public void OnBeforeConvertRun(BuildReport report, Il2CppBuildPipelineData data)
{ {
BuildTarget target = report.summary.platform; // 此回调只在 2020中调用
CopyStripDlls(GetStripAssembliesDir2020(target), target); CopyStripDlls(GetStripAssembliesDir2020(data.target), data.target);
} }
#endif #endif
@ -114,21 +78,10 @@ namespace HybridCLR.Editor.BuildProcessors
public void OnPostprocessBuild(BuildReport report) public void OnPostprocessBuild(BuildReport report)
{ {
#if UNITY_2021_1_OR_NEWER #if UNITY_2021_1_OR_NEWER && !UNITY_IOS
BuildTarget target = report.summary.platform; BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
string srcStripDllPath = GetStripAssembliesDir2021(target); CopyStripDlls(GetStripAssembliesDir2021(target), target);
if (!string.IsNullOrEmpty(srcStripDllPath) && Directory.Exists(srcStripDllPath))
{
CopyStripDlls(srcStripDllPath, target);
}
#endif #endif
} }
public void OnPreprocessBuild(BuildReport report)
{
BuildTarget target = report.summary.platform;
var dstPath = SettingsUtil.GetAssembliesPostIl2CppStripDir(target);
BashUtil.RecreateDir(dstPath);
}
} }
} }

View File

@ -1,7 +1,6 @@
using HybridCLR.Editor.Meta; using HybridCLR.Editor.Meta;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -26,18 +25,15 @@ namespace HybridCLR.Editor.BuildProcessors
return assemblies; return assemblies;
} }
List<string> allHotUpdateDllNames = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved; List<string> allHotUpdateDllNames = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved;
List<string> allHotupdateDllFiles = SettingsUtil.HotUpdateAssemblyFilesExcludePreserved;
// 检查是否重复填写 // 检查是否重复填写
var hotUpdateDllSet = new HashSet<string>(); var hotUpdateDllSet = new HashSet<string>();
foreach(var hotUpdateDll in allHotUpdateDllNames) foreach(var hotUpdateDll in allHotUpdateDllNames)
{ {
if (string.IsNullOrWhiteSpace(hotUpdateDll))
{
throw new BuildFailedException($"hot update assembly name cann't be empty");
}
if (!hotUpdateDllSet.Add(hotUpdateDll)) if (!hotUpdateDllSet.Add(hotUpdateDll))
{ {
throw new BuildFailedException($"hot update assembly:{hotUpdateDll} is duplicated"); throw new Exception($"热更新 assembly:{hotUpdateDll} 在列表中重复,请除去重复条目");
} }
} }
@ -45,24 +41,16 @@ namespace HybridCLR.Editor.BuildProcessors
// 检查是否填写了正确的dll名称 // 检查是否填写了正确的dll名称
foreach (var hotUpdateDllName in allHotUpdateDllNames) foreach (var hotUpdateDllName in allHotUpdateDllNames)
{ {
if (assemblies.Select(Path.GetFileNameWithoutExtension).All(ass => ass != hotUpdateDllName) string hotUpdateDllFile = hotUpdateDllName + ".dll";
&& string.IsNullOrEmpty(assResolver.ResolveAssembly(hotUpdateDllName, false))) if (assemblies.All(ass => !ass.EndsWith(hotUpdateDllFile)) && string.IsNullOrEmpty(assResolver.ResolveAssembly(hotUpdateDllName, false)))
{ {
throw new BuildFailedException($"hot update assembly:{hotUpdateDllName} doesn't exist"); throw new Exception($"热更新 assembly:{hotUpdateDllFile} 不存在,请检查拼写错误");
} }
Debug.Log($"[FilterHotFixAssemblies] 过滤热更新assembly:{hotUpdateDllFile}");
} }
// 将热更dll从打包列表中移除 // 将热更dll从打包列表中移除
return assemblies.Where(ass => return assemblies.Where(ass => allHotupdateDllFiles.All(dll => !ass.EndsWith(dll, StringComparison.OrdinalIgnoreCase))).ToArray();
{
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();
} }
} }
} }

View File

@ -1,32 +0,0 @@
#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

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 8bff6cadf0b8db54b87ba51b24d080f6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -9,30 +9,21 @@ using UnityEditor;
using UnityEditor.Android; using UnityEditor.Android;
using UnityEditor.Build; using UnityEditor.Build;
using UnityEditor.Build.Reporting; using UnityEditor.Build.Reporting;
using UnityEditor.Il2Cpp;
using UnityEditor.UnityLinker; using UnityEditor.UnityLinker;
using UnityEngine; using UnityEngine;
using UnityFS; using UnityFS;
#if !UNITY_2023_1_OR_NEWER
using UnityEditor.Il2Cpp;
#endif
namespace HybridCLR.Editor.BuildProcessors namespace HybridCLR.Editor.BuildProcessors
{ {
public class PatchScriptingAssemblyList : public class PatchScriptingAssemblyList :
#if UNITY_ANDROID #if UNITY_ANDROID
IPostGenerateGradleAndroidProject, IPostGenerateGradleAndroidProject,
#elif UNITY_OPENHARMONY
UnityEditor.OpenHarmony.IPostGenerateOpenHarmonyProject,
#endif #endif
IPostprocessBuildWithReport IPostprocessBuildWithReport
#if !UNITY_2021_1_OR_NEWER && UNITY_WEBGL #if !UNITY_2021_1_OR_NEWER && UNITY_WEBGL
, IIl2CppProcessor , IIl2CppProcessor
#endif #endif
#if UNITY_PS5
, IUnityLinkerProcessor
#endif
{ {
public int callbackOrder => 0; public int callbackOrder => 0;
@ -51,37 +42,17 @@ namespace HybridCLR.Editor.BuildProcessors
} }
} }
#if UNITY_OPENHARMONY
public void OnPostGenerateOpenHarmonyProject(string path)
{
OnPostGenerateGradleAndroidProject(path);
}
#endif
public void OnPostprocessBuild(BuildReport report) public void OnPostprocessBuild(BuildReport report)
{ {
// 如果target为Android,由于已经在OnPostGenerateGradelAndroidProject中处理过 // 如果target为Android,由于已经在OnPostGenerateGradelAndroidProject中处理过
// 这里不再重复处理 // 这里不再重复处理
#if !UNITY_ANDROID && !UNITY_WEBGL && !UNITY_OPENHARMONY #if !UNITY_ANDROID && !UNITY_WEBGL
PathScriptingAssembilesFile(report.summary.outputPath); PathScriptingAssembilesFile(report.summary.outputPath);
#endif #endif
} }
#if UNITY_PS5 private void PathScriptingAssembilesFile(string path)
/// <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) if (!SettingsUtil.Enable)
{ {
@ -113,7 +84,7 @@ namespace HybridCLR.Editor.BuildProcessors
if (jsonFiles.Length == 0) if (jsonFiles.Length == 0)
{ {
Debug.LogWarning($"can not find file {SettingsUtil.ScriptingAssembliesJsonFile}"); //Debug.LogError($"can not find file {SettingsUtil.ScriptingAssembliesJsonFile}");
return; return;
} }
@ -125,11 +96,9 @@ namespace HybridCLR.Editor.BuildProcessors
patcher.Save(file); patcher.Save(file);
} }
} }
private void AddHotFixAssembliesToBinFile(string path) private void AddHotFixAssembliesToBinFile(string path)
{ {
#if UNITY_STANDALONE_OSX
path = Path.GetDirectoryName(path);
#endif
if (AddHotFixAssembliesToGlobalgamemanagers(path)) if (AddHotFixAssembliesToGlobalgamemanagers(path))
{ {
return; return;
@ -179,7 +148,7 @@ namespace HybridCLR.Editor.BuildProcessors
return true; return true;
} }
#if UNITY_WEBGL && !UNITY_2022_3_OR_NEWER #if UNITY_WEBGL
public void OnBeforeConvertRun(BuildReport report, Il2CppBuildPipelineData data) public void OnBeforeConvertRun(BuildReport report, Il2CppBuildPipelineData data)
{ {
PathScriptingAssembilesFile($"{SettingsUtil.ProjectDir}/Temp/StagingArea/Data"); PathScriptingAssembilesFile($"{SettingsUtil.ProjectDir}/Temp/StagingArea/Data");

View File

@ -1,50 +0,0 @@
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);
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 4455f7304f8678f408dd6cf21734f55e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -2,7 +2,6 @@
using HybridCLR.Editor.Meta; using HybridCLR.Editor.Meta;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -11,7 +10,6 @@ using UnityEngine;
namespace HybridCLR.Editor.Commands namespace HybridCLR.Editor.Commands
{ {
using Analyzer = HybridCLR.Editor.AOT.Analyzer;
public static class AOTReferenceGeneratorCommand public static class AOTReferenceGeneratorCommand
{ {
@ -23,16 +21,13 @@ namespace HybridCLR.Editor.Commands
GenerateAOTGenericReference(target); GenerateAOTGenericReference(target);
} }
/// <summary>
/// 计算热更代码中的泛型引用
/// </summary>
/// <param name="target"></param>
public static void GenerateAOTGenericReference(BuildTarget target) public static void GenerateAOTGenericReference(BuildTarget target)
{ {
var gs = SettingsUtil.HybridCLRSettings; var gs = SettingsUtil.HybridCLRSettings;
List<string> hotUpdateDllNames = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved; List<string> hotUpdateDllNames = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved;
AssemblyReferenceDeepCollector collector = new AssemblyReferenceDeepCollector(MetaUtil.CreateHotUpdateAndAOTAssemblyResolver(target, hotUpdateDllNames), hotUpdateDllNames); using (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), MaxIterationCount = Math.Min(20, gs.maxGenericReferenceIteration),
@ -45,88 +40,6 @@ namespace HybridCLR.Editor.Commands
writer.Write(analyzer.AotGenericTypes.ToList(), analyzer.AotGenericMethods.ToList(), $"{Application.dataPath}/{gs.outputAOTGenericReferenceFile}"); writer.Write(analyzer.AotGenericTypes.ToList(), analyzer.AotGenericMethods.ToList(), $"{Application.dataPath}/{gs.outputAOTGenericReferenceFile}");
AssetDatabase.Refresh(); AssetDatabase.Refresh();
} }
//[MenuItem("HybridCLR/Generate/AOTGenericReference2", priority = 103)]
//public static void GeneratedAOTGenericReferenceExcludeExists()
//{
// GeneratedAOTGenericReferenceExcludeExists(EditorUserBuildSettings.activeBuildTarget);
//}
/// <summary>
/// 计算热更新代码中的泛型引用但排除AOT已经存在的泛型引用
/// </summary>
/// <param name="target"></param>
///
public static void GeneratedAOTGenericReferenceExcludeExistsAOTClassAndMethods(BuildTarget target)
{
var gs = SettingsUtil.HybridCLRSettings;
List<string> hotUpdateDllNames = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved;
AssemblyReferenceDeepCollector hotUpdateCollector = new AssemblyReferenceDeepCollector(MetaUtil.CreateHotUpdateAndAOTAssemblyResolver(target, hotUpdateDllNames), hotUpdateDllNames);
var hotUpdateAnalyzer = new Analyzer(new Analyzer.Options
{
MaxIterationCount = Math.Min(10, gs.maxGenericReferenceIteration),
Collector = hotUpdateCollector,
});
hotUpdateAnalyzer.Run();
string aotDllDir = SettingsUtil.GetAssembliesPostIl2CppStripDir(target);
List<string> aotAssemblyNames = Directory.Exists(aotDllDir) ?
Directory.GetFiles(aotDllDir, "*.dll", SearchOption.TopDirectoryOnly).Select(Path.GetFileNameWithoutExtension).ToList()
: new List<string>();
if (aotAssemblyNames.Count == 0)
{
throw new Exception($"no aot assembly found. please run `HybridCLR/Generate/All` or `HybridCLR/Generate/AotDlls` to generate aot dlls before runing `HybridCLR/Generate/AOTGenericReference`");
}
AssemblyReferenceDeepCollector aotCollector = new AssemblyReferenceDeepCollector(MetaUtil.CreateAOTAssemblyResolver(target), aotAssemblyNames);
var aotAnalyzer = new Analyzer(new Analyzer.Options
{
MaxIterationCount = Math.Min(10, gs.maxGenericReferenceIteration),
Collector = aotCollector,
ComputeAotAssembly = true,
});
aotAnalyzer.Run();
var (resultTypes, resultMethods) = ExcludeExistAOTGenericTypeAndMethodss(hotUpdateAnalyzer.AotGenericTypes.ToList(), hotUpdateAnalyzer.AotGenericMethods.ToList(), aotAnalyzer.AotGenericTypes.ToList(), aotAnalyzer.AotGenericMethods.ToList());
var writer = new GenericReferenceWriter();
writer.Write(resultTypes, resultMethods, $"{Application.dataPath}/{gs.outputAOTGenericReferenceFile}");
AssetDatabase.Refresh();
}
private static (List<GenericClass>, List<GenericMethod>) ExcludeExistAOTGenericTypeAndMethodss(List<GenericClass> hotUpdateTypes, List<GenericMethod> hotUpdateMethods, List<GenericClass> aotTypes, List<GenericMethod> aotMethods)
{
var types = new List<GenericClass>();
var typeSig2Type = hotUpdateTypes.ToDictionary(t => t.Type.DefinitionAssembly.Name + ":" + t.ToTypeSig(), t => t);
foreach (var t in aotTypes)
{
string key = t.Type.DefinitionAssembly.Name + ":" + t.ToTypeSig();
if (typeSig2Type.TryGetValue(key, out var removedType))
{
typeSig2Type.Remove(key);
Debug.Log($"remove AOT type:{removedType.ToTypeSig()} ");
}
}
var methodSig2Method = hotUpdateMethods.ToDictionary(m => m.Method.DeclaringType.DefinitionAssembly.Name + ":" + m.ToMethodSpec().ToString(), m => m);
foreach (var m in aotMethods)
{
string key = m.Method.DeclaringType.DefinitionAssembly.Name + ":" + m.ToMethodSpec().ToString();
if (methodSig2Method.TryGetValue(key, out var removedMethod))
{
methodSig2Method.Remove(key);
Debug.Log($"remove AOT method:{removedMethod.ToMethodSpec()} ");
}
}
return (typeSig2Type.Values.ToList(), methodSig2Method.Values.ToList());
} }
} }
} }

View File

@ -12,48 +12,31 @@ namespace HybridCLR.Editor.Commands
{ {
public class CompileDllCommand public class CompileDllCommand
{ {
public static void CompileDll(string buildDir, BuildTarget target, bool developmentBuild) public static void CompileDll(string buildDir, BuildTarget target)
{ {
var group = BuildPipeline.GetBuildTargetGroup(target); var group = BuildPipeline.GetBuildTargetGroup(target);
ScriptCompilationSettings scriptCompilationSettings = new ScriptCompilationSettings(); ScriptCompilationSettings scriptCompilationSettings = new ScriptCompilationSettings();
scriptCompilationSettings.group = group; scriptCompilationSettings.group = group;
scriptCompilationSettings.target = target; scriptCompilationSettings.target = target;
scriptCompilationSettings.options = developmentBuild ? ScriptCompilationOptions.DevelopmentBuild : ScriptCompilationOptions.None;
Directory.CreateDirectory(buildDir); Directory.CreateDirectory(buildDir);
ScriptCompilationResult scriptCompilationResult = PlayerBuildInterface.CompilePlayerScripts(scriptCompilationSettings, buildDir); ScriptCompilationResult scriptCompilationResult = PlayerBuildInterface.CompilePlayerScripts(scriptCompilationSettings, buildDir);
#if UNITY_2022 foreach (var ass in scriptCompilationResult.assemblies)
UnityEditor.EditorUtility.ClearProgressBar(); {
#endif //Debug.LogFormat("compile assemblies:{1}/{0}", ass, buildDir);
Debug.Log($"compile finish!!! buildDir:{buildDir} target:{target} development:{developmentBuild}"); }
Debug.Log("compile finish!!!");
} }
public static void CompileDll(BuildTarget target) public static void CompileDll(BuildTarget target)
{ {
CompileDll(target, EditorUserBuildSettings.development); CompileDll(SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target), target);
}
public static void CompileDll(BuildTarget target, bool developmentBuild)
{
CompileDll(SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target), target, developmentBuild);
} }
[MenuItem("HybridCLR/CompileDll/ActiveBuildTarget", priority = 100)] [MenuItem("HybridCLR/CompileDll/ActiveBuildTarget", priority = 100)]
public static void CompileDllActiveBuildTarget() public static void CompileDllActiveBuildTarget()
{ {
CompileDll(EditorUserBuildSettings.activeBuildTarget, EditorUserBuildSettings.development); CompileDll(EditorUserBuildSettings.activeBuildTarget);
}
[MenuItem("HybridCLR/CompileDll/ActiveBuildTarget_Release", priority = 102)]
public static void CompileDllActiveBuildTargetRelease()
{
CompileDll(EditorUserBuildSettings.activeBuildTarget, false);
}
[MenuItem("HybridCLR/CompileDll/ActiveBuildTarget_Development", priority = 104)]
public static void CompileDllActiveBuildTargetDevelopment()
{
CompileDll(EditorUserBuildSettings.activeBuildTarget, true);
} }
[MenuItem("HybridCLR/CompileDll/Win32", priority = 200)] [MenuItem("HybridCLR/CompileDll/Win32", priority = 200)]
@ -68,34 +51,16 @@ namespace HybridCLR.Editor.Commands
CompileDll(BuildTarget.StandaloneWindows64); CompileDll(BuildTarget.StandaloneWindows64);
} }
[MenuItem("HybridCLR/CompileDll/MacOS", priority = 202)] [MenuItem("HybridCLR/CompileDll/Android", priority = 202)]
public static void CompileDllMacOS()
{
CompileDll(BuildTarget.StandaloneOSX);
}
[MenuItem("HybridCLR/CompileDll/Linux", priority = 203)]
public static void CompileDllLinux()
{
CompileDll(BuildTarget.StandaloneLinux64);
}
[MenuItem("HybridCLR/CompileDll/Android", priority = 210)]
public static void CompileDllAndroid() public static void CompileDllAndroid()
{ {
CompileDll(BuildTarget.Android); CompileDll(BuildTarget.Android);
} }
[MenuItem("HybridCLR/CompileDll/IOS", priority = 220)] [MenuItem("HybridCLR/CompileDll/IOS", priority = 203)]
public static void CompileDllIOS() public static void CompileDllIOS()
{ {
CompileDll(BuildTarget.iOS); CompileDll(BuildTarget.iOS);
} }
[MenuItem("HybridCLR/CompileDll/WebGL", priority = 230)]
public static void CompileDllWebGL()
{
CompileDll(BuildTarget.WebGL);
}
} }
} }

View File

@ -1,5 +1,4 @@
using HybridCLR.Editor.Link; using HybridCLR.Editor.Link;
using HybridCLR.Editor.Settings;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -20,10 +19,8 @@ namespace HybridCLR.Editor.Commands
{ {
UnityVersion = Application.unityVersion, UnityVersion = Application.unityVersion,
HotUpdateAssemblies = SettingsUtil.HotUpdateAssemblyNamesIncludePreserved, HotUpdateAssemblies = SettingsUtil.HotUpdateAssemblyNamesIncludePreserved,
UnityVersionTemplateFile = $"{SettingsUtil.TemplatePathInPackage}/UnityVersion.h.tpl", OutputFile = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp/il2cpp-config.h",
UnityVersionOutputFile = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr/generated/UnityVersion.h", OutputFile2 = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr/Il2CppCompatibleDef.cpp",
AssemblyManifestTemplateFile = $"{SettingsUtil.TemplatePathInPackage}/AssemblyManifest.cpp.tpl",
AssemblyManifestOutputFile = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr/generated/AssemblyManifest.cpp",
}; };
var g = new Il2CppDef.Il2CppDefGenerator(options); var g = new Il2CppDef.Il2CppDefGenerator(options);

View File

@ -0,0 +1,22 @@
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);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b91d62dfcf14d1241b7654d79d5b98a0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -8,7 +8,6 @@ using UnityEngine;
namespace HybridCLR.Editor.Commands namespace HybridCLR.Editor.Commands
{ {
using Analyzer = HybridCLR.Editor.Link.Analyzer;
public static class LinkGeneratorCommand public static class LinkGeneratorCommand
{ {

View File

@ -10,12 +10,10 @@ using System.Reflection;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using UnityEditor; using UnityEditor;
using UnityEditor.Build;
using UnityEngine; using UnityEngine;
namespace HybridCLR.Editor.Commands namespace HybridCLR.Editor.Commands
{ {
using Analyzer = HybridCLR.Editor.MethodBridge.Analyzer;
public class MethodBridgeGeneratorCommand public class MethodBridgeGeneratorCommand
{ {
@ -30,67 +28,55 @@ namespace HybridCLR.Editor.Commands
Directory.Delete(il2cppBuildCachePath, true); Directory.Delete(il2cppBuildCachePath, true);
} }
private static void GenerateMethodBridgeCppFile(IReadOnlyCollection<GenericMethod> genericMethods, List<RawMonoPInvokeCallbackMethodInfo> reversePInvokeMethods, IReadOnlyCollection<CallNativeMethodSignatureInfo> calliMethodSignatures, string tempFile, string outputFile) private static void GenerateMethodBridgeCppFile(Analyzer analyzer, PlatformABI platform, string templateCode, string outputFile)
{ {
string templateCode = File.ReadAllText(tempFile, Encoding.UTF8);
var g = new Generator(new Generator.Options() var g = new Generator(new Generator.Options()
{ {
PlatformABI = platform,
TemplateCode = templateCode, TemplateCode = templateCode,
OutputFile = outputFile, OutputFile = outputFile,
GenericMethods = genericMethods, GenericMethods = analyzer.GenericMethods,
ReversePInvokeMethods = reversePInvokeMethods, NotGenericMethods = analyzer.NotGenericMethods,
CalliMethodSignatures = calliMethodSignatures,
Development = EditorUserBuildSettings.development,
}); });
g.PrepareMethods();
g.Generate(); g.Generate();
Debug.LogFormat("[MethodBridgeGeneratorCommand] output:{0}", outputFile); Debug.LogFormat("== output:{0} ==", outputFile);
} }
[MenuItem("HybridCLR/Generate/MethodBridgeAndReversePInvokeWrapper", priority = 101)] [MenuItem("HybridCLR/Generate/MethodBridge", priority = 101)]
public static void GenerateMethodBridgeAndReversePInvokeWrapper() public static void CompileAndGenerateMethodBridge()
{ {
BuildTarget target = EditorUserBuildSettings.activeBuildTarget; BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
GenerateMethodBridgeAndReversePInvokeWrapper(target); CompileDllCommand.CompileDll(target);
GenerateMethodBridge(target);
} }
public static void GenerateMethodBridgeAndReversePInvokeWrapper(BuildTarget target) public static void GenerateMethodBridge(BuildTarget target)
{ {
string aotDllDir = SettingsUtil.GetAssembliesPostIl2CppStripDir(target); List<string> hotUpdateDllNames = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved;
List<string> aotAssemblyNames = Directory.Exists(aotDllDir) ? using (AssemblyReferenceDeepCollector collector = new AssemblyReferenceDeepCollector(MetaUtil.CreateHotUpdateAndAOTAssemblyResolver(target, hotUpdateDllNames), hotUpdateDllNames))
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/MethodBridge`"); var analyzer = new Analyzer(new Analyzer.Options
}
AssemblyReferenceDeepCollector collector = new AssemblyReferenceDeepCollector(MetaUtil.CreateAOTAssemblyResolver(target), aotAssemblyNames);
var methodBridgeAnalyzer = new Analyzer(new Analyzer.Options
{ {
MaxIterationCount = Math.Min(20, SettingsUtil.HybridCLRSettings.maxMethodBridgeGenericIteration), MaxIterationCount = Math.Min(20, SettingsUtil.HybridCLRSettings.maxMethodBridgeGenericIteration),
Collector = collector, Collector = collector,
}); });
methodBridgeAnalyzer.Run(); analyzer.Run();
List<string> hotUpdateDlls = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved; var tasks = new List<Task>();
var cache = new AssemblyCache(MetaUtil.CreateHotUpdateAndAOTAssemblyResolver(target, hotUpdateDlls)); string templateCode = File.ReadAllText($"{SettingsUtil.TemplatePathInPackage}/MethodBridgeStub.cpp");
foreach (PlatformABI platform in Enum.GetValues(typeof(PlatformABI)))
var reversePInvokeAnalyzer = new MonoPInvokeCallbackAnalyzer(cache, hotUpdateDlls); {
reversePInvokeAnalyzer.Run(); string outputFile = $"{SettingsUtil.GeneratedCppDir}/MethodBridge_{platform}.cpp";
tasks.Add(Task.Run(() =>
var calliAnalyzer = new CalliAnalyzer(cache, hotUpdateDlls); {
calliAnalyzer.Run(); GenerateMethodBridgeCppFile(analyzer, platform, templateCode, outputFile);
var pinvokeAnalyzer = new PInvokeAnalyzer(cache, hotUpdateDlls); }));
pinvokeAnalyzer.Run(); }
var callPInvokeMethodSignatures = pinvokeAnalyzer.PInvokeMethodSignatures; Task.WaitAll(tasks.ToArray());
}
string templateFile = $"{SettingsUtil.TemplatePathInPackage}/MethodBridge.cpp.tpl";
string outputFile = $"{SettingsUtil.GeneratedCppDir}/MethodBridge.cpp";
var callNativeMethodSignatures = calliAnalyzer.CalliMethodSignatures.Concat(pinvokeAnalyzer.PInvokeMethodSignatures).ToList();
GenerateMethodBridgeCppFile(methodBridgeAnalyzer.GenericMethods, reversePInvokeAnalyzer.ReversePInvokeMethods, callNativeMethodSignatures, templateFile, outputFile);
CleanIl2CppBuildCache(); CleanIl2CppBuildCache();
} }

View File

@ -4,7 +4,6 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using UnityEditor; using UnityEditor;
using UnityEditor.Build;
namespace HybridCLR.Editor.Commands namespace HybridCLR.Editor.Commands
{ {
@ -16,23 +15,19 @@ namespace HybridCLR.Editor.Commands
[MenuItem("HybridCLR/Generate/All", priority = 200)] [MenuItem("HybridCLR/Generate/All", priority = 200)]
public static void GenerateAll() public static void GenerateAll()
{ {
var installer = new Installer.InstallerController();
if (!installer.HasInstalledHybridCLR())
{
throw new BuildFailedException($"You have not initialized HybridCLR, please install it via menu 'HybridCLR/Installer'");
}
BuildTarget target = EditorUserBuildSettings.activeBuildTarget; BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
CompileDllCommand.CompileDll(target, EditorUserBuildSettings.development); CompileDllCommand.CompileDll(target);
Il2CppDefGeneratorCommand.GenerateIl2CppDef(); Il2CppDefGeneratorCommand.GenerateIl2CppDef();
// 这几个生成依赖HotUpdateDlls // 这几个生成依赖HotUpdateDlls
LinkGeneratorCommand.GenerateLinkXml(target); LinkGeneratorCommand.GenerateLinkXml(target);
// 生成裁剪后的aot dll // 生成裁剪后的aot dll
StripAOTDllCommand.GenerateStripedAOTDlls(target); StripAOTDllCommand.GenerateStripedAOTDlls(target, EditorUserBuildSettings.selectedBuildTargetGroup);
// 桥接函数生成依赖于AOT dll必须保证已经build过生成AOT dll // 桥接函数生成依赖于AOT dll必须保证已经build过生成AOT dll
MethodBridgeGeneratorCommand.GenerateMethodBridgeAndReversePInvokeWrapper(target); MethodBridgeGeneratorCommand.GenerateMethodBridge(target);
ReversePInvokeWrapperGeneratorCommand.GenerateReversePInvokeWrapper(target);
AOTReferenceGeneratorCommand.GenerateAOTGenericReference(target); AOTReferenceGeneratorCommand.GenerateAOTGenericReference(target);
} }
} }

View File

@ -0,0 +1,53 @@
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();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7db18e1736f593c4089c85d764cf8620
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,15 +1,12 @@
using HybridCLR.Editor.BuildProcessors; using HybridCLR.Editor.Installer;
using HybridCLR.Editor.Installer;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
using static UnityEngine.Networking.UnityWebRequest;
namespace HybridCLR.Editor.Commands namespace HybridCLR.Editor.Commands
{ {
@ -18,38 +15,7 @@ namespace HybridCLR.Editor.Commands
[MenuItem("HybridCLR/Generate/AOTDlls", priority = 105)] [MenuItem("HybridCLR/Generate/AOTDlls", priority = 105)]
public static void GenerateStripedAOTDlls() public static void GenerateStripedAOTDlls()
{ {
GenerateStripedAOTDlls(EditorUserBuildSettings.activeBuildTarget); GenerateStripedAOTDlls(EditorUserBuildSettings.activeBuildTarget, EditorUserBuildSettings.selectedBuildTargetGroup);
}
static BuildOptions GetBuildPlayerOptions(BuildTarget buildTarget)
{
BuildOptions options = BuildOptions.None;
bool development = EditorUserBuildSettings.development;
if (development)
{
options |= BuildOptions.Development;
}
if (EditorUserBuildSettings.allowDebugging && development)
{
options |= BuildOptions.AllowDebugging;
}
if (EditorUserBuildSettings.connectProfiler && (development || buildTarget == BuildTarget.WSAPlayer))
{
options |= BuildOptions.ConnectWithProfiler;
}
if (EditorUserBuildSettings.buildWithDeepProfilingSupport && development)
{
options |= BuildOptions.EnableDeepProfilingSupport;
}
#if UNITY_2021_2_OR_NEWER
options |= BuildOptions.CleanBuildCache;
#endif
return options;
} }
private static string GetLocationPathName(string buildDir, BuildTarget target) private static string GetLocationPathName(string buildDir, BuildTarget target)
@ -57,42 +23,31 @@ namespace HybridCLR.Editor.Commands
switch(target) switch(target)
{ {
case BuildTarget.StandaloneWindows: case BuildTarget.StandaloneWindows:
case BuildTarget.StandaloneWindows64: return $"{buildDir}/{PlayerSettings.productName}.exe"; case BuildTarget.StandaloneWindows64: return $"{buildDir}/{target}";
case BuildTarget.StandaloneOSX: return buildDir; case BuildTarget.StandaloneOSX: return buildDir;
case BuildTarget.iOS: return buildDir; case BuildTarget.iOS: return buildDir;
case BuildTarget.Android: return buildDir; case BuildTarget.Android: return buildDir;
case BuildTarget.StandaloneLinux64: return $"{buildDir}/{PlayerSettings.productName}"; case BuildTarget.StandaloneLinux64: return buildDir;
default: return buildDir; default: return buildDir;
} }
} }
public static void GenerateStripedAOTDlls(BuildTarget target) public static void GenerateStripedAOTDlls(BuildTarget target, BuildTargetGroup group)
{ {
string outputPath = $"{SettingsUtil.HybridCLRDataDir}/StrippedAOTDllsTempProj/{target}"; string outputPath = $"{SettingsUtil.HybridCLRDataDir}/StrippedAOTDllsTempProj/{target}";
BashUtil.RemoveDir(outputPath); BashUtil.RemoveDir(outputPath);
var buildOptions = GetBuildPlayerOptions(target); var buildOptions = BuildOptions.BuildScriptsOnly;
bool oldExportAndroidProj = EditorUserBuildSettings.exportAsGoogleAndroidProject; bool oldExportAndroidProj = EditorUserBuildSettings.exportAsGoogleAndroidProject;
#if UNITY_EDITOR_OSX #if UNITY_EDITOR_OSX
bool oldCreateSolution = UnityEditor.OSXStandalone.UserBuildSettings.createXcodeProject; bool oldCreateSolution = UnityEditor.OSXStandalone.UserBuildSettings.createXcodeProject;
#elif UNITY_EDITOR_WIN #elif UNITY_EDITOR_WIN
bool oldCreateSolution = UnityEditor.WindowsStandalone.UserBuildSettings.createSolution; bool oldCreateSolution = UnityEditor.WindowsStandalone.UserBuildSettings.createSolution;
#endif
#if TUANJIE_2022_3_OR_NEWER
bool oldOpenHarmonyProj = EditorUserBuildSettings.exportAsOpenHarmonyProject;
#endif #endif
bool oldBuildScriptsOnly = EditorUserBuildSettings.buildScriptsOnly; bool oldBuildScriptsOnly = EditorUserBuildSettings.buildScriptsOnly;
string oldBuildLocation = EditorUserBuildSettings.GetBuildLocation(target);
try
{
CheckSettings.DisableMethodBridgeDevelopmentFlagChecking = true;
EditorUserBuildSettings.buildScriptsOnly = true; EditorUserBuildSettings.buildScriptsOnly = true;
string location = GetLocationPathName(outputPath, target);
EditorUserBuildSettings.SetBuildLocation(target, location);
switch (target) switch (target)
{ {
case BuildTarget.StandaloneWindows: case BuildTarget.StandaloneWindows:
@ -110,52 +65,25 @@ namespace HybridCLR.Editor.Commands
#endif #endif
break; break;
} }
#if TUANJIE_2022_3_OR_NEWER
case BuildTarget.HMIAndroid:
#endif
case BuildTarget.Android: case BuildTarget.Android:
{ {
EditorUserBuildSettings.exportAsGoogleAndroidProject = true; EditorUserBuildSettings.exportAsGoogleAndroidProject = true;
break; break;
} }
#if TUANJIE_2022_3_OR_NEWER
case BuildTarget.OpenHarmony:
{
EditorUserBuildSettings.exportAsOpenHarmonyProject = true;
break;
} }
#endif
}
Debug.Log($"GenerateStripedAOTDlls build option:{buildOptions}");
BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions() BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions()
{ {
scenes = EditorBuildSettings.scenes.Where(s => s.enabled).Select(s => s.path).ToArray(), scenes = EditorBuildSettings.scenes.Where(s => s.enabled).Select(s => s.path).ToArray(),
locationPathName = location, locationPathName = GetLocationPathName(outputPath, target),
options = buildOptions, options = buildOptions,
target = target, target = target,
targetGroup = BuildPipeline.GetBuildTargetGroup(target), targetGroup = group,
#if UNITY_SERVER
subtarget = (int)StandaloneBuildSubtarget.Server,
#endif
}; };
var report = BuildPipeline.BuildPlayer(buildPlayerOptions); var report = BuildPipeline.BuildPlayer(buildPlayerOptions);
if (report.summary.result != UnityEditor.Build.Reporting.BuildResult.Succeeded)
{
throw new Exception("GenerateStripedAOTDlls failed");
}
}
finally
{
CheckSettings.DisableMethodBridgeDevelopmentFlagChecking = false;
EditorUserBuildSettings.buildScriptsOnly = oldBuildScriptsOnly; EditorUserBuildSettings.buildScriptsOnly = oldBuildScriptsOnly;
EditorUserBuildSettings.SetBuildLocation(target, oldBuildLocation);
switch (target) switch (target)
{ {
case BuildTarget.StandaloneWindows: case BuildTarget.StandaloneWindows:
@ -173,24 +101,19 @@ namespace HybridCLR.Editor.Commands
#endif #endif
break; break;
} }
#if TUANJIE_2022_3_OR_NEWER
case BuildTarget.HMIAndroid:
#endif
case BuildTarget.Android: case BuildTarget.Android:
{ {
EditorUserBuildSettings.exportAsGoogleAndroidProject = oldExportAndroidProj; EditorUserBuildSettings.exportAsGoogleAndroidProject = oldExportAndroidProj;
break; break;
} }
#if TUANJIE_2022_3_OR_NEWER }
case BuildTarget.OpenHarmony:
if (report.summary.result != UnityEditor.Build.Reporting.BuildResult.Succeeded)
{ {
EditorUserBuildSettings.exportAsOpenHarmonyProject = oldOpenHarmonyProj; Debug.LogError("GenerateStripedAOTDlls 失败");
break; return;
} }
#endif Debug.Log($"GenerateStripedAOTDlls target:{target} group:{group} path:{outputPath}");
}
}
Debug.Log($"GenerateStripedAOTDlls target:{target} path:{outputPath}");
} }
} }
} }

View File

@ -1,109 +0,0 @@
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;
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: bdd260aca2a6deb44b20210f01faa86b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -17,13 +17,9 @@ namespace HybridCLR.Editor.Il2CppDef
{ {
public List<string> HotUpdateAssemblies { get; set; } public List<string> HotUpdateAssemblies { get; set; }
public string UnityVersionTemplateFile { get; set; } public string OutputFile { get; set; }
public string UnityVersionOutputFile { get; set; } public string OutputFile2 { get; set; }
public string AssemblyManifestTemplateFile { get; set; }
public string AssemblyManifestOutputFile { get; set; }
public string UnityVersion { get; set; } public string UnityVersion { get; set; }
} }
@ -45,7 +41,7 @@ namespace HybridCLR.Editor.Il2CppDef
private void GenerateIl2CppConfig() private void GenerateIl2CppConfig()
{ {
var frr = new FileRegionReplace(File.ReadAllText(_options.UnityVersionTemplateFile)); var frr = new FileRegionReplace(File.ReadAllText(_options.OutputFile));
List<string> lines = new List<string>(); List<string> lines = new List<string>();
@ -56,40 +52,23 @@ namespace HybridCLR.Editor.Il2CppDef
lines.Add($"#define HYBRIDCLR_UNITY_VERSION {majorVer}{minorVer1.ToString("D2")}{minorVer2.ToString("D2")}"); lines.Add($"#define HYBRIDCLR_UNITY_VERSION {majorVer}{minorVer1.ToString("D2")}{minorVer2.ToString("D2")}");
lines.Add($"#define HYBRIDCLR_UNITY_{majorVer} 1"); lines.Add($"#define HYBRIDCLR_UNITY_{majorVer} 1");
for (int ver = 2019; ver <= 2023; ver++) for (int ver = 2019; ver <= 2024; ver++)
{ {
if (majorVer >= ver) if (majorVer >= ver)
{ {
lines.Add($"#define HYBRIDCLR_UNITY_{ver}_OR_NEW 1"); lines.Add($"#define HYBRIDCLR_UNITY_{ver}_OR_NEW 1");
} }
} }
for (int ver = 6000; ver <= 6100; ver++)
{
if (majorVer >= ver)
{
lines.Add($"#define HYBRIDCLR_UNITY_{ver}_OR_NEW 1");
}
}
#if TUANJIE_1_1_OR_NEWER
var tuanjieMatch = Regex.Matches(Application.tuanjieVersion, @"(\d+)\.(\d+)\.(\d+)");
int tuanjieMajorVer = int.Parse(tuanjieMatch[0].Groups[1].Value);
int tuanjieMinorVer1 = int.Parse(tuanjieMatch[0].Groups[2].Value);
int tuanjieMinorVer2 = int.Parse(tuanjieMatch[0].Groups[3].Value);
lines.Add($"#define HYBRIDCLR_TUANJIE_VERSION {tuanjieMajorVer}{tuanjieMinorVer1.ToString("D2")}{tuanjieMinorVer2.ToString("D2")}");
#elif TUANJIE_2022_3_OR_NEWER
lines.Add($"#define HYBRIDCLR_TUANJIE_VERSION 10000");
#endif
frr.Replace("UNITY_VERSION", string.Join("\n", lines)); frr.Replace("UNITY_VERSION", string.Join("\n", lines));
frr.Commit(_options.UnityVersionOutputFile); frr.Commit(_options.OutputFile);
Debug.Log($"[HybridCLR.Editor.Il2CppDef.Generator] output:{_options.UnityVersionOutputFile}"); Debug.Log($"[HybridCLR.Editor.Il2CppDef.Generator] output:{_options.OutputFile}");
} }
private void GeneratePlaceHolderAssemblies() private void GeneratePlaceHolderAssemblies()
{ {
var frr = new FileRegionReplace(File.ReadAllText(_options.AssemblyManifestTemplateFile)); var frr = new FileRegionReplace(File.ReadAllText(_options.OutputFile2));
List<string> lines = new List<string>(); List<string> lines = new List<string>();
@ -100,8 +79,8 @@ namespace HybridCLR.Editor.Il2CppDef
frr.Replace("PLACE_HOLDER", string.Join("\n", lines)); frr.Replace("PLACE_HOLDER", string.Join("\n", lines));
frr.Commit(_options.AssemblyManifestOutputFile); frr.Commit(_options.OutputFile2);
Debug.Log($"[HybridCLR.Editor.Il2CppDef.Generator] output:{_options.AssemblyManifestOutputFile}"); Debug.Log($"[HybridCLR.Editor.Il2CppDef.Generator] output:{_options.OutputFile2}");
} }
} }
} }

View File

@ -4,7 +4,6 @@ using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace HybridCLR.Editor.Installer namespace HybridCLR.Editor.Installer
@ -64,12 +63,6 @@ namespace HybridCLR.Editor.Installer
{ {
UnityEngine.Debug.Log($"[BashUtil] RemoveDir dir:{dir}"); UnityEngine.Debug.Log($"[BashUtil] RemoveDir dir:{dir}");
} }
int maxTryCount = 5;
for (int i = 0; i < maxTryCount; ++i)
{
try
{
if (!Directory.Exists(dir)) if (!Directory.Exists(dir))
{ {
return; return;
@ -83,15 +76,7 @@ namespace HybridCLR.Editor.Installer
{ {
RemoveDir(subDir); RemoveDir(subDir);
} }
Directory.Delete(dir, true); Directory.Delete(dir);
break;
}
catch (Exception e)
{
UnityEngine.Debug.LogError($"[BashUtil] RemoveDir:{dir} with exception:{e}. try count:{i}");
Thread.Sleep(100);
}
}
} }
public static void RecreateDir(string dir) public static void RecreateDir(string dir)
@ -102,23 +87,23 @@ namespace HybridCLR.Editor.Installer
} }
Directory.CreateDirectory(dir); Directory.CreateDirectory(dir);
} }
public static void CopyDir(string src, string dst, bool log = false) public static void CopyDir(string src, string dst, bool log = false)
{ {
if (log) if (log)
{ {
UnityEngine.Debug.Log($"[BashUtil] CopyDir {src} => {dst}"); UnityEngine.Debug.Log($"[BashUtil] CopyDir {src} => {dst}");
} }
if (Directory.Exists(dst))
{
RemoveDir(dst); RemoveDir(dst);
} Directory.CreateDirectory(dst);
else foreach(var file in Directory.GetFiles(src))
{ {
string parentDir = Path.GetDirectoryName(Path.GetFullPath(dst)); File.Copy(file, $"{dst}/{Path.GetFileName(file)}");
Directory.CreateDirectory(parentDir); }
foreach(var subDir in Directory.GetDirectories(src))
{
CopyDir(subDir, $"{dst}/{Path.GetFileName(subDir)}");
} }
UnityEditor.FileUtil.CopyFileOrDirectory(src, dst);
} }
} }
} }

View File

@ -1,16 +1,27 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks;
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Diagnostics;
using Debug = UnityEngine.Debug; using Debug = UnityEngine.Debug;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Linq;
using HybridCLR.Editor.Settings;
namespace HybridCLR.Editor.Installer namespace HybridCLR.Editor.Installer
{ {
public enum InstallErrorCode
{
Ok,
}
public class InstallerController public class InstallerController
{ {
@ -25,17 +36,11 @@ namespace HybridCLR.Editor.Installer
private readonly HybridclrVersionManifest _versionManifest; private readonly HybridclrVersionManifest _versionManifest;
private readonly HybridclrVersionInfo _curDefaultVersion; private readonly HybridclrVersionInfo _curDefaultVersion;
public string PackageVersion { get; private set; }
public string InstalledLibil2cppVersion { get; private set; }
public InstallerController() public InstallerController()
{ {
_curVersion = ParseUnityVersion(Application.unityVersion); _curVersion = ParseUnityVersion(Application.unityVersion);
_versionManifest = GetHybridCLRVersionManifest(); _versionManifest = GetHybridCLRVersionManifest();
_curDefaultVersion = _versionManifest.versions.FirstOrDefault(v => _curVersion.isTuanjieEngine ? v.unity_version == $"{_curVersion.major}-tuanjie" : v.unity_version == _curVersion.major.ToString()); _curDefaultVersion = _versionManifest.versions.Find(v => v.unity_version == _curVersion.major.ToString());
PackageVersion = LoadPackageInfo().version;
InstalledLibil2cppVersion = ReadLocalVersion();
} }
private HybridclrVersionManifest GetHybridCLRVersionManifest() private HybridclrVersionManifest GetHybridCLRVersionManifest()
@ -44,21 +49,6 @@ namespace HybridCLR.Editor.Installer
return JsonUtility.FromJson<HybridclrVersionManifest>(File.ReadAllText(versionFile, Encoding.UTF8)); return JsonUtility.FromJson<HybridclrVersionManifest>(File.ReadAllText(versionFile, Encoding.UTF8));
} }
private PackageInfo LoadPackageInfo()
{
string packageJson = $"{SettingsUtil.ProjectDir}/Packages/{SettingsUtil.PackageName}/package.json";
return JsonUtility.FromJson<PackageInfo>(File.ReadAllText(packageJson, Encoding.UTF8));
}
[Serializable]
class PackageInfo
{
public string name;
public string version;
}
[Serializable] [Serializable]
class VersionDesc class VersionDesc
{ {
@ -88,7 +78,6 @@ namespace HybridCLR.Editor.Installer
public int major; public int major;
public int minor1; public int minor1;
public int minor2; public int minor2;
public bool isTuanjieEngine;
public override string ToString() public override string ToString()
{ {
@ -98,6 +87,10 @@ namespace HybridCLR.Editor.Installer
private static readonly Regex s_unityVersionPat = new Regex(@"(\d+)\.(\d+)\.(\d+)"); private static readonly Regex s_unityVersionPat = new Regex(@"(\d+)\.(\d+)\.(\d+)");
public const int min2019_4_CompatibleMinorVersion = 40;
public const int min2020_3_CompatibleMinorVersion = 21;
public const int min2021_3_CompatibleMinorVersion = 0;
private UnityVersion ParseUnityVersion(string versionStr) private UnityVersion ParseUnityVersion(string versionStr)
{ {
var matches = s_unityVersionPat.Matches(versionStr); var matches = s_unityVersionPat.Matches(versionStr);
@ -105,12 +98,13 @@ namespace HybridCLR.Editor.Installer
{ {
return null; return null;
} }
// 找最后一个匹配的
Match match = matches[matches.Count - 1]; Match match = matches[matches.Count - 1];
// Debug.Log($"capture count:{match.Groups.Count} {match.Groups[1].Value} {match.Groups[2].Value}");
int major = int.Parse(match.Groups[1].Value); int major = int.Parse(match.Groups[1].Value);
int minor1 = int.Parse(match.Groups[2].Value); int minor1 = int.Parse(match.Groups[2].Value);
int minor2 = int.Parse(match.Groups[3].Value); int minor2 = int.Parse(match.Groups[3].Value);
bool isTuanjieEngine = versionStr.Contains("t"); return new UnityVersion { major = major, minor1 = minor1, minor2 = minor2 };
return new UnityVersion { major = major, minor1 = minor1, minor2 = minor2, isTuanjieEngine = isTuanjieEngine };
} }
public string GetCurrentUnityVersionMinCompatibleVersionStr() public string GetCurrentUnityVersionMinCompatibleVersionStr()
@ -122,41 +116,49 @@ namespace HybridCLR.Editor.Installer
{ {
switch(majorVersion) switch(majorVersion)
{ {
case 2019: return "2019.4.0"; case 2019: return $"2019.4.{min2019_4_CompatibleMinorVersion}";
case 2020: return "2020.3.0"; case 2020: return $"2020.3.{min2020_3_CompatibleMinorVersion}";
case 2021: return "2021.3.0"; case 2021: return $"2021.3.{min2021_3_CompatibleMinorVersion}";
case 2022: return "2022.3.0"; default: throw new Exception($"not support version:{majorVersion}");
case 2023: return "2023.2.0";
case 6000: return "6000.0.0";
default: return $"2020.3.0";
} }
} }
public enum CompatibleType public bool IsComaptibleVersion()
{
Compatible,
MaybeIncompatible,
Incompatible,
}
public CompatibleType GetCompatibleType()
{ {
UnityVersion version = _curVersion; UnityVersion version = _curVersion;
if (version == null) switch (version.major)
{ {
return CompatibleType.Incompatible; case 2019:
}
if ((version.major == 2019 && version.minor1 < 4)
|| (version.major >= 2020 && version.major <= 2022 && version.minor1 < 3))
{ {
return CompatibleType.MaybeIncompatible; 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.Compatible;
} }
public string HybridclrLocalVersion => _curDefaultVersion?.hybridclr?.branch; public string HybridclrLocalVersion => _curDefaultVersion.hybridclr.branch;
public string Il2cppPlusLocalVersion => _curDefaultVersion?.il2cpp_plus?.branch; public string Il2cppPlusLocalVersion => _curDefaultVersion.il2cpp_plus.branch;
private string GetIl2CppPathByContentPath(string contentPath) private string GetIl2CppPathByContentPath(string contentPath)
@ -164,29 +166,10 @@ namespace HybridCLR.Editor.Installer
return $"{contentPath}/il2cpp"; return $"{contentPath}/il2cpp";
} }
public string ApplicationIl2cppPath => GetIl2CppPathByContentPath(EditorApplication.applicationContentsPath);
public string LocalVersionFile => $"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr/generated/libil2cpp-version.txt";
private string ReadLocalVersion()
{
if (!File.Exists(LocalVersionFile))
{
return null;
}
return File.ReadAllText(LocalVersionFile, Encoding.UTF8);
}
public void WriteLocalVersion()
{
InstalledLibil2cppVersion = PackageVersion;
File.WriteAllText(LocalVersionFile, PackageVersion, Encoding.UTF8);
Debug.Log($"Write installed version:'{PackageVersion}' to {LocalVersionFile}");
}
public void InstallDefaultHybridCLR() public void InstallDefaultHybridCLR()
{ {
InstallFromLocal(PrepareLibil2cppWithHybridclrFromGitRepo()); RunInitLocalIl2CppData(GetIl2CppPathByContentPath(EditorApplication.applicationContentsPath), _curVersion);
} }
public bool HasInstalledHybridCLR() public bool HasInstalledHybridCLR()
@ -194,6 +177,7 @@ namespace HybridCLR.Editor.Installer
return Directory.Exists($"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr"); return Directory.Exists($"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr");
} }
private string GetUnityIl2CppDllInstallLocation() private string GetUnityIl2CppDllInstallLocation()
{ {
#if UNITY_EDITOR_WIN #if UNITY_EDITOR_WIN
@ -206,9 +190,9 @@ namespace HybridCLR.Editor.Installer
private string GetUnityIl2CppDllModifiedPath(string curVersionStr) private string GetUnityIl2CppDllModifiedPath(string curVersionStr)
{ {
#if UNITY_EDITOR_WIN #if UNITY_EDITOR_WIN
return $"{SettingsUtil.ProjectDir}/{SettingsUtil.HybridCLRDataPathInPackage}/ModifiedUnityAssemblies/{curVersionStr}/Unity.IL2CPP-Win.dll"; return $"{SettingsUtil.ProjectDir}/{SettingsUtil.HybridCLRDataPathInPackage}/ModifiedUnityAssemblies/{curVersionStr}/Unity.IL2CPP-Win.dll.bytes";
#else #else
return $"{SettingsUtil.ProjectDir}/{SettingsUtil.HybridCLRDataPathInPackage}/ModifiedUnityAssemblies/{curVersionStr}/Unity.IL2CPP-Mac.dll"; return $"{SettingsUtil.ProjectDir}/{SettingsUtil.HybridCLRDataPathInPackage}/ModifiedUnityAssemblies/{curVersionStr}/Unity.IL2CPP-Mac.dll.bytes";
#endif #endif
} }
@ -218,51 +202,31 @@ namespace HybridCLR.Editor.Installer
BashUtil.RunCommand(workDir, "git", new string[] {"clone", "-b", branch, "--depth", "1", repoUrl, repoDir}); BashUtil.RunCommand(workDir, "git", new string[] {"clone", "-b", branch, "--depth", "1", repoUrl, repoDir});
} }
private string PrepareLibil2cppWithHybridclrFromGitRepo() private void RunInitLocalIl2CppData(string editorIl2cppPath, UnityVersion version)
{ {
if (!IsComaptibleVersion())
{
Debug.LogError($"il2cpp 版本不兼容,最小版本为 {GetCurrentUnityVersionMinCompatibleVersionStr()}");
return;
}
string workDir = SettingsUtil.HybridCLRDataDir; string workDir = SettingsUtil.HybridCLRDataDir;
Directory.CreateDirectory(workDir); Directory.CreateDirectory(workDir);
//BashUtil.RecreateDir(workDir); //BashUtil.RecreateDir(workDir);
string buildiOSDir = $"{workDir}/iOSBuild";
BashUtil.RemoveDir(buildiOSDir);
BashUtil.CopyDir($"{SettingsUtil.HybridCLRDataPathInPackage}/iOSBuild", buildiOSDir, true);
// clone hybridclr // clone hybridclr
string hybridclrRepoURL = HybridCLRSettings.Instance.hybridclrRepoURL; string hybridclrRepoURL = HybridCLRSettings.Instance.hybridclrRepoURL;
string hybridclrRepoDir = $"{workDir}/{hybridclr_repo_path}"; string hybridclrRepoDir = $"{workDir}/{hybridclr_repo_path}";
CloneBranch(workDir, hybridclrRepoURL, _curDefaultVersion.hybridclr.branch, hybridclrRepoDir); CloneBranch(workDir, hybridclrRepoURL, _curDefaultVersion.hybridclr.branch, hybridclrRepoDir);
if (!Directory.Exists(hybridclrRepoDir))
{
throw new Exception($"clone hybridclr fail. url: {hybridclrRepoURL}");
}
// clone il2cpp_plus // clone il2cpp_plus
string il2cppPlusRepoURL = HybridCLRSettings.Instance.il2cppPlusRepoURL; string il2cppPlusRepoURL = HybridCLRSettings.Instance.il2cppPlusRepoURL;
string il2cppPlusRepoDir = $"{workDir}/{il2cpp_plus_repo_path}"; string il2cppPlusRepoDir = $"{workDir}/{il2cpp_plus_repo_path}";
CloneBranch(workDir, il2cppPlusRepoURL, _curDefaultVersion.il2cpp_plus.branch, il2cppPlusRepoDir); CloneBranch(workDir, il2cppPlusRepoURL, _curDefaultVersion.il2cpp_plus.branch, il2cppPlusRepoDir);
if (!Directory.Exists(il2cppPlusRepoDir))
{
throw new Exception($"clone il2cpp_plus fail. url: {il2cppPlusRepoDir}");
}
Directory.Move($"{hybridclrRepoDir}/hybridclr", $"{il2cppPlusRepoDir}/libil2cpp/hybridclr");
return $"{il2cppPlusRepoDir}/libil2cpp";
}
public void InstallFromLocal(string libil2cppWithHybridclrSourceDir)
{
RunInitLocalIl2CppData(ApplicationIl2cppPath, libil2cppWithHybridclrSourceDir, _curVersion);
}
private void RunInitLocalIl2CppData(string editorIl2cppPath, string libil2cppWithHybridclrSourceDir, UnityVersion version)
{
if (GetCompatibleType() == CompatibleType.Incompatible)
{
Debug.LogError($"Incompatible with current version, minimum compatible version: {GetCurrentUnityVersionMinCompatibleVersionStr()}");
return;
}
string workDir = SettingsUtil.HybridCLRDataDir;
Directory.CreateDirectory(workDir);
// create LocalIl2Cpp // create LocalIl2Cpp
string localUnityDataDir = SettingsUtil.LocalUnityDataDir; string localUnityDataDir = SettingsUtil.LocalUnityDataDir;
BashUtil.RecreateDir(localUnityDataDir); BashUtil.RecreateDir(localUnityDataDir);
@ -275,10 +239,12 @@ namespace HybridCLR.Editor.Installer
// replace libil2cpp // replace libil2cpp
string dstLibil2cppDir = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp"; string dstLibil2cppDir = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp";
BashUtil.CopyDir($"{libil2cppWithHybridclrSourceDir}", dstLibil2cppDir, true); BashUtil.CopyDir($"{il2cppPlusRepoDir}/libil2cpp", dstLibil2cppDir, true);
BashUtil.CopyDir($"{hybridclrRepoDir}/hybridclr", $"{dstLibil2cppDir}/hybridclr", true);
// clean Il2cppBuildCache // clean Il2cppBuildCache
BashUtil.RemoveDir($"{SettingsUtil.ProjectDir}/Library/Il2cppBuildCache", true); BashUtil.RemoveDir($"{SettingsUtil.ProjectDir}/Library/Il2cppBuildCache", true);
if (version.major == 2019) if (version.major == 2019)
{ {
string curVersionStr = version.ToString(); string curVersionStr = version.ToString();
@ -291,17 +257,16 @@ namespace HybridCLR.Editor.Installer
} }
else else
{ {
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"); Debug.LogError($"未找到当前版本:{curVersionStr} 对应的改造过的 Unity.IL2CPP.dll打包出的程序将会崩溃");
} }
} }
if (HasInstalledHybridCLR()) if (HasInstalledHybridCLR())
{ {
WriteLocalVersion(); Debug.Log("安装成功");
Debug.Log("Install Sucessfully");
} }
else else
{ {
Debug.LogError("Installation failed!"); Debug.LogError("安装失败");
} }
} }
} }

View File

@ -1,5 +1,4 @@
using System; using System;
using System.IO;
using System.Reflection; using System.Reflection;
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
@ -11,10 +10,6 @@ namespace HybridCLR.Editor.Installer
{ {
private InstallerController _controller; private InstallerController _controller;
private bool _installFromDir;
private string _installLibil2cppWithHybridclrSourceDir;
private void OnEnable() private void OnEnable()
{ {
_controller = new InstallerController(); _controller = new InstallerController();
@ -30,7 +25,7 @@ namespace HybridCLR.Editor.Installer
height = 24 height = 24
}; };
var content = EditorGUIUtility.IconContent("Settings"); var content = EditorGUIUtility.IconContent("Settings");
content.tooltip = "HybridCLR Settings"; content.tooltip = "点击打开HybridCLR Settings";
if (GUI.Button(rect, content, GUI.skin.GetStyle("IconButton"))) if (GUI.Button(rect, content, GUI.skin.GetStyle("IconButton")))
{ {
SettingsService.OpenProjectSettings("Project/HybridCLR Settings"); SettingsService.OpenProjectSettings("Project/HybridCLR Settings");
@ -41,73 +36,50 @@ namespace HybridCLR.Editor.Installer
GUILayout.Space(10f); GUILayout.Space(10f);
EditorGUILayout.BeginVertical("box"); EditorGUILayout.BeginVertical("box");
EditorGUILayout.LabelField($"Installed: {hasInstall}", EditorStyles.boldLabel); EditorGUILayout.LabelField($"安装状态:{(hasInstall ? "" : "")}", EditorStyles.boldLabel);
GUILayout.Space(10f); GUILayout.Space(10f);
EditorGUILayout.LabelField($"Package Version: v{_controller.PackageVersion}"); EditorGUILayout.LabelField($"HybridCLR 版本: {_controller.HybridclrLocalVersion}");
GUILayout.Space(5f); GUILayout.Space(5f);
EditorGUILayout.LabelField($"Installed Version: v{_controller.InstalledLibil2cppVersion ?? " Unknown"}"); EditorGUILayout.LabelField($"il2cpp_plus 版本: {_controller.Il2cppPlusLocalVersion}");
GUILayout.Space(5f); GUILayout.Space(5f);
//GUIInstallButton("检查更新", "检查", UpdateHybridCLR);
//GUILayout.Space(40f);
GUILayout.Space(10f); GUILayout.Space(10f);
InstallerController.CompatibleType compatibleType = _controller.GetCompatibleType();
if (compatibleType != InstallerController.CompatibleType.Incompatible) //EditorGUILayout.BeginHorizontal();
{ //EditorGUILayout.LabelField("待安装的 hybridclr 仓库版本号(或branch或tag)(默认取最新版本):", GUILayout.MaxWidth(400));
if (compatibleType == InstallerController.CompatibleType.MaybeIncompatible) //_hybridclrVersion = EditorGUILayout.TextField(_hybridclrVersion);
{ //EditorGUILayout.EndHorizontal();
EditorGUILayout.HelpBox($"Maybe incompatible with current version, recommend minimum compatible version:{_controller.GetCurrentUnityVersionMinCompatibleVersionStr()}", MessageType.Warning);
//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();
} }
EditorGUILayout.BeginHorizontal(); private void GUIInstallButton(string content, string button)
_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(); EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("Install", GUILayout.Width(100))) EditorGUILayout.LabelField(content);
if (GUILayout.Button(button, GUILayout.Width(100)))
{ {
InstallLocalHybridCLR(); InstallLocalHybridCLR();
GUIUtility.ExitGUI(); GUIUtility.ExitGUI();
} }
EditorGUILayout.EndHorizontal(); EditorGUILayout.EndHorizontal();
}
else
{
EditorGUILayout.HelpBox($"Incompatible with current version, minimum compatible version:{_controller.GetCurrentUnityVersionMinCompatibleVersionStr()}", MessageType.Error);
}
EditorGUILayout.EndVertical();
} }
private void InstallLocalHybridCLR() private void InstallLocalHybridCLR()
{
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(); _controller.InstallDefaultHybridCLR();
} }
} }
} }
}

View File

@ -7,7 +7,6 @@ using System.Threading.Tasks;
using dnlib.DotNet; using dnlib.DotNet;
using HybridCLR.Editor.Meta; using HybridCLR.Editor.Meta;
using UnityEditor; using UnityEditor;
using UnityEngine;
using IAssemblyResolver = HybridCLR.Editor.Meta.IAssemblyResolver; using IAssemblyResolver = HybridCLR.Editor.Meta.IAssemblyResolver;
namespace HybridCLR.Editor.Link namespace HybridCLR.Editor.Link
@ -23,7 +22,8 @@ namespace HybridCLR.Editor.Link
public HashSet<TypeRef> CollectRefs(List<string> rootAssemblies) public HashSet<TypeRef> CollectRefs(List<string> rootAssemblies)
{ {
var assCollector = new AssemblyCache(_resolver); using (var assCollector = new AssemblyCache(_resolver))
{
var rootAssemblyNames = new HashSet<string>(rootAssemblies); var rootAssemblyNames = new HashSet<string>(rootAssemblies);
var typeRefs = new HashSet<TypeRef>(TypeEqualityComparer.Instance); var typeRefs = new HashSet<TypeRef>(TypeEqualityComparer.Instance);
@ -32,18 +32,16 @@ namespace HybridCLR.Editor.Link
var dnAss = assCollector.LoadModule(rootAss, false); var dnAss = assCollector.LoadModule(rootAss, false);
foreach (var type in dnAss.GetTypeRefs()) foreach (var type in dnAss.GetTypeRefs())
{ {
if (type.DefinitionAssembly == null)
{
Debug.LogWarning($"assembly:{dnAss.Name} TypeRef {type.FullName} has no DefinitionAssembly");
continue;
}
if (!rootAssemblyNames.Contains(type.DefinitionAssembly.Name.ToString())) if (!rootAssemblyNames.Contains(type.DefinitionAssembly.Name.ToString()))
{ {
typeRefs.Add(type); typeRefs.Add(type);
} }
} }
} }
assCollector.Dispose();
return typeRefs; return typeRefs;
} }
} }
} }
}

View File

@ -9,7 +9,7 @@ using System.Threading.Tasks;
namespace HybridCLR.Editor.Link namespace HybridCLR.Editor.Link
{ {
public class LinkXmlWriter internal class LinkXmlWriter
{ {
public void Write(string outputLinkXmlFile, HashSet<TypeRef> refTypes) public void Write(string outputLinkXmlFile, HashSet<TypeRef> refTypes)
{ {
@ -22,24 +22,18 @@ namespace HybridCLR.Editor.Link
writer.WriteStartElement("linker"); writer.WriteStartElement("linker");
var typesByAssembly = refTypes.GroupBy(t => t.DefinitionAssembly.Name.String).ToList(); var typesByAssembly = refTypes.GroupBy(t => t.DefinitionAssembly.Name.String).ToList();
typesByAssembly.Sort((a, b) => String.Compare(a.Key, b.Key, StringComparison.Ordinal)); typesByAssembly.Sort((a, b) => a.Key.CompareTo(b.Key));
foreach(var assembly in typesByAssembly) foreach(var assembly in typesByAssembly)
{ {
writer.WriteStartElement("assembly"); writer.WriteStartElement("assembly");
writer.WriteAttributeString("fullname", assembly.Key); writer.WriteAttributeString("fullname", assembly.Key);
List<string> assTypeNames = assembly.Select(t => t.FullName).ToList(); List<TypeRef> assTypes = assembly.ToList();
assTypeNames.Sort(string.CompareOrdinal); assTypes.Sort((a, b) => a.FullName.CompareTo(b.FullName));
foreach(var typeName in assTypeNames) foreach(var type in assTypes)
{ {
#if UNITY_2023_1_OR_NEWER
if (typeName == "UnityEngine.Debug")
{
continue;
}
#endif
writer.WriteStartElement("type"); writer.WriteStartElement("type");
writer.WriteAttributeString("fullname", typeName); writer.WriteAttributeString("fullname", type.FullName);
writer.WriteAttributeString("preserve", "all"); writer.WriteAttributeString("preserve", "all");
writer.WriteEndElement(); writer.WriteEndElement();
} }

View File

@ -9,12 +9,73 @@ using UnityEngine;
namespace HybridCLR.Editor.Meta namespace HybridCLR.Editor.Meta
{ {
public class AssemblyCache : AssemblyCacheBase public class AssemblyCache : IDisposable
{ {
private readonly IAssemblyResolver _assemblyPathResolver;
private readonly ModuleContext _modCtx;
private readonly AssemblyResolver _asmResolver;
private bool disposedValue;
public AssemblyCache(IAssemblyResolver assemblyResolver) : base(assemblyResolver) public Dictionary<string, ModuleDefMD> LoadedModules { get; } = new Dictionary<string, ModuleDefMD>();
public AssemblyCache(IAssemblyResolver assemblyResolver)
{ {
_assemblyPathResolver = assemblyResolver;
_modCtx = ModuleDef.CreateModuleContext();
_asmResolver = (AssemblyResolver)_modCtx.AssemblyResolver;
_asmResolver.EnableTypeDefCache = true;
_asmResolver.UseGAC = false;
}
public ModuleDefMD LoadModule(string moduleName, bool loadReferenceAssemblies = true)
{
// Debug.Log($"load module:{moduleName}");
if (LoadedModules.TryGetValue(moduleName, out var mod))
{
return mod;
}
mod = DoLoadModule(_assemblyPathResolver.ResolveAssembly(moduleName, true));
LoadedModules.Add(moduleName, mod);
if (loadReferenceAssemblies)
{
foreach (var refAsm in mod.GetAssemblyRefs())
{
LoadModule(refAsm.Name);
}
}
return mod;
}
private ModuleDefMD DoLoadModule(string dllPath)
{
//Debug.Log($"do load module:{dllPath}");
ModuleDefMD mod = ModuleDefMD.Load(dllPath, _modCtx);
_asmResolver.AddToCache(mod);
return mod;
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
foreach(var mod in LoadedModules.Values)
{
mod.Dispose();
}
LoadedModules.Clear();
}
disposedValue = true;
}
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
} }
} }
} }

View File

@ -1,99 +0,0 @@
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;
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 3b01fa99119e72141bfee5628c0ffce1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -9,10 +9,17 @@ using UnityEngine;
namespace HybridCLR.Editor.Meta namespace HybridCLR.Editor.Meta
{ {
public class AssemblyReferenceDeepCollector : AssemblyCacheBase public class AssemblyReferenceDeepCollector : IDisposable
{ {
private readonly IAssemblyResolver _assemblyPathResolver;
private readonly List<string> _rootAssemblies; private readonly List<string> _rootAssemblies;
private readonly ModuleContext _modCtx;
private readonly AssemblyResolver _asmResolver;
private bool disposedValue;
public Dictionary<string, ModuleDefMD> LoadedModules { get; } = new Dictionary<string, ModuleDefMD>();
public IReadOnlyList<string> GetRootAssemblyNames() public IReadOnlyList<string> GetRootAssemblyNames()
{ {
return _rootAssemblies; return _rootAssemblies;
@ -23,19 +30,19 @@ namespace HybridCLR.Editor.Meta
return LoadedModules.Where(e => !_rootAssemblies.Contains(e.Key)).Select(e => e.Value).ToList(); return LoadedModules.Where(e => !_rootAssemblies.Contains(e.Key)).Select(e => e.Value).ToList();
} }
public List<ModuleDefMD> GetLoadedModules()
{
return LoadedModules.Select(e => e.Value).ToList();
}
public List<ModuleDefMD> GetLoadedModulesOfRootAssemblies() public List<ModuleDefMD> GetLoadedModulesOfRootAssemblies()
{ {
return _rootAssemblies.Select(ass => LoadedModules[ass]).ToList(); return _rootAssemblies.Select(ass => LoadedModules[ass]).ToList();
} }
public AssemblyReferenceDeepCollector(IAssemblyResolver assemblyResolver, List<string> rootAssemblies) : base(assemblyResolver) public AssemblyReferenceDeepCollector(IAssemblyResolver assemblyResolver, List<string> rootAssemblies)
{ {
_assemblyPathResolver = assemblyResolver;
_rootAssemblies = rootAssemblies; _rootAssemblies = rootAssemblies;
_modCtx = ModuleDef.CreateModuleContext();
_asmResolver = (AssemblyResolver)_modCtx.AssemblyResolver;
_asmResolver.EnableTypeDefCache = true;
_asmResolver.UseGAC = false;
LoadAllAssembiles(); LoadAllAssembiles();
} }
@ -46,5 +53,52 @@ namespace HybridCLR.Editor.Meta
LoadModule(asm); LoadModule(asm);
} }
} }
private ModuleDefMD LoadModule(string moduleName)
{
// Debug.Log($"load module:{moduleName}");
if (LoadedModules.TryGetValue(moduleName, out var mod))
{
return mod;
}
mod = DoLoadModule(_assemblyPathResolver.ResolveAssembly(moduleName, true));
LoadedModules.Add(moduleName, mod);
foreach (var refAsm in mod.GetAssemblyRefs())
{
LoadModule(refAsm.Name);
}
return mod;
}
private ModuleDefMD DoLoadModule(string dllPath)
{
//Debug.Log($"do load module:{dllPath}");
ModuleDefMD mod = ModuleDefMD.Load(dllPath, _modCtx);
_asmResolver.AddToCache(mod);
return mod;
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
foreach(var mod in LoadedModules.Values)
{
mod.Dispose();
}
}
LoadedModules.Clear();
disposedValue = true;
}
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
} }
} }

View File

@ -16,14 +16,11 @@ namespace HybridCLR.Editor.Meta
} }
if (throwExIfNotFind) if (throwExIfNotFind)
{ {
if (SettingsUtil.HotUpdateAssemblyNamesIncludePreserved.Contains(assemblyName)) #if UNITY_2021_1_OR_NEWER && UNITY_IOS
{ throw new Exception($"resolve assembly:{assemblyName} 失败! 请按照Install文档正确替换了UnityEditor.CoreModule.dll或者升级hybridclr_unity到2.0.1及更高版本");
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 assembly:{assemblyName} 失败! 请参阅常见错误文档");
else #endif
{
throw new Exception($"resolve AOT dll:{assemblyName} failed! Please make sure that the AOT project has referenced the dll and generated the trimmed AOT dll correctly.");
}
} }
return null; return null;
} }

View File

@ -1,105 +0,0 @@
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);
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: b9b8eb45398fa344daa8c6e9b9fbf291
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -29,12 +29,6 @@ namespace HybridCLR.Editor.Meta
Debug.Log($"[FixedSetAssemblyResolver] resolve:{assemblyName} path:{assemblyPath}"); Debug.Log($"[FixedSetAssemblyResolver] resolve:{assemblyName} path:{assemblyPath}");
return true; return true;
} }
assemblyPath = $"{_rootDir}/{assemblyName}.dll.bytes";
if (File.Exists(assemblyPath))
{
Debug.Log($"[FixedSetAssemblyResolver] resolve:{assemblyName} path:{assemblyPath}");
return true;
}
} }
assemblyPath = null; assemblyPath = null;
return false; return false;

View File

@ -7,11 +7,13 @@ using System.Threading.Tasks;
namespace HybridCLR.Editor.Meta namespace HybridCLR.Editor.Meta
{ {
/// <summary>
public class GenericArgumentContext /// Replaces generic type/method var with its generic argument
/// </summary>
public sealed class GenericArgumentContext
{ {
private readonly List<TypeSig> typeArgsStack; List<TypeSig> typeArgsStack = new List<TypeSig>();
private readonly List<TypeSig> methodArgsStack; List<TypeSig> methodArgsStack = new List<TypeSig>();
public GenericArgumentContext(List<TypeSig> typeArgsStack, List<TypeSig> methodArgsStack) public GenericArgumentContext(List<TypeSig> typeArgsStack, List<TypeSig> methodArgsStack)
{ {
@ -19,6 +21,16 @@ namespace HybridCLR.Editor.Meta
this.methodArgsStack = methodArgsStack; this.methodArgsStack = methodArgsStack;
} }
/// <summary>
/// Replaces a generic type/method var with its generic argument (if any). If
/// <paramref name="typeSig"/> isn't a generic type/method var or if it can't
/// be resolved, it itself is returned. Else the resolved type is returned.
/// </summary>
/// <param name="typeSig">Type signature</param>
/// <returns>New <see cref="TypeSig"/> which is never <c>null</c> unless
/// <paramref name="typeSig"/> is <c>null</c></returns>
public TypeSig Resolve(TypeSig typeSig) public TypeSig Resolve(TypeSig typeSig)
{ {
if (!typeSig.ContainsGenericParameter) if (!typeSig.ContainsGenericParameter)
@ -29,9 +41,9 @@ namespace HybridCLR.Editor.Meta
switch (typeSig.ElementType) switch (typeSig.ElementType)
{ {
case ElementType.Ptr: return new PtrSig(Resolve(typeSig.Next)); case ElementType.Ptr: return new PtrSig(Resolve(typeSig.Next));
case ElementType.ByRef: return new ByRefSig(Resolve(typeSig.Next)); case ElementType.ByRef: return new PtrSig(Resolve(typeSig.Next));
case ElementType.SZArray: return new SZArraySig(Resolve(typeSig.Next)); case ElementType.SZArray: return new PtrSig(Resolve(typeSig.Next));
case ElementType.Array: case ElementType.Array:
{ {
var ara = (ArraySig)typeSig; var ara = (ArraySig)typeSig;
@ -41,7 +53,7 @@ namespace HybridCLR.Editor.Meta
case ElementType.Var: case ElementType.Var:
{ {
GenericVar genericVar = (GenericVar)typeSig; GenericVar genericVar = (GenericVar)typeSig;
var newSig = Resolve(typeArgsStack, genericVar.Number); var newSig = Resolve(typeArgsStack, genericVar.Number, true);
if (newSig == null) if (newSig == null)
{ {
throw new Exception(); throw new Exception();
@ -52,7 +64,7 @@ namespace HybridCLR.Editor.Meta
case ElementType.MVar: case ElementType.MVar:
{ {
GenericMVar genericVar = (GenericMVar)typeSig; GenericMVar genericVar = (GenericMVar)typeSig;
var newSig = Resolve(methodArgsStack, genericVar.Number); var newSig = Resolve(methodArgsStack, genericVar.Number, true);
if (newSig == null) if (newSig == null)
{ {
throw new Exception(); throw new Exception();
@ -67,29 +79,7 @@ namespace HybridCLR.Editor.Meta
case ElementType.FnPtr: case ElementType.FnPtr:
{ {
var fptr = (FnPtrSig)typeSig; throw new NotSupportedException(typeSig.ToString());
var cs = fptr.Signature;
CallingConventionSig ccs;
switch (cs)
{
case MethodSig ms:
{
ccs = new MethodSig(ms.GetCallingConvention(), ms.GenParamCount, Resolve(ms.RetType), ms.Params.Select(p => Resolve(p)).ToList());
break;
}
case PropertySig ps:
{
ccs = new PropertySig(ps.HasThis, Resolve(ps.RetType));
break;
}
case GenericInstMethodSig gims:
{
ccs = new GenericInstMethodSig(gims.GenericArguments.Select(ga => Resolve(ga)).ToArray());
break;
}
default: throw new NotSupportedException(cs.ToString());
}
return new FnPtrSig(ccs);
} }
case ElementType.ValueArray: case ElementType.ValueArray:
@ -101,9 +91,13 @@ namespace HybridCLR.Editor.Meta
} }
} }
private TypeSig Resolve(List<TypeSig> args, uint number) private TypeSig Resolve(List<TypeSig> args, uint number, bool isTypeVar)
{ {
return args[(int)number]; var typeSig = args[(int)number];
var gvar = typeSig as GenericSig;
if (gvar is null || gvar.IsTypeVar != isTypeVar)
return typeSig;
return gvar;
} }
} }

View File

@ -22,7 +22,7 @@ namespace HybridCLR.Editor.Meta
public GenericClass ToGenericShare() public GenericClass ToGenericShare()
{ {
return new GenericClass(Type, MetaUtil.ToShareTypeSigs(Type.Module.CorLibTypes, KlassInst)); return new GenericClass(Type, MetaUtil.ToShareTypeSigs(KlassInst));
} }
public override bool Equals(object obj) public override bool Equals(object obj)

View File

@ -26,8 +26,7 @@ namespace HybridCLR.Editor.Meta
public GenericMethod ToGenericShare() public GenericMethod ToGenericShare()
{ {
ICorLibTypes corLibTypes = Method.Module.CorLibTypes; return new GenericMethod(Method, MetaUtil.ToShareTypeSigs(KlassInst), MetaUtil.ToShareTypeSigs(MethodInst));
return new GenericMethod(Method, MetaUtil.ToShareTypeSigs(corLibTypes, KlassInst), MetaUtil.ToShareTypeSigs(corLibTypes, MethodInst));
} }
public override bool Equals(object obj) public override bool Equals(object obj)
@ -94,7 +93,7 @@ namespace HybridCLR.Editor.Meta
methodDef = method.ResolveMethodDef(); methodDef = method.ResolveMethodDef();
if (methodDef == null) if (methodDef == null)
{ {
//Debug.LogWarning($"method:{method} ResolveMethodDef() == null"); Debug.LogWarning($"method:{method} ResolveMethodDef() == null");
return null; return null;
} }
if (method is MethodSpec methodSpec) if (method is MethodSpec methodSpec)

View File

@ -1,6 +1,5 @@
using dnlib.DotNet; using dnlib.DotNet;
using HybridCLR.Editor.Meta; using HybridCLR.Editor.Meta;
using HybridCLR.Editor.Settings;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@ -60,8 +59,13 @@ namespace HybridCLR.Editor.Meta
return ctx.Resolve(sig); return ctx.Resolve(sig);
} }
public static TypeSig ToShareTypeSig(ICorLibTypes corTypes, TypeSig typeSig) public static TypeSig ToShareTypeSig(TypeSig typeSig)
{ {
var corTypes = typeSig?.Module?.CorLibTypes;
if (corTypes == null)
{
return typeSig;
}
var a = typeSig.RemovePinnedAndModifiers(); var a = typeSig.RemovePinnedAndModifiers();
switch (a.ElementType) switch (a.ElementType)
{ {
@ -84,45 +88,22 @@ namespace HybridCLR.Editor.Meta
case ElementType.U: return corTypes.UIntPtr; case ElementType.U: return corTypes.UIntPtr;
case ElementType.Object: return corTypes.Object; case ElementType.Object: return corTypes.Object;
case ElementType.Sentinel: return typeSig; case ElementType.Sentinel: return typeSig;
case ElementType.Ptr: return corTypes.UIntPtr; case ElementType.Ptr: return corTypes.IntPtr;
case ElementType.ByRef: return corTypes.UIntPtr; case ElementType.ByRef: return corTypes.IntPtr;
case ElementType.SZArray: return corTypes.Object; case ElementType.SZArray: return corTypes.Object;
case ElementType.Array: return corTypes.Object; case ElementType.Array: return corTypes.Object;
case ElementType.ValueType: case ElementType.ValueType: return typeSig;
{
TypeDef typeDef = a.ToTypeDefOrRef().ResolveTypeDef();
if (typeDef == null)
{
throw new Exception($"type:{a} definition could not be found");
}
if (typeDef.IsEnum)
{
return ToShareTypeSig(corTypes, typeDef.GetEnumUnderlyingType());
}
return typeSig;
}
case ElementType.Var:
case ElementType.MVar:
case ElementType.Class: return corTypes.Object; case ElementType.Class: return corTypes.Object;
case ElementType.GenericInst: case ElementType.GenericInst:
{ {
var gia = (GenericInstSig)a; var gia = (GenericInstSig)a;
TypeDef typeDef = gia.GenericType.ToTypeDefOrRef().ResolveTypeDef(); if (gia.GenericType.IsClassSig)
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 corTypes.Object;
} }
return new GenericInstSig(gia.GenericType, gia.GenericArguments.Select(ga => ToShareTypeSig(corTypes, ga)).ToList()); return new GenericInstSig(gia.GenericType, gia.GenericArguments.Select(ga => ToShareTypeSig(ga)).ToList());
} }
case ElementType.FnPtr: return corTypes.UIntPtr; case ElementType.FnPtr: return corTypes.IntPtr;
case ElementType.ValueArray: return typeSig; case ElementType.ValueArray: return typeSig;
case ElementType.Module: return typeSig; case ElementType.Module: return typeSig;
default: default:
@ -130,13 +111,13 @@ namespace HybridCLR.Editor.Meta
} }
} }
public static List<TypeSig> ToShareTypeSigs(ICorLibTypes corTypes, IList<TypeSig> typeSigs) public static List<TypeSig> ToShareTypeSigs(IList<TypeSig> typeSigs)
{ {
if (typeSigs == null) if (typeSigs == null)
{ {
return null; return null;
} }
return typeSigs.Select(s => ToShareTypeSig(corTypes, s)).ToList(); return typeSigs.Select(s => ToShareTypeSig(s)).ToList();
} }
public static IAssemblyResolver CreateHotUpdateAssemblyResolver(BuildTarget target, List<string> hotUpdateDlls) public static IAssemblyResolver CreateHotUpdateAssemblyResolver(BuildTarget target, List<string> hotUpdateDlls)
@ -172,46 +153,6 @@ namespace HybridCLR.Editor.Meta
CreateHotUpdateAssemblyResolver(target, hotUpdateDlls), CreateHotUpdateAssemblyResolver(target, hotUpdateDlls),
CreateAOTAssemblyResolver(target) CreateAOTAssemblyResolver(target)
); );
}
public static string ResolveNetStandardAssemblyPath(string assemblyName)
{
return $"{SettingsUtil.HybridCLRDataPathInPackage}/NetStandard/{assemblyName}.dll";
}
public static List<TypeSig> CreateDefaultGenericParams(ModuleDef module, int genericParamCount)
{
var methodGenericParams = new List<TypeSig>();
for (int i = 0; i < genericParamCount; i++)
{
methodGenericParams.Add(module.CorLibTypes.Object);
}
return methodGenericParams;
}
public static bool IsSupportedPInvokeTypeSig(TypeSig typeSig)
{
typeSig = typeSig.RemovePinnedAndModifiers();
if (typeSig.IsByRef)
{
return true;
}
switch (typeSig.ElementType)
{
case ElementType.SZArray:
case ElementType.Array:
//case ElementType.Class:
case ElementType.String:
//case ElementType.Object:
return false;
default: return true;
}
}
public static bool IsSupportedPInvokeMethodSignature(MethodSig methodSig)
{
return IsSupportedPInvokeTypeSig(methodSig.RetType) && methodSig.Params.All(p => IsSupportedPInvokeTypeSig(p));
} }
} }
} }

View File

@ -1,5 +1,4 @@
using dnlib.DotNet; using dnlib.DotNet;
using HybridCLR.Editor.ABI;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
@ -11,17 +10,26 @@ namespace HybridCLR.Editor.Meta
{ {
public class MethodReferenceAnalyzer public class MethodReferenceAnalyzer
{ {
private readonly Action<MethodDef, List<TypeSig>, List<TypeSig>, GenericMethod> _onNewMethod; private readonly Action<GenericMethod> _onNewMethod;
private readonly ConcurrentDictionary<MethodDef, List<IMethod>> _methodEffectInsts = new ConcurrentDictionary<MethodDef, List<IMethod>>(); private readonly ConcurrentDictionary<MethodDef, List<IMethod>> _methodEffectInsts = new ConcurrentDictionary<MethodDef, List<IMethod>>();
public MethodReferenceAnalyzer(Action<MethodDef, List<TypeSig>, List<TypeSig>, GenericMethod> onNewMethod) public MethodReferenceAnalyzer(Action<GenericMethod> onNewMethod)
{ {
_onNewMethod = onNewMethod; _onNewMethod = onNewMethod;
} }
public void WalkMethod(MethodDef method, List<TypeSig> klassGenericInst, List<TypeSig> methodGenericInst) public void WalkMethod(MethodDef method, List<TypeSig> klassGenericInst, List<TypeSig> methodGenericInst)
{ {
if (klassGenericInst != null || methodGenericInst != null)
{
//var typeSig = klassGenericInst != null ? new GenericInstSig(method.DeclaringType.ToTypeSig().ToClassOrValueTypeSig(), klassGenericInst) : method.DeclaringType?.ToTypeSig();
//Debug.Log($"== walk generic method {typeSig}::{method.Name} {method.MethodSig}");
}
else
{
//Debug.Log($"== walk not geneeric method:{method}");
}
var ctx = new GenericArgumentContext(klassGenericInst, methodGenericInst); var ctx = new GenericArgumentContext(klassGenericInst, methodGenericInst);
if (_methodEffectInsts.TryGetValue(method, out var effectInsts)) if (_methodEffectInsts.TryGetValue(method, out var effectInsts))
@ -29,7 +37,7 @@ namespace HybridCLR.Editor.Meta
foreach (var met in effectInsts) foreach (var met in effectInsts)
{ {
var resolveMet = GenericMethod.ResolveMethod(met, ctx)?.ToGenericShare(); var resolveMet = GenericMethod.ResolveMethod(met, ctx)?.ToGenericShare();
_onNewMethod(method, klassGenericInst, methodGenericInst, resolveMet); _onNewMethod(resolveMet);
} }
return; return;
} }
@ -61,7 +69,7 @@ namespace HybridCLR.Editor.Meta
continue; continue;
} }
effectInsts.Add(met); effectInsts.Add(met);
_onNewMethod(method, klassGenericInst, methodGenericInst, resolveMet); _onNewMethod(resolveMet);
break; break;
} }
case ITokenOperand token: case ITokenOperand token:

View File

@ -20,16 +20,11 @@ namespace HybridCLR.Editor.Meta
{ {
foreach(var path in _searchPaths) foreach(var path in _searchPaths)
{ {
assemblyPath = Path.Combine(path, $"{assemblyName}.dll"); string assPath = Path.Combine(path, assemblyName + ".dll");
if (File.Exists(assemblyPath)) if (File.Exists(assPath))
{ {
Debug.Log($"resolve {assemblyName} at {assemblyPath}"); Debug.Log($"resolve {assemblyName} at {assPath}");
return true; assemblyPath = assPath;
}
assemblyPath = Path.Combine(path, $"{assemblyName}.dll.bytes");
if (File.Exists(assemblyPath))
{
Debug.Log($"resolve {assemblyName} at {assemblyPath}");
return true; return true;
} }
} }

Some files were not shown because too many files have changed in this diff Show More