Estou tentando criar o pacote NuGet para um assembly .Net que faz pinvoke para uma dll win32 nativa. Preciso compactar o assembly e a dll nativa com o assembly adicionado às referências do projeto (sem problemas nesta parte) e a dll nativa deve ser copiada no diretório de saída do projeto ou em algum outro diretório relativo.
Minhas perguntas são:
- Como empacotar a dll nativa sem o visual studio tentar adicioná-lo à lista de referências?
- Preciso escrever um install.ps1 para copiar a dll nativa? Se sim, como posso acessar o conteúdo do pacote para copiá-lo?
nuget
nuget-package
nuget-spec
AlonFStackoverflow
fonte
fonte
Respostas:
O uso do
Copy
destino no arquivo de destinos para copiar as bibliotecas necessárias não copiará esses arquivos para outros projetos que fazem referência ao projeto, resultando em um arquivoDllNotFoundException
. No entanto, isso pode ser feito com um arquivo de destinos muito mais simples, usando umNone
elemento, pois o MSBuild copiará todos osNone
arquivos para projetos de referência.Inclua o arquivo de destinos no
build
diretório do pacote nuget, juntamente com as bibliotecas nativas necessárias. O arquivo de destinos incluirá todos osdll
arquivos em todos os diretórios filhos dobuild
diretório. Portanto, para adicionar uma versãox86
ex64
uma biblioteca nativa usada por umAny CPU
assembly gerenciado, você terminaria com uma estrutura de diretório semelhante à seguinte:Os mesmos diretórios
x86
ex64
serão criados no diretório de saída do projeto quando criados. Se você não precisa de subdiretórios em seguida, o**
e%(RecursiveDir)
podem ser removidos e, em vez incluir os arquivos necessários nobuild
diretório diretamente. Outros arquivos de conteúdo necessários também podem ser adicionados da mesma maneira.Os arquivos adicionados como
None
no arquivo de destinos não serão mostrados no projeto quando abertos no Visual Studio. Se você está se perguntando por que não uso aContent
pasta no nupkg, é porque não há como definir oCopyToOutputDirectory
elemento sem usar um script PowerShell (que só será executado no Visual Studio, não no prompt de comando, nos servidores de compilação ou no outros IDEs, e não é suportado nos projetos project.json / xproj DNX ) e eu prefiro usarLink
a nos arquivos em vez de ter uma cópia adicional dos arquivos no projeto.Atualização: Embora isso também deva funcionar, em
Content
vez deNone
parecer que existe um bug no msbuild, os arquivos não serão copiados para referenciar projetos mais de uma etapa removida (por exemplo, proj1 -> proj2 -> proj3, proj3 não obterá os arquivos do pacote NuGet do proj1, mas o proj2 será).fonte
'$(MSBuildThisFileDirectory)' != '' And HasTrailingSlash('$(MSBuildThisFileDirectory)')
necessária? Eu pensei que oMSBuildThisFileDirectory
está sempre definido. Quando não seria esse o caso?**\*.dll
? Isso é copiar todos os.dll
arquivos em todos os diretórios. Você poderia fazer isso facilmente**\*.*
para copiar uma árvore de diretórios inteira.Recentemente, tive o mesmo problema ao tentar criar um pacote EmguCV NuGet, incluindo assemblies gerenciados e lirários compartilhados não gerenciados (que também precisavam ser colocados em um
x86
subdiretório), que precisavam ser copiados automaticamente para o diretório de saída da compilação após cada compilação .Aqui está uma solução que eu criei, que depende apenas do NuGet e MSBuild:
Coloque os assemblies gerenciados no
/lib
diretório do pacote (parte óbvia) e as bibliotecas compartilhadas não gerenciadas e os arquivos relacionados (por exemplo, pacotes .pdb) no/build
subdiretório (conforme descrito nos documentos do NuGet ).Renomeie todas as
*.dll
terminações de arquivos não gerenciados para algo diferente, por exemplo,*.dl_
para impedir que o NuGet gagueje sobre as alegadas assembléias serem colocadas em um local errado ( "Problema: montagem fora da pasta lib" ).Adicione um
<PackageName>.targets
arquivo personalizado no/build
subdiretório com algo como o seguinte conteúdo (veja abaixo uma descrição):O
.targets
arquivo acima será injetado em uma instalação do pacote NuGet no arquivo de projeto de destino e é responsável por copiar as bibliotecas nativas para o diretório de saída.<AvailableItemName Include="NativeBinary" />
adiciona um novo item "Build Action" para o projeto (que também fica disponível no menu suspenso "Build Action", dentro do Visual Studio).<NativeBinary Include="...
adiciona as bibliotecas nativas inseridas no/build/x86
projeto atual e as torna acessíveis ao destino personalizado que copia esses arquivos no diretório de saída.<TargetPath>x86</TargetPath>
adiciona metadados personalizados aos arquivos e informa ao destino personalizado para copiar os arquivos nativos nox86
subdiretório do diretório de saída real.O
<PrepareForRunDependsOn ...
bloco adiciona o destino personalizado à lista de destinos da qual a compilação depende, consulte o arquivo Microsoft.Common.targets para obter detalhes.O destino personalizado,,
CopyNativeBinaries
contém duas tarefas de cópia. O primeiro é responsável por copiar todos os*.dl_
arquivos para o diretório de saída enquanto altera sua extensão para o original*.dll
. O segundo simplesmente copia o restante (por exemplo, qualquer*.pdb
arquivo) para o mesmo local. Isso poderia ser substituído por uma tarefa de cópia única e um script install.ps1 que precisou renomear todos os*.dl_
arquivos*.dll
durante a instalação do pacote.No entanto, essa solução ainda não copiava os binários nativos no diretório de saída de outro projeto que referencia o que inicialmente inclui o pacote NuGet. Você ainda precisa fazer referência ao pacote NuGet no seu projeto "final" também.
fonte
DllNotFoundException
lançado.<NoWarn>NU5100</NoWarn>
ao seu arquivo de projetoAqui está uma alternativa que usa o
.targets
para injetar a DLL nativa no projeto com as seguintes propriedades.Build action
=None
Copy to Output Directory
=Copy if newer
O principal benefício dessa técnica é que a DLL nativa é copiada transitivamente para a
bin/
pasta de projetos dependentes .Veja o layout do
.nuspec
arquivo:Aqui está o
.targets
arquivo:Isso insere
MyNativeLib.dll
como se fosse parte do projeto original (mas, curiosamente, o arquivo não é visível no Visual Studio).Observe o
<Link>
elemento que define o nome do arquivo de destino nabin/
pasta.fonte
Content
paraNone
?Se mais alguém se deparar com isso.
O
.targets
nome do arquivo DEVE ser igual ao ID do pacote NuGetQualquer outra coisa não vai funcionar.
Os créditos vão para: https://sushihangover.github.io/nuget-and-msbuild-targets/
Eu deveria ter lido mais detalhadamente, como é realmente observado aqui. Levou-me idades ..
fonte
É um pouco tarde, mas eu criei um pacote de nuget exatamente para isso.
A idéia é ter uma pasta especial adicional em seu pacote de nuget. Tenho certeza que você já conhece a Lib e o Content. O pacote de pepitas que criei procura uma pasta chamada Saída e copia tudo o que está lá na pasta de saída dos projetos.
A única coisa que você precisa fazer é adicionar uma dependência de nuget ao pacote http://www.nuget.org/packages/Baseclass.Contrib.Nuget.Output/
Eu escrevi um post sobre isso: http://www.baseclass.ch/blog/Lists/Beitraege/Post.aspx?ID=6&mobile=0
fonte
Existe uma solução C # pura que eu acho bastante fácil de usar e não preciso me preocupar com as limitações do NuGet. Siga esses passos:
Inclua a biblioteca nativa no seu projeto e defina sua propriedade Build Action como
Embedded Resource
.Cole o seguinte código na classe em que você invocou esta biblioteca.
Chame esse método do construtor estático da seguinte maneira
UnpackNativeLibrary("win32");
e ele descompactará a biblioteca no disco antes de você precisar. Obviamente, você precisa ter certeza de que possui permissões de gravação para essa parte do disco.fonte
Esta é uma pergunta antiga, mas agora tenho o mesmo problema e encontrei uma resposta um pouco complicada, mas muito simples e eficaz: crie na pasta Nuget Standard Content a seguinte estrutura com uma subpasta para cada configuração:
Ao compactar o arquivo nuspec, você receberá a seguinte mensagem para cada biblioteca nativa nas pastas Debug and Release:
Não precisamos dessa "solução" porque esse é apenas o nosso objetivo: que as bibliotecas nativas não sejam adicionadas como referências ao NET Assemblies.
As vantagens são:
As desvantagens são:
fonte
Não consigo resolver o seu problema exato, mas posso lhe dar uma sugestão.
Seu principal requisito é: "E não registre automaticamente a referência" .....
Então você terá que se familiarizar com os "itens da solução"
Veja a referência aqui:
Adicionando itens no nível da solução em um pacote NuGet
Você precisará escrever um vodu do powershell para obter a cópia da sua dll nativa em sua casa (novamente, porque você NÃO deseja que o vodu de adição automática de referência seja acionado)
Aqui está um arquivo ps1 que escrevi ... para colocar arquivos em uma pasta de referências de terceiros.
Há o suficiente para você descobrir como copiar sua dll nativa para alguma "casa" ... sem ter que começar do zero.
Novamente, não é um golpe direto, mas é melhor que nada.
fonte
Coloque é a pasta de conteúdo
o comando
nuget pack [projfile].csproj
fará isso por você automaticamente se você marcar os arquivos como conteúdo.edite o arquivo do projeto conforme mencionado aqui, adicionando o elemento ItemGroup & NativeLibs & None
trabalhou para mim
fonte