Próbuję utworzyć pakiet NuGet dla zestawu .Net, który wykonuje pinvoke do natywnej biblioteki dll win32. Muszę spakować zarówno zestaw, jak i natywną bibliotekę dll z zestawem dodanym do odwołań do projektu (nie ma problemu w tej części), a natywną bibliotekę dll należy skopiować do katalogu wyjściowego projektu lub innego katalogu względnego.
Moje pytania to:
- Jak spakować natywną bibliotekę dll bez próby dodania jej do listy referencji przez Visual Studio?
- Czy muszę napisać plik install.ps1, aby skopiować natywną bibliotekę dll? Jeśli tak, jak mogę uzyskać dostęp do zawartości pakietu w celu jego skopiowania?
nuget
nuget-package
nuget-spec
AlonFStackoverflow
źródło
źródło
Odpowiedzi:
Użycie elementu
Copy
docelowego w pliku docelowym do skopiowania wymaganych bibliotek nie spowoduje skopiowania tych plików do innych projektów, które odwołują się do projektu, co spowoduje utworzenie plikuDllNotFoundException
. Można to zrobić za pomocą znacznie prostszego pliku docelowego, używającNone
elementu, ponieważ program MSBuild skopiuje wszystkieNone
pliki do projektów odwołujących się.Dodaj plik docelowy do
build
katalogu pakietu nuget wraz z wymaganymi bibliotekami natywnymi. Plik docelowy będzie zawierał wszystkiedll
pliki we wszystkich katalogach podrzędnychbuild
katalogu. Aby więc dodać wersjęx86
ix64
wersję biblioteki natywnej używanej przez zestawAny CPU
zarządzany, otrzymamy strukturę katalogów podobną do następującej:To samo
x86
ix64
katalogi zostaną utworzone w katalogu wyjściowym projektu po zbudowaniu. Jeśli nie trzeba podkatalogi wtedy**
i%(RecursiveDir)
mogą być usunięte i zamiast zawierać wymagane pliki wbuild
katalogu bezpośrednio. W ten sam sposób można dodać inne wymagane pliki zawartości.Pliki dodane
None
w pliku docelowym nie będą wyświetlane w projekcie po otwarciu w programie Visual Studio. Jeśli zastanawiasz się, dlaczego nie używamContent
folderu w nupkg, to dlatego, że nie ma możliwości ustawieniaCopyToOutputDirectory
elementu bez użycia skryptu PowerShell (który będzie uruchamiany tylko w programie Visual Studio, a nie z wiersza polecenia, na serwerach kompilacji lub w inne IDE i nie jest obsługiwane w projektach project.json / xproj DNX ) i wolę używać aLink
do plików, zamiast mieć dodatkową kopię plików w projekcie.Aktualizacja: Chociaż powinno to również działać,
Content
aNone
nie wydaje się, że jest błąd w msbuild, więc pliki nie będą kopiowane do projektów odwołujących się więcej niż jeden krok usunięty (np. Proj1 -> proj2 -> proj3, proj3 nie pobierze plików z pakietu NuGet proj1, ale proj2 będzie).źródło
'$(MSBuildThisFileDirectory)' != '' And HasTrailingSlash('$(MSBuildThisFileDirectory)')
wymagany? Myślałem, żeMSBuildThisFileDirectory
jest zawsze ustawione. Kiedy tak by się nie stało?**\*.dll
? To kopiowanie wszystkich.dll
plików we wszystkich katalogach. Możesz łatwo**\*.*
skopiować całe drzewo katalogów.Niedawno miałem ten sam problem, gdy próbowałem zbudować pakiet NuGet EmguCV, w tym zarówno zarządzane zestawy, jak i niezarządzane udostępnione biblioteki (które również musiały być umieszczone w
x86
podkatalogu), które musiały być automatycznie kopiowane do katalogu wyjściowego kompilacji po każdej kompilacji .Oto rozwiązanie, które wymyśliłem, które opiera się tylko na NuGet i MSBuild:
Umieść zarządzane zespoły w
/lib
katalogu pakietu (część oczywista), a niezarządzane biblioteki współużytkowane i powiązane pliki (np. Pakiety pdb) w/build
podkatalogu (zgodnie z opisem w dokumentacji NuGet ).Zmień nazwę wszystkich niezarządzanych
*.dll
zakończeń plików na coś innego, na przykład*.dl_
aby zapobiec narzekaniu przez program NuGet na temat umieszczania domniemanych zestawów w niewłaściwym miejscu ( „Problem: zestaw poza folderem lib” ).Dodaj niestandardowy
<PackageName>.targets
plik do/build
podkatalogu z podobną zawartością (patrz opis poniżej):Powyższy
.targets
plik zostanie wstrzyknięty podczas instalacji pakietu NuGet w docelowym pliku projektu i jest odpowiedzialny za kopiowanie natywnych bibliotek do katalogu wyjściowego.<AvailableItemName Include="NativeBinary" />
dodaje nowy element „Akcja kompilacji” dla projektu (który jest również dostępny na liście rozwijanej „Akcja kompilacji” w programie Visual Studio).<NativeBinary Include="...
dodaje biblioteki natywne umieszczone w/build/x86
bieżącym projekcie i udostępnia je celowi niestandardowemu, który kopiuje te pliki do katalogu wyjściowego.<TargetPath>x86</TargetPath>
dodaje niestandardowe metadane do plików i informuje cel niestandardowy, aby skopiować pliki natywne do plikux86
podkatalogu rzeczywistego katalogu wyjściowego.Plik
<PrepareForRunDependsOn ...
Blok dodaje cel niestandardowy do listy celów build zależy, zobacz Microsoft.Common.targets plik o szczegóły.Cel niestandardowy,,
CopyNativeBinaries
zawiera dwa zadania kopiowania. Pierwszy z nich odpowiada za kopiowanie dowolnych*.dl_
plików do katalogu wyjściowego podczas zmiany ich rozszerzenia z powrotem na oryginalne*.dll
. Drugi po prostu kopiuje resztę (na przykład dowolne*.pdb
pliki) do tej samej lokalizacji. Można to zastąpić pojedynczym zadaniem kopiowania i skryptem install.ps1, który musiał zmienić nazwy wszystkich*.dl_
plików na*.dll
podczas instalacji pakietu.Jednak to rozwiązanie nadal nie skopiowałoby natywnych plików binarnych do katalogu wyjściowego innego projektu odwołującego się do tego, który początkowo zawiera pakiet NuGet. Nadal musisz odwoływać się do pakietu NuGet w swoim „ostatecznym” projekcie.
źródło
DllNotFoundException
.<NoWarn>NU5100</NoWarn>
do pliku projektuOto alternatywa, która używa
.targets
do wstrzyknięcia natywnej biblioteki DLL w projekcie z następującymi właściwościami.Build action
=None
Copy to Output Directory
=Copy if newer
Główną zaletą tej techniki jest to, że natywna biblioteka DLL jest przejściowo kopiowana do
bin/
folderu projektów zależnych .Zobacz układ
.nuspec
pliku:Oto
.targets
plik:Spowoduje to wstawienie
MyNativeLib.dll
pliku tak, jakby był częścią oryginalnego projektu (ale co ciekawe, plik nie jest widoczny w programie Visual Studio).Zwróć uwagę na
<Link>
element, który ustawia nazwę pliku docelowego wbin/
folderze.źródło
Content
naNone
?Jeśli ktoś się na to natknie.
Nazwa
.targets
pliku MUSI być równa identyfikatorowi pakietu NuGetCokolwiek innego nie zadziała.
Kredyty idą do: https://sushihangover.github.io/nuget-and-msbuild-targets/
Powinienem był przeczytać dokładniej, ponieważ zostało to tutaj odnotowane. Zajęło mi to wieki ...
źródło
Jest trochę za późno, ale specjalnie do tego stworzyłem pakiet nuget.
Pomysł polega na tym, aby mieć dodatkowy specjalny folder w pakiecie nuget. Jestem pewien, że znasz już Lib i Content. Utworzony przeze mnie pakiet NuGet szuka folderu o nazwie Wyjście i skopiuje wszystko, co się tam znajduje, do folderu wyjściowego projektów.
Jedyne, co musisz zrobić, to dodać zależność NuGet do pakietu http://www.nuget.org/packages/Baseclass.Contrib.Nuget.Output/
Napisałem o tym post na blogu: http://www.baseclass.ch/blog/Lists/Beitraege/Post.aspx?ID=6&mobile=0
źródło
Istnieje czyste rozwiązanie C #, które wydaje mi się dość łatwe w użyciu i nie muszę przejmować się ograniczeniami NuGet. Wykonaj następujące kroki:
Uwzględnij bibliotekę natywną w projekcie i ustaw jej właściwość Build Action na
Embedded Resource
.Wklej następujący kod do klasy, w której PInvoke tej biblioteki.
Wywołaj tę metodę z konstruktora statycznego, jak poniżej,
UnpackNativeLibrary("win32");
a rozpakuje bibliotekę na dysk tuż przed jej użyciem. Oczywiście musisz mieć pewność, że masz uprawnienia do zapisu w tej części dysku.źródło
To jest stare pytanie, ale mam teraz ten sam problem i znalazłem rozwiązanie, które jest trochę trudne, ale bardzo proste i skuteczne: utwórz w folderze zawartości standardowej Nuget następującą strukturę z jednym podfolderem dla każdej konfiguracji:
Po spakowaniu pliku nuspec zostanie wyświetlony następujący komunikat dla każdej biblioteki natywnej w folderach Debug i Release:
Nie potrzebujemy takiego „rozwiązania”, ponieważ jest to tylko nasz cel: aby biblioteki natywne nie były dodawane jako odwołania do zestawów NET.
Zalety to:
Wady to:
źródło
Nie mogę rozwiązać konkretnego problemu, ale mogę zasugerować.
Twój kluczowy wymóg to: „I nie rejestruj automatycznie referencji” .....
Musisz więc zapoznać się z „elementami rozwiązań”
Zobacz odniesienie tutaj:
Dodawanie elementów na poziomie rozwiązania w pakiecie NuGet
Będziesz musiał napisać kilka voodoo w PowerShell, aby pobrać kopię swojej natywnej biblioteki dll do jej domu (ponownie, ponieważ NIE chcesz, aby voodoo automatycznie dodawało referencje)
Oto plik ps1, który napisałem ..... aby umieścić pliki w folderze referencyjnym innej firmy.
Jest tam wystarczająco dużo miejsca, aby dowiedzieć się, jak skopiować natywną bibliotekę dll do jakiegoś „domu” ... bez konieczności rozpoczynania od zera.
Ponownie, nie jest to trafienie bezpośrednie, ale lepsze niż nic.
źródło
Umieść to w folderze zawartości
polecenie
nuget pack [projfile].csproj
zrobi to automatycznie, jeśli oznaczysz pliki jako zawartość.następnie edytuj plik projektu, jak wspomniano tutaj, dodając element ItemGroup & NativeLibs & None
pracował dla mnie
źródło