I'm trying to create a NuGet package that runs an external application before build. That application creates a compilationtime.h file to know the time of compilation to show it in the About dialog box.
My NuGet package has a Tools folder with the CreateCompilationTimeFile.exe and an Build folder with {packagename}.props file.
I've tried a lot of combinations to create the Pre-Build event in the {packagename}.props file but none of them is working.
I tried with this:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemDefinitionGroup>
<PreBuildEvent>
<Command>"$(MSBuildThisFileDirectory)..\tools\CreateCompilationTimeFile.exe"</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
</Project>
Also with this:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="BeforeBuild2" BeforeTargets="Build">
<Exec Command="$(MSBuildThisFileDirectory)..\tools\CreateCompilationTimeFile.exe"/>
</Target>
</Project>
If I do it without the NuGet package and I do it with the next property sheet, it works correctly:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup>
<PreBuildEvent>
<Command>"$(SolutionDir)Tools\CreateCompilationTimeFile.exe"</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemGroup />
</Project>
But I want to do it with the NuGet package and not with property sheets.
What am I doing wrong? Thanks.
As @leo-liu-msft says, the second solution works, but it's not working as expected, as I will explain below.
If the {packagename}.props contains this:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="CreateCompilationFileTimeTarget" BeforeTargets="Build">
<Exec Command="$(MSBuildThisFileDirectory)..\tools\CreateCompilationTimeFile.exe"/>
</Target>
</Project>
Suppose that you just created a brand new C++ project and include compilationtime.h file in one of your .cpp files:
#include "compilationtime.h"
Remember, the project is new and you don't have any compilationtime.h file jet, it is supposed to be created before the build process because of the {packagename}.props.
If you build your C++ project, you'll get a C0183 Cannot open include file: 'CompilationTime.h': No such file or directory error.
If then you open the project folder, the compilationtime.h file is not where it supposes to be.
Now comment the #include "compilationfile.h"
line and compile it again. The compiler will finish without any errors and if you analyze the folder, the file will be there!
Now that your compilationfile.h already exists, edit it and change the tm_year to 0 for example:
#pragma once
static struct tm GetCompilationTime()
{
struct tm compilationTime = { 0 };
compilationTime.tm_year=0;
compilationTime.tm_mon=9;
compilationTime.tm_mday=15;
compilationTime.tm_hour=15;
compilationTime.tm_min=37;
compilationTime.tm_sec=41;
return compilationTime;
}
..and then in your .cpp file, print the year to the console:
#include "pch.h"
#include <iostream>
#include "CompilationTime.h"
int main()
{
std::cout << GetCompilationTime().tm_year << std::endl;
}
Compile and run the program. The program will print 0 and not the current year, but if you open the compilationtime.h file, it is modified with the current year, so the compiler is behaving as if instead of BeforeTargets="Build"
we had configured AfterTargets="Build"
.
Finally I solved the problem changing the BeforeTargets to PrepareForBuild like this:
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="CreateCompilationFileTimeTarget" BeforeTargets="PrepareForBuild">
<Exec Command="$(MSBuildThisFileDirectory)..\tools\CreateCompilationTimeFile.exe"/>
</Target>
</Project>
and now it creates/updates the compilationtime.h file always before build as I wanted.