I have build chains in TeamCity, where the dependent artifact is copied to /bin directory of the main project. The project file references the artifact. That all works.
What I want is to allow a project file include, instead of the binary reference, when building/debugging from Visual Studio. I have tried some approaches, such as using conditionals in the project file, but is there a nice clean way to approach this?
May be there is the part of solution.
May way of using several referencing types of projs.
<ItemGroup Condition=" '$(ReferencedDACPAC)' == '' ">
<ProjectReference Include="..\OmniUS\OmniUS.sqlproj">
<Name>OmniUS</Name>
<Project>{26075a62-f6b0-40c3-baa2-b9a9829da3c4}</Project>
<Private>False</Private>
<SuppressMissingDependenciesErrors>False</SuppressMissingDependenciesErrors>
</ProjectReference>
<ProjectReference Include="..\OmniUS_Finance_Jural\OmniUS_Finance_Jural.sqlproj">
<Name>OmniUS_Finance_Jural</Name>
<Project>{c8b0aee7-c2a4-4370-8451-13b455bb5363}</Project>
<Private>False</Private>
<SuppressMissingDependenciesErrors>False</SuppressMissingDependenciesErrors>
</ProjectReference>
</ItemGroup>
<ItemGroup Condition=" '$(ReferencedDACPAC)' == 'true' ">
<ArtifactReference Include="..\DacPacs\OmniUS.sqlproj.dacpac">
<SuppressMissingDependenciesErrors>False</SuppressMissingDependenciesErrors>
</ArtifactReference>
<ArtifactReference Include="..\DacPacs\OmniUS_Finance_Jural.sqlproj.dacpac">
<SuppressMissingDependenciesErrors>False</SuppressMissingDependenciesErrors>
</ArtifactReference>
</ItemGroup>
When I build in TeamCity, I send ReferencedDACPAC as the "System" variable in the build, and thus refer to "ArtifactReference". When i build in VisualStudio, there is no var and the referencing occurs as "ProjectReference".
Related
I'm developing plugin for nopcommerce,
I'm using VS 2019 and nopcommerce 4.40.4(.net 5)
I should use a nuget package in my plugin,
If I set CopyLocalLockFileAssemblies to true, when I build my project, it created runtimes folder, which is about 65 MB,
If I set CopyLocalLockFileAssemblies to false, it does not create runtimes folder, but, the dll of nuget package which I should use, not included in the build folder,
would you please help me about this?
Note: set copy local to no, make no difference when I change for Nop.Services which I use in the project
this is my csproj and my the package is > SmsIrRestful.NetCore :
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<OutputPath>..\..\Presentation\Nop.Web\Plugins\AttributeStockSMS</OutputPath>
<OutDir>$(OutputPath)</OutDir>
<!--Set this parameter to true to get the dlls copied from the NuGet cache to the output of your project.
You need to set this parameter to true if your plugin has a nuget package
to ensure that the dlls copied from the NuGet cache to the output of your project-->
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<ItemGroup>
<ClearPluginAssemblies Include="$(MSBuildProjectDirectory)\..\..\Build\ClearPluginAssemblies.proj" />
</ItemGroup>
<ItemGroup>
<None Remove="plugin.json" />
</ItemGroup>
<ItemGroup>
<Content Include="plugin.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="SmsIrRestful.NetCore" Version="1.1.5" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Libraries\Nop.Services\Nop.Services.csproj">
<Private>false</Private>
</ProjectReference>
</ItemGroup>
<Target Name="NopTarget" AfterTargets="Build">
<!-- Delete unnecessary libraries from plugins path -->
<MSBuild Projects="#(ClearPluginAssemblies)" Properties="PluginPath=$(MSBuildProjectDirectory)\$(OutDir)" Targets="NopClear" />
</Target>
</Project>
Instead of using NuGet reference, include the dll file of that NuGet package. For example, You are going to use TaxJar library then follow these steps.
Added NuGet reference.
Right click on NuGet package and go to properties.
Copy path value from property values as below.
Go to that path in file explorer.
Find dll file(s) from there, copy-paste into your plugin folder and add refence.
Repeat same procedures for dependent packages also (if any).
Mark as Copy Local to Yes from properties.
So I have a requirement where my project should use different GoogleServices files for Android/iOS while using different configurations like for eg while I am using the debug configuration it should use the debug version of the file and in the release, it should use the release version.
Something similar to
Xamarin firebase different google-services,json for different build configurations
When I follow the accepted the answer I get a compile-time error saying
The command COPY /Y "$(ProjectDir)GoogleServices\google-services-development.json" "$(ProjectDir)google-services.json" exited with code 1.
I tried clean build and cleaning bin/obj nothing changed.
So I tried the other solution mentioned here and what happens is the GoogleServices files(all of them) are excluded from the project and nothing happens if I build and run. I am unsure if this is even working or not.
I have added the following lines in my csproj for release and debug respectively
<ItemGroup Condition="'$(Configuration)'=='Debug'">
<GoogleServicesJson Include="Dev\google-services.json">
<Link>google-services.json</Link>
</GoogleServicesJson>
</ItemGroup>
<ItemGroup Condition="'$(Configuration)'=='Release'">
<GoogleServicesJson Include="Prod\google-services.json">
<Link>google-services.json</Link>
</GoogleServicesJson>
</ItemGroup>
Where dev and prod are root folders in my native android project
Any suggestions are welcome.
You have to edit *.csproj file.
Using a solution to use multiple Info.plist (LogicalName tag) and Condition tag you can play with any other files all you want.
For Android I added two *.json files to Resources folder and added this snippet to my *.csproj file:
<ItemGroup Condition=" '$(Configuration)' != 'Release' ">
<GoogleServicesJson Include="Resources\dev-google-services.json">
<LogicalName>Resources\google-services.json</LogicalName>
</GoogleServicesJson>
</ItemGroup>
<ItemGroup Condition=" '$(Configuration)' == 'Release' ">
<GoogleServicesJson Include="Resources\release-google-services.json">
<LogicalName>Resources\google-services.json</LogicalName>
</GoogleServicesJson>
</ItemGroup>
In this example I use release-google-services.json for the "Release" build configuration, and dev-google-services.json for any other configurations.
Same for iOS. I added two *.plist files to root folder and added this snippet to my *.csproj file:
<ItemGroup Condition=" '$(Configuration)' != 'AppStore' ">
<BundleResource Include="Dev-GoogleService-Info.plist">
<LogicalName>GoogleService-Info.plist</LogicalName>
</BundleResource>
</ItemGroup>
<ItemGroup Condition=" '$(Configuration)' == 'AppStore' ">
<BundleResource Include="Release-GoogleService-Info.plist">
<LogicalName>GoogleService-Info.plist</LogicalName>
</BundleResource>
</ItemGroup>
This approach works for me. I guess it doesn't matter where you put these files and how you name them. Just use the LogicalName that you need.
Also, you can combine it with other variables to compose more complicated conditions. For example, in order to build two *.apk in Release configuration with different *.json files you can:
<ItemGroup Condition=" '$(Configuration)|$(DynamicConstants)' != 'Release|' ">
<GoogleServicesJson Include="Resources\dev-google-services.json">
<LogicalName>Resources\google-services.json</LogicalName>
</GoogleServicesJson>
</ItemGroup>
<ItemGroup Condition=" '$(Configuration)|$(DynamicConstants)' == 'Release|' ">
<GoogleServicesJson Include="Resources\release-google-services.json">
<LogicalName>Resources\google-services.json</LogicalName>
</GoogleServicesJson>
</ItemGroup>
Build your project like this:
msbuild MobileApp.sln /p:Configuration=Release /p:DynamicConstants=DEBUG
When you use DEBUG parameter you build Release apk with dev-google-services.json.
When you omit DEBUG parameter you build Release apk with release-google-services.json.
I have an ASP.NET Core project that builds properly with VS but fails with TeamCity.
It is a project that compiles to a library, but TeamCity tries to build it as an executable, and complains about the lack of 'main':
CSC error CS5001: Program does not contain a static 'Main' method suitable for an entry point
The content of the .csproj file are as follow:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputType>Library</OutputType>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net462</TargetFramework>
<RuntimeIdentifier>win7-x86</RuntimeIdentifier>
<OutputTypeEx>library</OutputTypeEx>
<StartupObject />
<AssemblyName>Test</AssemblyName>
<RootNamespace>Test</RootNamespace>
</PropertyGroup>
<ItemGroup>
<Folder Include="wwwroot\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.3" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
</ItemGroup>
</Project>
Visual studio has no problem building the dll file.
To reproduce:
Create an ASP.NET Core (.NET Framework) project
Change the output type to library
Remove the program.cs / startup.cs files
Compile with Visual Studio to confirm a library is being built
Build with Team City and an error will appear
To avoid that error, Please look into this SO post or this
You should be using the dotnet core plugin or you can easily
configure dotnet build command(if dotnet is present in your build
servers).
Or you can refer the MusicStore build.cmd file for reference. This basically downloads and installs the dotnet and all the dependencies and then builds the project.
Hope it helps!
I found a workaround; in the project file, VS puts this:
<OutputTypeEx>library</OutputTypeEx>
I need to add one line:
<OutputType>Library</OutputType>
<OutputTypeEx>library</OutputTypeEx>
So it looks like the build with TeamCity is not handling the OutputTypeEx propery but it handles the OutputType one.
I still see this as a bug, but at least there is a workaround.
I have two projects, let's call them Project A and Project B.
Project A has a CopyToOutputDirectory content item, as follows:
<ItemGroup>
<Content Include="MyExampleDependency.txt">
<Link>MyFunOutputLocation\MyExampleDependency.txt</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
Project B references Project A:
<ItemGroup>
<ProjectReference Include="..\..\Shared\Project A.csproj">
<Project>{My GUID here</Project>
<Name>Project A</Name>
</ProjectReference>
</ItemGroup>
When I build Project B, it is smart enough to copy the .dll produced by Project A, as well as this text file, to the output. That is, I end up with something like this when I build Project B:
bin\Project A\Project A.dll
bin\Project A\MyFunOutputLocation\MyExampleDependency.txt
bin\Project B\Project A.dll
bin\Project B\Project B.exe
bin\Project B\MyFunOutputLocation\MyExampleDependency.txt
I have a new dependency that I want to start generating in Project A; for example from a T4 transform. This could be a file I generate with an <Exec task, or a file generated by some custom target, or similar. For example:
<ItemGroup>
<Content Include="Foo.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<OutputFilePath>$(OutDir)</OutputFilePath>
<LastGenOutput>Foo.xml</LastGenOutput>
</Content>
</ItemGroup>
Now when I build I end up with something like this:
bin\Project A\Project A.dll
bin\Project A\Foo.xml <-- Not copied to Project B!
bin\Project A\MyFunOutputLocation\MyExampleDependency.txt
bin\Project B\Project A.dll
bin\Project B\Project B.exe
bin\Project B\MyFunOutputLocation\MyExampleDependency.txt
Note that the generated file which is required for Project A.dll to work is not being copied alongside that dll when it gets copied into Project B. How do I inform Project B that it needs to copy this file from Project A (without editing Project B's .csproj file)?
If it's just a design-time Foo.tt output then it's as simple as expanding it in Solution Explorer and marking Foo.txt with appropriate Copy To Output Directory, just remember to mark it again if you ever change the extension as that'll delete and read it into the itemgroup losing the CopyToOutputDirectory metadata.
If it's an outside task, then you need to hook into a delayed event (so it doesn't pollute explorer on load or even error on clean) in Project A and add it to Content preferably with a wildcard or exists condition. Keep in mind that event you choose needs to run after your custom task but before _CopyFilesMarkedCopyLocal, e.g. if you create a file in PreBuildEvent of Project A and hook into BeforeBuild it won't work on clean build on Project B, you'd have to rebuild it again as BeforeBuild runs first and won't find anything at point of evaluation.
Project A.csproj
<Target Name="BeforeBuild">
<ItemGroup>
<Content Include="$(OutputPath)\Bar.txt" Condition="Exists('$(OutputPath)\Bar.txt')">
<Link>Bar.txt</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Target>
Edit:
Try the following.
In Project A define a Foo target for delayed/ondemand inclusion of the T4 output.
<Target Name="Foo">
<ItemGroup>
<Content Include="Foo.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Target>
You said you're transforming on build, so somewhere in the project you have the TextTemplating import that defines Transform target and its dependencies.
<PropertyGroup>
<TransformOnBuild>true</TransformOnBuild>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v12.0\TextTemplating\Microsoft.TextTemplating.targets" />
Hook into one of them, i.e. AfterTransform, after the .targets import.
<PropertyGroup>
<AfterTransform>$(AfterTransform);Foo</AfterTransform>
</PropertyGroup>
That'll cover 90% of cases, the 9% left is building Project B directly in Visual Studio individually of Project A. The Rebuild would work out right thanks to AfterTransform but we need to hook into the Import since as you saw BeforeBuild is not executed as there are no changes and Visual Studio caches everything. We do this with InitialTargets on Project A.
<Project InitialTargets="Foo"
The final 1% is when you delete the .xml manually and build again as oppose to rebuild, but it's identical behaviour to deleting the .pdb, cached VS build will copy it again only if the .dll itself is missing or different.
Is there a way to automatically use a separate app.config when building in release mode?
In other words, I want to test with one app.config, and release with another.
Currently, I keep a separate copy called app.config.production, and manually overwrite bin\Release\Application.exe.config after building for release.
Unload the project in Solution Explorer via the context menu.
Edit the .csproj file via the context menu and add this:
<PropertyGroup>
<AppConfig>App.$(Configuration).config</AppConfig>
</PropertyGroup>
I have recently posted a supremely belated response to a similar SO topic:
https://stackoverflow.com/a/27546685/2798367
I will repeat it here for clarity:
This is somewhat late to the party, but I stumbled upon a nice way of implementing the web.transform approach for app.config files. (i.e. it makes use of the namespace http://schemas.microsoft.com/XML-Document-Transform)
I think it is "nice" because it is a pure xml approach and doesn't require 3rd party software.
A parent / default App.config file is descended from, according to your various build configurations.
These descendants then only override what they need to.
In my opinion this is much more sophisticated and robust than having to maintain x number of config files which get copied in their entirety, such as in other answers.
A walkthrough has been posted here: http://mitasoft.wordpress.com/2011/09/28/multipleappconfig/
Look, Mom - No explicit post-build events in my IDE!
A clean solution is to group 2 files App.Debug.config and App.Release.config into App.config and change the good file into App.config depending on the configuration at compile time:
<ItemGroup>
<None Include="App.config" />
<None Include="App.Debug.config">
<DependentUpon>App.config</DependentUpon>
</None>
<None Include="App.Release.config">
<DependentUpon>App.config</DependentUpon>
</None>
</ItemGroup>
<Target Name="SetAppConfig" BeforeTargets="Compile">
<Copy SourceFiles="App.Debug.config" DestinationFiles="App.config" OverwriteReadOnlyFiles="true" Condition=" '$(Configuration)' == 'Debug' " />
<Copy SourceFiles="App.Release.config" DestinationFiles="App.config" OverwriteReadOnlyFiles="true" Condition=" '$(Configuration)' == 'Release' " />
</Target>
With this solution you will get something like this in Visual Studio:
A simple and fast way is to create a second file "App.release.config" and insert this pre-build event:
IF $(ConfigurationName) == Release COPY /Y "$(ProjectDir)App.config" "$(ProjectDir)App.debug.config"
IF $(ConfigurationName) == Release COPY /Y "$(ProjectDir)App.release.config" "$(ProjectDir)App.config"
And this post build event:
IF $(ConfigurationName) == Release COPY /Y "$(ProjectDir)App.debug.config" "$(ProjectDir)App.config"
This might be a bit odd, but it will allow you to keep using the .Settings files as debug settings, that are still linked to the App.config. The App.release.config must be build by hand, but it's pretty easy to switch this functionality.
I highly recommend SlowCheetah for app.config transformations. Visit this nuget gem here Visual Studio Gallery
Similar to top answer but with this approach you can see the actual file if preferred and intellisense doesn't complain in csproj file:
<Target Name="SetAppConfig" BeforeTargets="Compile">
<Copy SourceFiles="debug.config" DestinationFiles="app.config" OverwriteReadOnlyFiles="true" Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' " />
<Copy SourceFiles="release.config" DestinationFiles="app.config" OverwriteReadOnlyFiles="true" Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " />
</Target>
I don't know if this helps, but app.config will recognise the standard MSBUILD substitution strings such as $(Configuration).