2016-01-05 5 views
11

मैं सी # में लिखी गई यूनिवर्सल विंडोज प्लेटफ़ॉर्म लाइब्रेरी को कैसे पैकेज करूं जो केवल आर्किटेक्चर-निर्भर बनाता है? चित्रण के लिए, मान लें कि मेरे पास प्रत्येक आर्किटेक्चर के लिए सशर्त रूप से संकलित कुछ आर्किटेक्चर-विशिष्ट कोड है (#if ARM और समकक्षों का उपयोग करके)।यूनिवर्सल विंडोज प्लेटफॉर्म को लक्षित करने वाली बहु-आर्किटेक्चर .NET लाइब्रेरी को कैसे पैकेज करें?

स्पष्ट होने के लिए, मेरी लाइब्रेरी के लिए कोई भीCPCP बिल्ड मौजूद नहीं है - केवल x86, x64 और ARM।

एक समकक्ष और संभावित रूप से अधिक सामान्य स्थिति एक है जहां मेरी बाहरी पुस्तकालय पर निर्भरता है जिसे केवल आर्किटेक्चर-विशिष्ट बिल्ड (उदा। Win2D) के रूप में प्रदान किया जाता है। संदर्भ को सरल रखने के लिए, मान लीजिए कि कोई निर्भरता नहीं है और केवल मेरा स्वयं का कोड शामिल है - समाधान को किसी भी तरह से कम करना चाहिए।

:

यह सवाल और जवाब है कि आधुनिक NuGet पैकेज संलेखन के विषय पर मेरी निष्कर्ष दस्तावेज़, NuGet 3. साथ किए गए बदलावों पर विशेष रूप से ध्यान केंद्रित कर तुम भी कुछ संबंधित प्रश्नों में रुचि हो सकती की एक श्रृंखला है

उत्तर

10

इस उत्तर principles of .NET Framework library packaging और principles of Universal Windows Platform library packaging पर बनाता है। निम्नलिखित को बेहतर ढंग से समझने के लिए पहले लिंक किए गए उत्तरों को पढ़ें।

मैं मानता हूं कि आपके सभी आर्किटेक्चर-विशिष्ट बिल्डों में एक ही एपीआई सतह का पर्दाफाश होता है, केवल उन एपीआई के कार्यान्वयन के साथ ही भिन्न होता है।

इस परिदृश्य के साथ मुख्य उलझन है कि निर्माण toolchain संकलन समय संदर्भ समाधान के लिए एक AnyCPU विधानसभा की आवश्यकता है, भले ही यह विधानसभा कार्यावधि में इस्तेमाल कभी नहीं किया जाता है। चूंकि आपके परिदृश्य में एसीसीपीयू बिल्ड आउटपुट नहीं है, इसलिए हमें एक वर्कअराउंड ढूंढना होगा। यहां लागू अवधारणा संदर्भ असेंबली का है - AnyCPU असेंबली केवल संदर्भ सत्यापन के लिए संकलन-समय पर उपयोग की जाती है। इसलिए, अपनी लाइब्रेरी को प्रकाशित करने के लिए, आपको एक संदर्भ असेंबली बनाने और नीचे उल्लिखित संपत्तियों को पैकेज करने की आवश्यकता होगी।

सादगी के लिए, मुझे लगता है कि आपकी लाइब्रेरी में अन्य NuGet संकुलों पर कोई निर्भरता नहीं है। यह अभ्यास में मामला होने की संभावना नहीं है लेकिन निर्भरता प्रबंधन पहले से जुड़े अन्य उत्तरों द्वारा कवर किया गया है और इसलिए इस उत्तर से छोड़ा गया है।

NuGet पैकेज के वांछित संरचना इस प्रकार है:

+---ref 
| \---uap10.0 
|  | MultiArchitectureUwpLibrary.dll 
|  | MultiArchitectureUwpLibrary.pri 
|  | MultiArchitectureUwpLibrary.XML 
|  | 
|  \---MultiArchitectureUwpLibrary 
|    ArchitectureControl.xaml 
|    MultiArchitectureUwpLibrary.xr.xml 
| 
+---runtimes 
| +---win10-arm 
| | \---lib 
| |  \---uap10.0 
| |    MultiArchitectureUwpLibrary.dll 
| |    MultiArchitectureUwpLibrary.pdb 
| | 
| +---win10-x64 
| | \---lib 
| |  \---uap10.0 
| |    MultiArchitectureUwpLibrary.dll 
| |    MultiArchitectureUwpLibrary.pdb 
| | 
| \---win10-x86 
|  \---lib 
|   \---uap10.0 
|     MultiArchitectureUwpLibrary.dll 
|     MultiArchitectureUwpLibrary.pdb 

