How should I create or upload a 32-bit and 64-bit

2019-01-16 18:15发布

I have an x86 and x64 version of a binary that I want to upload to NuGet. What's the recommendation or required method for creating/uploading that package? I can't find much to base my decision on. I see two methods...

  1. Upload them both in the same package
    • Which one should I install by default?
    • Is there a way to test the processor architecture of the project to make the decision?
  2. Upload two separate packages

Bonus question: What if I'm using something like Chocolatey, which wraps up NuGet with package manager semantics? I might need/want the x86 and x64 packages installed on my system.

3条回答
forever°为你锁心
2楼-- · 2019-01-16 18:52

You can add x64 and x86 support to a project by using conditional references. It would appear that for now Nuget does not like having two references with the same name. So we need to add in the second reference manually and then make the references conditional.

Save x64 assemblies in a folder called x64 & x86 assemblies in a folder called x86 They must both have the same assembly name. Then update the allowedReferences array with the names of all assemblies to add.

Use the following scripts.

Install.ps1

$allowedReferences = @("Noesis.Javascript")

# Full assembly name is required
Add-Type -AssemblyName 'Microsoft.Build, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'

$projectCollection = [Microsoft.Build.Evaluation.ProjectCollection]::GlobalProjectCollection

$allProjects = $projectCollection.GetLoadedProjects($project.Object.Project.FullName).GetEnumerator();

if($allProjects.MoveNext())
{
    $currentProject = $allProjects.Current

    foreach($Reference in $currentProject.GetItems('Reference') | ? {$allowedReferences -contains $_.Xml.Include })
    {
        $hintPath = $Reference.GetMetadataValue("HintPath")

        write-host "Matched againt $hintPath"

        #If it is x64 specific add condition (Include 'Any Cpu' as x64)
        if ($hintPath -match '.*\\(amd64|x64)\\.*\.dll$')
        {
            $Reference.Xml.Condition = "'TargetPlatform' != 'x86'"

            $condition = $Reference.Xml.Condition
            write-host "hintPath = $hintPath"
            write-host "condition = $condition"

            #Visual Studio doesnt allow the same reference twice (so try add friends)
            $matchingReferences = $currentProject.GetItems('Reference') | ? {($_.Xml.Include -eq $Reference.Xml.Include) -and ($_.GetMetadataValue("HintPath") -match ".*\\(x86)\\.*\.dll$")}

            if (($matchingReferences | Measure-Object).Count -eq 0)
            {
                $x86 = $hintPath -replace '(.*\\)(amd64|x64)(\\.*\.dll)$', '$1x86$3'
                $x86Path = Join-Path $installPath $x86

                if (Test-Path $x86Path) {
                    #Add 
                    write-host "Adding reference to $x86"

                    $metaData = new-object "System.Collections.Generic.Dictionary``2[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"
                    $metaData.Add("HintPath", $x86)
                    $currentProject.AddItem('Reference', $Reference.Xml.Include, $metaData)

                    $newReference = $currentProject.GetItems('Reference') | ? {($_.Xml.Include -eq $Reference.Xml.Include) -and ($_.GetMetadataValue("HintPath") -eq $x86)} | Select-Object -First 1

                    $newReference.Xml.Condition = "'TargetPlatform' == 'x86'"           
                }
            }
        }

        #If it is x86 specific add condition 
        if ($hintPath -match '.*\\x86\\.*\.dll$')
        {
            $Reference.Xml.Condition = "'TargetPlatform' == 'x86'"

            $condition = $Reference.Xml.Condition
            write-host "hintPath = $hintPath"
            write-host "condition = $condition"

            #Visual Studio doesnt allow the same reference twice (so try add friends)
            $matchingReferences = $currentProject.GetItems('Reference') | ? {($_.Xml.Include -eq $Reference.Xml.Include) -and ($_.GetMetadataValue("HintPath") -match ".*\\(amd64|x64)\\.*\.dll$")}

            if (($matchingReferences | Measure-Object).Count -eq 0)
            {
                $x64 = $hintPath -replace '(.*\\)(x86)(\\.*\.dll)$', '$1x64$3'
                $x64Path = Join-Path $installPath $x64

                if (Test-Path $x64Path) {
                    #Add 
                    write-host "Adding reference to $x64"

                    $metaData = new-object "System.Collections.Generic.Dictionary``2[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"
                    $metaData.Add("HintPath", $x64)
                    $currentProject.AddItem('Reference', $Reference.Xml.Include, $metaData)

                    $newReference = $currentProject.GetItems('Reference') | ? {($_.Xml.Include -eq $Reference.Xml.Include) -and ($_.GetMetadataValue("HintPath") -eq $x64)} | Select-Object -First 1

                    $newReference.Xml.Condition = "'TargetPlatform' != 'x86'"           
                } else {
                    $amd64 = $hintPath -replace '(.*\\)(x86)(\\.*\.dll)$', '$1amd64$3'
                    $amd64Path = Join-Path $installPath $amd64

                    if (Test-Path $amd64Path) {
                        #Add 
                        write-host "Adding reference to $amd64"

                        $metaData = new-object "System.Collections.Generic.Dictionary``2[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"
                        $metaData.Add("HintPath", $amd64)
                        $currentProject.AddItem('Reference', $Reference.Xml.Include, $metaData)

                        $newReference = $currentProject.GetItems('Reference') | ? {($_.Xml.Include -eq $Reference.Xml.Include) -and ($_.GetMetadataValue("HintPath") -eq $amd64)} | Select-Object -First 1

                        $newReference.Xml.Condition = "'TargetPlatform' != 'x86'"           
                    }               
                }               
            }           
        }
    }
}

Uninstall.ps1

$allowedReferences = @("Noesis.Javascript")

# Full assembly name is required
Add-Type -AssemblyName 'Microsoft.Build, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'

$projectCollection = [Microsoft.Build.Evaluation.ProjectCollection]::GlobalProjectCollection

$allProjects = $projectCollection.GetLoadedProjects($project.Object.Project.FullName).GetEnumerator();

if($allProjects.MoveNext())
{
    foreach($Reference in $allProjects.Current.GetItems('Reference') | ? {$allowedReferences -contains $_.UnevaluatedInclude })
    {
        $allProjects.Current.RemoveItem($Reference)
    }
}
查看更多
Anthone
3楼-- · 2019-01-16 18:55

There doesn't seem to be a specific target for 32 or 64 bit architectures. Bit of a pain, but can you do something with the powershell scripts (install.ps1) to detect the architecture and install accordingly?

See Automatically Running PowerShell Scripts During Package Installation and Removal - http://docs.nuget.org/docs/creating-packages/creating-and-publishing-a-package

查看更多
smile是对你的礼貌
4楼-- · 2019-01-16 19:01

We've been discussing a similar issue on the Chocolatey Google Group. There aren't any semantics built into NuGet. The requirement wouldn't be, what processor architecture are you running on. It would have to be what processor architecture is your project targeting. And then that complicates things... you'd have to understand AnyCPU as well.

I think for now, I'm going to upload two packages. I can always published a combined one when I fix up an install.ps1 that can handle querying the project target.

mypackage.x86
mypackage.x64
查看更多
登录 后发表回答