Problem with dynamically generated C# files in msbuild - msbuild

I have a source XML file that is used to create C# files that are then compiled as part of a project.
Currently I have a BeforeBuild target that runs my XML to C# converter.
The problem is that by the time the BeforeBuild step is run the old files appear to have been stored by the build system so the new files are ignored.
How can I get around this? It seems that Transforms would be the way but they are limited in what they can do.

I guess your "stored by the build system" can be translated as the ItemGroup containing the .cs files you wish to compile is generated when the msbuild file is read, as opposed to when your compile target is executed. You have several options:
<CreateItem> see CreateItem task
<Output> see Output element
I hope this helps.

Well we have something similar-ish here. We gen a .cs off an xml file using a .tt. Both files are part of a specific csproj. Going properties->BuildEvents on the csproj gives this little snippet in the Pre-build event command line:
del "$(ProjectDir)MyCsFile.cs"
copy /b /y "$(ProjectDir)\MyXmlFile.xml" "$(TargetDir)"
"$(ProjectDir)tt.bat" "$(ProjectDir)MyTemplateFile.tt"
No idea if that's of any use to you, I hope it might suffice as a last chance workaround.

I think you need to show us a little of your rule/build file. You should have a rule/dependency for the cs file that has the xml as the dependency.
I am not sure what you mean by "stored by the build system"
Check your rules carefully for errors/omissions.

Related

How to avoid long paths in code built with CMake

I am using CMake to link and build my C++ project, and in said project I am using the fstream library to read from a file. However, when passing the path of the file to my code, I am forced to use a long string such as "../../../../folder/folder/folder/file" to properly reference which file I want opened. I presume this is because my .exe that CMake creates is buried deep, "far" away from my source code, which is why I would have to backtrack so much.
I am wondering if there is something I could put in my CMakeLists.txt to potentially allow for the shortening of this inclusion path.
To save myself some time I have not included my file structure as of now, but if it is needed in order for a solution to be formed I certainly can edit and add it in. I do not necessarily need a case-specific solution, rather just a generalized method in which I could go about doing this.
It looks like CMake doesn't provide such functionality , CMake doesn't do much with execution of your application.
So, For solution you have following
can either create a shell script to copy the file into the desired location which can be picked by the executable and shell script can be run while make process
pass it as a commandline argument to your c++ executable.
create a macro with this location and use this macro in the source file : - CMake can help you in this
Using add_compile_definitions( ...)

Rules for Custom build's <Outputs> tag check for directories changed in Visual Studio 2019?

Lets make obscure question simple...
We have a solution which consists of many projects and some of them have set Custom build events using 3rd party stuff for some dark magic compilation and looks similar like this:
<CustomBuild Include="..\folder\somestuff.xyz">
<FileType>Document</FileType>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">C:\Tcl\bin\tclsh.exe $(APP_PATH)\modules\APP\bin\generator.tcl -o %(RelativeDir)%(Filename) %(RelativeDir)%(Filename).xyz</Command>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">APPGEN %(RelativeDir)%(Filename)</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(RelativeDir)%(Filename).cpp;%(RelativeDir)%(Filename).h;%(RelativeDir)%(Outputs)</Outputs>
</CustomBuild>
This was working properly until we switch form VS2015 to VS2019 as now during the compilation it reports that:
Project is not up-to-date: build output 'd:\projects\program\app\src\plugins\shared\' is missing. This would be more or less ok, but it forces the compiler to recompile also the dependencies of this project and this start to be really annoying as you need to rebuild several projects everytime even when no changes were done.
I found out that the problem originates from this line of Custom build:
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(RelativeDir)%(Filename).cpp;%(RelativeDir)%(Filename).h;%(RelativeDir)%(Outputs)</Outputs>
More precisely from this part: %(RelativeDir)%(Outputs) as the check for .cpp and .h file in the same tag do not generate any issues. So I removed this check for directory. When this chunk of code is removed the project compiles properly and do not re-compile all day long.
So why the Custom build's Output check is now working properly just with files and directories are generating this kind of issue?
And yes, the examined dir exists and it refers to the existing correct path.
The real problem is that your real project is always rebuild due to the metadata Outputs.
The special point is that you should make sure the validity and legitimacy of the value of Outputs.
The problem is under %(RelativeDir) of %(RelativeDir)%(Outputs). When you add it, the outputs has an illegal folder structure rather than a file which makes the outputs always find the missing illegal folder structure so that causes the project always rebuild.
Let me describe it in detail,
when msbuild reads outputs proeperty, when it reads till %(RelativeDir)%(Filename).cpp;%(RelativeDir)%(Filename).h;%(RelativeDir), the value of Outputs is this:
..\folder\somestuff.cpp;..\folder\somestuff.h;..\folder\
Then, it reads %(Outputs)(reads itself), which is more like copy the above value twice:
..\folder\somestuff.cpp;..\folder\somestuff.h;..\folder\..\folder\somestuff.cpp;..\folder\somestuff.h;..\folder\
You will find the last part ..\folder\ is not a file and it is a folder structure which is illegal for the outputs.
That is the reason.
And it is more like your problem that the folder structure d:\projects\program\app\src\plugins\shared\ is missing.
Suggestion
So you should not add outputs again.
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(RelativeDir)%(Filename).cpp;%(RelativeDir)%(Filename).h;</Outputs>

