Merge pull request #620 from mono/merge-objc
Merge objc branch into master
This commit is contained in:
Коммит
b56e22dd56
|
@ -9,12 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "managed-generic", "tests\ma
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "managed-pcl", "tests\managed\pcl\managed-pcl.csproj", "{43B5C8AC-74C4-4EB4-AF2D-C62E36F41379}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "managed-android", "tests\managed\android\managed-android.csproj", "{10E2D025-DED3-490D-8EC6-E99B30FE3E4F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoEmbeddinator4000.Tests", "tests\MonoEmbeddinator4000.Tests\MonoEmbeddinator4000.Tests.csproj", "{8B817EDA-6575-4C17-8255-85652BDD1366}"
|
||||
EndProject
|
||||
Project("{E46AB94E-5081-B7E4-99F8-4206054E886C}") = "Embeddinator-4000", "build\projects\Embeddinator-4000.csproj", "{509699E3-3C25-23AD-E543-37A8D1B13353}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dependencies", "dependencies", "{7B2816C2-7370-43B2-820E-FC9C798429BB}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Android.Tools", "build\projects\Xamarin.Android.Tools.csproj", "{83A10A50-EF0D-C64A-B801-5EA8242DE8B2}"
|
||||
|
@ -35,29 +31,35 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CppSharp.Parser", "build\pr
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CppSharp.Runtime", "build\projects\CppSharp.Runtime.csproj", "{189FF169-0498-10BC-2DCA-F5401922F0C7}"
|
||||
EndProject
|
||||
Project("{f2a71f9b-5d33-465a-a702-920d77279786}") = "fsharp-android", "tests\managed\fsharp-android\fsharp-android.fsproj", "{558BCEC3-1B1F-4DEC-AF4C-47B404A05DE6}"
|
||||
EndProject
|
||||
Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "managedwarn", "tests\managedwarn\managedwarn.csproj", "{39EC3FCA-104C-48DA-8B08-18A11148B8F7}"
|
||||
EndProject
|
||||
Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "objcgentest", "tests\objcgentest\objcgentest.csproj", "{DEAAD0EA-0FC2-427A-8B7A-173872FD3629}"
|
||||
EndProject
|
||||
Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "leaktest", "tests\leaktest\leaktest.csproj", "{44509EA7-2580-46DE-9557-6AA3B64C1F6B}"
|
||||
EndProject
|
||||
Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "managed-ios", "tests\managed\ios\managed-ios.csproj", "{7222DF15-4E26-417D-8B5A-5BD9F1006219}"
|
||||
EndProject
|
||||
Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "managed-macos-system", "tests\managed\macos-system\managed-macos-system.csproj", "{5E0CB07E-E4DF-4590-9FF4-C78A92A2D230}"
|
||||
EndProject
|
||||
Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "managed-macos-full", "tests\managed\macos-full\managed-macos-full.csproj", "{3B06BDD0-46A5-4362-85BE-3EB7C438D58C}"
|
||||
EndProject
|
||||
Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "managed-macos-modern", "tests\managed\macos-modern\managed-macos-modern.csproj", "{22434C3A-ED76-4769-A384-5F48ED66EE75}"
|
||||
EndProject
|
||||
Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "managed-netstandard", "tests\managed\netstandard\managed-netstandard.csproj", "{76C06121-9565-438F-A750-024641D9CDF2}"
|
||||
EndProject
|
||||
Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "objcgen", "objcgen\objcgen.csproj", "{4D0EB624-B2C9-4484-BA73-BFD5653BF0F6}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "managed-netstandard", "tests\managed\netstandard\managed-netstandard.csproj", "{76C06121-9565-438F-A750-024641D9CDF2}"
|
||||
EndProject
|
||||
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "fsharp-shared", "tests\managed\fsharp-shared\fsharp-shared.shproj", "{B46AC5CA-D13A-4F82-8A83-76B32F2F74EF}"
|
||||
EndProject
|
||||
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "fsharp-generic", "tests\managed\fsharp-generic\fsharp-generic.fsproj", "{1D70C6B6-B63D-49F3-AC02-E6F93BAA4377}"
|
||||
Project("{f2a71f9b-5d33-465a-a702-920d77279786}") = "fsharp-generic", "tests\managed\fsharp-generic\fsharp-generic.fsproj", "{1D70C6B6-B63D-49F3-AC02-E6F93BAA4377}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "managedwarn", "tests\managedwarn\managedwarn.csproj", "{73C4FAF0-C37A-4CEE-A3F3-B1F80748D5B2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "objcgentest", "tests\objcgentest\objcgentest.csproj", "{076A871B-0C13-47D8-8923-B9242995BFF8}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "leaktest", "tests\leaktest\leaktest.csproj", "{33D1E7E3-A123-43F0-B047-163C6E75D3BF}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "managed-ios", "tests\managed\ios\managed-ios.csproj", "{0D7BFE1A-730A-48B0-A99A-F6E6A6C134DC}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "managed-macos-system", "tests\managed\macos-system\managed-macos-system.csproj", "{73636472-C245-4F57-9229-1DB22D643DFD}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "managed-macos-full", "tests\managed\macos-full\managed-macos-full.csproj", "{8846BDE1-3377-4BED-BAB4-820F5CDF6D37}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "managed-macos-modern", "tests\managed\macos-modern\managed-macos-modern.csproj", "{1A66B3FB-3482-4981-B3E9-2658A8773E9A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "managed-tvos", "tests\managed\tvos\managed-tvos.csproj", "{C5EBF917-C812-4D46-B7EE-0960FEB51081}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Embeddinator-4000", "build\projects\Embeddinator-4000.csproj", "{E46AB94E-5081-B7E4-99F8-4206054E886C}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "objcgen", "objcgen\objcgen.csproj", "{C166803B-011F-4EAF-B8C2-D7DBBA3CF1EC}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "managed-android", "tests\managed\android\managed-android.csproj", "{10E2D025-DED3-490D-8EC6-E99B30FE3E4F}"
|
||||
EndProject
|
||||
Project("{f2a71f9b-5d33-465a-a702-920d77279786}") = "fsharp-android", "tests\managed\fsharp-android\fsharp-android.fsproj", "{558BCEC3-1B1F-4DEC-AF4C-47B404A05DE6}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
@ -73,18 +75,10 @@ Global
|
|||
{43B5C8AC-74C4-4EB4-AF2D-C62E36F41379}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{43B5C8AC-74C4-4EB4-AF2D-C62E36F41379}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{43B5C8AC-74C4-4EB4-AF2D-C62E36F41379}.Release|x86.Build.0 = Release|Any CPU
|
||||
{10E2D025-DED3-490D-8EC6-E99B30FE3E4F}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{10E2D025-DED3-490D-8EC6-E99B30FE3E4F}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{10E2D025-DED3-490D-8EC6-E99B30FE3E4F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{10E2D025-DED3-490D-8EC6-E99B30FE3E4F}.Release|x86.Build.0 = Release|Any CPU
|
||||
{8B817EDA-6575-4C17-8255-85652BDD1366}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{8B817EDA-6575-4C17-8255-85652BDD1366}.Debug|x86.Build.0 = Debug|x86
|
||||
{8B817EDA-6575-4C17-8255-85652BDD1366}.Release|x86.ActiveCfg = Release|x86
|
||||
{8B817EDA-6575-4C17-8255-85652BDD1366}.Release|x86.Build.0 = Release|x86
|
||||
{509699E3-3C25-23AD-E543-37A8D1B13353}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{509699E3-3C25-23AD-E543-37A8D1B13353}.Debug|x86.Build.0 = Debug|x86
|
||||
{509699E3-3C25-23AD-E543-37A8D1B13353}.Release|x86.ActiveCfg = Release|x86
|
||||
{509699E3-3C25-23AD-E543-37A8D1B13353}.Release|x86.Build.0 = Release|x86
|
||||
{83A10A50-EF0D-C64A-B801-5EA8242DE8B2}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{83A10A50-EF0D-C64A-B801-5EA8242DE8B2}.Debug|x86.Build.0 = Debug|x86
|
||||
{83A10A50-EF0D-C64A-B801-5EA8242DE8B2}.Release|x86.ActiveCfg = Release|x86
|
||||
|
@ -121,52 +115,63 @@ Global
|
|||
{189FF169-0498-10BC-2DCA-F5401922F0C7}.Debug|x86.Build.0 = Debug|x86
|
||||
{189FF169-0498-10BC-2DCA-F5401922F0C7}.Release|x86.ActiveCfg = Release|x86
|
||||
{189FF169-0498-10BC-2DCA-F5401922F0C7}.Release|x86.Build.0 = Release|x86
|
||||
{558BCEC3-1B1F-4DEC-AF4C-47B404A05DE6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{558BCEC3-1B1F-4DEC-AF4C-47B404A05DE6}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{558BCEC3-1B1F-4DEC-AF4C-47B404A05DE6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{558BCEC3-1B1F-4DEC-AF4C-47B404A05DE6}.Release|x86.Build.0 = Release|Any CPU
|
||||
{39EC3FCA-104C-48DA-8B08-18A11148B8F7}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{39EC3FCA-104C-48DA-8B08-18A11148B8F7}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{39EC3FCA-104C-48DA-8B08-18A11148B8F7}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{39EC3FCA-104C-48DA-8B08-18A11148B8F7}.Release|x86.Build.0 = Release|Any CPU
|
||||
{DEAAD0EA-0FC2-427A-8B7A-173872FD3629}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{DEAAD0EA-0FC2-427A-8B7A-173872FD3629}.Debug|x86.Build.0 = Debug|x86
|
||||
{DEAAD0EA-0FC2-427A-8B7A-173872FD3629}.Release|x86.ActiveCfg = Release|x86
|
||||
{DEAAD0EA-0FC2-427A-8B7A-173872FD3629}.Release|x86.Build.0 = Release|x86
|
||||
{44509EA7-2580-46DE-9557-6AA3B64C1F6B}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{44509EA7-2580-46DE-9557-6AA3B64C1F6B}.Debug|x86.Build.0 = Debug|x86
|
||||
{44509EA7-2580-46DE-9557-6AA3B64C1F6B}.Release|x86.ActiveCfg = Release|x86
|
||||
{44509EA7-2580-46DE-9557-6AA3B64C1F6B}.Release|x86.Build.0 = Release|x86
|
||||
{7222DF15-4E26-417D-8B5A-5BD9F1006219}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{7222DF15-4E26-417D-8B5A-5BD9F1006219}.Debug|x86.Build.0 = Debug|x86
|
||||
{7222DF15-4E26-417D-8B5A-5BD9F1006219}.Release|x86.ActiveCfg = Release|x86
|
||||
{7222DF15-4E26-417D-8B5A-5BD9F1006219}.Release|x86.Build.0 = Release|x86
|
||||
{5E0CB07E-E4DF-4590-9FF4-C78A92A2D230}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{5E0CB07E-E4DF-4590-9FF4-C78A92A2D230}.Debug|x86.Build.0 = Debug|x86
|
||||
{5E0CB07E-E4DF-4590-9FF4-C78A92A2D230}.Release|x86.ActiveCfg = Release|x86
|
||||
{5E0CB07E-E4DF-4590-9FF4-C78A92A2D230}.Release|x86.Build.0 = Release|x86
|
||||
{3B06BDD0-46A5-4362-85BE-3EB7C438D58C}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{3B06BDD0-46A5-4362-85BE-3EB7C438D58C}.Debug|x86.Build.0 = Debug|x86
|
||||
{3B06BDD0-46A5-4362-85BE-3EB7C438D58C}.Release|x86.ActiveCfg = Release|x86
|
||||
{3B06BDD0-46A5-4362-85BE-3EB7C438D58C}.Release|x86.Build.0 = Release|x86
|
||||
{22434C3A-ED76-4769-A384-5F48ED66EE75}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{22434C3A-ED76-4769-A384-5F48ED66EE75}.Debug|x86.Build.0 = Debug|x86
|
||||
{22434C3A-ED76-4769-A384-5F48ED66EE75}.Release|x86.ActiveCfg = Release|x86
|
||||
{22434C3A-ED76-4769-A384-5F48ED66EE75}.Release|x86.Build.0 = Release|x86
|
||||
{76C06121-9565-438F-A750-024641D9CDF2}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{76C06121-9565-438F-A750-024641D9CDF2}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{76C06121-9565-438F-A750-024641D9CDF2}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{76C06121-9565-438F-A750-024641D9CDF2}.Release|x86.Build.0 = Release|Any CPU
|
||||
{4D0EB624-B2C9-4484-BA73-BFD5653BF0F6}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{4D0EB624-B2C9-4484-BA73-BFD5653BF0F6}.Debug|x86.Build.0 = Debug|x86
|
||||
{4D0EB624-B2C9-4484-BA73-BFD5653BF0F6}.Release|x86.ActiveCfg = Release|x86
|
||||
{4D0EB624-B2C9-4484-BA73-BFD5653BF0F6}.Release|x86.Build.0 = Release|x86
|
||||
{73C4FAF0-C37A-4CEE-A3F3-B1F80748D5B2}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{73C4FAF0-C37A-4CEE-A3F3-B1F80748D5B2}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{73C4FAF0-C37A-4CEE-A3F3-B1F80748D5B2}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{73C4FAF0-C37A-4CEE-A3F3-B1F80748D5B2}.Release|x86.Build.0 = Release|Any CPU
|
||||
{076A871B-0C13-47D8-8923-B9242995BFF8}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{076A871B-0C13-47D8-8923-B9242995BFF8}.Debug|x86.Build.0 = Debug|x86
|
||||
{076A871B-0C13-47D8-8923-B9242995BFF8}.Release|x86.ActiveCfg = Release|x86
|
||||
{076A871B-0C13-47D8-8923-B9242995BFF8}.Release|x86.Build.0 = Release|x86
|
||||
{33D1E7E3-A123-43F0-B047-163C6E75D3BF}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{33D1E7E3-A123-43F0-B047-163C6E75D3BF}.Debug|x86.Build.0 = Debug|x86
|
||||
{33D1E7E3-A123-43F0-B047-163C6E75D3BF}.Release|x86.ActiveCfg = Release|x86
|
||||
{33D1E7E3-A123-43F0-B047-163C6E75D3BF}.Release|x86.Build.0 = Release|x86
|
||||
{0D7BFE1A-730A-48B0-A99A-F6E6A6C134DC}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{0D7BFE1A-730A-48B0-A99A-F6E6A6C134DC}.Debug|x86.Build.0 = Debug|x86
|
||||
{0D7BFE1A-730A-48B0-A99A-F6E6A6C134DC}.Release|x86.ActiveCfg = Release|x86
|
||||
{0D7BFE1A-730A-48B0-A99A-F6E6A6C134DC}.Release|x86.Build.0 = Release|x86
|
||||
{73636472-C245-4F57-9229-1DB22D643DFD}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{73636472-C245-4F57-9229-1DB22D643DFD}.Debug|x86.Build.0 = Debug|x86
|
||||
{73636472-C245-4F57-9229-1DB22D643DFD}.Release|x86.ActiveCfg = Release|x86
|
||||
{73636472-C245-4F57-9229-1DB22D643DFD}.Release|x86.Build.0 = Release|x86
|
||||
{8846BDE1-3377-4BED-BAB4-820F5CDF6D37}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{8846BDE1-3377-4BED-BAB4-820F5CDF6D37}.Debug|x86.Build.0 = Debug|x86
|
||||
{8846BDE1-3377-4BED-BAB4-820F5CDF6D37}.Release|x86.ActiveCfg = Release|x86
|
||||
{8846BDE1-3377-4BED-BAB4-820F5CDF6D37}.Release|x86.Build.0 = Release|x86
|
||||
{1A66B3FB-3482-4981-B3E9-2658A8773E9A}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{1A66B3FB-3482-4981-B3E9-2658A8773E9A}.Debug|x86.Build.0 = Debug|x86
|
||||
{1A66B3FB-3482-4981-B3E9-2658A8773E9A}.Release|x86.ActiveCfg = Release|x86
|
||||
{1A66B3FB-3482-4981-B3E9-2658A8773E9A}.Release|x86.Build.0 = Release|x86
|
||||
{C5EBF917-C812-4D46-B7EE-0960FEB51081}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{C5EBF917-C812-4D46-B7EE-0960FEB51081}.Debug|x86.Build.0 = Debug|x86
|
||||
{C5EBF917-C812-4D46-B7EE-0960FEB51081}.Release|x86.ActiveCfg = Release|x86
|
||||
{C5EBF917-C812-4D46-B7EE-0960FEB51081}.Release|x86.Build.0 = Release|x86
|
||||
{E46AB94E-5081-B7E4-99F8-4206054E886C}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{E46AB94E-5081-B7E4-99F8-4206054E886C}.Debug|x86.Build.0 = Debug|x86
|
||||
{E46AB94E-5081-B7E4-99F8-4206054E886C}.Release|x86.ActiveCfg = Release|x86
|
||||
{E46AB94E-5081-B7E4-99F8-4206054E886C}.Release|x86.Build.0 = Release|x86
|
||||
{C166803B-011F-4EAF-B8C2-D7DBBA3CF1EC}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{C166803B-011F-4EAF-B8C2-D7DBBA3CF1EC}.Debug|x86.Build.0 = Debug|x86
|
||||
{C166803B-011F-4EAF-B8C2-D7DBBA3CF1EC}.Release|x86.ActiveCfg = Release|x86
|
||||
{C166803B-011F-4EAF-B8C2-D7DBBA3CF1EC}.Release|x86.Build.0 = Release|x86
|
||||
{10E2D025-DED3-490D-8EC6-E99B30FE3E4F}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{10E2D025-DED3-490D-8EC6-E99B30FE3E4F}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{10E2D025-DED3-490D-8EC6-E99B30FE3E4F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{10E2D025-DED3-490D-8EC6-E99B30FE3E4F}.Release|x86.Build.0 = Release|Any CPU
|
||||
{558BCEC3-1B1F-4DEC-AF4C-47B404A05DE6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{558BCEC3-1B1F-4DEC-AF4C-47B404A05DE6}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{558BCEC3-1B1F-4DEC-AF4C-47B404A05DE6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{558BCEC3-1B1F-4DEC-AF4C-47B404A05DE6}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{C75D4267-5757-4078-BCF4-7136BE033E96} = {21776062-DBDA-4408-BF22-9DCB2682DCBC}
|
||||
{D56A7E3F-FF5C-4EC2-879F-1260ABBD1903} = {21776062-DBDA-4408-BF22-9DCB2682DCBC}
|
||||
{43B5C8AC-74C4-4EB4-AF2D-C62E36F41379} = {21776062-DBDA-4408-BF22-9DCB2682DCBC}
|
||||
{10E2D025-DED3-490D-8EC6-E99B30FE3E4F} = {21776062-DBDA-4408-BF22-9DCB2682DCBC}
|
||||
{8B817EDA-6575-4C17-8255-85652BDD1366} = {21776062-DBDA-4408-BF22-9DCB2682DCBC}
|
||||
{83A10A50-EF0D-C64A-B801-5EA8242DE8B2} = {7B2816C2-7370-43B2-820E-FC9C798429BB}
|
||||
{95A93EAD-0135-AC71-0A46-2F6676500872} = {7B2816C2-7370-43B2-820E-FC9C798429BB}
|
||||
|
@ -177,15 +182,17 @@ Global
|
|||
{70148081-5C0E-A9D3-457B-3FE431140F40} = {7B2816C2-7370-43B2-820E-FC9C798429BB}
|
||||
{C105FD61-2D91-6A26-36A2-ED1AA2ACC626} = {7B2816C2-7370-43B2-820E-FC9C798429BB}
|
||||
{189FF169-0498-10BC-2DCA-F5401922F0C7} = {7B2816C2-7370-43B2-820E-FC9C798429BB}
|
||||
{558BCEC3-1B1F-4DEC-AF4C-47B404A05DE6} = {21776062-DBDA-4408-BF22-9DCB2682DCBC}
|
||||
{39EC3FCA-104C-48DA-8B08-18A11148B8F7} = {21776062-DBDA-4408-BF22-9DCB2682DCBC}
|
||||
{DEAAD0EA-0FC2-427A-8B7A-173872FD3629} = {21776062-DBDA-4408-BF22-9DCB2682DCBC}
|
||||
{44509EA7-2580-46DE-9557-6AA3B64C1F6B} = {21776062-DBDA-4408-BF22-9DCB2682DCBC}
|
||||
{7222DF15-4E26-417D-8B5A-5BD9F1006219} = {21776062-DBDA-4408-BF22-9DCB2682DCBC}
|
||||
{5E0CB07E-E4DF-4590-9FF4-C78A92A2D230} = {21776062-DBDA-4408-BF22-9DCB2682DCBC}
|
||||
{3B06BDD0-46A5-4362-85BE-3EB7C438D58C} = {21776062-DBDA-4408-BF22-9DCB2682DCBC}
|
||||
{22434C3A-ED76-4769-A384-5F48ED66EE75} = {21776062-DBDA-4408-BF22-9DCB2682DCBC}
|
||||
{76C06121-9565-438F-A750-024641D9CDF2} = {21776062-DBDA-4408-BF22-9DCB2682DCBC}
|
||||
{B46AC5CA-D13A-4F82-8A83-76B32F2F74EF} = {21776062-DBDA-4408-BF22-9DCB2682DCBC}
|
||||
{73C4FAF0-C37A-4CEE-A3F3-B1F80748D5B2} = {21776062-DBDA-4408-BF22-9DCB2682DCBC}
|
||||
{076A871B-0C13-47D8-8923-B9242995BFF8} = {21776062-DBDA-4408-BF22-9DCB2682DCBC}
|
||||
{33D1E7E3-A123-43F0-B047-163C6E75D3BF} = {21776062-DBDA-4408-BF22-9DCB2682DCBC}
|
||||
{0D7BFE1A-730A-48B0-A99A-F6E6A6C134DC} = {21776062-DBDA-4408-BF22-9DCB2682DCBC}
|
||||
{73636472-C245-4F57-9229-1DB22D643DFD} = {21776062-DBDA-4408-BF22-9DCB2682DCBC}
|
||||
{8846BDE1-3377-4BED-BAB4-820F5CDF6D37} = {21776062-DBDA-4408-BF22-9DCB2682DCBC}
|
||||
{1A66B3FB-3482-4981-B3E9-2658A8773E9A} = {21776062-DBDA-4408-BF22-9DCB2682DCBC}
|
||||
{C5EBF917-C812-4D46-B7EE-0960FEB51081} = {21776062-DBDA-4408-BF22-9DCB2682DCBC}
|
||||
{10E2D025-DED3-490D-8EC6-E99B30FE3E4F} = {21776062-DBDA-4408-BF22-9DCB2682DCBC}
|
||||
{558BCEC3-1B1F-4DEC-AF4C-47B404A05DE6} = {21776062-DBDA-4408-BF22-9DCB2682DCBC}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
@ -47,6 +47,9 @@ namespace Embeddinator
|
|||
|
||||
string binPath = MonoDroidSdk.BinPath;
|
||||
|
||||
if (binPath == null)
|
||||
throw new Exception ($"Cannot find Android SDK installed.");
|
||||
|
||||
//On Windows, it is generally correct, but probe for "lib"
|
||||
if (File.Exists(Combine(binPath, "lib")))
|
||||
return GetFullPath(MonoDroidSdk.BinPath);
|
||||
|
|
|
@ -218,6 +218,11 @@ Selectors on the [NSObjectProtocol](https://developer.apple.com/reference/object
|
|||
Note: The list of reserved selectors will evolve with new versions of the tool.
|
||||
|
||||
|
||||
<h3><a name="EM1052"/>Element `E` is not generated its name conflicts with other elements on the same class.</h3>
|
||||
|
||||
This is a **warning** that Element `E` is not generated as its name conflicts with other elements on the same class.
|
||||
|
||||
|
||||
<!-- 2xxx: code generation -->
|
||||
|
||||
# EM2xxx: Code Generation
|
||||
|
|
|
@ -41,3 +41,4 @@ Known Issues
|
|||
|
||||
A list of issues, including bugs, enhancements and ideas, is being tracked on [github](https://github.com/mono/Embeddinator-4000/issues).
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
using System;
|
||||
|
||||
namespace Embeddinator
|
||||
{
|
||||
class CachedValue<T> where T : class
|
||||
{
|
||||
Func<T> CalculateProc;
|
||||
T LastCalculatedValue;
|
||||
|
||||
public bool IsFrozen { get; private set; }
|
||||
public void Freeze () => IsFrozen = true;
|
||||
|
||||
public CachedValue (Func<T> calculateProc)
|
||||
{
|
||||
CalculateProc = calculateProc;
|
||||
}
|
||||
|
||||
public T Value {
|
||||
get {
|
||||
if (IsFrozen) {
|
||||
if (LastCalculatedValue == null)
|
||||
LastCalculatedValue = CalculateProc ();
|
||||
return LastCalculatedValue;
|
||||
} else {
|
||||
return CalculateProc ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Diagnostics;
|
||||
using ProductException = Embeddinator.ObjC.EmbeddinatorException;
|
||||
|
||||
namespace Embeddinator.ObjC
|
||||
|
@ -93,8 +93,10 @@ namespace Embeddinator.ObjC
|
|||
foreach (var ex in exceptions)
|
||||
error |= ShowInternal (ex);
|
||||
|
||||
if (error)
|
||||
if (error) {
|
||||
DumpLog ();
|
||||
Exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
static public void Show (Exception e)
|
||||
|
@ -107,8 +109,17 @@ namespace Embeddinator.ObjC
|
|||
foreach (var ex in exceptions)
|
||||
error |= ShowInternal (ex);
|
||||
|
||||
if (error)
|
||||
if (error) {
|
||||
DumpLog ();
|
||||
Exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
[Conditional ("DEBUG")]
|
||||
static void DumpLog ()
|
||||
{
|
||||
Console.WriteLine ("Debug Log:");
|
||||
Logger.Dump ();
|
||||
}
|
||||
|
||||
static void Exit (int exitCode)
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Embeddinator.ObjC
|
||||
{
|
||||
public static class Logger
|
||||
{
|
||||
public static void Log (string line) => Log (1, line);
|
||||
|
||||
#if DEBUG
|
||||
static List<string> Entries = new List<string> ();
|
||||
#endif
|
||||
|
||||
public static void Log (int verbosityRequired, string line)
|
||||
{
|
||||
if (ErrorHelper.Verbosity >= verbosityRequired)
|
||||
Console.WriteLine (line);
|
||||
#if DEBUG
|
||||
Entries.Add (line);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void Dump ()
|
||||
{
|
||||
#if DEBUG
|
||||
Entries.ForEach (l => Console.WriteLine (l));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +1,14 @@
|
|||
# Minimum Mono version
|
||||
MIN_MONO_VERSION=5.0.0.18
|
||||
MAX_MONO_VERSION=5.2.99
|
||||
MIN_MONO_URL=https://bosstoragemirror.blob.core.windows.net/wrench/mono-2017-02/9e/9ed0907eea13005d4e93b9c5f42c5c3015eba409/MonoFramework-MDK-5.0.0.18.macos10.xamarin.universal.pkg
|
||||
MIN_MONO_VERSION=5.4.1.7
|
||||
MAX_MONO_VERSION=5.4.1.7
|
||||
MIN_MONO_URL=https://download.mono-project.com/archive/5.4.1/macos-10-universal/MonoFramework-MDK-5.4.1.7.macos10.xamarin.universal.pkg
|
||||
|
||||
# Minimum Xamarin.iOS version
|
||||
MIN_XI_VERSION=10.11.0.136
|
||||
MAX_XI_VERSION=10.11.0.136
|
||||
MIN_XI_URL=https://bosstoragemirror.blob.core.windows.net/wrench/macios-mac-master/a3/a3264f64d6917ea8a1aab3884e4f51d229f31eda/xamarin.ios-10.11.0.136.pkg
|
||||
MIN_XI_VERSION=11.6.1.3
|
||||
MAX_XI_VERSION=11.6.1.3
|
||||
MIN_XI_URL=https://dl.xamarin.com/MonoTouch/Mac/xamarin.ios-11.6.1.3.pkg
|
||||
|
||||
# Minimum Xamarin.Mac version
|
||||
MIN_XM_VERSION=3.5.0.144
|
||||
MAX_XM_VERSION=3.5.0.144
|
||||
MIN_XM_URL=https://bosstoragemirror.blob.core.windows.net/wrench/macios-mac-master/c3/c3cecd577f9d0813308df6d6d7159ed94073ddfb/xamarin.mac-3.5.0.144.pkg
|
||||
MIN_XM_VERSION=4.0.0.215
|
||||
MAX_XM_VERSION=4.0.0.215
|
||||
MIN_XM_URL=https://dl.xamarin.com/XamarinforMac/Mac/xamarin.mac-4.0.0.215.pkg
|
||||
|
|
|
@ -2,7 +2,7 @@ all: bin/Debug/objcgen.exe shellcheck
|
|||
|
||||
-include Make.config.inc
|
||||
|
||||
PACKAGE_VERSION=0.2.0
|
||||
PACKAGE_VERSION=0.3.0
|
||||
PACKAGE_FULLVERSION=$(PACKAGE_VERSION).$(COMMIT_DISTANCE)
|
||||
|
||||
Make.config.inc: Makefile
|
||||
|
|
|
@ -61,10 +61,12 @@ namespace Embeddinator.ObjC {
|
|||
{
|
||||
if (t.IsByRef) {
|
||||
var et = t.GetElementType ();
|
||||
if (Type.GetTypeCode (et) == TypeCode.Decimal) // This is boxed into NSDecimalNumber
|
||||
var typecode = Type.GetTypeCode (et);
|
||||
|
||||
if (typecode == TypeCode.Decimal || typecode == TypeCode.DateTime) // This is boxed into NSDecimalNumber/NSDate
|
||||
return GetTypeName (et) + "_Nonnull * _Nullable";
|
||||
|
||||
return GetTypeName (et) + (et.IsValueType ? " " : " _Nonnull ") + "* _Nullable";
|
||||
return GetTypeName (et) + " * " + (et.IsValueType ? "_Nullable" : "_Nonnull");
|
||||
}
|
||||
|
||||
if (t.IsEnum)
|
||||
|
@ -117,6 +119,8 @@ namespace Embeddinator.ObjC {
|
|||
return "NSString *";
|
||||
case TypeCode.Decimal:
|
||||
return "NSDecimalNumber *";
|
||||
case TypeCode.DateTime:
|
||||
return "NSDate *";
|
||||
default:
|
||||
throw new NotImplementedException ($"Converting type {t.Name} to a native type name");
|
||||
}
|
||||
|
@ -174,6 +178,8 @@ namespace Embeddinator.ObjC {
|
|||
return "string";
|
||||
case TypeCode.Decimal:
|
||||
return "System.Decimal";
|
||||
case TypeCode.DateTime:
|
||||
return "System.DateTime";
|
||||
default:
|
||||
throw new NotImplementedException ($"Converting type {t.Name} to a mono type name");
|
||||
}
|
||||
|
@ -205,6 +211,8 @@ namespace Embeddinator.ObjC {
|
|||
return $"NSArray<{GetObjCName (t)} *> *";
|
||||
case TypeCode.Decimal:
|
||||
return "NSArray <NSDecimalNumber *> *";
|
||||
case TypeCode.DateTime:
|
||||
return "NSArray <NSDate *> *";
|
||||
default:
|
||||
throw new NotImplementedException ($"Converting type {t.Name} to a native type name");
|
||||
}
|
||||
|
@ -225,6 +233,8 @@ namespace Embeddinator.ObjC {
|
|||
{
|
||||
string pName = p.Name;
|
||||
string ptname = GetTypeName (p.ParameterType);
|
||||
if (RestrictedNames.IsRestrictedName (pName))
|
||||
pName = "managed" + pName;
|
||||
if (p.Name.Length < 3) {
|
||||
if (!ObjCTypeToArgument.TryGetValue (ptname, out pName))
|
||||
pName = "anObject";
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Embeddinator.ObjC
|
||||
{
|
||||
public enum DuplicationStatus
|
||||
{
|
||||
None,
|
||||
Unresolvable
|
||||
}
|
||||
|
||||
public class TypeMapper
|
||||
{
|
||||
Dictionary<ProcessedType, Dictionary<string, ProcessedMemberBase>> MappedTypes = new Dictionary<ProcessedType, Dictionary<string, ProcessedMemberBase>> ();
|
||||
|
||||
Dictionary <string, ProcessedMemberBase> GetRegistrationForType (ProcessedType t)
|
||||
{
|
||||
Dictionary<string, ProcessedMemberBase> data;
|
||||
if (MappedTypes.TryGetValue (t, out data))
|
||||
return data;
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool IsSelectorTaken (ProcessedMemberBase member)
|
||||
{
|
||||
var typeRegistration = GetRegistrationForType (member.DeclaringType);
|
||||
if (typeRegistration != null) {
|
||||
foreach (var selector in member.Selectors) {
|
||||
if (typeRegistration.ContainsKey (selector))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public IEnumerable <ProcessedMemberBase> WithSameSelector (ProcessedMemberBase member)
|
||||
{
|
||||
var typeRegistration = GetRegistrationForType (member.DeclaringType);
|
||||
if (typeRegistration != null) {
|
||||
foreach (var selector in member.Selectors) {
|
||||
ProcessedMemberBase registeredMember = null;
|
||||
if (typeRegistration.TryGetValue (selector, out registeredMember))
|
||||
yield return registeredMember;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Register (ProcessedMemberBase member)
|
||||
{
|
||||
Logger.Log ($"TypeMapper Register: {member} {String.Join (" ", member.Selectors)}");
|
||||
|
||||
var typeRegistration = GetRegistrationForType (member.DeclaringType);
|
||||
if (typeRegistration == null) {
|
||||
typeRegistration = new Dictionary<string, ProcessedMemberBase> ();
|
||||
MappedTypes.Add (member.DeclaringType, typeRegistration);
|
||||
}
|
||||
foreach (var selector in member.Selectors) {
|
||||
typeRegistration.Add (selector, member);
|
||||
}
|
||||
}
|
||||
|
||||
public DuplicationStatus CheckForDuplicateSelectors (ProcessedMemberBase member)
|
||||
{
|
||||
if (IsSelectorTaken (member)) {
|
||||
foreach (var conflictMethod in WithSameSelector (member))
|
||||
conflictMethod.FallBackToTypeName = true;
|
||||
member.FallBackToTypeName = true;
|
||||
}
|
||||
// Check to see if FallBackToTypeName is insufficient and scream
|
||||
if (IsSelectorTaken (member))
|
||||
return DuplicationStatus.Unresolvable;
|
||||
return DuplicationStatus.None;
|
||||
}
|
||||
}
|
||||
}
|
1050
objcgen/driver.cs
1050
objcgen/driver.cs
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,947 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using IKVM.Reflection;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
|
||||
namespace Embeddinator.ObjC
|
||||
{
|
||||
public class Embedder
|
||||
{
|
||||
string outputDirectory = ".";
|
||||
|
||||
public string OutputDirectory
|
||||
{
|
||||
get { return outputDirectory; }
|
||||
set
|
||||
{
|
||||
if (!Directory.Exists (value)) {
|
||||
try {
|
||||
Directory.CreateDirectory (value);
|
||||
Console.WriteLine ($"Creating output directory `{Path.GetFullPath (value)}`");
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new EmbeddinatorException (1, true, e, $"Could not create output directory `{value}`");
|
||||
}
|
||||
}
|
||||
outputDirectory = value;
|
||||
}
|
||||
}
|
||||
|
||||
string bundleIdentifier;
|
||||
public string BundleIdentifier
|
||||
{
|
||||
get { return bundleIdentifier ?? LibraryName; }
|
||||
set { bundleIdentifier = value; }
|
||||
}
|
||||
|
||||
public bool CompileCode { get; set; }
|
||||
|
||||
public bool Debug { get; set; }
|
||||
|
||||
public bool Extension { get; set; }
|
||||
|
||||
public bool Shared { get { return CompilationTarget == CompilationTarget.SharedLibrary; } }
|
||||
|
||||
public bool EnableLinker { get; set; }
|
||||
|
||||
public string LibraryName { get; set; }
|
||||
|
||||
public List<string> ABIs { get; private set; } = new List<string> ();
|
||||
|
||||
public void SetPlatform (string platform)
|
||||
{
|
||||
switch (platform.ToLowerInvariant ()) {
|
||||
case "osx":
|
||||
case "macosx":
|
||||
case "macos":
|
||||
case "mac":
|
||||
Platform = Platform.macOS;
|
||||
EnableLinker = false;
|
||||
break;
|
||||
case "macosmodern":
|
||||
case "macos-modern":
|
||||
Platform = Platform.macOSModern;
|
||||
EnableLinker = true;
|
||||
break;
|
||||
case "macosfull":
|
||||
case "macos-full":
|
||||
Platform = Platform.macOSFull;
|
||||
EnableLinker = false;
|
||||
break;
|
||||
case "macossystem":
|
||||
case "macos-system":
|
||||
Platform = Platform.macOSSystem;
|
||||
EnableLinker = false;
|
||||
break;
|
||||
case "ios":
|
||||
Platform = Platform.iOS;
|
||||
EnableLinker = true;
|
||||
break;
|
||||
case "tvos":
|
||||
Platform = Platform.tvOS;
|
||||
EnableLinker = true;
|
||||
break;
|
||||
case "watchos":
|
||||
Platform = Platform.watchOS;
|
||||
EnableLinker = true;
|
||||
break;
|
||||
default:
|
||||
throw new EmbeddinatorException (3, true, $"The platform `{platform}` is not valid.");
|
||||
}
|
||||
}
|
||||
|
||||
public void SetTarget (string value)
|
||||
{
|
||||
switch (value.ToLowerInvariant ()) {
|
||||
case "objc":
|
||||
case "obj-c":
|
||||
case "objectivec":
|
||||
case "objective-c":
|
||||
TargetLanguage = TargetLanguage.ObjectiveC;
|
||||
break;
|
||||
default:
|
||||
throw new EmbeddinatorException (4, true, $"The target `{value}` is not valid.");
|
||||
}
|
||||
}
|
||||
|
||||
public void SetCompilationTarget (string value)
|
||||
{
|
||||
switch (value.ToLowerInvariant ()) {
|
||||
case "library":
|
||||
case "sharedlibrary":
|
||||
case "dylib":
|
||||
CompilationTarget = CompilationTarget.SharedLibrary;
|
||||
break;
|
||||
case "framework":
|
||||
CompilationTarget = CompilationTarget.Framework;
|
||||
break;
|
||||
case "static":
|
||||
case "staticlibrary":
|
||||
CompilationTarget = CompilationTarget.StaticLibrary;
|
||||
break;
|
||||
default:
|
||||
throw new EmbeddinatorException (5, true, $"The compilation target `{value}` is not valid.");
|
||||
}
|
||||
}
|
||||
|
||||
public List<Assembly> Assemblies { get; private set; } = new List<Assembly> ();
|
||||
public Platform Platform { get; set; } = Platform.macOS;
|
||||
public TargetLanguage TargetLanguage { get; private set; } = TargetLanguage.ObjectiveC;
|
||||
public CompilationTarget CompilationTarget { get; set; } = CompilationTarget.SharedLibrary;
|
||||
|
||||
public string [] PlatformSdkDirectories
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (Platform) {
|
||||
case Platform.iOS:
|
||||
return new[] { "/Library/Frameworks/Xamarin.iOS.framework/Versions/Current/lib/mono/Xamarin.iOS" };
|
||||
case Platform.tvOS:
|
||||
return new[] { "/Library/Frameworks/Xamarin.iOS.framework/Versions/Current/lib/mono/Xamarin.TVOS" };
|
||||
case Platform.watchOS:
|
||||
return new[] { "/Library/Frameworks/Xamarin.iOS.framework/Versions/Current/lib/mono/Xamarin.WatchOS" };
|
||||
case Platform.macOS:
|
||||
case Platform.macOSSystem:
|
||||
return new[] { "/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.5", "/Library/Frameworks/Xamarin.Mac.framework/Versions/Current/lib/mono/4.5" };
|
||||
case Platform.macOSFull:
|
||||
return new[] { "/Library/Frameworks/Xamarin.Mac.framework/Versions/Current/lib/mono/4.5" };
|
||||
case Platform.macOSModern:
|
||||
return new[] { "/Library/Frameworks/Xamarin.Mac.framework/Versions/Current/lib/mono/Xamarin.Mac" };
|
||||
default:
|
||||
throw ErrorHelper.CreateError (99, "Internal error: invalid platform {0}. Please file a bug report with a test case (https://github.com/mono/Embeddinator-4000/issues).", Platform);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int Generate (List<string> args)
|
||||
{
|
||||
Console.WriteLine ("Parsing assemblies...");
|
||||
|
||||
var universe = new Universe (UniverseOptions.MetadataOnly);
|
||||
|
||||
universe.AssemblyResolve += (object sender, IKVM.Reflection.ResolveEventArgs resolve_args) => {
|
||||
var directories = new List<string> ();
|
||||
foreach (var v in PlatformSdkDirectories) {
|
||||
directories.Add (v);
|
||||
directories.Add (Path.Combine (v, "Facades"));
|
||||
}
|
||||
foreach (var asm in Assemblies)
|
||||
directories.Add (Path.GetDirectoryName (asm.Location));
|
||||
|
||||
AssemblyName an = new AssemblyName (resolve_args.Name);
|
||||
foreach (var dir in directories) {
|
||||
var filename = Path.Combine (dir, an.Name + ".dll");
|
||||
if (File.Exists (filename))
|
||||
return universe.LoadFile (filename);
|
||||
}
|
||||
throw ErrorHelper.CreateError (13, $"Can't find the assembly '{resolve_args.Name}', referenced by '{resolve_args.RequestingAssembly.FullName}'.");
|
||||
};
|
||||
|
||||
foreach (var arg in args) {
|
||||
if (!File.Exists (arg))
|
||||
throw ErrorHelper.CreateError (11, $"The assembly {arg} does not exist.");
|
||||
|
||||
Assemblies.Add (universe.LoadFile (arg));
|
||||
Console.WriteLine ($"\tParsed '{arg}'");
|
||||
}
|
||||
|
||||
// if not specified then we use the first specified assembly name
|
||||
if (LibraryName == null)
|
||||
LibraryName = Path.GetFileNameWithoutExtension (args[0]);
|
||||
|
||||
Console.WriteLine ("Processing assemblies...");
|
||||
var p = new ObjCProcessor ();
|
||||
p.Process (Assemblies.Select (x => new ProcessedAssembly (x) { UserCode = true}));
|
||||
|
||||
Console.WriteLine ("Generating binding code...");
|
||||
var g = new ObjCGenerator () {
|
||||
Processor = p,
|
||||
GenerateLinkerExclusions = EnableLinker,
|
||||
};
|
||||
g.Generate ();
|
||||
g.Write (OutputDirectory);
|
||||
|
||||
var exe = typeof (Driver).Assembly;
|
||||
foreach (var res in exe.GetManifestResourceNames ()) {
|
||||
if (res == "main.c") {
|
||||
// no main is needed for dylib and don't re-write an existing main.c file - it's a template
|
||||
if (CompilationTarget != CompilationTarget.StaticLibrary || File.Exists ("main.c"))
|
||||
continue;
|
||||
}
|
||||
var path = Path.Combine (OutputDirectory, res);
|
||||
Console.WriteLine ($"\tGenerated: {path}");
|
||||
using (var sw = new StreamWriter (path))
|
||||
exe.GetManifestResourceStream (res).CopyTo (sw.BaseStream);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static string xcode_app;
|
||||
public static string XcodeApp
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty (xcode_app)) {
|
||||
int exitCode;
|
||||
string output;
|
||||
if (!Utils.RunProcess ("xcode-select", "-p", out exitCode, out output))
|
||||
throw ErrorHelper.CreateError (6, "Could not find the Xcode location.");
|
||||
xcode_app = Path.GetDirectoryName (Path.GetDirectoryName (output.Trim ()));
|
||||
}
|
||||
return xcode_app;
|
||||
}
|
||||
}
|
||||
|
||||
class BuildInfo
|
||||
{
|
||||
public string Sdk;
|
||||
public string[] Architectures;
|
||||
public string SdkName; // used in -m{SdkName}-version-min
|
||||
public string MinVersion;
|
||||
public string XamariniOSSDK;
|
||||
public string CompilerFlags;
|
||||
public string LinkerFlags;
|
||||
|
||||
public bool IsSimulator
|
||||
{
|
||||
get { return Sdk.Contains ("Simulator"); }
|
||||
}
|
||||
}
|
||||
|
||||
void VerifyDependencies ()
|
||||
{
|
||||
SystemCheck.VerifyMono ();
|
||||
switch (Platform) {
|
||||
case Platform.iOS:
|
||||
case Platform.tvOS:
|
||||
case Platform.watchOS:
|
||||
SystemCheck.VerifyXamariniOS ();
|
||||
break;
|
||||
case Platform.macOS:
|
||||
case Platform.macOSFull:
|
||||
case Platform.macOSModern:
|
||||
case Platform.macOSSystem:
|
||||
SystemCheck.VerifyXamarinMac ();
|
||||
break;
|
||||
default:
|
||||
throw ErrorHelper.CreateError (99, "Internal error: invalid platform {0}. Please file a bug report with a test case (https://github.com/mono/Embeddinator-4000/issues).", Platform);
|
||||
}
|
||||
}
|
||||
|
||||
public int Compile ()
|
||||
{
|
||||
Console.WriteLine ("Compiling binding code...");
|
||||
|
||||
VerifyDependencies ();
|
||||
|
||||
BuildInfo[] build_infos;
|
||||
|
||||
switch (Platform) {
|
||||
case Platform.macOS:
|
||||
case Platform.macOSFull:
|
||||
case Platform.macOSModern:
|
||||
case Platform.macOSSystem:
|
||||
build_infos = new BuildInfo[] {
|
||||
new BuildInfo { Sdk = "MacOSX", Architectures = new string [] { "i386", "x86_64" }, SdkName = "macosx", MinVersion = "10.7" },
|
||||
};
|
||||
break;
|
||||
case Platform.iOS:
|
||||
build_infos = new BuildInfo[] {
|
||||
new BuildInfo { Sdk = "iPhoneOS", Architectures = new string [] { "armv7", "armv7s", "arm64" }, SdkName = "iphoneos", MinVersion = "8.0", XamariniOSSDK = "MonoTouch.iphoneos.sdk" },
|
||||
new BuildInfo { Sdk = "iPhoneSimulator", Architectures = new string [] { "i386", "x86_64" }, SdkName = "ios-simulator", MinVersion = "8.0", XamariniOSSDK = "MonoTouch.iphonesimulator.sdk" },
|
||||
};
|
||||
break;
|
||||
case Platform.tvOS:
|
||||
build_infos = new BuildInfo[] {
|
||||
new BuildInfo { Sdk = "AppleTVOS", Architectures = new string [] { "arm64" }, SdkName = "tvos", MinVersion = "9.0", XamariniOSSDK = "Xamarin.AppleTVOS.sdk", CompilerFlags = "-fembed-bitcode", LinkerFlags = "-fembed-bitcode" },
|
||||
new BuildInfo { Sdk = "AppleTVSimulator", Architectures = new string [] { "x86_64" }, SdkName = "tvos-simulator", MinVersion = "9.0", XamariniOSSDK = "Xamarin.AppleTVSimulator.sdk" },
|
||||
};
|
||||
break;
|
||||
case Platform.watchOS:
|
||||
build_infos = new BuildInfo[] {
|
||||
new BuildInfo { Sdk = "WatchOS", Architectures = new string [] { "armv7k" }, SdkName = "watchos", MinVersion = "2.0", XamariniOSSDK = "Xamarin.WatchOS.sdk", CompilerFlags = "-fembed-bitcode", LinkerFlags = "-fembed-bitcode" },
|
||||
new BuildInfo { Sdk = "WatchSimulator", Architectures = new string [] { "i386" }, SdkName = "watchos-simulator", MinVersion = "2.0", XamariniOSSDK = "Xamarin.WatchSimulator.sdk" },
|
||||
};
|
||||
break;
|
||||
default:
|
||||
throw ErrorHelper.CreateError (99, "Internal error: invalid platform {0}. Please file a bug report with a test case (https://github.com/mono/Embeddinator-4000/issues).", Platform);
|
||||
}
|
||||
|
||||
// filter/validate ABIs
|
||||
if (ABIs.Count > 0) {
|
||||
// Validate
|
||||
var all_architectures = build_infos.SelectMany ((v) => v.Architectures);
|
||||
var invalid_architectures = ABIs.Except (all_architectures).ToArray ();
|
||||
if (invalid_architectures.Length > 0) {
|
||||
var arch = invalid_architectures[0];
|
||||
throw ErrorHelper.CreateError (8, $"The architecture '{arch}' is not valid for {Platform}. Valid architectures for {Platform} are: {string.Join (", ", all_architectures)}");
|
||||
}
|
||||
|
||||
// Filter
|
||||
foreach (var info in build_infos)
|
||||
info.Architectures = info.Architectures.Where ((v) => ABIs.Contains (v)).ToArray ();
|
||||
}
|
||||
|
||||
var lipo_files = new List<string> ();
|
||||
var output_file = string.Empty;
|
||||
|
||||
var files = new string[] {
|
||||
Path.Combine (OutputDirectory, "glib.c"),
|
||||
Path.Combine (OutputDirectory, "mono_embeddinator.c"),
|
||||
Path.Combine (OutputDirectory, "objc-support.m"),
|
||||
Path.Combine (OutputDirectory, "bindings.m"),
|
||||
};
|
||||
|
||||
switch (CompilationTarget) {
|
||||
case CompilationTarget.SharedLibrary:
|
||||
output_file = $"lib{LibraryName}.dylib";
|
||||
break;
|
||||
case CompilationTarget.StaticLibrary:
|
||||
case CompilationTarget.Framework:
|
||||
output_file = $"{LibraryName}.a";
|
||||
break;
|
||||
default:
|
||||
throw ErrorHelper.CreateError (99, "Internal error: invalid compilation target {0}. Please file a bug report with a test case (https://github.com/mono/Embeddinator-4000/issues).", CompilationTarget);
|
||||
}
|
||||
|
||||
int exitCode;
|
||||
|
||||
/*
|
||||
* For static libraries we
|
||||
* * Compile all source files to .o files, per architecture.
|
||||
* * Then we archive .o files into per-sdk .a files, then we archive all .o files into a global .a file. So we end up with one .a for device, one for simulator, and one for both device and simulator.
|
||||
* * Then we dsym the global .a file
|
||||
*
|
||||
* For dynamic libraries we
|
||||
* * Compile all source files to .o files, per architecture.
|
||||
* * Then we link all .o files per architecture into a .dylib.
|
||||
* * Then we lipo .dylib files into per-sdk fat .dylib, then we lipo all .dylib into a global .dylib file. So we end up with one fat .dylib for device, one fat .dylib for simulator, and one very fat .dylib for both simulator and device.
|
||||
* * Finally we dsymutil the global .dylib
|
||||
*
|
||||
* For frameworks we
|
||||
* * First we build the source files to .o files and then archive to .a files just like for static libraries.
|
||||
* * Then we call mtouch to build a framework of the managed assemblies, passing the static library we just created as a gcc_flag so that it's linked in. This is done per sdk (simulator/device).
|
||||
* * Finally we merge the simulator framework and the device framework into a global framework, that supports both simulator and device.
|
||||
* * We dsymutil those frameworks.
|
||||
*/
|
||||
|
||||
foreach (var build_info in build_infos) {
|
||||
foreach (var arch in build_info.Architectures) {
|
||||
var archOutputDirectory = Path.Combine (OutputDirectory, arch);
|
||||
Directory.CreateDirectory (archOutputDirectory);
|
||||
|
||||
var common_options = new StringBuilder ("clang ");
|
||||
if (Debug)
|
||||
common_options.Append ("-g -O0 ");
|
||||
else {
|
||||
common_options.Append ("-O2 ");
|
||||
if (Platform == Platform.macOS) {
|
||||
// Token lookup only works if the linker isn't involved.
|
||||
// If the linker is enabled, all assemblies are loaded and re-saved
|
||||
// (even if only linking SDK assemblies), which means metadata
|
||||
// tokens may change even for non-linked assemblies. So completely
|
||||
// disable token lookup for platforms that uses the linker (all platforms
|
||||
// except macOS).
|
||||
common_options.Append ("-DTOKENLOOKUP ");
|
||||
}
|
||||
}
|
||||
common_options.Append ("-fobjc-arc ");
|
||||
common_options.Append ("-ObjC ");
|
||||
common_options.Append ("-Wall ");
|
||||
common_options.Append ($"-arch {arch} ");
|
||||
common_options.Append ($"-isysroot {XcodeApp}/Contents/Developer/Platforms/{build_info.Sdk}.platform/Developer/SDKs/{build_info.Sdk}.sdk ");
|
||||
common_options.Append ($"-m{build_info.SdkName}-version-min={build_info.MinVersion} ");
|
||||
|
||||
switch (Platform) {
|
||||
case Platform.macOS:
|
||||
common_options.Append ("-I/Library/Frameworks/Mono.framework/Versions/Current/include/mono-2.0 ");
|
||||
break;
|
||||
case Platform.macOSSystem:
|
||||
case Platform.macOSModern:
|
||||
case Platform.macOSFull:
|
||||
common_options.Append ("-I/Library/Frameworks/Xamarin.Mac.framework/Versions/Current/include ");
|
||||
common_options.Append ("-DXAMARIN_MAC ");
|
||||
break;
|
||||
case Platform.iOS:
|
||||
case Platform.tvOS:
|
||||
case Platform.watchOS:
|
||||
common_options.Append ($"-I/Library/Frameworks/Xamarin.iOS.framework/Versions/Current/SDKs/{build_info.XamariniOSSDK}/usr/include ");
|
||||
common_options.Append ("-DXAMARIN_IOS ");
|
||||
break;
|
||||
default:
|
||||
throw ErrorHelper.CreateError (99, "Internal error: invalid platform {0}. Please file a bug report with a test case (https://github.com/mono/Embeddinator-4000/issues).", Platform);
|
||||
}
|
||||
|
||||
// Build each source file to a .o
|
||||
var object_files = new List<string> ();
|
||||
foreach (var file in files) {
|
||||
var compiler_options = new StringBuilder (common_options.ToString ());
|
||||
compiler_options.Append ("-DMONO_EMBEDDINATOR_DLL_EXPORT ");
|
||||
compiler_options.Append (build_info.CompilerFlags).Append (" ");
|
||||
compiler_options.Append ("-c ");
|
||||
compiler_options.Append (Utils.Quote (file)).Append (" ");
|
||||
var objfile = Path.Combine (archOutputDirectory, Path.ChangeExtension (Path.GetFileName (file), "o"));
|
||||
compiler_options.Append ($"-o {Utils.Quote (objfile)} ");
|
||||
object_files.Add (objfile);
|
||||
if (!Utils.Xcrun (compiler_options, out exitCode))
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
// Link/archive object files to .a/.dylib
|
||||
switch (CompilationTarget) {
|
||||
case CompilationTarget.SharedLibrary:
|
||||
// Link all the .o files into a .dylib
|
||||
var options = new StringBuilder (common_options.ToString ());
|
||||
options.Append ($"-dynamiclib ");
|
||||
options.Append (build_info.LinkerFlags).Append (" ");
|
||||
options.Append ("-lobjc ");
|
||||
options.Append ("-framework CoreFoundation ");
|
||||
options.Append ("-framework Foundation ");
|
||||
options.Append ($"-install_name {Utils.Quote ("@rpath/" + output_file)} ");
|
||||
|
||||
foreach (var objfile in object_files)
|
||||
options.Append (Utils.Quote (objfile)).Append (" ");
|
||||
|
||||
var dynamic_ofile = Path.Combine (archOutputDirectory, output_file);
|
||||
options.Append ($"-o ").Append (Utils.Quote (dynamic_ofile)).Append (" ");
|
||||
lipo_files.Add (dynamic_ofile);
|
||||
if (!string.IsNullOrEmpty (build_info.XamariniOSSDK)) {
|
||||
options.Append ($"-L/Library/Frameworks/Xamarin.iOS.framework/Versions/Current/SDKs/{build_info.XamariniOSSDK}/usr/lib ");
|
||||
options.Append ("-lxamarin ");
|
||||
}
|
||||
else {
|
||||
options.Append ("-L/Library/Frameworks/Mono.framework/Versions/Current/lib/ ");
|
||||
}
|
||||
options.Append ("-lmonosgen-2.0 ");
|
||||
if (!Utils.Xcrun (options, out exitCode))
|
||||
return exitCode;
|
||||
break;
|
||||
case CompilationTarget.Framework:
|
||||
case CompilationTarget.StaticLibrary:
|
||||
// Archive all the .o files into a .a
|
||||
var archive_options = new StringBuilder ("ar cru ");
|
||||
var static_ofile = Path.Combine (archOutputDirectory, output_file);
|
||||
archive_options.Append (static_ofile).Append (" ");
|
||||
lipo_files.Add (static_ofile);
|
||||
foreach (var objfile in object_files)
|
||||
archive_options.Append (objfile).Append (" ");
|
||||
if (!Utils.Xcrun (archive_options, out exitCode))
|
||||
return exitCode;
|
||||
break;
|
||||
default:
|
||||
throw ErrorHelper.CreateError (99, "Internal error: invalid compilation target {0}. Please file a bug report with a test case (https://github.com/mono/Embeddinator-4000/issues).", CompilationTarget);
|
||||
}
|
||||
}
|
||||
|
||||
// Create the per-sdk output file
|
||||
var sdk_output_file = Path.Combine (OutputDirectory, build_info.Sdk, output_file);
|
||||
if (!Utils.Lipo (lipo_files, sdk_output_file, out exitCode))
|
||||
return exitCode;
|
||||
|
||||
if (CompilationTarget == CompilationTarget.Framework) {
|
||||
var appdir = Path.GetFullPath (Path.Combine (OutputDirectory, build_info.Sdk, LibraryName));
|
||||
var cachedir = Path.GetFullPath (Path.Combine (outputDirectory, build_info.Sdk, "build-cache"));
|
||||
|
||||
string fwdir;
|
||||
string headers;
|
||||
|
||||
switch (Platform) {
|
||||
case Platform.macOS:
|
||||
case Platform.macOSFull:
|
||||
case Platform.macOSModern:
|
||||
case Platform.macOSSystem:
|
||||
fwdir = Path.Combine (appdir, $"{LibraryName}.framework");
|
||||
headers = Path.Combine (fwdir, "Headers");
|
||||
Directory.CreateDirectory (Path.Combine (fwdir, "Versions", "A", "Headers"));
|
||||
Utils.CreateSymlink (Path.Combine (fwdir, "Versions", "Current"), "A");
|
||||
Utils.CreateSymlink (Path.Combine (fwdir, "Headers"), "Versions/Current/Headers");
|
||||
Utils.CreateSymlink (Path.Combine (fwdir, "Resources"), "Versions/Current/Resources");
|
||||
break;
|
||||
case Platform.iOS:
|
||||
case Platform.tvOS:
|
||||
case Platform.watchOS:
|
||||
fwdir = Path.Combine (appdir, "Frameworks", $"{LibraryName}.framework");
|
||||
headers = Path.Combine (fwdir, "Headers");
|
||||
Directory.CreateDirectory (headers);
|
||||
break;
|
||||
default:
|
||||
throw ErrorHelper.CreateError (99, "Internal error: invalid platform {0}. Please file a bug report with a test case (https://github.com/mono/Embeddinator-4000/issues).", Platform);
|
||||
}
|
||||
|
||||
switch (Platform) {
|
||||
case Platform.macOS:
|
||||
var resources_dir = Path.Combine (fwdir, "Versions", "A", "Resources");
|
||||
Directory.CreateDirectory (resources_dir);
|
||||
|
||||
// Link the .a files into a framework
|
||||
var options = new StringBuilder ("clang ");
|
||||
options.Append ($"-dynamiclib ");
|
||||
options.Append (build_info.LinkerFlags).Append (" ");
|
||||
options.Append ("-lobjc ");
|
||||
options.Append ("-framework CoreFoundation ");
|
||||
options.Append ("-framework Foundation ");
|
||||
options.Append ($"-install_name {Utils.Quote ($"@loader_path/../Frameworks/{LibraryName}.framework/Versions/A/{LibraryName}")} ");
|
||||
options.Append ("-force_load ").Append (Utils.Quote (sdk_output_file)).Append (" ");
|
||||
options.Append ($"-o ").Append (Utils.Quote (Path.Combine (fwdir, "Versions", "A", LibraryName))).Append (" ");
|
||||
options.Append ("-L/Library/Frameworks/Mono.framework/Versions/Current/lib/ ");
|
||||
options.Append ("-lmonosgen-2.0 ");
|
||||
if (!Utils.Xcrun (options, out exitCode))
|
||||
return exitCode;
|
||||
// Create framework structure
|
||||
Utils.CreateSymlink (Path.Combine (fwdir, LibraryName), $"Versions/Current/{LibraryName}");
|
||||
|
||||
File.WriteAllText (Path.Combine (fwdir, "Versions", "A", "Resources", "Info.plist"), $@"<?xml version=""1.0"" encoding=""UTF-8""?>
|
||||
<!DOCTYPE plist PUBLIC ""-//Apple//DTD PLIST 1.0//EN"" ""http://www.apple.com/DTDs/PropertyList-1.0.dtd"">
|
||||
<plist version=""1.0"">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>{LibraryName}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>{BundleIdentifier}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>{LibraryName}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
<array>
|
||||
<string>MacOSX</string>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>DTCompiler</key>
|
||||
<string>com.apple.compilers.llvm.clang.1_0</string>
|
||||
<key>DTPlatformBuild</key>
|
||||
<string>8C38</string>
|
||||
<key>DTPlatformVersion</key>
|
||||
<string>GM</string>
|
||||
<key>DTSDKBuild</key>
|
||||
<string>16C58</string>
|
||||
<key>DTSDKName</key>
|
||||
<string>macosx10.12</string>
|
||||
<key>DTXcode</key>
|
||||
<string>0620</string>
|
||||
<key>DTXcodeBuild</key>
|
||||
<string>6C131e</string>
|
||||
<key>BuildMachineOSBuild</key>
|
||||
<string>13F34</string>
|
||||
</dict>
|
||||
</plist>
|
||||
");
|
||||
|
||||
// Copy any assemblies to the framework
|
||||
var bundleDir = Path.Combine (resources_dir, "MonoBundle");
|
||||
Directory.CreateDirectory (bundleDir);
|
||||
foreach (var asm in Assemblies) {
|
||||
var src = asm.Location;
|
||||
var tgt = Path.Combine (bundleDir, Path.GetFileName (asm.Location));
|
||||
File.Copy (src, tgt, true);
|
||||
Utils.FileCopyIfExists (Path.ChangeExtension (src, "pdb"), Path.ChangeExtension (tgt, "pdb"));
|
||||
Utils.FileCopyIfExists (src + ".config", tgt + ".config");
|
||||
// FIXME: Satellite assemblies?
|
||||
}
|
||||
// Add the headers to the framework
|
||||
File.Copy (Path.Combine (OutputDirectory, "embeddinator.h"), Path.Combine (headers, "embeddinator.h"), true);
|
||||
File.Copy (Path.Combine (OutputDirectory, "bindings.h"), Path.Combine (headers, $"bindings.h"), true);
|
||||
// Create an umbrella header for the everything in the framework.
|
||||
File.WriteAllText (Path.Combine (headers, LibraryName + ".h"),
|
||||
@"
|
||||
#include ""bindings.h""
|
||||
");
|
||||
break;
|
||||
case Platform.macOSFull:
|
||||
case Platform.macOSModern:
|
||||
case Platform.macOSSystem:
|
||||
var mmp = new StringBuilder ();
|
||||
mmp.Append ($"--output={Utils.Quote (appdir)} ");
|
||||
mmp.Append ($"--arch={string.Join (",", build_info.Architectures)} ");
|
||||
if (build_info.Architectures.Length > 1)
|
||||
throw new NotImplementedException ("fat Xamarin.Mac apps");
|
||||
mmp.Append ($"--sdkroot {XcodeApp} ");
|
||||
mmp.Append ($"--minos {build_info.MinVersion} ");
|
||||
mmp.Append ($"--embeddinator ");
|
||||
foreach (var asm in Assemblies)
|
||||
mmp.Append (Utils.Quote (Path.GetFullPath (asm.Location))).Append (" ");
|
||||
mmp.Append ($"-a:{GetPlatformAssembly ()} ");
|
||||
mmp.Append ($"--sdk {GetSdkVersion (build_info.Sdk.ToLower ())} ");
|
||||
// FIXME: once merged add support for linking the platform (Xamarin.Mac.dll)
|
||||
if (Platform == Platform.macOSModern) {
|
||||
mmp.Append ("--linksdkonly ");
|
||||
mmp.Append ($"--xml={Utils.Quote (Path.Combine (OutputDirectory, "bindings.xml"))} ");
|
||||
}
|
||||
else {
|
||||
// mmp default is to link everything
|
||||
mmp.Append ("--nolink ");
|
||||
}
|
||||
mmp.Append ("--registrar:static ");
|
||||
mmp.Append ($"--cache {Utils.Quote (cachedir)} ");
|
||||
if (Debug)
|
||||
mmp.Append ("--debug ");
|
||||
mmp.Append ("-p "); // generate a plist
|
||||
mmp.Append ($"--target-framework {GetTargetFramework ()} ");
|
||||
mmp.Append ($"\"--link_flags=-force_load {Path.GetFullPath (sdk_output_file)}\" ");
|
||||
if (!Utils.RunProcess ("/Library/Frameworks/Xamarin.Mac.framework/Versions/Current/bin/mmp", mmp.ToString (), out exitCode))
|
||||
return exitCode;
|
||||
|
||||
// Add the headers to the framework
|
||||
File.Copy (Path.Combine (OutputDirectory, "embeddinator.h"), Path.Combine (headers, "embeddinator.h"), true);
|
||||
File.Copy (Path.Combine (OutputDirectory, "bindings.h"), Path.Combine (headers, $"bindings.h"), true);
|
||||
// Create an umbrella header for the everything in the framework.
|
||||
File.WriteAllText (Path.Combine (headers, LibraryName + ".h"),
|
||||
@"
|
||||
#include ""bindings.h""
|
||||
#if defined(__i386__)
|
||||
#include ""registrar-i386.h""
|
||||
#elif defined(__x86_64__)
|
||||
#include ""registrar-x86_64.h""
|
||||
#else
|
||||
#error Unknown architecture
|
||||
#endif
|
||||
");
|
||||
if (build_info.Architectures.Contains ("i386"))
|
||||
Utils.FileCopyIfExists (Path.Combine (cachedir, "registrar.h"), Path.Combine (headers, "registrar-i386.h"));
|
||||
if (build_info.Architectures.Contains ("x86_64"))
|
||||
Utils.FileCopyIfExists (Path.Combine (cachedir, "registrar.h"), Path.Combine (headers, "registrar-x86_64.h"));
|
||||
break;
|
||||
case Platform.iOS:
|
||||
case Platform.tvOS:
|
||||
case Platform.watchOS:
|
||||
var mtouch = new StringBuilder ();
|
||||
mtouch.Append (build_info.IsSimulator ? "--sim " : "--dev ");
|
||||
mtouch.Append ($"{Utils.Quote (appdir)} ");
|
||||
mtouch.Append ($"--abi={string.Join (",", build_info.Architectures)} ");
|
||||
mtouch.Append ($"--sdkroot {XcodeApp} ");
|
||||
mtouch.Append ($"--targetver {build_info.MinVersion} ");
|
||||
mtouch.Append ("--dsym:false ");
|
||||
mtouch.Append ("--msym:false ");
|
||||
mtouch.Append ($"--embeddinator ");
|
||||
foreach (var asm in Assemblies)
|
||||
mtouch.Append (Utils.Quote (Path.GetFullPath (asm.Location))).Append (" ");
|
||||
mtouch.Append ($"-r:{GetPlatformAssembly ()} ");
|
||||
mtouch.Append ($"--sdk {GetSdkVersion (build_info.Sdk.ToLower ())} ");
|
||||
mtouch.Append ("--linksdkonly ");
|
||||
mtouch.Append ($"--xml={Utils.Quote (Path.Combine (OutputDirectory, "bindings.xml"))} ");
|
||||
mtouch.Append ("--registrar:static ");
|
||||
mtouch.Append ($"--cache {Utils.Quote (cachedir)} ");
|
||||
if (Debug)
|
||||
mtouch.Append ("--debug ");
|
||||
mtouch.Append ($"--assembly-build-target=@all=framework={LibraryName}.framework ");
|
||||
mtouch.Append ($"--target-framework {GetTargetFramework ()} ");
|
||||
mtouch.Append ($"\"--gcc_flags=-force_load {Path.GetFullPath (sdk_output_file)}\" ");
|
||||
if (!Utils.RunProcess ("/Library/Frameworks/Xamarin.iOS.framework/Versions/Current/bin/mtouch", mtouch.ToString (), out exitCode))
|
||||
return exitCode;
|
||||
|
||||
// Add the headers to the framework
|
||||
File.Copy (Path.Combine (OutputDirectory, "embeddinator.h"), Path.Combine (headers, "embeddinator.h"), true);
|
||||
File.Copy (Path.Combine (OutputDirectory, "bindings.h"), Path.Combine (headers, $"bindings.h"), true);
|
||||
// Create an umbrella header for the everything in the framework.
|
||||
File.WriteAllText (Path.Combine (headers, LibraryName + ".h"),
|
||||
@"
|
||||
#include ""bindings.h""
|
||||
#if defined(__i386__)
|
||||
#include ""registrar-i386.h""
|
||||
#elif defined(__x86_64__)
|
||||
#include ""registrar-x86_64.h""
|
||||
#elif defined(__arm__)
|
||||
#include ""registrar-arm32.h"" // this includes all 32-bit arm architectures.
|
||||
#elif defined(__aarch64__)
|
||||
#include ""registrar-arm64.h""
|
||||
#else
|
||||
#error Unknown architecture
|
||||
#endif
|
||||
");
|
||||
switch (Platform) {
|
||||
case Platform.iOS:
|
||||
if (build_info.IsSimulator) {
|
||||
Utils.FileCopyIfExists (Path.Combine (cachedir, "32", "registrar.h"), Path.Combine (headers, "registrar-i386.h"));
|
||||
Utils.FileCopyIfExists (Path.Combine (cachedir, "64", "registrar.h"), Path.Combine (headers, "registrar-x86_64.h"));
|
||||
}
|
||||
else {
|
||||
Utils.FileCopyIfExists (Path.Combine (cachedir, "32", "registrar.h"), Path.Combine (headers, "registrar-arm32.h"));
|
||||
Utils.FileCopyIfExists (Path.Combine (cachedir, "64", "registrar.h"), Path.Combine (headers, "registrar-arm64.h"));
|
||||
}
|
||||
break;
|
||||
case Platform.tvOS:
|
||||
Utils.FileCopyIfExists (Path.Combine (cachedir, "registrar.h"), Path.Combine (headers, build_info.IsSimulator ? "registrar-x86_64.h" : "registrar-arm64.h"));
|
||||
break;
|
||||
default:
|
||||
throw ErrorHelper.CreateError (99, "Internal error: invalid platform {0}. Please file a bug report with a test case (https://github.com/mono/Embeddinator-4000/issues).", Platform);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw ErrorHelper.CreateError (99, "Internal error: invalid platform {0}. Please file a bug report with a test case (https://github.com/mono/Embeddinator-4000/issues).", Platform);
|
||||
}
|
||||
|
||||
// Move the framework to the output directory
|
||||
var fwpath = Path.Combine (OutputDirectory, build_info.Sdk, $"{LibraryName}.framework");
|
||||
if (Directory.Exists (fwpath))
|
||||
Directory.Delete (fwpath, true);
|
||||
Directory.Move (fwdir, fwpath);
|
||||
Directory.Delete (appdir, true); // We don't need this anymore.
|
||||
}
|
||||
}
|
||||
|
||||
var output_path = Path.Combine (OutputDirectory, output_file);
|
||||
if (!Utils.Lipo (lipo_files, output_path, out exitCode))
|
||||
return exitCode;
|
||||
|
||||
if (!DSymUtil (output_path, out exitCode))
|
||||
return exitCode;
|
||||
|
||||
if (CompilationTarget == CompilationTarget.Framework) {
|
||||
var fwpath = Path.Combine (OutputDirectory, $"{LibraryName}.framework");
|
||||
if (build_infos.Length == 2) {
|
||||
var dev_fwpath = Path.Combine (OutputDirectory, build_infos[0].Sdk, $"{LibraryName}.framework");
|
||||
var sim_fwpath = Path.Combine (OutputDirectory, build_infos[1].Sdk, $"{LibraryName}.framework");
|
||||
if (!MergeFrameworks (fwpath, dev_fwpath, sim_fwpath, out exitCode))
|
||||
return exitCode;
|
||||
}
|
||||
else {
|
||||
if (Directory.Exists (fwpath))
|
||||
Directory.Delete (fwpath, true);
|
||||
var fwsdkpath = Path.Combine (OutputDirectory, build_infos[0].Sdk, $"{LibraryName}.framework");
|
||||
Directory.Move (fwsdkpath, fwpath);
|
||||
}
|
||||
Console.WriteLine ($"Successfully created framework: {fwpath}");
|
||||
}
|
||||
else {
|
||||
Console.WriteLine ($"Successfully created library: {output_path}");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// All files from both frameworks will be included.
|
||||
// For files present in both frameworks:
|
||||
// * The executables will be lipoed
|
||||
// * Info.plist will be manually merged.
|
||||
// * Headers: should be identical, so we just choose one of them.
|
||||
// * other files: show an error.
|
||||
static bool MergeFrameworks (string output, string deviceFramework, string simulatorFramework, out int exitCode)
|
||||
{
|
||||
if (deviceFramework[deviceFramework.Length - 1] == Path.DirectorySeparatorChar)
|
||||
deviceFramework = deviceFramework.Substring (0, deviceFramework.Length - 1);
|
||||
if (simulatorFramework[simulatorFramework.Length - 1] == Path.DirectorySeparatorChar)
|
||||
simulatorFramework = simulatorFramework.Substring (0, simulatorFramework.Length - 1);
|
||||
|
||||
var name = Path.GetFileNameWithoutExtension (deviceFramework);
|
||||
var deviceFiles = Directory.GetFiles (deviceFramework, "*", SearchOption.AllDirectories);
|
||||
var simulatorFiles = Directory.GetFiles (simulatorFramework, "*", SearchOption.AllDirectories);
|
||||
|
||||
Directory.CreateDirectory (output);
|
||||
var executables = new List<string> ();
|
||||
executables.Add (Path.Combine (deviceFramework, name));
|
||||
executables.Add (Path.Combine (simulatorFramework, name));
|
||||
if (!Utils.Lipo (executables, Path.Combine (output, name), out exitCode))
|
||||
return false;
|
||||
|
||||
var relativeDeviceFiles = deviceFiles.Select ((v) => v.Substring (deviceFramework.Length + 1));
|
||||
var relativeSimulatorFiles = simulatorFiles.Select ((v) => v.Substring (simulatorFramework.Length + 1));
|
||||
var allFiles = relativeDeviceFiles.Concat (relativeSimulatorFiles).ToList ();
|
||||
allFiles.RemoveAll ((v) => v == name); // the executable, which we've already handled (lipoed).
|
||||
|
||||
var groupedFiles = allFiles.GroupBy ((v) => v);
|
||||
foreach (var @group in groupedFiles) {
|
||||
var file = @group.Key;
|
||||
var unique = @group.Count () == 1;
|
||||
var targetPath = Path.Combine (output, file);
|
||||
Directory.CreateDirectory (Path.GetDirectoryName (targetPath));
|
||||
if (unique) {
|
||||
// A single file, just copy it.
|
||||
string srcPath;
|
||||
if (relativeDeviceFiles.Contains (file)) {
|
||||
srcPath = Path.Combine (deviceFramework, file);
|
||||
}
|
||||
else {
|
||||
srcPath = Path.Combine (simulatorFramework, file);
|
||||
}
|
||||
File.Copy (srcPath, targetPath, true);
|
||||
}
|
||||
else {
|
||||
// Same file in both device and simulator frameworks.
|
||||
if (file == "Info.plist") {
|
||||
MergeInfoPlists (Path.Combine (output, file), Path.Combine (deviceFramework, file), Path.Combine (simulatorFramework, file));
|
||||
}
|
||||
else if (file.StartsWith ("Headers/", StringComparison.Ordinal)) {
|
||||
// Headers are identical between simulator and device, so no special processing needed, just choose one of them.
|
||||
File.Copy (Path.Combine (deviceFramework, file), targetPath, true);
|
||||
}
|
||||
else {
|
||||
throw ErrorHelper.CreateError (10, $"Can't merge the frameworks '{simulatorFramework}' and '{deviceFramework}' because the file '{file}' exists in both.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Merge CFBundleSupportPlatforms from both Info.plists.
|
||||
// At the moment all other values are only from the first plist.
|
||||
static void MergeInfoPlists (string output, string a, string b)
|
||||
{
|
||||
var adoc = new XmlDocument ();
|
||||
var bdoc = new XmlDocument ();
|
||||
XmlReaderSettings settings = new XmlReaderSettings () {
|
||||
XmlResolver = null,
|
||||
DtdProcessing = DtdProcessing.Parse
|
||||
};
|
||||
|
||||
using (var srA = new StreamReader (a, Encoding.UTF8, true))
|
||||
using (var readerA = XmlReader.Create (srA, settings))
|
||||
using (var srB = new StreamReader (b, Encoding.UTF8, true))
|
||||
using (var readerB = XmlReader.Create (srB, settings)) {
|
||||
adoc.Load (readerA);
|
||||
bdoc.Load (readerB);
|
||||
|
||||
var a_supported_platforms = ((XmlNode)adoc.SelectSingleNode ("/plist/dict/key[text()='CFBundleSupportedPlatforms']/following-sibling::array"));
|
||||
var b_supported_platforms = ((XmlNode)bdoc.SelectSingleNode ("/plist/dict/key[text()='CFBundleSupportedPlatforms']/following-sibling::array"));
|
||||
|
||||
foreach (XmlNode b_platform in b_supported_platforms.ChildNodes) {
|
||||
var node = adoc.ImportNode (b_platform, true);
|
||||
a_supported_platforms.AppendChild (node);
|
||||
}
|
||||
|
||||
var writerSettings = new XmlWriterSettings ();
|
||||
writerSettings.Encoding = new UTF8Encoding (false);
|
||||
writerSettings.IndentChars = " ";
|
||||
writerSettings.Indent = true;
|
||||
using (var writer = XmlWriter.Create (output, writerSettings))
|
||||
adoc.Save (writer);
|
||||
|
||||
// Apple's plist reader does not like empty internal subset declaration,
|
||||
// even though this is allowed according to the xml spec: http://stackoverflow.com/a/6192048/183422
|
||||
// So manually fix the xml :(
|
||||
var contents = File.ReadAllText (output);
|
||||
contents = contents.Replace (
|
||||
@"<!DOCTYPE plist PUBLIC ""-//Apple//DTD PLIST 1.0//EN"" ""http://www.apple.com/DTDs/PropertyList-1.0.dtd""[]>",
|
||||
@"<!DOCTYPE plist PUBLIC ""-//Apple//DTD PLIST 1.0//EN"" ""http://www.apple.com/DTDs/PropertyList-1.0.dtd"">");
|
||||
File.WriteAllText (output, contents);
|
||||
}
|
||||
}
|
||||
|
||||
string GetSdkVersion (string sdk)
|
||||
{
|
||||
int exitCode;
|
||||
string output;
|
||||
if (!Utils.RunProcess ("xcrun", $"--show-sdk-version --sdk {sdk}", out exitCode, out output))
|
||||
throw ErrorHelper.CreateError (7, $"Could not get the sdk version for '{sdk}'");
|
||||
return output.Trim ();
|
||||
}
|
||||
|
||||
string GetPlatformAssembly ()
|
||||
{
|
||||
switch (Platform) {
|
||||
case Platform.macOS:
|
||||
throw new NotImplementedException ("platform assembly for macOS"); // We need to know full/mobile
|
||||
case Platform.macOSSystem:
|
||||
case Platform.macOSFull:
|
||||
return "/Library/Frameworks/Xamarin.Mac.framework/Versions/Current/lib/mono/4.5/Xamarin.Mac.dll";
|
||||
case Platform.macOSModern:
|
||||
return "/Library/Frameworks/Xamarin.Mac.framework/Versions/Current/lib/mono/Xamarin.Mac/Xamarin.Mac.dll";
|
||||
case Platform.iOS:
|
||||
return "/Library/Frameworks/Xamarin.iOS.framework/Versions/Current/lib/mono/Xamarin.iOS/Xamarin.iOS.dll";
|
||||
case Platform.tvOS:
|
||||
return "/Library/Frameworks/Xamarin.iOS.framework/Versions/Current/lib/mono/Xamarin.TVOS/Xamarin.TVOS.dll";
|
||||
case Platform.watchOS:
|
||||
return "/Library/Frameworks/Xamarin.iOS.framework/Versions/Current/lib/mono/Xamarin.WatchOS/Xamarin.WatchOS.dll";
|
||||
default:
|
||||
throw ErrorHelper.CreateError (99, "Internal error: invalid platform {0}. Please file a bug report with a test case (https://github.com/mono/Embeddinator-4000/issues).", Platform);
|
||||
}
|
||||
}
|
||||
|
||||
string GetTargetFramework ()
|
||||
{
|
||||
switch (Platform) {
|
||||
case Platform.macOSSystem:
|
||||
return "Xamarin.Mac,Version=v4.5,Profile=System";
|
||||
case Platform.macOSFull:
|
||||
return "Xamarin.Mac,Version=v4.5,Profile=Full";
|
||||
case Platform.macOSModern:
|
||||
return "Xamarin.Mac,Version=v2.0,Profile=Mobile";
|
||||
case Platform.iOS:
|
||||
return "Xamarin.iOS,v1.0";
|
||||
case Platform.tvOS:
|
||||
return "Xamarin.TVOS,v1.0";
|
||||
case Platform.watchOS:
|
||||
return "Xamarin.WatchOS,v1.0";
|
||||
default:
|
||||
throw ErrorHelper.CreateError (99, "Internal error: invalid platform {0}. Please file a bug report with a test case (https://github.com/mono/Embeddinator-4000/issues).", Platform);
|
||||
}
|
||||
}
|
||||
|
||||
bool DSymUtil (string input, out int exitCode)
|
||||
{
|
||||
exitCode = 0;
|
||||
|
||||
if (!Debug)
|
||||
return true;
|
||||
|
||||
string output;
|
||||
switch (CompilationTarget) {
|
||||
case CompilationTarget.StaticLibrary:
|
||||
case CompilationTarget.Framework:
|
||||
return true;
|
||||
case CompilationTarget.SharedLibrary:
|
||||
output = input + ".dSYM";
|
||||
break;
|
||||
default:
|
||||
throw ErrorHelper.CreateError (99, "Internal error: invalid compilation target {0}. Please file a bug report with a test case (https://github.com/mono/Embeddinator-4000/issues).", CompilationTarget);
|
||||
}
|
||||
|
||||
var dsymutil_options = new StringBuilder ("dsymutil ");
|
||||
dsymutil_options.Append (Utils.Quote (input)).Append (" ");
|
||||
dsymutil_options.Append ($"-o {Utils.Quote (output)} ");
|
||||
return Utils.Xcrun (dsymutil_options, out exitCode);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -200,4 +200,12 @@ namespace Embeddinator.ObjC {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static class EnumerableExtensions {
|
||||
public static IEnumerable<T> Yield<T> (this T item)
|
||||
{
|
||||
yield return item;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ namespace Embeddinator.ObjC {
|
|||
|
||||
var method = "__method";
|
||||
if (IsVirtual) {
|
||||
implementation.WriteLine ($"MonoMethod* __virtual_method = mono_object_get_virtual_method ({instance}, __method);");
|
||||
implementation.WriteLine ($"MonoMethod* __virtual_method = mono_object_get_virtual_method ((MonoObject *){instance}, __method);");
|
||||
method = "__virtual_method";
|
||||
}
|
||||
if (!IsConstructor && (ReturnType != "void"))
|
||||
|
|
|
@ -60,6 +60,11 @@
|
|||
<Compile Include="NameGenerator.cs" />
|
||||
<Compile Include="processor.cs" />
|
||||
<Compile Include="system-check.cs" />
|
||||
<Compile Include="embedder.cs" />
|
||||
<Compile Include="utils.cs" />
|
||||
<Compile Include="CachedValue.cs" />
|
||||
<Compile Include="TypeMapper.cs" />
|
||||
<Compile Include="Logger.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="support\" />
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
|
@ -10,10 +11,11 @@ namespace Embeddinator.ObjC {
|
|||
// A set of post-processing steps needed to add hints
|
||||
// to the input of the generation step
|
||||
public partial class ObjCProcessor {
|
||||
|
||||
TypeMapper Mapper = new TypeMapper ();
|
||||
|
||||
protected IEnumerable<ProcessedMethod> PostProcessMethods (IEnumerable<ProcessedMethod> methods)
|
||||
{
|
||||
HashSet<string> duplicateNames = FindDuplicateNames (methods);
|
||||
|
||||
var equals = new HashSet<MethodInfo> ();
|
||||
foreach (var m in methods) {
|
||||
if (m.MethodType == MethodType.NSObjectProcotolIsEqual)
|
||||
|
@ -28,19 +30,24 @@ namespace Embeddinator.ObjC {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (duplicateNames.Contains (CreateStringRep (method)) && method.Name != "CompareTo") // HACK
|
||||
processedMethod.FallBackToTypeName = true;
|
||||
|
||||
if (IsOperatorOrFriendlyVersion (method))
|
||||
processedMethod.IsOperator = true;
|
||||
|
||||
ProcessPotentialNameOverride (processedMethod);
|
||||
ProcessPotentialName (processedMethod);
|
||||
|
||||
if (Mapper.CheckForDuplicateSelectors (processedMethod) == DuplicationStatus.Unresolvable) {
|
||||
Delayed.Add (ErrorHelper.CreateWarning (1052, $"Element {method.Name} is not generated as its name conflicts with other elements on the same class."));
|
||||
continue;
|
||||
}
|
||||
|
||||
Mapper.Register (processedMethod);
|
||||
|
||||
processedMethod.Freeze ();
|
||||
yield return processedMethod;
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessPotentialNameOverride (ProcessedMethod processedMethod)
|
||||
void ProcessPotentialName (ProcessedMethod processedMethod)
|
||||
{
|
||||
MethodInfo method = processedMethod.Method;
|
||||
if (IsOperatorOrFriendlyVersion (method)) {
|
||||
|
@ -48,6 +55,13 @@ namespace Embeddinator.ObjC {
|
|||
if (nameOverride != null)
|
||||
processedMethod.NameOverride = nameOverride;
|
||||
}
|
||||
|
||||
string objCSignature = processedMethod.ObjCSignature;
|
||||
if (RestrictedObjSelectors.IsImportantSelector (objCSignature)) {
|
||||
string newName = "managed" + method.Name.PascalCase ();
|
||||
processedMethod.NameOverride = newName;
|
||||
Delayed.Add (ErrorHelper.CreateWarning (1051, $"Element {method.Name} is generated instead as {newName} because its name conflicts with an important objective-c selector."));
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsOperatorOrFriendlyVersion (MethodInfo method)
|
||||
|
@ -55,84 +69,120 @@ namespace Embeddinator.ObjC {
|
|||
return method.IsOperatorMethod () || OperatorOverloads.MatchesOperatorFriendlyName (method);
|
||||
}
|
||||
|
||||
protected IEnumerable<ProcessedProperty> PostProcessProperties (IEnumerable<PropertyInfo> properties)
|
||||
protected IEnumerable<ProcessedProperty> PostProcessProperties (IEnumerable<ProcessedProperty> properties)
|
||||
{
|
||||
foreach (PropertyInfo property in properties) {
|
||||
ProcessedProperty processedProperty = new ProcessedProperty (property, this);
|
||||
foreach (ProcessedProperty processedProperty in properties) {
|
||||
|
||||
ProcessPotentialName (processedProperty);
|
||||
|
||||
if (Mapper.CheckForDuplicateSelectors (processedProperty) == DuplicationStatus.Unresolvable){
|
||||
Delayed.Add (ErrorHelper.CreateWarning (1052, $"Element {processedProperty.Name} is not generated as its name conflicts with other elements on the same class."));
|
||||
continue;
|
||||
}
|
||||
|
||||
Mapper.Register (processedProperty);
|
||||
|
||||
processedProperty.Freeze ();
|
||||
yield return processedProperty;
|
||||
}
|
||||
}
|
||||
|
||||
protected IEnumerable<ProcessedProperty> PostProcessSubscriptProperties (IEnumerable<PropertyInfo> properties)
|
||||
void ProcessPotentialName (ProcessedProperty processedProperty)
|
||||
{
|
||||
foreach (PropertyInfo property in properties) {
|
||||
ProcessedProperty processedProperty = new ProcessedProperty (property, this);
|
||||
string getSignature = processedProperty.HasGetter ? processedProperty.GetMethod.ObjCSignature : "";
|
||||
string setSignature = processedProperty.HasSetter ? processedProperty.SetMethod.ObjCSignature : "";
|
||||
|
||||
if (RestrictedObjSelectors.IsImportantSelector (getSignature) || RestrictedObjSelectors.IsImportantSelector (setSignature)) {
|
||||
string newName = "managed" + processedProperty.Name.PascalCase ();
|
||||
Delayed.Add (ErrorHelper.CreateWarning (1051, $"Element {processedProperty.Name} is generated instead as {newName} because its name conflicts with an important objective-c selector."));
|
||||
processedProperty.NameOverride = newName;
|
||||
}
|
||||
}
|
||||
|
||||
protected IEnumerable<ProcessedProperty> PostProcessSubscriptProperties (IEnumerable<ProcessedProperty> properties)
|
||||
{
|
||||
foreach (ProcessedProperty processedProperty in properties) {
|
||||
|
||||
if (Mapper.CheckForDuplicateSelectors (processedProperty) == DuplicationStatus.Unresolvable) {
|
||||
Delayed.Add (ErrorHelper.CreateWarning (1052, $"Element {processedProperty.Name} is not generated as its name conflicts with other elements on the same class."));
|
||||
continue;
|
||||
}
|
||||
|
||||
Mapper.Register (processedProperty);
|
||||
|
||||
yield return processedProperty;
|
||||
}
|
||||
}
|
||||
|
||||
protected IEnumerable<ProcessedFieldInfo> PostProcessFields (IEnumerable<FieldInfo> fields)
|
||||
void ProcessPotentialName (ProcessedFieldInfo processedField)
|
||||
{
|
||||
foreach (FieldInfo field in fields) {
|
||||
ProcessedFieldInfo processedField = new ProcessedFieldInfo (field, this);
|
||||
if (RestrictedObjSelectors.IsImportantSelector (processedField.GetterName) || RestrictedObjSelectors.IsImportantSelector (processedField.SetterName)) {
|
||||
string newName = "managed" + processedField.Name.PascalCase ();
|
||||
Delayed.Add (ErrorHelper.CreateWarning (1051, $"Element {processedField.Name} is generated instead as {newName} because its name conflicts with an important objective-c selector."));
|
||||
processedField.NameOverride = newName;
|
||||
}
|
||||
}
|
||||
|
||||
protected IEnumerable<ProcessedFieldInfo> PostProcessFields (IEnumerable<ProcessedFieldInfo> fields)
|
||||
{
|
||||
foreach (ProcessedFieldInfo processedField in fields) {
|
||||
ProcessPotentialName (processedField);
|
||||
|
||||
if (Mapper.CheckForDuplicateSelectors (processedField) == DuplicationStatus.Unresolvable) {
|
||||
Delayed.Add (ErrorHelper.CreateWarning (1052, $"Element {processedField.Name} is not generated as its name conflicts with other elements on the same class."));
|
||||
continue;
|
||||
}
|
||||
|
||||
Mapper.Register (processedField);
|
||||
|
||||
yield return processedField;
|
||||
}
|
||||
}
|
||||
|
||||
protected IEnumerable<ProcessedConstructor> PostProcessConstructors (IEnumerable<ConstructorInfo> constructors)
|
||||
protected IEnumerable<ProcessedConstructor> PostProcessConstructors (IEnumerable<ProcessedConstructor> constructors)
|
||||
{
|
||||
HashSet<string> duplicateNames = FindDuplicateNames (constructors);
|
||||
foreach (ProcessedConstructor processedConstructor in constructors) {
|
||||
if (Mapper.CheckForDuplicateSelectors (processedConstructor) == DuplicationStatus.Unresolvable)
|
||||
continue;
|
||||
|
||||
foreach (ConstructorInfo constructor in constructors) {
|
||||
ProcessedConstructor processedConstructor = new ProcessedConstructor (constructor, this);
|
||||
|
||||
if (duplicateNames.Contains (CreateStringRep(constructor)))
|
||||
processedConstructor.FallBackToTypeName = true;
|
||||
Mapper.Register (processedConstructor);
|
||||
|
||||
processedConstructor.Freeze ();
|
||||
yield return processedConstructor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static string CreateStringRep (ConstructorInfo constructor)
|
||||
{
|
||||
StringBuilder str = new StringBuilder ();
|
||||
foreach (var arg in constructor.GetParameters ())
|
||||
str.Append (arg.Name + ":"); // This format is arbitrary
|
||||
return str.ToString ();
|
||||
}
|
||||
static class RestrictedNames
|
||||
{
|
||||
static readonly HashSet<string> Names = new HashSet<string> { "static", "auto" };
|
||||
|
||||
static string CreateStringRep (MethodInfo method)
|
||||
public static bool IsRestrictedName (string name)
|
||||
{
|
||||
StringBuilder str = new StringBuilder (method.Name);
|
||||
foreach (var arg in method.GetParameters ())
|
||||
str.Append (":"); // This format is arbitrary
|
||||
return str.ToString ();
|
||||
}
|
||||
|
||||
static string CreateStringRep (MemberInfo i)
|
||||
{
|
||||
if (i is ConstructorInfo)
|
||||
return CreateStringRep ((ConstructorInfo)i);
|
||||
if (i is MethodInfo)
|
||||
return CreateStringRep ((MethodInfo)i);
|
||||
return i.Name;
|
||||
}
|
||||
|
||||
// temporary quasi-duplicate
|
||||
static HashSet<string> FindDuplicateNames (IEnumerable<ProcessedMethod> members)
|
||||
{
|
||||
Dictionary<string, int> methodNames = new Dictionary<string, int> ();
|
||||
foreach (var member in members)
|
||||
methodNames.IncrementValue (CreateStringRep (member.Method));
|
||||
return new HashSet<string> (methodNames.Where (x => x.Value > 1).Select (x => x.Key));
|
||||
}
|
||||
|
||||
static HashSet<string> FindDuplicateNames (IEnumerable<MemberInfo> members)
|
||||
{
|
||||
Dictionary<string, int> methodNames = new Dictionary<string, int> ();
|
||||
foreach (MemberInfo member in members)
|
||||
methodNames.IncrementValue (CreateStringRep (member));
|
||||
return new HashSet<string> (methodNames.Where (x => x.Value > 1).Select (x => x.Key));
|
||||
return Names.Contains (name);
|
||||
}
|
||||
}
|
||||
|
||||
static class RestrictedObjSelectors
|
||||
{
|
||||
static readonly HashSet<string> ImportantObjcSelectors = new HashSet<string> { "hash", "class", "superclass", "isEqual:", "self", "isKindOfClass:",
|
||||
"isMemberOfClass:", "respondsToSelector:", "conformsToProtocol:", "description", "debugDescription", "performSelector:", "performSelector:withObject:",
|
||||
"performSelector:withObject:withObject:", "isProxy", "retain", "release", "autorelease", "retainCount", "zone" };
|
||||
|
||||
static public bool IsImportantSelector (string selector)
|
||||
{
|
||||
if (selector.StartsWith ("get", StringComparison.Ordinal))
|
||||
selector = selector.Substring (3).CamelCase ();
|
||||
|
||||
if (selector.StartsWith ("set", StringComparison.Ordinal)) {
|
||||
selector = selector.Substring (3).CamelCase ();
|
||||
int colonLocation = selector.IndexOf (':');
|
||||
if (colonLocation > 0)
|
||||
selector = selector.Substring (0, colonLocation);
|
||||
}
|
||||
|
||||
return ImportantObjcSelectors.Contains (selector);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ namespace Embeddinator.ObjC {
|
|||
|
||||
public override void Generate ()
|
||||
{
|
||||
Logger.Log ($"Begin Generator");
|
||||
|
||||
var types = Processor.Types;
|
||||
headers.WriteLine ("#include \"embeddinator.h\"");
|
||||
headers.WriteLine ("#import <Foundation/Foundation.h>");
|
||||
|
@ -27,6 +29,10 @@ namespace Embeddinator.ObjC {
|
|||
headers.WriteLine ("#endif");
|
||||
headers.WriteLine ();
|
||||
|
||||
headers.WriteLine ("#ifdef __cplusplus");
|
||||
headers.WriteLine ("extern \"C\" {");
|
||||
headers.WriteLine ("#endif");
|
||||
|
||||
headers.WriteLine ("// forward declarations");
|
||||
foreach (var t in types.Where ((arg) => arg.IsClass))
|
||||
headers.WriteLine ($"@class {t.TypeName};");
|
||||
|
@ -86,10 +92,16 @@ namespace Embeddinator.ObjC {
|
|||
|
||||
headers.WriteLine ("NS_ASSUME_NONNULL_END");
|
||||
headers.WriteLine ();
|
||||
|
||||
headers.WriteLine ("#ifdef __cplusplus");
|
||||
headers.WriteLine ("} /* extern \"C\" */");
|
||||
headers.WriteLine ("#endif");
|
||||
}
|
||||
|
||||
protected override void Generate (ProcessedAssembly a)
|
||||
{
|
||||
Logger.Log ($"Generating Assembly: {a.Name}");
|
||||
|
||||
var originalName = a.Name;
|
||||
var name = a.SafeName;
|
||||
implementation.WriteLine ($"static void __lookup_assembly_{name} ()");
|
||||
|
@ -152,6 +164,8 @@ namespace Embeddinator.ObjC {
|
|||
|
||||
void GenerateCategory (Type definedType, Type extendedType, List<ProcessedMethod> methods)
|
||||
{
|
||||
Logger.Log ($"Generating Catagory: {definedType.Name}");
|
||||
|
||||
var etn = NameGenerator.GetTypeName (extendedType).Replace (" *", String.Empty);
|
||||
var name = $"{etn} ({NameGenerator.GetTypeName (definedType)})";
|
||||
headers.WriteLine ($"/** Category {name}");
|
||||
|
@ -164,7 +178,7 @@ namespace Embeddinator.ObjC {
|
|||
implementation.WriteLine ();
|
||||
|
||||
foreach (var mi in methods) {
|
||||
ImplementMethod (mi.Method, mi.Method.Name.CamelCase (), mi, isExtension: true);
|
||||
ImplementMethod (mi);
|
||||
}
|
||||
|
||||
headers.WriteLine ("@end");
|
||||
|
@ -176,6 +190,8 @@ namespace Embeddinator.ObjC {
|
|||
|
||||
void GenerateEnum (ProcessedType type)
|
||||
{
|
||||
Logger.Log ($"Generating Enum: {type.TypeName}");
|
||||
|
||||
Type t = type.Type;
|
||||
var managed_name = type.ObjCName;
|
||||
var underlying_type = t.GetEnumUnderlyingType ();
|
||||
|
@ -216,6 +232,8 @@ namespace Embeddinator.ObjC {
|
|||
|
||||
void GenerateProtocol (ProcessedType type)
|
||||
{
|
||||
Logger.Log ($"Generating Protocol: {type.TypeName}");
|
||||
|
||||
Type t = type.Type;
|
||||
var pbuilder = new ProtocolHelper (headers, implementation, private_headers) {
|
||||
AssemblyQualifiedName = t.AssemblyQualifiedName,
|
||||
|
@ -269,6 +287,8 @@ namespace Embeddinator.ObjC {
|
|||
|
||||
protected override void Generate (ProcessedType type)
|
||||
{
|
||||
Logger.Log ($"Generating Type: {type.TypeName}");
|
||||
|
||||
Type t = type.Type;
|
||||
var aname = t.Assembly.GetName ().Name.Sanitize ();
|
||||
var static_type = t.IsSealed && t.IsAbstract;
|
||||
|
@ -304,11 +324,11 @@ namespace Embeddinator.ObjC {
|
|||
default_init |= pcount == 0;
|
||||
|
||||
var parameters = ctor.Parameters;
|
||||
string name = ctor.ObjCName;
|
||||
string name = ctor.BaseName;
|
||||
string signature = ".ctor()";
|
||||
if (parameters.Length > 0) {
|
||||
name = ctor.GetObjcSignature ();
|
||||
signature = ctor.GetMonoSignature ();
|
||||
name = ctor.ObjCSignature;
|
||||
signature = ctor.MonoSignature;
|
||||
}
|
||||
|
||||
if (ctor.Unavailable) {
|
||||
|
@ -357,7 +377,7 @@ namespace Embeddinator.ObjC {
|
|||
}
|
||||
builder.WriteInvoke (args);
|
||||
implementation.Write (postInvoke);
|
||||
implementation.WriteLine ("_object = mono_embeddinator_create_object (__instance);");
|
||||
implementation.WriteLine ("_object = (MonoEmbedObject *)mono_embeddinator_create_object (__instance);");
|
||||
implementation.Indent--;
|
||||
implementation.WriteLine ("}");
|
||||
if (Processor.Types.HasClass (t.BaseType))
|
||||
|
@ -392,7 +412,7 @@ namespace Embeddinator.ObjC {
|
|||
implementation.Indent++;
|
||||
implementation.WriteLine ($"MonoObject* __instance = mono_object_new (__mono_context.domain, {managed_name}_class);");
|
||||
// no call to `WriteInvoke` since there is not such method if we reached this case
|
||||
implementation.WriteLine ("_object = mono_embeddinator_create_object (__instance);");
|
||||
implementation.WriteLine ("_object = (MonoEmbedObject *)mono_embeddinator_create_object (__instance);");
|
||||
implementation.Indent--;
|
||||
implementation.WriteLine ("}");
|
||||
if (HasClass (t.BaseType))
|
||||
|
@ -505,7 +525,8 @@ namespace Embeddinator.ObjC {
|
|||
case TypeCode.UInt16:
|
||||
case TypeCode.UInt32:
|
||||
case TypeCode.UInt64:
|
||||
var ctype = NameGenerator.GetTypeName (t);
|
||||
var ut = t.IsEnum ? t.GetEnumUnderlyingType () : t;
|
||||
var ctype = NameGenerator.GetTypeName (ut);
|
||||
string ctypep;
|
||||
if (typecode == TypeCode.SByte)
|
||||
ctypep = "Char"; // GetTypeName returns signed char
|
||||
|
@ -518,6 +539,10 @@ namespace Embeddinator.ObjC {
|
|||
postwriter.WriteLine ($"MonoDecimal {presarrval} = mono_array_get ({presarr}, MonoDecimal, {pindex});");
|
||||
postwriter.WriteLine ($"{presobj} = mono_embeddinator_get_nsdecimalnumber (&{presarrval});");
|
||||
break;
|
||||
case TypeCode.DateTime:
|
||||
postwriter.WriteLine ($"E4KDateTime {presarrval} = mono_array_get ({presarr}, E4KDateTime, {pindex});");
|
||||
postwriter.WriteLine ($"{presobj} = mono_embeddinator_get_nsdate (&{presarrval});");
|
||||
break;
|
||||
case TypeCode.Byte:
|
||||
postwriter.WriteLine ($"NSData* {presobj} = [NSData dataWithBytes:mono_array_addr ({presarr}, unsigned char, 0) length:{parrlength}];");
|
||||
break;
|
||||
|
@ -540,7 +565,7 @@ namespace Embeddinator.ObjC {
|
|||
postwriter.WriteLine ($"if ({presarrval}) {{");
|
||||
postwriter.Indent++;
|
||||
postwriter.WriteLine ($"{tname}* {ptemp} = [[{tname} alloc] initForSuper];");
|
||||
postwriter.WriteLine ($"{ptemp}->_object = mono_embeddinator_create_object ({presarrval});");
|
||||
postwriter.WriteLine ($"{ptemp}->_object = (MonoEmbedObject *)mono_embeddinator_create_object ({presarrval});");
|
||||
postwriter.WriteLine ($"{presobj} = {ptemp};");
|
||||
postwriter.Indent--;
|
||||
postwriter.WriteLine ("} else");
|
||||
|
@ -614,10 +639,12 @@ namespace Embeddinator.ObjC {
|
|||
case TypeCode.Double:
|
||||
var typeName = NameGenerator.GetTypeName (type);
|
||||
string returnValue;
|
||||
if (typeCode == TypeCode.SByte)
|
||||
if (typeCode == TypeCode.SByte) {
|
||||
returnValue = $"charValue"; // GetTypeName returns signed char
|
||||
else
|
||||
returnValue = $"{typeName.CamelCase (true)}Value";
|
||||
} else {
|
||||
string returnValueTypeName = type.IsEnum ? NameGenerator.GetTypeName (type.GetEnumUnderlyingType ()) : typeName;
|
||||
returnValue = $"{returnValueTypeName.CamelCase (true)}Value";
|
||||
}
|
||||
|
||||
implementation.WriteLine ($"NSNumber* {pnameRet} = {(is_by_ref ? $"(*{parameterName})" : parameterName)}[{pnameIdx}];");
|
||||
implementation.WriteLine ($"if (!{pnameRet} || [{pnameRet} isKindOfClass:[NSNull class]])");
|
||||
|
@ -635,6 +662,15 @@ namespace Embeddinator.ObjC {
|
|||
implementation.Indent--;
|
||||
implementation.WriteLine ($"mono_array_set ({pnameArr}, MonoDecimal, {pnameIdx}, mono_embeddinator_get_system_decimal ({pnameRet}, &__mono_context));");
|
||||
break;
|
||||
case TypeCode.DateTime:
|
||||
var dtparname = is_by_ref ? $"(*{parameterName})" : parameterName;
|
||||
implementation.WriteLine ($"NSDate* {pnameRet} = {dtparname}[{pnameIdx}];");
|
||||
implementation.WriteLine ($"if (!{pnameRet} || [{pnameRet} isKindOfClass:[NSNull class]])");
|
||||
implementation.Indent++;
|
||||
implementation.WriteLine ($"continue;");
|
||||
implementation.Indent--;
|
||||
implementation.WriteLine ($"mono_array_set ({pnameArr}, E4KDateTime, {pnameIdx}, mono_embeddinator_get_system_datetime ({pnameRet}, &__mono_context));");
|
||||
break;
|
||||
case TypeCode.String:
|
||||
implementation.WriteLine ($"NSString* {pnameRet} = {(is_by_ref ? $"(*{parameterName})" : parameterName)}[{pnameIdx}];");
|
||||
implementation.WriteLine ($"if (!{pnameRet} || [{pnameRet} isKindOfClass:[NSNull class]])");
|
||||
|
@ -706,17 +742,23 @@ namespace Embeddinator.ObjC {
|
|||
switch (Type.GetTypeCode (t)) {
|
||||
case TypeCode.String:
|
||||
if (is_by_ref) {
|
||||
implementation.WriteLine ($"MonoString* __string = *{paramaterName} ? mono_string_new (__mono_context.domain, [*{paramaterName} UTF8String]) : nil;");
|
||||
implementation.WriteLine ($"{argumentName} = &__string;");
|
||||
post.AppendLine ($"*{paramaterName} = mono_embeddinator_get_nsstring (__string);");
|
||||
implementation.WriteLine ($"MonoString* __string_{paramaterName} = *{paramaterName} ? mono_string_new (__mono_context.domain, [*{paramaterName} UTF8String]) : nil;");
|
||||
implementation.WriteLine ($"{argumentName} = &__string_{paramaterName};");
|
||||
post.AppendLine ($"*{paramaterName} = mono_embeddinator_get_nsstring (__string_{paramaterName});");
|
||||
} else
|
||||
implementation.WriteLine ($"{argumentName} = {paramaterName} ? mono_string_new (__mono_context.domain, [{paramaterName} UTF8String]) : nil;");
|
||||
break;
|
||||
case TypeCode.Decimal:
|
||||
implementation.WriteLine ($"MonoDecimal __mdec = mono_embeddinator_get_system_decimal ({(is_by_ref ? "*" : string.Empty)}{paramaterName}, &__mono_context);");
|
||||
implementation.WriteLine ($"{argumentName} = &__mdec;");
|
||||
implementation.WriteLine ($"MonoDecimal __mdec_{paramaterName} = mono_embeddinator_get_system_decimal ({(is_by_ref ? "*" : string.Empty)}{paramaterName}, &__mono_context);");
|
||||
implementation.WriteLine ($"{argumentName} = &__mdec_{paramaterName};");
|
||||
if (is_by_ref)
|
||||
post.AppendLine ($"*{paramaterName} = mono_embeddinator_get_nsdecimalnumber (&__mdec);");
|
||||
post.AppendLine ($"*{paramaterName} = mono_embeddinator_get_nsdecimalnumber (&__mdec_{paramaterName});");
|
||||
break;
|
||||
case TypeCode.DateTime:
|
||||
implementation.WriteLine ($"E4KDateTime __mdatetime_{paramaterName} = mono_embeddinator_get_system_datetime ({(is_by_ref ? "*" : string.Empty)}{paramaterName}, &__mono_context);");
|
||||
implementation.WriteLine ($"{argumentName} = &__mdatetime_{paramaterName};");
|
||||
if (is_by_ref)
|
||||
post.AppendLine ($"*{paramaterName} = mono_embeddinator_get_nsdate (&__mdatetime_{paramaterName});");
|
||||
break;
|
||||
case TypeCode.Boolean:
|
||||
case TypeCode.Char:
|
||||
|
@ -751,37 +793,40 @@ namespace Embeddinator.ObjC {
|
|||
|
||||
protected override void Generate (ProcessedProperty property)
|
||||
{
|
||||
PropertyInfo pi = property.Property;
|
||||
var getter = pi.GetGetMethod ();
|
||||
var setter = pi.GetSetMethod ();
|
||||
Logger.Log ($"Generating Property: {property.Name}");
|
||||
|
||||
var getter = property.GetMethod;
|
||||
var setter = property.SetMethod;
|
||||
// setter-only properties are handled as methods (and should not reach this code)
|
||||
if (getter == null && setter != null)
|
||||
throw new EmbeddinatorException (99, "Internal error `setter only`. Please file a bug report with a test case (https://github.com/mono/Embeddinator-4000/issues");
|
||||
|
||||
var name = pi.Name.CamelCase ();
|
||||
|
||||
headers.Write ("@property (nonatomic");
|
||||
if (getter.IsStatic)
|
||||
if (getter.Method.IsStatic)
|
||||
headers.Write (", class");
|
||||
if (setter == null)
|
||||
headers.Write (", readonly");
|
||||
var pt = pi.PropertyType;
|
||||
var pt = property.Property.PropertyType;
|
||||
var property_type = NameGenerator.GetTypeName (pt);
|
||||
if (pt.IsInterface)
|
||||
property_type = $"id<{property_type}>";
|
||||
if (HasClass (pt))
|
||||
property_type += " *";
|
||||
|
||||
var spacing = property_type [property_type.Length - 1] == '*' ? string.Empty : " ";
|
||||
headers.WriteLine ($") {property_type}{spacing}{name};");
|
||||
headers.WriteLine ($") {property_type}{spacing}{property.Name};");
|
||||
|
||||
ImplementMethod (getter, name, property.GetMethod, pi: pi);
|
||||
ImplementMethod (property.GetMethod);
|
||||
if (setter == null)
|
||||
return;
|
||||
|
||||
ImplementMethod (setter, "set" + pi.Name, property.SetMethod, pi: pi);
|
||||
ImplementMethod (property.SetMethod);
|
||||
}
|
||||
|
||||
protected void Generate (ProcessedFieldInfo field)
|
||||
{
|
||||
Logger.Log ($"Generating Field: {field.Name}");
|
||||
|
||||
FieldInfo fi = field.Field;
|
||||
bool read_only = fi.IsInitOnly || fi.IsLiteral;
|
||||
|
||||
|
@ -799,10 +844,9 @@ namespace Embeddinator.ObjC {
|
|||
if (bound)
|
||||
field_type += " *";
|
||||
|
||||
var name = fi.Name.CamelCase ();
|
||||
|
||||
var spacing = field_type [field_type.Length - 1] == '*' ? string.Empty : " ";
|
||||
headers.WriteLine ($") {field_type}{spacing}{name};");
|
||||
headers.WriteLine ($") {field_type}{spacing}{field.Name};");
|
||||
|
||||
// it's similar, but different from implementing a method
|
||||
|
||||
|
@ -811,7 +855,7 @@ namespace Embeddinator.ObjC {
|
|||
var return_type = GetReturnType (type, fi.FieldType);
|
||||
|
||||
implementation.Write (fi.IsStatic ? '+' : '-');
|
||||
implementation.WriteLine ($" ({return_type}) {name}");
|
||||
implementation.WriteLine ($" ({return_type}) {field.GetterName}");
|
||||
implementation.WriteLine ("{");
|
||||
implementation.Indent++;
|
||||
implementation.WriteLine ("static MonoClassField* __field = nil;");
|
||||
|
@ -845,7 +889,7 @@ namespace Embeddinator.ObjC {
|
|||
if (read_only)
|
||||
return;
|
||||
implementation.Write (fi.IsStatic ? '+' : '-');
|
||||
implementation.WriteLine ($" (void) set{fi.Name}:({field_type})value");
|
||||
implementation.WriteLine ($" (void) {field.SetterName}:({field_type})value");
|
||||
implementation.WriteLine ("{");
|
||||
implementation.Indent++;
|
||||
implementation.WriteLine ("static MonoClassField* __field = nil;");
|
||||
|
@ -888,30 +932,32 @@ namespace Embeddinator.ObjC {
|
|||
}
|
||||
|
||||
// TODO override with attribute ? e.g. [ObjC.Selector ("foo")]
|
||||
// HACK - This should take a ProcessedMethod and not much of this stuff - https://github.com/mono/Embeddinator-4000/issues/276
|
||||
string ImplementMethod (MethodInfo info, string name, ProcessedMethod method, bool isExtension = false, PropertyInfo pi = null)
|
||||
string ImplementMethod (ProcessedMethod method)
|
||||
{
|
||||
Logger.Log ($"Generating Method Impl: {method}");
|
||||
|
||||
MethodInfo info = method.Method;
|
||||
|
||||
var type = info.DeclaringType;
|
||||
var managed_type_name = NameGenerator.GetObjCName (type);
|
||||
|
||||
string objcsig = method.GetObjcSignature (name, isExtension);
|
||||
string monosig = method.GetMonoSignature (info.Name);
|
||||
|
||||
string objcsig = method.ObjCSignature;
|
||||
|
||||
var builder = new MethodHelper (headers, implementation) {
|
||||
AssemblySafeName = type.Assembly.GetName ().Name.Sanitize (),
|
||||
IsStatic = info.IsStatic,
|
||||
IsExtension = isExtension,
|
||||
IsExtension = method.IsExtension,
|
||||
ReturnType = GetReturnType (type, info.ReturnType),
|
||||
ManagedTypeName = type.FullName,
|
||||
MetadataToken = info.MetadataToken,
|
||||
MonoSignature = monosig,
|
||||
MonoSignature = method.MonoSignature,
|
||||
ObjCSignature = objcsig,
|
||||
ObjCTypeName = managed_type_name,
|
||||
IsValueType = type.IsValueType,
|
||||
IsVirtual = info.IsVirtual && !info.IsFinal,
|
||||
};
|
||||
|
||||
if (pi == null)
|
||||
if (!method.IsPropertyImplementation)
|
||||
builder.WriteHeaders ();
|
||||
|
||||
builder.BeginImplementation ();
|
||||
|
@ -921,7 +967,7 @@ namespace Embeddinator.ObjC {
|
|||
string postInvoke = String.Empty;
|
||||
var args = "nil";
|
||||
if (parametersInfo.Length > 0) {
|
||||
Generate (parametersInfo, isExtension, out postInvoke);
|
||||
Generate (parametersInfo, method.IsExtension, out postInvoke);
|
||||
args = "__args";
|
||||
}
|
||||
|
||||
|
@ -936,6 +982,8 @@ namespace Embeddinator.ObjC {
|
|||
|
||||
void GenerateDefaultValuesWrapper (ProcessedMemberWithParameters member)
|
||||
{
|
||||
Logger.Log ($"Generating Default Value Wrapper: {member.ObjCSelector}");
|
||||
|
||||
ProcessedMethod method = member as ProcessedMethod;
|
||||
ProcessedConstructor ctor = member as ProcessedConstructor;
|
||||
if (method == null && ctor == null)
|
||||
|
@ -963,9 +1011,8 @@ namespace Embeddinator.ObjC {
|
|||
}
|
||||
}
|
||||
|
||||
string name = method != null ? method.BaseName : ctor.ObjCName;
|
||||
string objcsig = method != null ? method.GetObjcSignature () : ctor.GetObjcSignature ();
|
||||
string monosig = method != null ? method.GetMonoSignature () : ctor.GetMonoSignature ();
|
||||
string name = member.BaseName;
|
||||
string objcsig = member.ObjCSignature;
|
||||
|
||||
var type = mb.DeclaringType;
|
||||
|
||||
|
@ -998,6 +1045,8 @@ namespace Embeddinator.ObjC {
|
|||
|
||||
protected override void Generate (ProcessedMethod method)
|
||||
{
|
||||
Logger.Log ($"Generating Method: {method}");
|
||||
|
||||
MethodHelper builder;
|
||||
switch (method.MethodType) {
|
||||
case MethodType.DefaultValueWrapper:
|
||||
|
@ -1013,7 +1062,7 @@ namespace Embeddinator.ObjC {
|
|||
builder = new EquatableHelper (method, headers, implementation);
|
||||
break;
|
||||
default:
|
||||
ImplementMethod (method.Method, method.BaseName, method);
|
||||
ImplementMethod (method);
|
||||
return;
|
||||
}
|
||||
builder.WriteHeaders ();
|
||||
|
@ -1051,7 +1100,8 @@ namespace Embeddinator.ObjC {
|
|||
case TypeCode.UInt16:
|
||||
case TypeCode.UInt32:
|
||||
case TypeCode.UInt64:
|
||||
var ctype = NameGenerator.GetTypeName (t);
|
||||
var dt = t.IsEnum ? t.GetEnumUnderlyingType () : t;
|
||||
var ctype = NameGenerator.GetTypeName (dt);
|
||||
string ctypep;
|
||||
if (typecode == TypeCode.SByte)
|
||||
ctypep = "Char"; // GetTypeName returns signed char
|
||||
|
@ -1064,6 +1114,10 @@ namespace Embeddinator.ObjC {
|
|||
implementation.WriteLine ($"MonoDecimal __resarrval = mono_array_get (__resarr, MonoDecimal, __residx);");
|
||||
implementation.WriteLine ($"__resobj = mono_embeddinator_get_nsdecimalnumber (&__resarrval);");
|
||||
break;
|
||||
case TypeCode.DateTime:
|
||||
implementation.WriteLine ($"E4KDateTime __resarrval = mono_array_get (__resarr, E4KDateTime, __residx);");
|
||||
implementation.WriteLine ($"__resobj = mono_embeddinator_get_nsdate (&__resarrval);");
|
||||
break;
|
||||
case TypeCode.Byte:
|
||||
implementation.WriteLine ("NSData* __resobj = [NSData dataWithBytes:mono_array_addr (__resarr, unsigned char, 0) length:__resarrlength];");
|
||||
break;
|
||||
|
@ -1086,7 +1140,7 @@ namespace Embeddinator.ObjC {
|
|||
implementation.WriteLine ("if (__resarrval) {");
|
||||
implementation.Indent++;
|
||||
implementation.WriteLine ($"{tname}* __tmpobj = [[{tname} alloc] initForSuper];");
|
||||
implementation.WriteLine ("__tmpobj->_object = mono_embeddinator_create_object (__resarrval);");
|
||||
implementation.WriteLine ("__tmpobj->_object = (MonoEmbedObject *)mono_embeddinator_create_object (__resarrval);");
|
||||
implementation.WriteLine ("__resobj = __tmpobj;");
|
||||
implementation.Indent--;
|
||||
implementation.WriteLine ("} else");
|
||||
|
@ -1129,6 +1183,10 @@ namespace Embeddinator.ObjC {
|
|||
implementation.WriteLine ("void* __unboxedresult = mono_object_unbox (__result);");
|
||||
implementation.WriteLine ("return mono_embeddinator_get_nsdecimalnumber (__unboxedresult);");
|
||||
break;
|
||||
case TypeCode.DateTime:
|
||||
implementation.WriteLine ("void* __unboxedresult = mono_object_unbox (__result);");
|
||||
implementation.WriteLine ("return mono_embeddinator_get_nsdate ((E4KDateTime *)__unboxedresult);");
|
||||
break;
|
||||
case TypeCode.Boolean:
|
||||
case TypeCode.Char:
|
||||
case TypeCode.SByte:
|
||||
|
@ -1160,7 +1218,7 @@ namespace Embeddinator.ObjC {
|
|||
if (HasProtocol (t))
|
||||
tname = "__" + tname + "Wrapper";
|
||||
implementation.WriteLine ($"{tname}* __peer = [[{tname} alloc] initForSuper];");
|
||||
implementation.WriteLine ("__peer->_object = mono_embeddinator_create_object (__result);");
|
||||
implementation.WriteLine ("__peer->_object = (MonoEmbedObject *)mono_embeddinator_create_object (__result);");
|
||||
implementation.WriteLine ("return __peer;");
|
||||
break;
|
||||
default:
|
||||
|
@ -1249,6 +1307,8 @@ namespace Embeddinator.ObjC {
|
|||
return string.Format (arrayCreator, $"{NameGenerator.GetObjCName (type)}_class");
|
||||
case TypeCode.Decimal:
|
||||
return string.Format (arrayCreator, "mono_embeddinator_get_decimal_class ()");
|
||||
case TypeCode.DateTime:
|
||||
return string.Format (arrayCreator, "mono_embeddinator_get_datetime_class ()");
|
||||
default:
|
||||
throw new NotImplementedException ($"Converting type {type.FullName} to mono class");
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ namespace Embeddinator.ObjC {
|
|||
ProcessedType system_iformatprovider;
|
||||
ProcessedType system_timespan;
|
||||
ProcessedType system_globalization_timespanstyles;
|
||||
ProcessedType system_datetime;
|
||||
|
||||
ProcessedAssembly GetMscorlib (Type t)
|
||||
{
|
||||
|
@ -62,13 +63,46 @@ namespace Embeddinator.ObjC {
|
|||
var string_type = corlib.Assembly.GetType ("System.String");
|
||||
var iformatprovider_type = corlib.Assembly.GetType ("System.IFormatProvider");
|
||||
var parse = t.GetMethod ("Parse", new Type [] { string_type, iformatprovider_type });
|
||||
system_decimal.Methods.Add (new ProcessedMethod (parse, this));
|
||||
system_decimal.Methods.Add (new ProcessedMethod (parse, this, system_decimal));
|
||||
var tostring = t.GetMethod ("ToString", new Type [] { iformatprovider_type });
|
||||
system_decimal.Methods.Add (new ProcessedMethod (tostring, this));
|
||||
system_decimal.Methods.Add (new ProcessedMethod (tostring, this, system_decimal));
|
||||
AddExtraType (system_decimal);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AddDateTimeSupport (Type t)
|
||||
{
|
||||
if (system_datetime != null)
|
||||
return true;
|
||||
|
||||
var corlib = GetMscorlib (t);
|
||||
system_datetime = new ProcessedType (t) {
|
||||
Assembly = corlib,
|
||||
// this is tracked because the linker (if enabled) needs to be aware of the requirement
|
||||
// but we do not want any code to be generated (it's referenced only from native/glue code)
|
||||
IsNativeReference = true,
|
||||
Methods = new List<ProcessedMethod> (),
|
||||
Properties = new List<ProcessedProperty> (),
|
||||
Constructors = new List<ProcessedConstructor> (),
|
||||
};
|
||||
var ticks = t.GetProperty ("Ticks");
|
||||
system_datetime.Properties.Add (new ProcessedProperty (ticks, this, system_datetime));
|
||||
|
||||
var kind = t.GetProperty ("Kind");
|
||||
system_datetime.Properties.Add (new ProcessedProperty (kind, this, system_datetime));
|
||||
|
||||
var dtk = corlib.Assembly.GetType ("System.DateTimeKind");
|
||||
var longT = corlib.Assembly.GetType ("System.Int64");
|
||||
var ctorLongKind = t.GetConstructor (new Type [] { longT, dtk });
|
||||
system_datetime.Constructors.Add (new ProcessedConstructor (ctorLongKind, this, system_datetime));
|
||||
|
||||
var toUniversalTime = t.GetMethod ("ToUniversalTime");
|
||||
system_datetime.Methods.Add (new ProcessedMethod (toUniversalTime, this, system_datetime));
|
||||
|
||||
AddExtraType (system_datetime);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsSupported (Type t)
|
||||
{
|
||||
if (t.IsByRef)
|
||||
|
@ -102,12 +136,10 @@ namespace Embeddinator.ObjC {
|
|||
Delayed.Add (ErrorHelper.CreateWarning (1011, $"Type `{t}` is not generated because it lacks a native counterpart."));
|
||||
unsupported.Add (t);
|
||||
return false;
|
||||
case "DateTime": // FIXME: NSDateTime
|
||||
Delayed.Add (ErrorHelper.CreateWarning (1012, $"Type `{t}` is not generated because it lacks a marshaling code with a native counterpart."));
|
||||
unsupported.Add (t);
|
||||
return false;
|
||||
case "Decimal":
|
||||
return AddDecimalSupport (t);
|
||||
case "DateTime":
|
||||
return AddDateTimeSupport (t);
|
||||
case "TimeSpan":
|
||||
if (system_timespan == null) {
|
||||
system_timespan = new ProcessedType (t) {
|
||||
|
@ -160,8 +192,10 @@ namespace Embeddinator.ObjC {
|
|||
}
|
||||
}
|
||||
|
||||
protected IEnumerable<ConstructorInfo> GetConstructors (Type t)
|
||||
protected IEnumerable<ProcessedConstructor> GetConstructors (ProcessedType processedType)
|
||||
{
|
||||
Type t = processedType.Type;
|
||||
|
||||
foreach (var ctor in t.GetConstructors ()) {
|
||||
// .cctor not to be called directly by native code
|
||||
if (ctor.IsStatic)
|
||||
|
@ -182,7 +216,7 @@ namespace Embeddinator.ObjC {
|
|||
if (!pcheck)
|
||||
continue;
|
||||
|
||||
yield return ctor;
|
||||
yield return new ProcessedConstructor (ctor, this, processedType);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -215,7 +249,7 @@ namespace Embeddinator.ObjC {
|
|||
}
|
||||
|
||||
if (mi.Match ("System.Boolean", "Equals", "System.Object")) {
|
||||
yield return new ProcessedMethod (mi, this) {
|
||||
yield return new ProcessedMethod (mi, this, type) {
|
||||
DeclaringType = type,
|
||||
MethodType = MethodType.NSObjectProcotolIsEqual,
|
||||
};
|
||||
|
@ -223,7 +257,7 @@ namespace Embeddinator.ObjC {
|
|||
}
|
||||
|
||||
if (implement_system_iequatable_t && mi.Match ("System.Boolean", "Equals", new string [] { null })) {
|
||||
yield return new ProcessedMethod (mi, this) {
|
||||
yield return new ProcessedMethod (mi, this, type) {
|
||||
DeclaringType = type,
|
||||
MethodType = MethodType.IEquatable,
|
||||
};
|
||||
|
@ -231,7 +265,7 @@ namespace Embeddinator.ObjC {
|
|||
}
|
||||
|
||||
if (mi.Match ("System.Int32", "GetHashCode")) {
|
||||
yield return new ProcessedMethod (mi, this) {
|
||||
yield return new ProcessedMethod (mi, this, type) {
|
||||
DeclaringType = type,
|
||||
MethodType = MethodType.NSObjectProcotolHash,
|
||||
};
|
||||
|
@ -273,12 +307,12 @@ namespace Embeddinator.ObjC {
|
|||
extmethods = new List<ProcessedMethod> ();
|
||||
extensions.Add (extended_type, extmethods);
|
||||
}
|
||||
extmethods.Add (new ProcessedMethod (mi, this));
|
||||
extmethods.Add (new ProcessedMethod (mi, this, type) { IsExtension = true } );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
yield return new ProcessedMethod (mi, this);
|
||||
yield return new ProcessedMethod (mi, this, type);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -294,9 +328,9 @@ namespace Embeddinator.ObjC {
|
|||
}
|
||||
}
|
||||
|
||||
protected IEnumerable<FieldInfo> GetFields (Type t)
|
||||
protected IEnumerable<ProcessedFieldInfo> GetFields (ProcessedType t)
|
||||
{
|
||||
foreach (var fi in t.GetFields (BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly)) {
|
||||
foreach (var fi in t.Type.GetFields (BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly)) {
|
||||
if (!fi.IsPublic)
|
||||
continue;
|
||||
var ft = fi.FieldType;
|
||||
|
@ -304,7 +338,7 @@ namespace Embeddinator.ObjC {
|
|||
Delayed.Add (ErrorHelper.CreateWarning (1050, $"Field `{fi}` is not generated because of field type `{ft}` is not supported."));
|
||||
continue;
|
||||
}
|
||||
yield return fi;
|
||||
yield return new ProcessedFieldInfo (fi, this, t);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -317,7 +351,7 @@ namespace Embeddinator.ObjC {
|
|||
bool extension_type;
|
||||
|
||||
|
||||
public override void Process (IEnumerable<Assembly> input)
|
||||
public override void Process (IEnumerable<ProcessedAssembly> input)
|
||||
{
|
||||
base.Process (input);
|
||||
|
||||
|
@ -327,7 +361,7 @@ namespace Embeddinator.ObjC {
|
|||
// proceed with extra adjustments before giving results to the generator
|
||||
foreach (var t in Types) {
|
||||
foreach (var uctor in GetUnavailableParentCtors (t)) {
|
||||
var c = new ProcessedConstructor (uctor.Constructor, this) { Unavailable = true };
|
||||
var c = new ProcessedConstructor (uctor.Constructor, this, t) { Unavailable = true };
|
||||
t.Constructors.Add (c);
|
||||
}
|
||||
}
|
||||
|
@ -337,7 +371,7 @@ namespace Embeddinator.ObjC {
|
|||
var pt = GetProcessedType (dv.DeclaringType);
|
||||
var ci = dv as ConstructorInfo;
|
||||
if (ci != null) {
|
||||
foreach (var pc in AddDefaultValuesWrappers (ci)) {
|
||||
foreach (var pc in AddDefaultValuesWrappers (ci, pt)) {
|
||||
if (!pt.SignatureExists (pc))
|
||||
pt.Constructors.Add (pc);
|
||||
else
|
||||
|
@ -346,7 +380,7 @@ namespace Embeddinator.ObjC {
|
|||
continue;
|
||||
}
|
||||
var mi = dv as MethodInfo;
|
||||
foreach (var pm in AddDefaultValuesWrappers (mi)) {
|
||||
foreach (var pm in AddDefaultValuesWrappers (mi, pt)) {
|
||||
if (!pt.SignatureExists (pm))
|
||||
pt.Methods.Add (pm);
|
||||
else
|
||||
|
@ -359,6 +393,7 @@ namespace Embeddinator.ObjC {
|
|||
|
||||
public override void Process (ProcessedType pt)
|
||||
{
|
||||
Logger.Log ($"Processing Type: {pt.TypeName}");
|
||||
Types.Add (pt);
|
||||
if (pt.IsNativeReference)
|
||||
return;
|
||||
|
@ -373,7 +408,7 @@ namespace Embeddinator.ObjC {
|
|||
implement_system_icomparable_t = t.Implements("System", "IComparable`1");
|
||||
implement_system_iequatable_t = t.Implements ("System", "IEquatable`1");
|
||||
|
||||
var constructors = GetConstructors (t).OrderBy ((arg) => arg.GetParameters ().Length).ToList ();
|
||||
var constructors = GetConstructors (pt).OrderBy ((arg) => arg.Constructor.GetParameters ().Length).ToList ();
|
||||
var processedConstructors = PostProcessConstructors (constructors).ToList ();
|
||||
pt.Constructors = processedConstructors;
|
||||
|
||||
|
@ -381,8 +416,8 @@ namespace Embeddinator.ObjC {
|
|||
var processedMethods = PostProcessMethods (meths).ToList ();
|
||||
pt.Methods = processedMethods;
|
||||
|
||||
var props = new List<PropertyInfo> ();
|
||||
var subscriptProps = new List<PropertyInfo> ();
|
||||
var props = new List<ProcessedProperty> ();
|
||||
var subscriptProps = new List<ProcessedProperty> ();
|
||||
foreach (var pi in GetProperties (t)) {
|
||||
var getter = pi.GetGetMethod ();
|
||||
var setter = pi.GetSetMethod ();
|
||||
|
@ -392,14 +427,14 @@ namespace Embeddinator.ObjC {
|
|||
|
||||
// indexers are implemented as methods and object subscripting
|
||||
if ((getter.GetParameters ().Length > 0) || ((setter != null) && setter.GetParameters ().Length > 1)) {
|
||||
subscriptProps.Add (pi);
|
||||
subscriptProps.Add (new ProcessedProperty (pi, this, pt));
|
||||
continue;
|
||||
}
|
||||
|
||||
// we can do better than methods for the more common cases (readonly and readwrite)
|
||||
processedMethods.RemoveAll (x => x.Method == getter);
|
||||
processedMethods.RemoveAll (x => x.Method == setter);
|
||||
props.Add (pi);
|
||||
props.Add (new ProcessedProperty (pi, this, pt));
|
||||
}
|
||||
props = props.OrderBy ((arg) => arg.Name).ToList ();
|
||||
var processedProperties = PostProcessProperties (props).ToList ();
|
||||
|
@ -413,7 +448,7 @@ namespace Embeddinator.ObjC {
|
|||
}
|
||||
|
||||
// fields will need to be wrapped within properties
|
||||
var f = GetFields (t).OrderBy ((arg) => arg.Name).ToList ();
|
||||
var f = GetFields (pt).OrderBy ((arg) => arg.Name).ToList ();
|
||||
var processedFields = PostProcessFields (f).ToList ();
|
||||
pt.Fields = processedFields;
|
||||
}
|
||||
|
@ -449,14 +484,14 @@ namespace Embeddinator.ObjC {
|
|||
return finalList;
|
||||
}
|
||||
|
||||
IEnumerable<ProcessedConstructor> AddDefaultValuesWrappers (ConstructorInfo ci)
|
||||
IEnumerable<ProcessedConstructor> AddDefaultValuesWrappers (ConstructorInfo ci, ProcessedType containingType)
|
||||
{
|
||||
// parameters with default values must be at the end and there can be many of them
|
||||
var parameters = ci.GetParameters ();
|
||||
for (int i = parameters.Length - 1; i >= 0; i--) {
|
||||
if (!parameters [i].HasDefaultValue)
|
||||
continue;
|
||||
var pc = new ProcessedConstructor (ci, this) {
|
||||
var pc = new ProcessedConstructor (ci, this, containingType) {
|
||||
ConstructorType = ConstructorType.DefaultValueWrapper,
|
||||
FirstDefaultParameter = i,
|
||||
};
|
||||
|
@ -464,14 +499,14 @@ namespace Embeddinator.ObjC {
|
|||
}
|
||||
}
|
||||
|
||||
IEnumerable<ProcessedMethod> AddDefaultValuesWrappers (MethodInfo mi)
|
||||
IEnumerable<ProcessedMethod> AddDefaultValuesWrappers (MethodInfo mi, ProcessedType containingType)
|
||||
{
|
||||
// parameters with default values must be at the end and there can be many of them
|
||||
var parameters = mi.GetParameters ();
|
||||
for (int i = parameters.Length - 1; i >= 0; i--) {
|
||||
if (!parameters [i].HasDefaultValue)
|
||||
continue;
|
||||
var pm = new ProcessedMethod (mi, this) {
|
||||
var pm = new ProcessedMethod (mi, this, containingType) {
|
||||
MethodType = MethodType.DefaultValueWrapper,
|
||||
FirstDefaultParameter = i,
|
||||
};
|
||||
|
|
|
@ -112,12 +112,16 @@ namespace Embeddinator.ObjC {
|
|||
|
||||
protected Processor Processor;
|
||||
public bool FallBackToTypeName { get; set; }
|
||||
public ProcessedType DeclaringType { get; set; }
|
||||
|
||||
public ProcessedMemberBase (Processor processor)
|
||||
public ProcessedMemberBase (Processor processor, ProcessedType declaringType)
|
||||
{
|
||||
Processor = processor;
|
||||
DeclaringType = declaringType;
|
||||
}
|
||||
|
||||
public abstract IEnumerable<string> Selectors { get; }
|
||||
|
||||
// this format can be consumed by the linker xml files
|
||||
// adapted from ikvm reflection and cecil source code
|
||||
// FIXME: double check when we implement generics support
|
||||
|
@ -150,45 +154,60 @@ namespace Embeddinator.ObjC {
|
|||
}
|
||||
|
||||
public abstract class ProcessedMemberWithParameters : ProcessedMemberBase {
|
||||
public ProcessedMemberWithParameters (Processor processor) : base (processor)
|
||||
public ProcessedMemberWithParameters (Processor processor, ProcessedType declaringType) : base (processor, declaringType)
|
||||
{
|
||||
objCSignature = new CachedValue<string> (() => GetObjcSignature (true));
|
||||
objCSelector = new CachedValue<string> (() => GetObjcSignature (false));
|
||||
monoSignature = new CachedValue<string> (GetMonoSignature);
|
||||
}
|
||||
|
||||
public abstract string BaseName { get; }
|
||||
|
||||
public ParameterInfo[] Parameters { get; protected set; }
|
||||
public int FirstDefaultParameter { get; set; }
|
||||
|
||||
public string ObjCSignature { get; set; }
|
||||
public string MonoSignature { get; set; }
|
||||
protected abstract void ComputeSignatures ();
|
||||
protected abstract string GetObjcSignature (bool includeParamNames);
|
||||
|
||||
int firstDefaultParameter;
|
||||
public int FirstDefaultParameter {
|
||||
get {
|
||||
return firstDefaultParameter;
|
||||
}
|
||||
set {
|
||||
firstDefaultParameter = value;
|
||||
ComputeSignatures ();
|
||||
}
|
||||
public override IEnumerable<string> Selectors => ObjCSelector.Yield ();
|
||||
|
||||
CachedValue<string> objCSignature;
|
||||
public string ObjCSignature => objCSignature.Value;
|
||||
|
||||
CachedValue<string> objCSelector;
|
||||
public string ObjCSelector => objCSelector.Value;
|
||||
|
||||
protected abstract string GetMonoSignature ();
|
||||
CachedValue<string> monoSignature;
|
||||
public string MonoSignature => monoSignature.Value;
|
||||
|
||||
public void Freeze ()
|
||||
{
|
||||
objCSignature.Freeze ();
|
||||
objCSelector.Freeze ();
|
||||
monoSignature.Freeze ();
|
||||
}
|
||||
}
|
||||
|
||||
public class ProcessedMethod : ProcessedMemberWithParameters {
|
||||
public MethodInfo Method { get; private set; }
|
||||
public bool IsOperator { get; set; }
|
||||
public string NameOverride { get; set; }
|
||||
public bool IsPropertyImplementation { get; set; }
|
||||
|
||||
public string BaseName {
|
||||
public string NameOverride { get; set; }
|
||||
public string ManagedName { get; set; }
|
||||
|
||||
public override string BaseName {
|
||||
get {
|
||||
if (NameOverride != null)
|
||||
return NameOverride;
|
||||
return IsOperator? Method.Name.Substring (3).CamelCase () : Method.Name.CamelCase ();
|
||||
return IsOperator ? Method.Name.Substring (3).CamelCase () : Method.Name.CamelCase ();
|
||||
}
|
||||
}
|
||||
|
||||
public MethodType MethodType { get; set; }
|
||||
public ProcessedType DeclaringType { get; set; }
|
||||
public bool IsExtension { get; set; }
|
||||
|
||||
public ProcessedMethod (MethodInfo method, Processor processor) : base (processor)
|
||||
public ProcessedMethod (MethodInfo method, Processor processor, ProcessedType declaringType) : base (processor, declaringType)
|
||||
{
|
||||
Method = method;
|
||||
MethodType = MethodType.Normal;
|
||||
|
@ -196,20 +215,11 @@ namespace Embeddinator.ObjC {
|
|||
FirstDefaultParameter = -1;
|
||||
}
|
||||
|
||||
protected override void ComputeSignatures ()
|
||||
{
|
||||
ObjCSignature = GetObjcSignature ();
|
||||
MonoSignature = GetMonoSignature ();
|
||||
}
|
||||
|
||||
public override string ToString () => ToString (Method);
|
||||
|
||||
public string GetMonoSignature (string name = null)
|
||||
protected override string GetMonoSignature ()
|
||||
{
|
||||
if (name == null)
|
||||
name = BaseName;
|
||||
|
||||
var mono = new StringBuilder (name);
|
||||
var mono = new StringBuilder (Method.Name);
|
||||
|
||||
mono.Append ('(');
|
||||
|
||||
|
@ -225,10 +235,10 @@ namespace Embeddinator.ObjC {
|
|||
return mono.ToString ();
|
||||
}
|
||||
|
||||
public string GetObjcSignature (string objName = null, bool isExtension = false)
|
||||
protected override string GetObjcSignature (bool includeParamNames)
|
||||
{
|
||||
if (objName == null)
|
||||
objName = BaseName;
|
||||
string objName = BaseName;
|
||||
|
||||
if (Method.IsSpecialName)
|
||||
objName = objName.Replace ("_", String.Empty);
|
||||
|
||||
|
@ -238,11 +248,13 @@ namespace Embeddinator.ObjC {
|
|||
for (int n = 0; n < end; ++n) {
|
||||
ParameterInfo p = Parameters[n];
|
||||
|
||||
if (objc.Length > objName.Length)
|
||||
objc.Append (' ');
|
||||
if (includeParamNames) {
|
||||
if (objc.Length > objName.Length)
|
||||
objc.Append (' ');
|
||||
}
|
||||
|
||||
string paramName = FallBackToTypeName ? NameGenerator.GetParameterTypeName (p.ParameterType) : p.Name;
|
||||
if (n > 0 || !isExtension) {
|
||||
if (n > 0 || !IsExtension) {
|
||||
if (n == 0) {
|
||||
if (FallBackToTypeName || Method.IsConstructor || (!Method.IsSpecialName && !IsOperator))
|
||||
objc.Append (paramName.PascalCase ());
|
||||
|
@ -250,9 +262,13 @@ namespace Embeddinator.ObjC {
|
|||
objc.Append (paramName.CamelCase ());
|
||||
}
|
||||
|
||||
if (n > 0 || !isExtension) {
|
||||
string ptname = NameGenerator.GetObjCParamTypeName (p, Processor.Types);
|
||||
objc.Append (":(").Append (ptname).Append (")").Append (NameGenerator.GetExtendedParameterName (p, Parameters));
|
||||
if (includeParamNames) {
|
||||
if (n > 0 || !IsExtension) {
|
||||
string ptname = NameGenerator.GetObjCParamTypeName (p, Processor.Types);
|
||||
objc.Append (":(").Append (ptname).Append (")").Append (NameGenerator.GetExtendedParameterName (p, Parameters));
|
||||
}
|
||||
} else {
|
||||
objc.Append (":");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -263,25 +279,70 @@ namespace Embeddinator.ObjC {
|
|||
public class ProcessedProperty: ProcessedMemberBase {
|
||||
public PropertyInfo Property { get; private set; }
|
||||
|
||||
public ProcessedProperty (PropertyInfo property, Processor processor) : base (processor)
|
||||
public override IEnumerable<string> Selectors
|
||||
{
|
||||
get {
|
||||
if (HasGetter)
|
||||
yield return GetterName;
|
||||
if (HasSetter)
|
||||
yield return SetterName;
|
||||
}
|
||||
}
|
||||
|
||||
public ProcessedProperty (PropertyInfo property, Processor processor, ProcessedType declaringType) : base (processor, declaringType)
|
||||
{
|
||||
Property = property;
|
||||
|
||||
var g = Property.GetGetMethod ();
|
||||
if (g != null)
|
||||
GetMethod = new ProcessedMethod (g, Processor);
|
||||
|
||||
var s = Property.GetSetMethod ();
|
||||
if (s != null)
|
||||
SetMethod = new ProcessedMethod (s, Processor);
|
||||
getMethod = new CachedValue<ProcessedMethod> (() => {
|
||||
var getter = Property.GetGetMethod ();
|
||||
if (getter != null) {
|
||||
return new ProcessedMethod (getter, Processor, declaringType) { NameOverride = GetterName, IsPropertyImplementation = true };
|
||||
}
|
||||
return null;
|
||||
});
|
||||
setMethod = new CachedValue<ProcessedMethod> (() => {
|
||||
var setter = Property.GetSetMethod ();
|
||||
if (setter != null) {
|
||||
return new ProcessedMethod (setter, Processor, declaringType) { NameOverride = SetterName, IsPropertyImplementation = true };
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
public override string ToString () => Property.ToString ();
|
||||
|
||||
public bool HasGetter => GetMethod != null;
|
||||
public bool HasSetter => SetMethod != null;
|
||||
public ProcessedMethod GetMethod { get; private set; }
|
||||
public ProcessedMethod SetMethod { get; private set; }
|
||||
public string Name => NameOverride != null ? NameOverride : Property.Name.CamelCase ();
|
||||
public string NameOverride { get; set; }
|
||||
|
||||
public bool HasGetter => Property.GetGetMethod () != null;
|
||||
public bool HasSetter => Property.GetSetMethod () != null;
|
||||
|
||||
public string GetterName {
|
||||
get {
|
||||
if (!HasGetter)
|
||||
return null;
|
||||
return (NameOverride ?? Property.Name).CamelCase ();
|
||||
}
|
||||
}
|
||||
|
||||
public string SetterName {
|
||||
get {
|
||||
if (!HasSetter)
|
||||
return null;
|
||||
return "set" + (NameOverride ?? Property.Name).PascalCase ();
|
||||
}
|
||||
}
|
||||
|
||||
CachedValue<ProcessedMethod> getMethod;
|
||||
public ProcessedMethod GetMethod => getMethod.Value;
|
||||
|
||||
CachedValue<ProcessedMethod> setMethod;
|
||||
public ProcessedMethod SetMethod => setMethod.Value;
|
||||
|
||||
public void Freeze ()
|
||||
{
|
||||
getMethod.Freeze ();
|
||||
setMethod.Freeze ();
|
||||
}
|
||||
}
|
||||
|
||||
public enum ConstructorType {
|
||||
|
@ -294,7 +355,7 @@ namespace Embeddinator.ObjC {
|
|||
public ConstructorInfo Constructor { get; private set; }
|
||||
|
||||
public bool Unavailable { get; set; }
|
||||
public string ObjCName {
|
||||
public override string BaseName {
|
||||
get {
|
||||
if (Parameters.Length == 0 || FirstDefaultParameter == 0)
|
||||
return "init";
|
||||
|
@ -303,22 +364,16 @@ namespace Embeddinator.ObjC {
|
|||
}
|
||||
public ConstructorType ConstructorType { get; set; }
|
||||
|
||||
public ProcessedConstructor (ConstructorInfo constructor, Processor processor) : base (processor)
|
||||
public ProcessedConstructor (ConstructorInfo constructor, Processor processor, ProcessedType declaringType) : base (processor, declaringType)
|
||||
{
|
||||
Constructor = constructor;
|
||||
Parameters = Constructor.GetParameters ();
|
||||
FirstDefaultParameter = -1;
|
||||
}
|
||||
|
||||
protected override void ComputeSignatures ()
|
||||
{
|
||||
ObjCSignature = GetObjcSignature ();
|
||||
MonoSignature = GetMonoSignature ();
|
||||
}
|
||||
|
||||
public override string ToString () => ToString (Constructor);
|
||||
|
||||
public string GetMonoSignature ()
|
||||
protected override string GetMonoSignature ()
|
||||
{
|
||||
var mono = new StringBuilder (Constructor.Name);
|
||||
|
||||
|
@ -336,16 +391,18 @@ namespace Embeddinator.ObjC {
|
|||
return mono.ToString ();
|
||||
}
|
||||
|
||||
public string GetObjcSignature ()
|
||||
protected override string GetObjcSignature (bool includeParamNames)
|
||||
{
|
||||
var objc = new StringBuilder (ObjCName);
|
||||
var objc = new StringBuilder (BaseName);
|
||||
|
||||
var end = FirstDefaultParameter == -1 ? Parameters.Length : FirstDefaultParameter;
|
||||
for (int n = 0; n < end; ++n) {
|
||||
ParameterInfo p = Parameters[n];
|
||||
|
||||
if (objc.Length > ObjCName.Length)
|
||||
objc.Append (' ');
|
||||
if (includeParamNames) {
|
||||
if (objc.Length > BaseName.Length)
|
||||
objc.Append (' ');
|
||||
}
|
||||
|
||||
string paramName = FallBackToTypeName ? NameGenerator.GetParameterTypeName (p.ParameterType) : p.Name;
|
||||
if (n == 0)
|
||||
|
@ -353,8 +410,12 @@ namespace Embeddinator.ObjC {
|
|||
else
|
||||
objc.Append (paramName.CamelCase ());
|
||||
|
||||
string ptname = NameGenerator.GetObjCParamTypeName (p, Processor.Types);
|
||||
objc.Append (":(").Append (ptname).Append (")").Append (NameGenerator.GetExtendedParameterName (p, Parameters));
|
||||
if (includeParamNames) {
|
||||
string ptname = NameGenerator.GetObjCParamTypeName (p, Processor.Types);
|
||||
objc.Append (":(").Append (ptname).Append (")").Append (NameGenerator.GetExtendedParameterName (p, Parameters));
|
||||
} else {
|
||||
objc.Append (":");
|
||||
}
|
||||
}
|
||||
|
||||
return objc.ToString ();
|
||||
|
@ -366,7 +427,17 @@ namespace Embeddinator.ObjC {
|
|||
public string TypeName { get; private set; }
|
||||
public string ObjCName { get; private set; }
|
||||
|
||||
public ProcessedFieldInfo (FieldInfo field, Processor processor) : base (processor)
|
||||
public string Name => (NameOverride ?? Field.Name).CamelCase ();
|
||||
public string NameOverride { get; set; }
|
||||
|
||||
public override IEnumerable<string> Selectors {
|
||||
get {
|
||||
yield return GetterName;
|
||||
yield return SetterName;
|
||||
}
|
||||
}
|
||||
|
||||
public ProcessedFieldInfo (FieldInfo field, Processor processor, ProcessedType declaringType) : base (processor, declaringType)
|
||||
{
|
||||
Field = field;
|
||||
TypeName = ObjC.NameGenerator.GetTypeName (Field.DeclaringType);
|
||||
|
@ -375,5 +446,8 @@ namespace Embeddinator.ObjC {
|
|||
|
||||
// linker compatible signature
|
||||
public override string ToString () => Field.FieldType.FullName + " " + Field.Name;
|
||||
|
||||
public string GetterName => (NameOverride ?? Field.Name).CamelCase ();
|
||||
public string SetterName => "set" + (NameOverride ?? Field.Name).PascalCase ();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using IKVM.Reflection;
|
||||
using Type = IKVM.Reflection.Type;
|
||||
|
||||
|
@ -16,16 +17,15 @@ namespace Embeddinator.ObjC {
|
|||
|
||||
protected List<Exception> Delayed = new List<Exception> ();
|
||||
|
||||
public virtual void Process (IEnumerable<Assembly> input)
|
||||
public virtual void Process (IEnumerable<ProcessedAssembly> input)
|
||||
{
|
||||
Logger.Log ($"Processing: {input.Count ()} assemblies");
|
||||
|
||||
foreach (var a in input) {
|
||||
var pa = new ProcessedAssembly (a) {
|
||||
UserCode = true,
|
||||
};
|
||||
// ignoring/warning one is not an option as they could be different (e.g. different builds/versions)
|
||||
if (!AddIfUnique (pa))
|
||||
throw ErrorHelper.CreateError (12, $"The assembly name `{pa.Name}` is not unique");
|
||||
assemblyQueue.Enqueue (pa);
|
||||
if (!AddIfUnique (a))
|
||||
throw ErrorHelper.CreateError (12, $"The assembly name `{a.Name}` is not unique");
|
||||
assemblyQueue.Enqueue (a);
|
||||
}
|
||||
|
||||
while (assemblyQueue.Count > 0) {
|
||||
|
@ -41,6 +41,8 @@ namespace Embeddinator.ObjC {
|
|||
if (!a.UserCode)
|
||||
return;
|
||||
|
||||
Logger.Log ($"Processing Assembly: {a.Name}");
|
||||
|
||||
foreach (var t in GetTypes (a.Assembly)) {
|
||||
var pt = new ProcessedType (t) {
|
||||
Assembly = a,
|
||||
|
|
|
@ -12,6 +12,7 @@ while ! test -z $1; do
|
|||
PROVISION_MONO=1
|
||||
PROVISION_XI=1
|
||||
PROVISION_XM=1
|
||||
PROVISION_XCODE=1
|
||||
shift
|
||||
;;
|
||||
--provision-mono)
|
||||
|
@ -26,10 +27,15 @@ while ! test -z $1; do
|
|||
PROVISION_XM=1
|
||||
shift
|
||||
;;
|
||||
--provision-xcode)
|
||||
PROVISION_XCODE=1
|
||||
shift
|
||||
;;
|
||||
--provision-all)
|
||||
PROVISION_MONO=1
|
||||
PROVISION_XI=1
|
||||
PROVISION_XM=1
|
||||
PROVISION_XCODE=1
|
||||
shift
|
||||
;;
|
||||
--ignore-mono)
|
||||
|
@ -44,6 +50,10 @@ while ! test -z $1; do
|
|||
IGNORE_XM=1
|
||||
shift
|
||||
;;
|
||||
--ignore-xcode)
|
||||
IGNORE_XCODE=1
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
echo "Unknown argument: $1"
|
||||
exit 1
|
||||
|
@ -307,11 +317,39 @@ function check_xamarin_mac () {
|
|||
ok "Found Xamarin.Mac $ACTUAL_XM_VERSION (at least $MIN_XM_VERSION and not more than $MAX_XM_VERSION is required)"
|
||||
}
|
||||
|
||||
function check_xcode () {
|
||||
if ! test -z $IGNORE_XCODE; then return; fi
|
||||
|
||||
if ! test -f /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/Version; then
|
||||
if ! test -z $PROVISION_XI; then
|
||||
install_xamarin_ios
|
||||
else
|
||||
fail "You must install Xamarin.iOS"
|
||||
return
|
||||
fi
|
||||
fi
|
||||
local CURRENT_XCODE_PATH=$(xcode-select -p)
|
||||
local REQUESTED_XCODE=$(awk '/RecommendedXcodeVersion/{getline; print}' /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/Versions.plist | sed -e 's/<[^>]*>//g' | sed -e 's/\.//g' | xargs)
|
||||
local NEEDED_XCODE_PATH=/Applications/Xcode$REQUESTED_XCODE.app/Contents/Developer
|
||||
if test "$NEEDED_XCODE_PATH" != "$CURRENT_XCODE_PATH"; then
|
||||
if ! test -z $PROVISION_XCODE; then
|
||||
log "Setting selected xcode to $NEEDED_XCODE_PATH"
|
||||
sudo xcode-select -s $NEEDED_XCODE_PATH
|
||||
else
|
||||
fail "You must set xcode-select to $NEEDED_XCODE_PATH"
|
||||
return
|
||||
fi
|
||||
else
|
||||
ok "Found Xcode $CURRENT_XCODE_PATH selected already"
|
||||
fi
|
||||
}
|
||||
|
||||
echo "Checking system..."
|
||||
|
||||
check_mono
|
||||
check_xamarin_ios
|
||||
check_xamarin_mac
|
||||
check_xcode
|
||||
|
||||
if test -z $FAIL; then
|
||||
echo "System check succeeded"
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Embeddinator.ObjC
|
||||
{
|
||||
public static class Utils
|
||||
{
|
||||
public static bool RunProcess (string filename, string arguments, out int exitCode, out string stdout, bool capture_stderr = false)
|
||||
{
|
||||
Console.WriteLine ($"\t{filename} {arguments}");
|
||||
var sb = new StringBuilder ();
|
||||
var stdout_done = new System.Threading.ManualResetEvent (false);
|
||||
var stderr_done = new System.Threading.ManualResetEvent (false);
|
||||
using (var p = new Process ()) {
|
||||
p.StartInfo.FileName = filename;
|
||||
p.StartInfo.Arguments = arguments;
|
||||
p.StartInfo.UseShellExecute = false;
|
||||
p.StartInfo.RedirectStandardOutput = true;
|
||||
p.StartInfo.RedirectStandardError = capture_stderr;
|
||||
p.OutputDataReceived += (sender, e) => {
|
||||
if (e.Data == null) {
|
||||
stdout_done.Set ();
|
||||
}
|
||||
else {
|
||||
lock (sb)
|
||||
sb.AppendLine (e.Data);
|
||||
}
|
||||
};
|
||||
if (capture_stderr) {
|
||||
p.ErrorDataReceived += (sender, e) => {
|
||||
if (e.Data == null) {
|
||||
stderr_done.Set ();
|
||||
}
|
||||
else {
|
||||
lock (sb)
|
||||
sb.AppendLine (e.Data);
|
||||
}
|
||||
};
|
||||
}
|
||||
p.Start ();
|
||||
p.BeginOutputReadLine ();
|
||||
if (capture_stderr)
|
||||
p.BeginErrorReadLine ();
|
||||
p.WaitForExit ();
|
||||
stdout_done.WaitOne (TimeSpan.FromSeconds (1));
|
||||
if (capture_stderr)
|
||||
stderr_done.WaitOne (TimeSpan.FromSeconds (1));
|
||||
stdout = sb.ToString ();
|
||||
exitCode = p.ExitCode;
|
||||
return exitCode == 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static int RunProcess (string filename, string arguments)
|
||||
{
|
||||
int exitCode;
|
||||
string output;
|
||||
RunProcess (filename, arguments, out exitCode, out output, capture_stderr: true);
|
||||
if (exitCode != 0)
|
||||
Console.WriteLine (output);
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
public static bool RunProcess (string filename, string arguments, out int exitCode)
|
||||
{
|
||||
exitCode = RunProcess (filename, arguments);
|
||||
return exitCode == 0;
|
||||
}
|
||||
|
||||
public static bool Xcrun (StringBuilder options, out int exitCode)
|
||||
{
|
||||
return RunProcess ("xcrun", options.ToString (), out exitCode);
|
||||
}
|
||||
|
||||
public static bool Lipo (System.Collections.Generic.List<string> inputs, string output, out int exitCode)
|
||||
{
|
||||
Directory.CreateDirectory (Path.GetDirectoryName (output));
|
||||
if (inputs.Count == 1) {
|
||||
File.Copy (inputs[0], output, true);
|
||||
exitCode = 0;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
var lipo_options = new StringBuilder ("lipo ");
|
||||
foreach (var file in inputs)
|
||||
lipo_options.Append (file).Append (" ");
|
||||
lipo_options.Append ("-create -output ");
|
||||
lipo_options.Append (Quote (output));
|
||||
return Xcrun (lipo_options, out exitCode);
|
||||
}
|
||||
}
|
||||
|
||||
public static string Quote (string f)
|
||||
{
|
||||
if (f.IndexOf (' ') == -1 && f.IndexOf ('\'') == -1 && f.IndexOf (',') == -1 && f.IndexOf ('$') == -1)
|
||||
return f;
|
||||
|
||||
var s = new StringBuilder ();
|
||||
|
||||
s.Append ('"');
|
||||
foreach (var c in f) {
|
||||
if (c == '"' || c == '\\')
|
||||
s.Append ('\\');
|
||||
|
||||
s.Append (c);
|
||||
}
|
||||
s.Append ('"');
|
||||
|
||||
return s.ToString ();
|
||||
}
|
||||
|
||||
|
||||
// Mono.Unix can't create symlinks to relative paths, it insists on making the target a full path before creating the symlink.
|
||||
[DllImport ("libc", SetLastError = true)]
|
||||
static extern int symlink (string path1, string path2);
|
||||
|
||||
[DllImport ("libc")]
|
||||
static extern int unlink (string pathname);
|
||||
|
||||
public static void CreateSymlink (string file, string target)
|
||||
{
|
||||
unlink (file);
|
||||
var rv = symlink (target, file);
|
||||
if (rv != 0)
|
||||
throw ErrorHelper.CreateError (16, $"Could not create symlink '{file}' -> '{target}': error {Marshal.GetLastWin32Error ()}");
|
||||
}
|
||||
|
||||
public static void FileCopyIfExists (string source, string target)
|
||||
{
|
||||
if (!File.Exists (source))
|
||||
return;
|
||||
File.Copy (source, target, true);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,8 +26,10 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if !defined (__OBJC__)
|
||||
#include <cstdbool>
|
||||
#include <cstdint>
|
||||
#endif
|
||||
#else
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
|
|
@ -105,7 +105,7 @@ ensure_capacity (GArrayPriv *priv, guint capacity)
|
|||
|
||||
new_capacity = (capacity + 63) & ~63;
|
||||
|
||||
priv->array.data = g_realloc (priv->array.data, element_length (priv, new_capacity));
|
||||
priv->array.data = (gchar*) g_realloc (priv->array.data, element_length (priv, new_capacity));
|
||||
|
||||
if (priv->clear_) {
|
||||
memset (element_offset (priv, priv->capacity),
|
||||
|
@ -293,7 +293,7 @@ g_array_set_size (GArray *array, gint length)
|
|||
#define GROW_IF_NECESSARY(s,l) { \
|
||||
if(s->len + l >= s->allocated_len) { \
|
||||
s->allocated_len = (s->allocated_len + l + 16) * 2; \
|
||||
s->str = g_realloc(s->str, s->allocated_len); \
|
||||
s->str = (char*)g_realloc(s->str, s->allocated_len); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
@ -322,7 +322,7 @@ g_string_new_len (const gchar *init, gssize len)
|
|||
|
||||
ret->len = len < 0 ? strlen(init) : len;
|
||||
ret->allocated_len = MAX(ret->len + 1, 16);
|
||||
ret->str = g_malloc(ret->allocated_len);
|
||||
ret->str = (char*)g_malloc(ret->allocated_len);
|
||||
if (init)
|
||||
memcpy(ret->str, init, ret->len);
|
||||
ret->str[ret->len] = 0;
|
||||
|
@ -341,7 +341,7 @@ g_string_sized_new (gsize default_size)
|
|||
{
|
||||
GString *ret = g_new (GString, 1);
|
||||
|
||||
ret->str = g_malloc (default_size);
|
||||
ret->str = (char*)g_malloc (default_size);
|
||||
ret->str [0] = 0;
|
||||
ret->len = 0;
|
||||
ret->allocated_len = default_size;
|
||||
|
|
|
@ -28,8 +28,13 @@
|
|||
#include <stdint.h>
|
||||
#include "embeddinator.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined (XAMARIN_IOS) || defined (XAMARIN_MAC)
|
||||
#include <xamarin/xamarin.h>
|
||||
|
||||
typedef void * gpointer;
|
||||
typedef uint16_t mono_unichar2;
|
||||
|
||||
|
@ -207,8 +212,8 @@ mono_threads_detach_coop (gpointer cookie, gpointer *dummy);
|
|||
|
||||
#endif
|
||||
|
||||
#ifndef MONODECIMAL
|
||||
#define MONODECIMAL
|
||||
#ifndef E4KDEFS
|
||||
#define E4KDEFS
|
||||
|
||||
// from: https://github.com/mono/mono/blob/master/mono/metadata/decimal-ms.h
|
||||
typedef struct {
|
||||
|
@ -245,4 +250,18 @@ typedef struct {
|
|||
} v;
|
||||
} MonoDecimal;
|
||||
|
||||
typedef enum {
|
||||
E4KDateTimeKind_Unspecified,
|
||||
E4KDateTimeKind_Utc,
|
||||
E4KDateTimeKind_Local
|
||||
} E4KDateTimeKind;
|
||||
|
||||
typedef struct {
|
||||
unsigned long long DateData;
|
||||
} E4KDateTime;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
|
|
@ -82,7 +82,7 @@ static gchar* strrchr_seperator (const gchar* filename)
|
|||
#endif
|
||||
char *p;
|
||||
|
||||
p = strrchr (filename, G_DIR_SEPARATOR);
|
||||
p = (char*)strrchr (filename, G_DIR_SEPARATOR);
|
||||
#ifdef G_OS_WIN32
|
||||
p2 = strrchr (filename, '/');
|
||||
if (p2 > p)
|
||||
|
@ -334,7 +334,7 @@ void* mono_embeddinator_install_error_report_hook(mono_embeddinator_error_report
|
|||
mono_embeddinator_error_report_hook_t prev = g_error_report_hook;
|
||||
g_error_report_hook = hook;
|
||||
|
||||
return prev;
|
||||
return (void*)prev;
|
||||
}
|
||||
|
||||
void mono_embeddinator_error(mono_embeddinator_error_t error)
|
||||
|
@ -390,3 +390,12 @@ MonoClass* mono_embeddinator_get_decimal_class ()
|
|||
}
|
||||
return decimalclass;
|
||||
}
|
||||
|
||||
MonoClass* mono_embeddinator_get_datetime_class ()
|
||||
{
|
||||
static MonoClass* datetimeclass = 0;
|
||||
if (!datetimeclass) {
|
||||
datetimeclass = mono_class_from_name (mono_get_corlib (), "System", "DateTime");
|
||||
}
|
||||
return datetimeclass;
|
||||
}
|
||||
|
|
|
@ -208,4 +208,10 @@ MonoObject* mono_embeddinator_get_cultureinfo_invariantculture_object ();
|
|||
MONO_EMBEDDINATOR_API
|
||||
MonoClass* mono_embeddinator_get_decimal_class ();
|
||||
|
||||
/**
|
||||
* Gets DateTime MonoClass.
|
||||
*/
|
||||
MONO_EMBEDDINATOR_API
|
||||
MonoClass* mono_embeddinator_get_datetime_class ();
|
||||
|
||||
MONO_EMBEDDINATOR_END_DECLS
|
||||
|
|
|
@ -51,5 +51,11 @@ NSDecimalNumber* mono_embeddinator_get_nsdecimalnumber (void* __unboxedresult);
|
|||
MONO_EMBEDDINATOR_API
|
||||
MonoDecimal mono_embeddinator_get_system_decimal (NSDecimalNumber* nsdecimalnumber, mono_embeddinator_context_t* context);
|
||||
|
||||
MONO_EMBEDDINATOR_API
|
||||
E4KDateTime mono_embeddinator_get_system_datetime (NSDate* nsdate, mono_embeddinator_context_t* context);
|
||||
|
||||
MONO_EMBEDDINATOR_API
|
||||
NSDate* mono_embeddinator_get_nsdate (E4KDateTime* datetime);
|
||||
|
||||
MONO_EMBEDDINATOR_END_DECLS
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ MonoObject* mono_embeddinator_get_object (id native, bool assertOnFailure)
|
|||
NSLog (@"`%@` is not a managed instance and cannot be used like one", [native description]);
|
||||
abort ();
|
||||
}
|
||||
int gchandle = (int) [native performSelector:@selector (xamarinGetGCHandle)];
|
||||
long gchandle = (long) [native performSelector:@selector (xamarinGetGCHandle)];
|
||||
return mono_gchandle_get_target (gchandle);
|
||||
}
|
||||
|
||||
|
@ -146,3 +146,93 @@ MonoDecimal mono_embeddinator_get_system_decimal (NSDecimalNumber* nsdecimalnumb
|
|||
|
||||
return mdecimal;
|
||||
}
|
||||
|
||||
// NSDate reference date 00:00:00 UTC on 1 January 2001
|
||||
// https://developer.apple.com/reference/foundation/nsdate
|
||||
#define NSDateRefDateTicks 631139040000000000LL
|
||||
#define NetTicksPerSecond 10000000LL
|
||||
#define DateTimeMaxValueTicks 3155378975999999999LL
|
||||
#define DateTimeMinValueTicks 0LL
|
||||
|
||||
NSDate* mono_embeddinator_get_nsdate (E4KDateTime* datetime)
|
||||
{
|
||||
static MonoMethod* dtticksmethod = nil;
|
||||
static MonoMethod* dtkindmethod = nil;
|
||||
static MonoMethod* dttoutcmethod = nil;
|
||||
|
||||
MonoClass* datetimeclass = mono_embeddinator_get_datetime_class ();
|
||||
|
||||
if (!dtticksmethod)
|
||||
dtticksmethod = mono_embeddinator_lookup_method ("System.DateTime:get_Ticks()", datetimeclass);
|
||||
if (!dtkindmethod)
|
||||
dtkindmethod = mono_embeddinator_lookup_method ("System.DateTimeKind:get_Kind()", datetimeclass);
|
||||
|
||||
MonoObject* kindex = nil;
|
||||
MonoObject* kindboxed = mono_runtime_invoke (dtkindmethod, datetime, NULL, &kindex);
|
||||
if (kindex)
|
||||
mono_embeddinator_throw_exception (kindex);
|
||||
E4KDateTimeKind kind = *(E4KDateTimeKind *) mono_object_unbox (kindboxed);
|
||||
|
||||
if (kind == E4KDateTimeKind_Local) {
|
||||
if (!dttoutcmethod)
|
||||
dttoutcmethod = mono_embeddinator_lookup_method ("System.DateTime:ToUniversalTime()", datetimeclass);
|
||||
|
||||
MonoObject* toutcex = nil;
|
||||
MonoObject* utcdtboxed = mono_runtime_invoke (dttoutcmethod, datetime, NULL, &toutcex);
|
||||
if (toutcex)
|
||||
mono_embeddinator_throw_exception (toutcex);
|
||||
datetime = (E4KDateTime*)mono_object_unbox (utcdtboxed);
|
||||
}
|
||||
|
||||
MonoObject* ticks_ex = nil;
|
||||
MonoObject* ticksboxed = mono_runtime_invoke (dtticksmethod, datetime, NULL, &ticks_ex);
|
||||
if (ticks_ex)
|
||||
mono_embeddinator_throw_exception (ticks_ex);
|
||||
long long ticks = *(long long *) mono_object_unbox (ticksboxed);
|
||||
|
||||
NSTimeInterval seconds = (NSTimeInterval) (ticks - NSDateRefDateTicks) / NetTicksPerSecond;
|
||||
NSDate* nsdate = [NSDate dateWithTimeIntervalSinceReferenceDate:seconds];
|
||||
|
||||
return nsdate;
|
||||
}
|
||||
|
||||
E4KDateTime mono_embeddinator_get_system_datetime (NSDate* nsdate, mono_embeddinator_context_t* context)
|
||||
{
|
||||
static MonoMethod* datetimector = nil;
|
||||
|
||||
MonoClass* datetimeclass = mono_embeddinator_get_datetime_class ();
|
||||
int utc = E4KDateTimeKind_Utc;
|
||||
long long minvalueticks = DateTimeMinValueTicks;
|
||||
|
||||
void* datetimeargs [2];
|
||||
long long nsdateinterval;
|
||||
long long dateticks;
|
||||
|
||||
if (!nsdate)
|
||||
datetimeargs [0] = &minvalueticks;
|
||||
else {
|
||||
nsdateinterval = [nsdate timeIntervalSinceReferenceDate];
|
||||
dateticks = nsdateinterval * NetTicksPerSecond + NSDateRefDateTicks;
|
||||
|
||||
if (dateticks > DateTimeMaxValueTicks)
|
||||
dateticks = DateTimeMaxValueTicks;
|
||||
else if (dateticks < DateTimeMinValueTicks)
|
||||
dateticks = DateTimeMinValueTicks;
|
||||
|
||||
datetimeargs [0] = &dateticks;
|
||||
}
|
||||
|
||||
datetimeargs [1] = &utc;
|
||||
|
||||
if (!datetimector)
|
||||
datetimector = mono_embeddinator_lookup_method ("System.DateTime:.ctor(long,System.DateTimeKind)", datetimeclass);
|
||||
|
||||
E4KDateTime datetime = { 0 };
|
||||
|
||||
MonoObject* ex = nil;
|
||||
mono_runtime_invoke (datetimector, &datetime, datetimeargs, &ex);
|
||||
if (ex)
|
||||
mono_embeddinator_throw_exception (ex);
|
||||
|
||||
return datetime;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ ALL_MANAGED_DLLS = \
|
|||
$(TVOS_MANAGED_DLL) \
|
||||
$(MACOS_MODERN_MANAGED_DLL) \
|
||||
$(MACOS_FULL_MANAGED_DLL) \
|
||||
$(MACOS_SYSTEM_MANAGED_DLL) \
|
||||
$(MACOS_SYSTEM_MANAGED_DLL)
|
||||
else
|
||||
ALL_MANAGED_DLLS = \
|
||||
$(GENERIC_MANAGED_DLL)
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
using System;
|
||||
|
||||
namespace Duplicates
|
||||
{
|
||||
public class WithRestrictedNamed
|
||||
{
|
||||
public bool Class { get; set; }
|
||||
public int Hash () => 42;
|
||||
}
|
||||
}
|
|
@ -42,5 +42,20 @@ namespace Enums {
|
|||
i = i == IntEnum.Min ? IntEnum.Max : IntEnum.Min;
|
||||
return ByteFlags.Bit5 | ByteFlags.Bit1;
|
||||
}
|
||||
|
||||
public static int Count (IntEnum[] values)
|
||||
{
|
||||
return values == null ? 0 : values.Length;
|
||||
}
|
||||
|
||||
// NSData is not ideal if `byte` is used as the underlying type
|
||||
public static ByteEnum[] Bucket { get; set; }
|
||||
}
|
||||
|
||||
public class github561 {
|
||||
[Flags]
|
||||
public enum ModeOfTransportW { Bus = 0b1, Tram = 0b10, Train = 0b100, }
|
||||
|
||||
public ModeOfTransportW[] ModesOfTransport { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,9 +6,9 @@ namespace Interfaces {
|
|||
|
||||
bool Boolean { get; }
|
||||
|
||||
string Convert (int integer);
|
||||
string Convert (int value);
|
||||
|
||||
string Convert (long longint);
|
||||
string Convert (long value);
|
||||
}
|
||||
|
||||
// not public - only the contract is exposed thru a static type
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
<Compile Include="$(MSBuildThisFileDirectory)overloads.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)nestedClasses.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)arrays.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)duplicates.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)keywords.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)abstracts.cs" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -136,7 +136,7 @@ namespace Methods {
|
|||
public class DuplicateMethods {
|
||||
public int DoIt () { return 42; }
|
||||
public int DoIt (int i) { return 42; }
|
||||
public int DoIt (string s) { return 42; }
|
||||
public int DoIt (string i) { return 42; }
|
||||
public int DoIt (int i, int j) { return 84; }
|
||||
|
||||
public bool Find (string name) { return true; }
|
||||
|
|
|
@ -81,14 +81,6 @@ public static class Type_String
|
|||
public static string NonEmptyString { get { return "Hello World"; } }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// NOTE: DateTime types are not exposed, this is for verifying DateTime.Now works
|
||||
/// </summary>
|
||||
public static class Type_DateTime
|
||||
{
|
||||
public static string Now { get { return DateTime.Now.ToString(); } }
|
||||
}
|
||||
|
||||
// objc: this type won't be generated (Exception is not supported) but the generation will succeed (with warnings)
|
||||
public class MyException : Exception {
|
||||
}
|
||||
|
@ -124,3 +116,21 @@ public class ExposeExtraTypes {
|
|||
get { return DateTime.Now.TimeOfDay; }
|
||||
}
|
||||
}
|
||||
|
||||
public static class Type_DateTime {
|
||||
public static string Now { get { return DateTime.Now.ToString (); } }
|
||||
|
||||
public static DateTime ReturnDate (DateTime datetime) => datetime;
|
||||
public static void RefDate (ref DateTime datetime) => datetime = DateTime.MinValue;
|
||||
public static DateTime [] ReverseDates (DateTime [] dates) => dates?.Reverse ().ToArray ();
|
||||
public static void ReverseRefDates (ref DateTime [] dates) => dates = dates?.Reverse ().ToArray ();
|
||||
|
||||
public static DateTime Max { get; } = DateTime.MaxValue;
|
||||
public static DateTime Min { get; } = DateTime.MinValue;
|
||||
|
||||
public static bool Between (DateTime dt1, DateTime dt2)
|
||||
{
|
||||
var now = DateTime.Now;
|
||||
return (now >= dt1) && (now <= dt2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -320,19 +320,19 @@
|
|||
|
||||
Fields_Struct *empty = [Fields_Struct empty];
|
||||
XCTAssertNotNil (empty, "empty / struct static readonly");
|
||||
XCTAssertNil ([empty class], "empty / class uninitialized");
|
||||
XCTAssertNil ([empty managedClass], "empty / class uninitialized");
|
||||
|
||||
Fields_Struct *struct1 = [[Fields_Struct alloc] initWithEnabled:true];
|
||||
XCTAssertTrue (struct1.boolean, "init / boolean / true");
|
||||
struct1.boolean = false;
|
||||
XCTAssertFalse (struct1.boolean, "init / boolean / set 1");
|
||||
|
||||
XCTAssertNotNil (struct1.class, "init / class initialized 1");
|
||||
XCTAssertFalse (struct1.class.boolean, "init / class / boolean / default");
|
||||
struct1.class = nil;
|
||||
XCTAssertNil (struct1.class, "init / class set 1");
|
||||
struct1.class = [[Fields_Class alloc] initWithEnabled:true];
|
||||
XCTAssertTrue (struct1.class.boolean, "init / class / boolean / true");
|
||||
XCTAssertNotNil (struct1.managedClass, "init / class initialized 1");
|
||||
XCTAssertFalse (struct1.managedClass.boolean, "init / class / boolean / default");
|
||||
struct1.managedClass = nil;
|
||||
XCTAssertNil (struct1.managedClass, "init / class set 1");
|
||||
struct1.managedClass = [[Fields_Class alloc] initWithEnabled:true];
|
||||
XCTAssertTrue (struct1.managedClass.boolean, "init / class / boolean / true");
|
||||
|
||||
Fields_Struct *struct2 = [[Fields_Struct alloc] initWithEnabled:false];
|
||||
XCTAssertNotNil ([struct2 class], "init / class initialized 2");
|
||||
|
@ -507,7 +507,48 @@
|
|||
|
||||
NSArray<NSDecimalNumber *> *decimalrefNilarr = nil;
|
||||
[Type_Decimal reverseDecimalArrRefDecArr:&decimalrefNilarr];
|
||||
XCTAssertNil(decimalrefNilarr, "decimalrefNilarr");
|
||||
XCTAssertNil (decimalrefNilarr, "decimalrefNilarr");
|
||||
|
||||
NSDate *distantFuture = [Type_DateTime returnDateDatetime:[NSDate distantFuture]];
|
||||
XCTAssertNotNil (distantFuture, "distantFuture");
|
||||
|
||||
NSDate *verydistantFuture = [NSDate dateWithTimeIntervalSinceReferenceDate:[distantFuture timeIntervalSinceReferenceDate] * 8];
|
||||
NSDate *netmaxverydistantFuture = [Type_DateTime returnDateDatetime:verydistantFuture];
|
||||
NSDate *nsnetmax = [NSDate dateWithTimeIntervalSinceReferenceDate:(NSTimeInterval) 252423993600];
|
||||
XCTAssertEqualWithAccuracy ([nsnetmax timeIntervalSinceReferenceDate], [netmaxverydistantFuture timeIntervalSinceReferenceDate], 0.001, "netmaxverydistantFuture");
|
||||
|
||||
NSDate *distantPast = [Type_DateTime returnDateDatetime:[NSDate distantPast]];
|
||||
NSDate *nsnetmin = [NSDate dateWithTimeIntervalSinceReferenceDate:(NSTimeInterval) -63113904000];
|
||||
XCTAssertEqualWithAccuracy ([nsnetmin timeIntervalSinceReferenceDate], [distantPast timeIntervalSinceReferenceDate], 0.001, "DateTime distantPast");
|
||||
|
||||
NSDate *netmax = Type_DateTime.max;
|
||||
XCTAssertEqualWithAccuracy ([nsnetmax timeIntervalSinceReferenceDate], [netmax timeIntervalSinceReferenceDate], 0.001, "DateTime Max");
|
||||
|
||||
NSDate *netmin = Type_DateTime.min;
|
||||
XCTAssertEqualWithAccuracy ([nsnetmin timeIntervalSinceReferenceDate], [netmin timeIntervalSinceReferenceDate], 0.001, "DateTime Min");
|
||||
|
||||
NSDate *refdate = nil;
|
||||
[Type_DateTime refDateDatetime:&refdate];
|
||||
XCTAssertEqualWithAccuracy ([nsnetmin timeIntervalSinceReferenceDate], [refdate timeIntervalSinceReferenceDate], 0.001, "DateTime refdate");
|
||||
|
||||
NSDate *nilTest = [Type_DateTime returnDateDatetime:nil];
|
||||
XCTAssertEqualWithAccuracy ([nsnetmin timeIntervalSinceReferenceDate], [nilTest timeIntervalSinceReferenceDate], 0.001, "DateTime nilTest");
|
||||
|
||||
NSArray<NSDate *> *datesArr = @[netmax, netmin];
|
||||
[Type_DateTime reverseRefDatesDates:&datesArr];
|
||||
XCTAssertEqualWithAccuracy ([nsnetmin timeIntervalSinceReferenceDate], [datesArr[0] timeIntervalSinceReferenceDate], 0.001, "DateTime reverseRefDatesDates Min");
|
||||
XCTAssertEqualWithAccuracy ([nsnetmax timeIntervalSinceReferenceDate], [datesArr[1] timeIntervalSinceReferenceDate], 0.001, "DateTime reverseRefDatesDates Max");
|
||||
|
||||
NSArray<NSDate *> *revdatesArr = [Type_DateTime reverseDatesDates:@[netmax, netmin]];
|
||||
XCTAssertEqualWithAccuracy ([nsnetmin timeIntervalSinceReferenceDate], [revdatesArr[0] timeIntervalSinceReferenceDate], 0.001, "DateTime reverseDatesDates Min");
|
||||
XCTAssertEqualWithAccuracy ([nsnetmax timeIntervalSinceReferenceDate], [revdatesArr[1] timeIntervalSinceReferenceDate], 0.001, "DateTime reverseDatesDates Max");
|
||||
|
||||
NSArray<NSDate *> *refnilarrdate = nil;
|
||||
[Type_DateTime reverseRefDatesDates:&refnilarrdate];
|
||||
XCTAssertNil (refnilarrdate, "DateTime refnilarrdate");
|
||||
|
||||
NSArray<NSDate *> *revdatesnillArr = [Type_DateTime reverseDatesDates:nil];
|
||||
XCTAssertNil (revdatesnillArr, "DateTime revdatesnillArr");
|
||||
}
|
||||
|
||||
- (void) testObjectIndexedSubscripting {
|
||||
|
@ -1313,6 +1354,12 @@
|
|||
}
|
||||
}
|
||||
|
||||
- (void)testRestrictedNames {
|
||||
Duplicates_WithRestrictedNamed * d = [[Duplicates_WithRestrictedNamed alloc] init];
|
||||
Class c = [d class];
|
||||
XCTAssertNotEqual(42, [d hash], "Must not call instance Hash ()");
|
||||
}
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
@end
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace DriverTest
|
|||
int exitCode;
|
||||
Console.WriteLine ($"{filename} {arguments}");
|
||||
// We capture stderr too, otherwise it won't show up in the test unit pad's output.
|
||||
if (Embedder.RunProcess (filename, arguments, out exitCode, out stdout, capture_stderr: true))
|
||||
if (Utils.RunProcess (filename, arguments, out exitCode, out stdout, capture_stderr: true))
|
||||
return;
|
||||
Console.WriteLine ($"Command failed with exit code: {exitCode}");
|
||||
Console.WriteLine (stdout);
|
||||
|
|
|
@ -193,7 +193,7 @@ namespace DriverTest {
|
|||
var csfile = Path.Combine (tmpdir, "foo.cs");
|
||||
var dllfile = Path.Combine (tmpdir, "foo.dll");
|
||||
File.WriteAllText (csfile, @"public class C { public Foundation.NSObject F () { throw new System.NotImplementedException (); } }");
|
||||
Asserts.RunProcess ("/Library/Frameworks/Mono.framework/Commands/csc", $"/target:library /out:{Embedder.Quote (dllfile)} {Embedder.Quote (csfile)} -r:/Library/Frameworks/Xamarin.iOS.framework/Versions/Current/lib/mono/Xamarin.iOS/Xamarin.iOS.dll", "compile dll");
|
||||
Asserts.RunProcess ("/Library/Frameworks/Mono.framework/Commands/csc", $"/target:library /out:{Utils.Quote (dllfile)} {Utils.Quote (csfile)} -r:/Library/Frameworks/Xamarin.iOS.framework/Versions/Current/lib/mono/Xamarin.iOS/Xamarin.iOS.dll", "compile dll");
|
||||
Asserts.ThrowsEmbeddinatorException (13, "Can't find the assembly 'Xamarin.iOS, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065', referenced by 'foo, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.", () => Driver.Main2 (dllfile, "--platform=tvOS", "--outdir=" + tmpdir));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace DriverTest
|
|||
|
||||
string output;
|
||||
int exitCode;
|
||||
Assert.IsTrue (Embedder.RunProcess ("xcrun", $"lipo -info {tmpdir}/libLibrary.dylib", out exitCode, out output), "lipo");
|
||||
Assert.IsTrue (Utils.RunProcess ("xcrun", $"lipo -info {tmpdir}/libLibrary.dylib", out exitCode, out output), "lipo");
|
||||
StringAssert.IsMatch ($"Non-fat file: .* is architecture: {abi}", output, "architecture");
|
||||
}
|
||||
|
||||
|
@ -91,7 +91,7 @@ namespace DriverTest
|
|||
|
||||
File.WriteAllText (cs_path, code);
|
||||
|
||||
if (!Embedder.RunProcess ("/Library/Frameworks/Mono.framework/Versions/Current/bin/csc", $"/target:library {Embedder.Quote (cs_path)} /out:{Embedder.Quote (dll_path)}", out exitCode))
|
||||
if (!Utils.RunProcess ("/Library/Frameworks/Mono.framework/Versions/Current/bin/csc", $"/target:library {Utils.Quote (cs_path)} /out:{Utils.Quote (dll_path)}", out exitCode))
|
||||
Assert.Fail ("Failed to compile test code");
|
||||
|
||||
return dll_path;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
run-tests:
|
||||
nuget restore ../../generator.sln
|
||||
nuget restore ../../Embeddinator-4000.sln
|
||||
msbuild objcgentest.csproj
|
||||
mono --debug ../../packages/NUnit.ConsoleRunner.3.6.1/tools/nunit3-console.exe bin/Debug/objcgentest.dll "--result=$(abspath $(CURDIR)/TestResult.xml);format=nunit2"
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
|
||||
using Embeddinator.ObjC;
|
||||
|
@ -10,6 +11,7 @@ using Xamarin;
|
|||
using DriverTest;
|
||||
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Interfaces;
|
||||
|
||||
namespace ExecutionTests
|
||||
{
|
||||
|
@ -72,7 +74,7 @@ namespace ExecutionTests
|
|||
[TestCase (false)]
|
||||
public void tvOS_simulator (bool debug)
|
||||
{
|
||||
RunManagedTests (Platform.tvOS, "-destination 'platform=tvOS Simulator,name=Apple TV 1080p,OS=latest'", debug: debug);
|
||||
RunManagedTests (Platform.tvOS, "-destination 'platform=tvOS Simulator,name=Apple TV 4K (at 1080p),OS=latest'", debug: debug);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -92,11 +94,19 @@ namespace ExecutionTests
|
|||
if (device_xml == null) {
|
||||
var cachedir = Cache.CreateTemporaryDirectory ();
|
||||
var xmlpath = Path.Combine (cachedir, "devices.xml");
|
||||
Asserts.RunProcess ("/Library/Frameworks/Xamarin.iOS.framework/Versions/Current/bin/mlaunch", $"--listdev={Embedder.Quote (xmlpath)} --output-format=xml", "mlaunch --listdev");
|
||||
Asserts.RunProcess ("/Library/Frameworks/Xamarin.iOS.framework/Versions/Current/bin/mlaunch", $"--listdev={Utils.Quote (xmlpath)} --output-format=xml", "mlaunch --listdev");
|
||||
var settings = new XmlReaderSettings () {
|
||||
XmlResolver = null,
|
||||
DtdProcessing = DtdProcessing.Parse
|
||||
};
|
||||
device_xml = new XmlDocument ();
|
||||
device_xml.Load (xmlpath);
|
||||
var sr = new StreamReader (xmlpath, Encoding.UTF8, true);
|
||||
var reader = XmlReader.Create (sr, settings);
|
||||
device_xml.Load (reader);
|
||||
}
|
||||
var nodes = device_xml.SelectNodes ("/MTouch/Device[" + string.Join (" or ", valid_classes.Select ((v) => "DeviceClass = \"" + v + "\"")) + "]/DeviceIdentifier");
|
||||
// filter by device type and ensure that we can use the device for debugging purposes.
|
||||
var xpathQuery = "/MTouch/Device[(" + string.Join(" or ", valid_classes.Select((v) => "DeviceClass = \"" + v + "\"")) + ") and IsUsableForDebugging =\"True\"]/DeviceIdentifier";
|
||||
var nodes = device_xml.SelectNodes (xpathQuery);
|
||||
var devices = new List<string> ();
|
||||
foreach (XmlNode node in nodes)
|
||||
devices.Add (node.InnerText);
|
||||
|
@ -197,7 +207,7 @@ namespace ExecutionTests
|
|||
var dll_path = Path.Combine (XcodeProjectGenerator.TestsRootDirectory, "managed", dlldir, "bin", configuration, dllname);
|
||||
|
||||
// This will build all the managed.dll variants, which is easier than calculating the relative path _as the makefile sees it_ to pass as the target.
|
||||
Asserts.RunProcess ("make", $"all CONFIG={configuration} -C {Embedder.Quote (Path.Combine (XcodeProjectGenerator.TestsRootDirectory, "managed"))}", "build " + Path.GetFileName (dll_path));
|
||||
Asserts.RunProcess ("make", $"all CONFIG={configuration} -C {Utils.Quote (Path.Combine (XcodeProjectGenerator.TestsRootDirectory, "managed"))}", "build " + Path.GetFileName (dll_path));
|
||||
|
||||
var outdir = tmpdir + "/out";
|
||||
var projectName = "foo";
|
||||
|
@ -217,7 +227,7 @@ namespace ExecutionTests
|
|||
|
||||
string output;
|
||||
var builddir = Path.Combine (tmpdir, "xcode-build-dir");
|
||||
Asserts.RunProcess ("xcodebuild", $"test -project {Embedder.Quote (projectDirectory)} -scheme Tests {test_destination} CONFIGURATION_BUILD_DIR={Embedder.Quote (builddir)}", out output, "run xcode tests");
|
||||
Asserts.RunProcess ("xcodebuild", $"test -project {Utils.Quote (projectDirectory)} -scheme Tests {test_destination} CONFIGURATION_BUILD_DIR={Utils.Quote (builddir)}", out output, "run xcode tests");
|
||||
// assert the number of tests passed, so that we can be sure we actually ran all the tests. Otherwise it's very easy to ignore when a bug is causing tests to not be built.
|
||||
Assert.That (output, Does.Match ($"Test Suite 'All tests' passed at .*\n\t Executed {managedTestCount} tests, with 0 failures"), "test count");
|
||||
}
|
||||
|
|
|
@ -161,7 +161,7 @@ namespace ObjCGenErrWarnTests {
|
|||
clangArgs.Append ($"-o {Path.Combine (tempWorkingDir, "foo.o")} ");
|
||||
|
||||
// Embedder.RunProcess returns false if exitcode != 0
|
||||
Assert.IsFalse (Embedder.RunProcess ("xcrun", clangArgs.ToString (), out int exitCode, out string output, capture_stderr: true), "clangbuild");
|
||||
Assert.IsFalse (Utils.RunProcess ("xcrun", clangArgs.ToString (), out int exitCode, out string output, capture_stderr: true), "clangbuild");
|
||||
Assert.That (output, Does.Contain (errorToSearch), $"Not found: {errorToSearch}");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace ObjCGeneratorTest {
|
|||
[Test]
|
||||
public void TypeMatchFailure ()
|
||||
{
|
||||
Assert.Throws<NotImplementedException> (() => NameGenerator.GetTypeName (mscorlib.GetType ("System.DateTime")), "DateTime");
|
||||
Assert.Throws<NotImplementedException> (() => NameGenerator.GetTypeName (mscorlib.GetType ("System.DBNull")), "DBNull");
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
Загрузка…
Ссылка в новой задаче