Changing output directory for a dll project - c++

Trying to make the output of a dll project go into desired folders.
i have done this before, i don't understand why it doesn't work.
I have a dll wrapping up a lib. I need the output of the dll to be in $(SolutionDir)\output\x86\$(Configuration) instead of $(SolutionDir)\output\$(Platform)\$(Configuration)
So I edited the vcxproj file, added
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<OutDir>$(SolutionDir)\output\x86\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)\output\x86\$(Configuration)\obj\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<OutDir>$(SolutionDir)\output\x86\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)\output\x86\$(Configuration)\obj\$(ProjectName)\</IntDir>
</PropertyGroup>
In project Properties, I verified that the Output Directory and Intermediate Directory of the Win32 configurations, has changed to to $(SolutionDir)\output\x86\$(Configuration)\ and the respective intDir.
still, my output goes to Win32.
Looking at Command Line (in project properties) I still get the output going to Win32, and this is what really happens during build.
It worked for the lib, but it doesn't work for the dll.
Is there another place i must make this change ?

I can see - after testing a lot of options and searching every project text file, and not finding anything - that I must modify / replace the OutDir in the linker section, everywhere it appears, with the desired path.
I thought that would happen as soon as I set the OutDir...

Related

Set debug/run environment variable in Visual Studio 2017 C++ project?