आप उत्तर ऊपर लिंक, फ़ाइलों सब पहले से ही आप के लिए पता होना चाहिए, हालांकि निर्देशिका संरचना बल्कि असामान्य है के साथ खुद को परिचित है इस मामले में। ref निर्देशिका में संदर्भ असेंबली, XML दस्तावेज़ और संसाधन फ़ाइलें हैं, जबकि आर्किटेक्चर-विशिष्ट संपत्तियों को runtimes निर्देशिका के अंतर्गत संरचित किया गया है।

इसमें से अधिकांश बिल्कुल स्पष्ट है और एक nuspec बनाई गई फ़ाइल निम्नलिखित टेम्पलेट पर आधारित का उपयोग करके पूरा किया जा सकता है:

<?xml version="1.0"?> 
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> 
    <metadata minClientVersion="3.2"> 
     <id>Example.MultiArchitectureUwpLibrary</id> 
     <version>1.0.0</version> 
     <authors>Firstname Lastname</authors> 
     <description>Example of library that is published as a set of architecture-specific assmeblies for the UWP platform.</description> 
    </metadata> 
    <files> 
     <!-- Architecture-independent reference library for use at compile-time; generated by the PowerShell script. --> 
     <file src="..\bin\Reference\Release\MultiArchitectureUwpLibrary.dll" target="ref\uap10.0" /> 

     <!-- XML documentation file goes together with the reference library. --> 
     <file src="..\bin\x86\Release\MultiArchitectureUwpLibrary.xml" target="ref\uap10.0" /> 

     <!-- Resource files go together with the reference library. --> 
     <file src="..\bin\x86\Release\MultiArchitectureUwpLibrary.pri" target="ref\uap10.0" /> 
     <file src="..\bin\x86\Release\MultiArchitectureUwpLibrary\*" target="ref\uap10.0\MultiArchitectureUwpLibrary" /> 

     <!-- The architecture-specific files go in architecture-specific directories. --> 
     <file src="..\bin\x86\Release\MultiArchitectureUwpLibrary.dll" target="runtimes\win10-x86\lib\uap10.0" /> 
     <file src="..\bin\x86\Release\MultiArchitectureUwpLibrary.pdb" target="runtimes\win10-x86\lib\uap10.0" /> 

     <file src="..\bin\x64\Release\MultiArchitectureUwpLibrary.dll" target="runtimes\win10-x64\lib\uap10.0" /> 
     <file src="..\bin\x64\Release\MultiArchitectureUwpLibrary.pdb" target="runtimes\win10-x64\lib\uap10.0" /> 

     <file src="..\bin\arm\Release\MultiArchitectureUwpLibrary.dll" target="runtimes\win10-arm\lib\uap10.0" /> 
     <file src="..\bin\arm\Release\MultiArchitectureUwpLibrary.pdb" target="runtimes\win10-arm\lib\uap10.0" /> 
    </files> 
</package> 

गायब टुकड़ा, ज़ाहिर है, संदर्भ विधानसभा है। शुक्र है, यह हल करने के लिए आसान है - एक संदर्भ असेंबली एक एएनसीपीयू असेंबली है जो रनटाइम असेंबली में समान कक्षाओं और विधियों को परिभाषित करती है। इसका मुख्य उद्देश्य कंपाइलर को काम करने का संदर्भ प्रदान करना है, इसलिए संकलक यह सत्यापित कर सकता है कि सभी विधि कॉल वास्तव में उन विधियों का संदर्भ दे रहे हैं जो रनटाइम पर मौजूद होंगी। संदर्भ असेंबली (यदि कोई है) में वास्तविक कोड किसी भी चीज़ के लिए उपयोग नहीं किया जाता है।

