Conditional references in .NET project, possible to get rid of warning? - c#

I have two references to a SQLite assembly, one for 32-bit and one for 64-bit, which looks like this (this is a test project to try to get rid of the warning, don't get hung up on the paths):
<Reference Condition=" '$(Platform)' == 'x64' " Include="System.Data.SQLite, Version=1.0.61.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=AMD64">
<SpecificVersion>True</SpecificVersion>
<HintPath>..\..\LVK Libraries\SQLite3\version_1.0.65.0\64-bit\System.Data.SQLite.DLL</HintPath>
</Reference>
<Reference Condition=" '$(Platform)' == 'x86' " Include="System.Data.SQLite, Version=1.0.65.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=x86">
<SpecificVersion>True</SpecificVersion>
<HintPath>..\..\LVK Libraries\SQLite3\version_1.0.65.0\32-bit\System.Data.SQLite.DLL</HintPath>
</Reference>
This produces the following warning:
Warning 1 The referenced component 'System.Data.SQLite' could not be found.
Is it possible for me to get rid of this warning?
One way I've looked at it to just configure my project to be 32-bit when I develop, and let the build machine fix the reference when building for 64-bit, but this seems a bit awkward and probably prone to errors.
Any other options?
The reason I want to get rid of it is that the warning is apparently being picked up by TeamCity and periodically flagged as something I need to look into, so I'd like to get completely rid of it.
Edit: Per the answer, I tried this:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
...
<SqlitePath>..\..\LVK Libraries\SQLite3\version_1.0.65.0\32-bit</SqlitePath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
...
<SqlitePath>..\..\LVK Libraries\SQLite3\version_1.0.65.0\32-bit</SqlitePath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
...
<SqlitePath>..\..\LVK Libraries\SQLite3\version_1.0.65.0\64-bit</SqlitePath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
...
<SqlitePath>..\..\LVK Libraries\SQLite3\version_1.0.65.0\64-bit</SqlitePath>
</PropertyGroup>
and then in my reference:
<Reference Include="System.Data.SQLite">
<SpecificVersion>False</SpecificVersion>
<HintPath>$(SqlitePath)\System.Data.SQLite.DLL</HintPath>
</Reference>
This got rid of the warning, but is it correct?

If there is no "AnyCPU" assembly for SQL Lite you are stuck with separate builds.
To do separate builds create a property that gives the correct path in a conditional property group and then use that property to have a single reference (i.e. move the conditional outside the references items group). There is an example of using such a property (for a custom FXCop extension) here, you can see lots of conditional properties being defined at the start of the .csproj file.
(Summary: VS doesn't handle all of the possibilities MSBuild does.)

As I see it, the problem with your original project was that you had <SpecificVersion>True</SpecificVersion> specifying System.Data.SQLite, Version=1.0.61.0, whereas the actual assembly was version 1.0.65. Fixing version in the assembly name in Reference ought to help.

Related

C# Switch dependencies depending on x86 or x64

We´ve got a third party dll which is either x86 or x64, now we have to change the x64 dll with x86 dependent on the TargetPlatform. May someone tell how?
The first try was to override the dll with a post build script.
With Configuration Manager we could brand the build with x86, x64 and with the macro $(PlatformName) we could name the dll path relative to the platform (x64/x86)
Important to know is, that the macro has to be set in *.csproj file directly e.g.:
<Reference Include="DLLNAME, Version=4.9.0.0, Culture=neutral, PublicKeyToken=TOKEN,
processorArchitecture=$(PlatformName)">
<HintPath>Lib\$(PlatformName)\DLLNAME.dll</HintPath>
</Reference>
Also if there is a Plugin which should be compiled into the main-programm folder, the build path has to be changed in *.csproj file directly. E.g:
<OutputPath>..\..\bin\$(PlatformName)\Debug\Features\</OutputPath>
Thats because VS escapes the '$(' and ')'
EDIT:
Too fast. The <OutputPath> doesn´t understand macros. Therefore we had to change the outputpath for every Build-Configuration. Eg:
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>..\..\bin\x86\Debug\Features\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>..\..\bin\x86\Release\Features\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
EDIT 2: For only x64 or x86 dependencies there is the Condition-Attribute which can seperate some cs-Files from x86 or x64 eg:
<Reference Condition="'$(Platform)'=='x64'" Include="STPadLibNet">
<HintPath>Lib\x64\DLLNAME.dll</HintPath>
</Reference>
and for some Clases u can use it like:
<Compile Condition="'$(Platform)'=='x64'" Include="MyClass.cs" />

.NET: Different target frameworks via project configuration

I would like to have two different .net framework targets via configuration in Visual Studio 2015. While for references, you can edit the CSPROJ file and add a conditions, this does not seem to work for the TargetFrameworkVersion in the first PropertyGroup of the file. I have the impression that any Condition in that element causes VS to completely ignore this element and to fall back to the default value of "v4.0".
Is there any way I can get different target framework versions for different configurations?
This is what I tried in the CSPROJ file:
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
...
<!-- this is what VS2015 would put into the file:
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
-->
<!-- this is what does not work: -->
<TargetFrameworkVersion Condition="'$(Configuration)' == 'OLD_Debug' OR '$(Configuration)' == 'OLD_Release'">v3.5</TargetFrameworkVersion>
<TargetFrameworkVersion Condition="'$(Configuration)' == 'NEW_Debug' OR '$(Configuration)' == 'NEW_Release'">v4.0</TargetFrameworkVersion>
...
</PropertyGroup>
...
</Project>
A similar approach with conditions for the assembly references works fine.
EDIT
I found a similar Stackoverflow question:
Targetting multiple .net framework versions by using different project configurations and tried the approach suggested in the non-accepted answer to remove the TargetFrameworkVersion from the first PropertyGroup block, and edit the later <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'OLD_Debug|AnyCPU' "> blocks to contain it, but my assembly is still compiled for framework 3.5 no matter which configuration I use. At least if I look at the assembly from Powershell using [System.Reflection.Assembly]::LoadFrom("C:\PATH\MyAssembly.dll").ImageRuntimeVersion, I always get version 2, not 4.
The approach found in this answer to a similar question works:
Keep the first PropertyGroup without configuration specific settings, remove the TargetFrameworkVersion element from it. And add the TargetFrameworkVersion settings to the configuration specific PropertyGroups which are in the file anyway, just double them for debug/release:
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
...
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'OLD_Debug|AnyCPU' ">
...
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'OLD_Release|AnyCPU' ">
...
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'NEW_Debug|AnyCPU' ">
...
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'NEW_Release|AnyCPU' ">
...
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
</PropertyGroup>
...
</Project>
I verified this as follows:
My assembly references version 2.0.0.0 of the mscorlib assembly for the 3.5 framework (OLD_... configurations), and version 4.0.0.0 of mscorlib for the 4.0 framework (NEW_... configurations).
Using ILSpy, I found that the 3.5 version of my assembly has no attribute for the target framework, as this was only introduced since version 4, but the version 4 framework appears as an attribute of the assembly:
[assembly: TargetFramework(".NETFramework,Version=v4.0", FrameworkDisplayName = ".NET Framework 4")]

Define a conditional constant for all builds in Visual Studio

I have a project with some code. I want to determine is RyuJIT is used and if so then write RyuJIT otherwise LegacyJIT.
I write:
#if RuyJIT
Console.WriteLine("RyuJIT");
#else
Console.WriteLine("LegacyJIT");
#endif
then I'm trying to define a constant. So i open my .csproj in notepad and write following:
<PropertyGroup>
<DefineConstants Condition=" $(TargetFrameworkVersion.Replace('v', '')) >= 4.6 ">RyuJIT</DefineConstants>
</PropertyGroup>
But it doesn't work: constant is not defined thus second line is always compiled for any target framework. What am I doing wrong? How can I share this constant between builds?
Solved with Choose node. Additionaly, now I'm able to reference .Net 4.6-only dlls.
<Choose>
<When Condition=" $(TargetFrameworkVersion.Replace('v', '')) >= 4.6 ">
<ItemGroup>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.1.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<PropertyGroup>
<DefineConstants>SIMD</DefineConstants>
</PropertyGroup>
</When>
</Choose>
I replaced RyuJIT with SIMD because it's more suitable

conditional references in visual studio - how to define the customized variable

I have a project which should reference other projects
done it this way:
<Reference Include="referencedDll" Condition=" '$(Configuration)' == 'Debug' ">
<HintPath>..\Resources\External DLLs\referencedDll.dll</HintPath>
</Reference>
this works fine and copies the dll just in case it is in debug.
but I want it not to depend on debug/ release but some other variable definition
something like:
<Reference Include="referencedDll" Condition=" '$(ReleaseType)' == 'INTERNAL_RELEASE' ">
<HintPath>..\Resources\External DLLs\referencedDll.dll</HintPath>
</Reference>
I did not find how to define the ReleaseType variable?
+ is there any way to use the same variable for both #if in the code and for conditional referencing?
I saw the option to use use
Condition=" $(DefineConstants.Contains('INTERNAL_RELEASE'))"
but it did not work as I'd expect
I'm not completely sure if there is a way to do that in Visual studio.
If you are running the build from msbuild directly you can use /P:ReleaseType=INTERNAL_RELEASE.
In my project I ended up changing Configuration property and instead of having it as Debug and Release I have more values like , DEV,QA,STAGE, etc...

Any tool that can change all the References in the Solution for us?

When we have a solution with more than one project and some of these projects are using references to the project in the same solution, for debugging purposes we change the reference to point to the Project , not to the DLL ... well we do it with hand! I was wondering if there is tool that does this for us automatically? so when I have a solution and I run this tool, it should be able to point the references to their project references?
Maybe using a code generation tool using CodeSmith or T4 templates. There you could setup the mappings once, and recreate it automatically. You got to then figure out the deployment part of the genned code.
You might be able to use MSBuild to help you. If you edit your csprog file so that you have 2 ItemGroup blocks with your references...
<ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<Reference Include="System" />
...
</ItemGroup>
<ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
...
</ItemGroup>
... then you would get different references in different builds. Note, VS.NET might not refresh the list of references, but you'll see the difference when you build.
This may mean you need to update your csproj by hand, or run some tool to create these two sets of references, but from then on your builds will take care of things automatically.

Categories