I'm trying to set automatically run/debug environmental variables for my project in Visual Studio.
I mean, is there any CMake or C++ code line to do this not needing to do it manually?
Here are the instructions how to do it manually (what I want to avoid).
Here there is an still unsolved question about how to do it with Cmake (seems not to be possible).
I also tried with setenv() and putenv() in different ways but it didn't work, because the main function doesn't even run until that line of code, before an error message shows up: "Some.dll was not found" and the program stops.
If your dll is one you are intending to use, this answer details how to quickly ensure it is found at runtime (putting the DLL alongside the executable)
If by 'automatic' you mean in code, you can set environment variables in code using _putenv as described in this answer similar to what you seem to be describing.
ostringstream classSize;
classSize << "classSize=" << howManyInClass;
_putenv(classSize.str().c_str());
The solution I found is base on this answer.
Steps for the solution:
Create a UserTemplate.vcxproj.user file next to the CMakeLists.txt file, with the next content:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LocalDebuggerEnvironment>PATH=..\Your\Path\to\Binaries;%PATH%".</LocalDebuggerEnvironment>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
</Project>
Where ..\Your\Path\to\Binaries is the relative path to your binary
files (the two points at the beginning .. are optional, if you
want to go up in the relative directory path, you may want to use
them).
Add the next lines of code in the CMakeLists.txt file.
# Configure the template file
SET(USER_FILE main.vcxproj.user)
SET(OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/${USER_FILE})
CONFIGURE_FILE(UserTemplate.vcxproj.user ${USER_FILE} #ONLY)
Where ProjectName is the name of the VS project where you want to define your PATH variable.

ResolveAssemblyReference cannot find dll and I cannot force it to look where it is

I have solution with n csharp projects and cpp project on top, this cpp provides interfaces and headers so those csharp ones can be used in other cpp solutions.
The build machine is configured to build csharp project with anyCPU architecture so it provides single assembly per build in Solution\bin\Release. For cpp the anyCpu is not available so I build project twice and store assemblies in Solution\bin\Release\x86 and x64 folders.
This is all to get it packaged in nuget as a single package with .targets file to ease consumption in other cpp projects.
Issue is that cpp project is looking for csharp asseblies using ResolveAssemblyReference and cannot find it, giving missleading message:
ResolveAssemblyReferences:
Primary reference "Implementation".
Could not find dependent files. Expected file "C:\Jenkins\Workspace\Solution\bin\Release\x86\Implementation.dll" does not exist.
Could not find dependent files. Expected file "C:\Jenkins\Workspace\Solution\bin\Release\x86\Implementation.dll" does not exist.
Resolved file path is "C:\Jenkins\Workspace\Solution\bin\Release\x86\Implementation.dll".
Reference found at search path location "".
I tried to alternate ResolveAssemblyReferences behaviour using command line properties, custom targets/properties, but without any luck. The parameters described in https://learn.microsoft.com/en-us/visualstudio/msbuild/resolveassemblyreference-task?view=vs-2017 seem to be computed during the build process and I cannot inject any value, which should be in this case something like $(OutDir)..
The one feasable solution seems to be copy c# dlls into each cpp folder, but I dont think it is the way to solve it properly.
Closes I got is by using /p:ReferencePath like below:
"C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MsBuild\15.0\bin\MsBuild.exe" /p:BuildProjectReferences=false /p:Configuration=Release /p:DebugType=full /p:DebugSymbols=true /p:PlatformToolset=v120 /p:WindowsTargetPlatformVersion=8.1 /p:ForceImportBeforeCppTargets="C:\Jenkins\Workspace\Solution\Cpp.props" /p:OutDir="C:\Jenkins\Workspace\Solution\bin\Release\x86\" /p:Platform=Win32 /t:Build Interface\Interface.vcxproj /p:ReferencePath="C:\jenkins\workspace\Solution\bin\Release"
My custom Cpp.props does:
<Target Name="Output" BeforeTargets="ResolveAssemblyReferences">
<Message Text="AssemblySearchPaths: $(AssemblySearchPaths)" />
</Target>
and by adding /p:ReferencePath it got added to AssemblySearchPaths as second record, after {CandidateAssemblyFiles}; but it is still not finding those dlls

C++ Windows Driver MSB3030 could not copy the file '' because it was not found

VS2017, SDK/WDK, C++ project
we have a c++ solution (driver) that is shared across developers via Team Foundation Services - visualstudio.com (now called azure devops?).
When I perform a get latest source code, and want to rebuild the solution I get two MSB3030 errors:
"Could not copy the file "C:\path of my colleague his file" because it was not found."
I found it strange that I saw on one of the two errors a path of my colleague his pc. He works on C:\ I'm working on E:\
Unloading the project, I saw he path being set here:
<ItemGroup>
<FilesToPackage Include="C:\path of my colleague\foo.xml" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<PackageRelativeDirectory>
</PackageRelativeDirectory>
</FilesToPackage>
We cannot get this solution to build because of the MSB3030. First we have to clean the specific projects individually, rebuild it, then build another project etc.. a few steps to perform manually in the correct order , trial and error, drinking coffee, throwing bananas to the pc and praying that a monkey outputs the code correctly.
Has anyone seen somehting similar regarding MSB3030 errors?
On my pc I see the path of my colleague, but he doesn't see my path (strange!).
C:\Program Files (x86)\Windows
Kits\10\build\WindowsDriver.common.targets(1699,5): error MSB3030:
Could not copy the file 'C:...' because it was not found.
I've set the Any CPU to x64 because it doesn't make any sense for c++.
C++ Windows Driver MSB3030 could not copy the file '' because it was not found
The reason for this issue is that the path of the ItemGroup is an absolute path in the project file:
<ItemGroup>
<FilesToPackage Include="C:\path of my colleague\foo.xml" ...>
...
</FilesToPackage>
</ItemGroup>
Regardless of whether your colleague has added this file to source control, when you pull the code from the TFS server to your local and put the code in a different local folder, the absolute path will bring you a lot of trouble, you need to manually check the code on the TFS server for this file and you need to modify the absolute path of this file in your project. But this problem will reappear after your colleague updates after you submit your code. Because an absolute path cannot be assigned to two different paths C:\ and E:\.
To resolve this issue, you need to change the absolute path to a relative path in the source code. Generally, we prefer to add this file to the Solution/Project folder, then use the MSBuild Macros $(SolutionDir)/$(ProjectDir) to specify it.
Check Common macros for build commands and properties for some more details.
Hope this helps.

Define user macros in different property sheet

Is it somehow possible to do following:
branch.prop:
// excerpt
<PropertyGroup Label="UserMacros">
<Branch>Trunk</Branch>
</PropertyGroup>
And another property sheet, common.prop:
// excerpt
<PropertyGroup>
<OutDir>D:\output\$(Branch)\VW$(VW_VERSION)\$(KN_BUILD)\</OutDir>
<IntDir>D:\output\$(Branch)\VS_Output\$(VW_VERSION)\$(KN_BUILD)\$(ProjectName)\</IntDir>
</PropertyGroup>
Problem
The problem is, that I use both property sheets in my project and if I show my projects properties I see that it shows the correct output directory and intermediate directory (like e.g. ' D:\output\Trunk\VW2016\Debug\' ) but when I compile my project it does not work, meaning that the user macro is missing so that logs show lines like following:
Library "D:\output\\VS_Output\2016\Debug\SomeProject\SomeProject.lib" ...
Pay attention to \\ instead of \Trunk\ in the log line!
Is there some way that property sheets work with user macros defined in different property sheets? Something like nesting them e.g. or any other trick?
I want to avoid to define my output directory and intermediate directory in each project manually (which would work)...
NOT WORKING ALTERNATIVE IDEAS
use a prebuild script that reads out the current svn path and setting an environment variable => because the environment variable is only read by VS on VS start, so if the prebuild script changes it VS does not recognise this until it is restarted
Why do I need this
I need this because I'm forced quite often to switch between trunk and a branch to create a hotfix and so want to avoid long build times because of overwriting intermediate / output files...
You can import your branch.prop in common.prop, like this:
<ImportGroup Label="PropertySheets" >
<Import Project="branch.prop"/>
</ImportGroup>

$(OutDir) is not set to project Output directory

I have a C++/CLI dll project in Visual Studio 2013 where I'm trying to change the output directory. I've set the "Output Directory" setting in Project properties > General to $(SolutionDir)Stage\$(Configuration)\bin$(PlatformArchitecture)\. I can see that in the vcxproj file this is reflected to the OutDir:
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)Stage\$(Configuration)\bin$(PlatformArchitecture)\</OutDir>
</PropertyGroup>
However, it does not seem to actually be used. Under Linker > General > Output File the default value is $(OutDir)$(TargetName)$(TargetExt), but the expanded value of $(OutDir) seen under Command Line does not reflect the changes I've made, rather it seems to have the value $(SolutionDir)Stage\$(ConfigurationName) ($(ConfigurationName) is eg "Debug_x64"). This is wierd, since that is not present in the vcxproj-file...
What do I need to do to make the change in Output Directory affect $(OutDir)? I have also noticed that there is a macro $(OutDirWasSpecified), which has the value false...
I believe $(OutDir) is typically set in file:
C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Platforms\x64\Microsoft.Cpp.x64.default.props
Or alternately, if on a 32-bit platform:
...\Win32\Microsoft.Cpp.Win32.default.props
Typically, you'll find in your project file:
MyProject.vcxproj
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
and if you find the Microsoft.Cpp.Default.props file, it will have:
<!-- Allow platforms to define the defaults first -->
<Import Condition="Exists('$(VCTargetsPath)\Platforms\$(Platform)\Microsoft.Cpp.$(Platform).default.props')" Project="$(VCTargetsPath)\Platforms\$(Platform)\Microsoft.Cpp.$(Platform).default.props"/>
Which is where $OutDir gets brought in.
It seems likely that this include-chain is somehow broken, or the original definition of $(OutDir) got erased/modified in the file Microsoft.Cpp.x64.default.props.
For what it's worth, my Visual Studio 2013 configuration is a tad different. I have a root folder C:\Program Files (x86)\MSBuild\Microsoft.Cpp, beneath which are two subfolders, C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V110 and C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V120.