चूंकि आपके सभी आर्किटेक्चर-विशिष्ट बिल्ड एक ही एपीआई सतह का पर्दाफाश करते हैं, इसलिए हम उनमें से किसी एक को ले सकते हैं और संकलक को संदर्भ असेंबली के रूप में उपयोग करने के लिए निर्देश दे सकते हैं। विंडोज एसडीके में एक उपयोगिता है जिसे CorFlags.exe नाम दिया गया है जिसका उपयोग किसी भी x86 असेंबली को किसी भी एसीसीपीयू असेंबली में परिवर्तित करने के लिए किया जा सकता है, जिससे यह संभव हो सके।

नीचे एक पैकेज निर्माण स्क्रिप्ट है जो पुस्तकालय पैकेजिंग से पहले आवश्यक संदर्भ असेंबली बनाता है। यह मानता है कि विंडोज एसडीके मानक स्थान में स्थापित है। तर्क के विवरण को समझने के लिए, इनलाइन टिप्पणियां देखें।

# Any assembly matching this filter will be transformed into an AnyCPU assembly. 
$referenceDllFilter = "MultiArchitectureUwpLibrary.dll" 

$programfilesx86 = "${Env:ProgramFiles(x86)}" 
$corflags = Join-Path $programfilesx86 "Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6 Tools\x64\CorFlags.exe" 

If (!(Test-Path $corflags)) 
{ 
    Throw "Unable to find CorFlags.exe" 
} 

$solutionRoot = Resolve-Path ..\.. 
$topLevelDirectories = Get-ChildItem $solutionRoot -Directory 
$binDirectories = $topLevelDirectories | %{ Get-ChildItem $_.FullName -Directory -Filter "bin" } 

# Create reference assemblies, because otherwise the NuGet packages cannot be used. 
# This creates them for all outputs that match the filter, in all output directories of all projects. 
# It's a bit overkill but who cares - the process is very fast and keeps the script simple. 
Foreach ($bin in $binDirectories) 
{ 
    $x86 = Join-Path $bin.FullName "x86" 
    $any = Join-Path $bin.FullName "Reference" 

    If (!(Test-Path $x86)) 
    { 
     Write-Host "Skipping reference assembly generation for $($bin.FullName) because it has no x86 directory." 
     continue; 
    } 

    if (Test-Path $any) 
    { 
     Remove-Item -Recurse $any 
    } 

    New-Item $any -ItemType Directory 
    New-Item "$any\Release" -ItemType Directory 

    $dlls = Get-ChildItem "$x86\Release" -File -Filter $referenceDllFilter 

    Foreach ($dll in $dlls) 
    { 
     Copy-Item $dll.FullName "$any\Release" 
    } 

    $dlls = Get-ChildItem "$any\Release" -File -Filter $referenceDllFilter 

    Foreach ($dll in $dlls) 
    { 
     Write-Host "Converting to AnyCPU: $dll" 

     & $corflags /32bitreq- $($dll.FullName) 
    } 
} 

# Delete any existing output. 
Remove-Item *.nupkg 

# Create new packages for any nuspec files that exist in this directory. 
Foreach ($nuspec in $(Get-Item *.nuspec)) 
{ 
    .\NuGet.exe pack "$nuspec" 
} 

आपको अपने समाधान में उपयोग किए गए सम्मेलनों से मेल खाने के लिए स्क्रिप्ट में पथ समायोजित करने की आवश्यकता हो सकती है।

इस स्क्रिप्ट को एक NuGet पैकेज बनाने के लिए चलाएं जो आपकी लाइब्रेरी को अपने सभी आर्किटेक्चर-विशिष्ट रूपों में उपयोग करने में सक्षम बनाता है! NuGet पैकेज बनाने से पहले सभी आर्किटेक्चर के लिए रिलीज कॉन्फ़िगरेशन का उपयोग करके अपना समाधान बनाना याद रखें।

एक नमूना पुस्तकालय और प्रासंगिक पैकेजिंग फ़ाइलें available on GitHub हैं। इस उत्तर से संबंधित समाधान MultiArchitectureUwpLibrary है।

+0

यदि आप इसका परीक्षण करते हैं, तो संस्करण को बदलना सुनिश्चित करें। मैंने इसका परीक्षण किया और यह पहले काम नहीं किया। क्योंकि न्यूजेट कैश करने के लिए सीम करता है कि यह पैकेज स्थापित नहीं कर सकता है। – lokimidgard

संबंधित मुद्दे

 संबंधित मुद्दे