Why is it called response file

MBuild can use response files to save and run commands. But why is it called response file? What is it responding to?
(Also in an MsBuild file the task elements are called Target. What is 'target' refering too?)
A target represents a collection of things you want to do. In an msbuild file, it is represented by an xml element that can have various child xml elements called tasks.
Conceptually it looks like this:
<Target Name="Foo">
<Task />
<AnotherTask />
</Target>
The target you want to execute can be passed in as a command line parameter to msbuild. There are other ways to execute the target of your choice, but you will need to read the docs for that:
https://learn.microsoft.com/en-us/visualstudio/msbuild/msbuild?view=vs-2019
In other build systems, a target can be called a goal.
Note:
Some build systems use a very rigid convention, where files have to be in certain places. MSBuild is not like that. It relies on configuration, where you can configure it any way you like. The only convention's really are the xml syntax and schema that you have to follow.
As for the response file name. Who knows and who cares anyways? It's just an extra place to put more command line parameters. I don't rely on it, and neither should you. If you know what you are doing you can stick all that stuff in a proper msbuild xml file and just invoke msbuild to kick off a build.

2 .msi files from one WiX Votive project

As the title says, I want to output 2 .msi files from one project (one is per-user, and the other is per-machine). I have seen in this thread that it can't be done in some conventional way, but perhaps there is a way to do so as some kind of hack in post-build.
I only need to rerun compilation and linking after the original build with slightly changed command line (actually, I need only different Product.wxs file). However, my light and candle command lines are huge, and I would risk making my project hard to maintain if I would hard-code them.
So, in conclusion, I need to know if there is a way to write a command line that would behave the same as Votive does when creating its build command line (getting all the files in project, linking them, passing project dependencies...), only in post build.
P.S.: I also had an idea of getting the whole command line from Votive, and only changing the Product file, that would also help, so if someone has suggestion on how to do it...
Create multiple configurations of your solution / project and set a preprocessor variable to some value for one of the configurations. In your wix source, conditionally include whatever else it is that needs included based on your preprocessor variable.

Target not being executed when imported to the main *.proj file

I use the TFS 2008 build facilities. I have a large MSBuild project (TFSBuild.proj) and I wanted to split it into a few files because it is becoming hard to maintain.
I found a strange behavior; when I extracted one of the targets (BeforeInitializeWorkspace) to a separate file and then imported it into the main *.proj file, it was not executed. Although, in my MSBuild log, there was information that the target has been imported and overridden, but hasn't been executed. If I have the same target defined in my main *.proj file, it is executed. Can someone explain why the target isn't executed when imported from a file?
Thanks,
Me being stupid ;)
I had the order of <Import> wrong. The first file to import was my overridden target, then the Microsoft.TeamFoundation.Build.targets was imported and overrode my target.
Anyway, changing the order helped. So now, the Microsoft.TeamFoundation.Build.targets is the first target to import and then all my other targets.