Sysprogs forums › Forums › VisualGDB › PREPROCESSOR DEFINE WITH CONTENT OF A BUILD VARIABLE (in MSBuild)
Tagged: MSBuild, PREPROCESSOR DEFINE
- This topic has 11 replies, 2 voices, and was last updated 6 years ago by support.
-
AuthorPosts
-
October 17, 2018 at 13:24 #22341SRParticipant
Hi,
I have read the following post:
PREPROCESSOR DEFINE WITH CONTENT OF A BUILD VARIABLE
I want to set a preprocessor define with the hash of my current git revision. I managed to put the revision into a custom build variable (git rev-parse HEAD in a custom build step).
and wondered how that can be accomplished when using VisualGDB with MSBuild.
Regards,
SR
October 17, 2018 at 17:41 #22345supportKeymasterHi,
If you are using MSBuild, you can script it by creating a custom MSBuild target (VisualGDB uses the same target system as regular MSBuild projects).
You can find extensive documentation on creating MSBuild tasks here: https://docs.microsoft.com/en-us/visualstudio/msbuild/task-writing?view=vs-2017
Also consider having a quick look through our version updating task used by our open-source plugins. You could create a similar C# task that would export an MSBuild variable and then reference this variable in the “Preprocessor Definitions” setting.
October 19, 2018 at 14:56 #22365SRParticipantTo summarize for everyone wondering:
- Make new C# Library GitProperties.dll
- Add NuGet-Packages: Microsoft.Build.Framework & Microsoft.Build.Utilities
- Add Task Class
public class GitPropertiesTask : Task { [Output] public string GitCommitHash {get; set; } public override bool Execute() { try { GitCommitHash = GetGitBuildHash(); } catch (Exception e) { Log.LogErrorFromException(e); return false; } return true; } private static string GetGitBuildHash() { ProcessStartInfo startInfo = new ProcessStartInfo { UseShellExecute = false, WindowStyle = ProcessWindowStyle.Hidden, FileName = "cmd.exe", Arguments = "/C git rev-parse --short=9 HEAD", RedirectStandardOutput = true, }; Process process = new Process { StartInfo = startInfo }; process.Start(); string buildHash = process.StandardOutput.ReadToEnd().Trim(); process.WaitForExit(); return buildHash; } }
- Add the following lines at the end of your Project file:
<UsingTask TaskName="GitPropertiesTask" AssemblyFile="./[Path]/GitProperties.dll" /> <Target Name="Build"> <GitPropertiesTask> <Output TaskParameter="GitCommitHash" PropertyName="GitCommitHash"/> </GitPropertiesTask> </Target>
- Add to your Project Settings –> C/C++ –> Preprocessor –> Preprocessor Defines:
GIT_BUILD_ID=$(GitCommitHash)
October 19, 2018 at 14:58 #22366SRParticipant@Support: I have seen that you used a .props file instead of the project file for better reusability.
I have tried this myself, but it didn’t work.
What do i have to configure for MSBuild to automatically load this file?
October 19, 2018 at 15:31 #22367SRParticipantOctober 19, 2018 at 16:12 #22370SRParticipantI have again read the AutoVersion.props as you suggested and added
<PropertyGroup> <BuildDependsOn>$(BuildDependsOn);GitPropertiesTarget</BuildDependsOn> </PropertyGroup>
But the GitPropertiesTarget isn’t invoked.
Does the VisualGDB Embedded ToolChain override these dependencies?
October 19, 2018 at 21:18 #22372supportKeymasterHi,
Thanks for sharing this. Indeed the target name should not collide with any of the existing targets, as it would override the original target. Setting $(BuildDependsOn) to include your target name should be the right thing to do.
If it doesn’t work, please try setting the MSBuild build log verbosity to “Diagnostic” via Tools->Options->Build and Run and then check that your target is being built, the task is being executed and returns the correct value and that it happens before the actual compilation phase.
October 22, 2018 at 12:20 #22381SRParticipantHi,
Using the MSBuild Diagnostic setting helped a lot to unterstand the procedure.
I changes small things in the Task to make it more reliable, but it doesn’t seem to be the problem.
My new Task:
using System; using System.Diagnostics; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; namespace GitBuildStep { public class GitPropertiesTask : Task { [Required] public string GitDir { get; set; } [Output] public int GitCommitDay { get; set; } [Output] public int GitCommitMonth { get; set; } [Output] public int GitCommitYear { get; set; } [Output] public string GitCommitHash { get; set; } public override bool Execute() { try { GitCommitHash = GetGitBuildHash(); DateTime buildTime = GetGitBuildDate(); GitCommitYear = buildTime.Year; GitCommitMonth = buildTime.Month; GitCommitDay = buildTime.Day; } catch (Exception e) { Log.LogErrorFromException(e); return false; } return true; } private string GetGitBuildHash() { string buildHash = RunCmd(@"git rev-parse --short=9 HEAD"); return buildHash; } private DateTime GetGitBuildDate() { var buildDate = RunCmd(@"git log -1 --format=%cd --date=short"); return DateTime.Parse(buildDate); } private string RunCmd(string cmd) { ProcessStartInfo startInfo = new ProcessStartInfo { UseShellExecute = false, WindowStyle = ProcessWindowStyle.Hidden, FileName = "cmd.exe", Arguments = $@"/C ({cmd})", RedirectStandardOutput = true, RedirectStandardError = true, WorkingDirectory = GitDir }; string pathEnv = Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Machine); startInfo.EnvironmentVariables.Add("PATH", pathEnv); Process process = new Process { StartInfo = startInfo }; process.Start(); process.WaitForExit(); string error = process.StandardError.ReadToEnd().Trim(); if (!String.IsNullOrWhiteSpace(error)) throw new Exception(error); string buildDate = process.StandardOutput.ReadToEnd().Trim(); return buildDate; } } }
And my changes to Project.vcxproj
<UsingTask TaskName="GitPropertiesTask" AssemblyFile="Utils/GitBuildStep.dll" /> <Target Name="GitPropertiesTarget"> <Message Text="Reading Git Properties!" Importance="high" /> <GitPropertiesTask GitDir="$(SolutionDir)"> <Output TaskParameter="GitCommitDay" PropertyName="GitCommitDay" /> <Output TaskParameter="GitCommitMonth" PropertyName="GitCommitMonth" /> <Output TaskParameter="GitCommitYear" PropertyName="GitCommitYear" /> <Output TaskParameter="GitCommitHash" PropertyName="GitCommitHash" /> </GitPropertiesTask> <Message Text="Git Properties:%0aDate=$(GitCommitDay).$(GitCommitMonth).$(GitCommitYear)%0aHash=$(GitCommitHash)" Importance="high" /> </Target>
And PreProcessor-Settings:
GIT_BUILD_ID=$(GitCommitHash);GIT_YEAR=$(GitCommitYear);GIT_MONTH=$(GitCommitMonth);GIT_DAY=$(GitCommitDay)
Outputs this:
1>Target "GitPropertiesTarget" in file "X:\Firmware\Firmware\Firmware.vcxproj": 1> Using "Message" task from assembly "Microsoft.Build.Tasks.Core, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a". 1> Task "Message" 1> Task Parameter:Text=Reading Git Properties! 1> Task Parameter:Importance=high 1> Reading Git Properties! 1> Done executing task "Message". 1> Using "GitPropertiesTask" task from assembly "X:\Firmware\Firmware\Utils/GitBuildStep.dll". 1> Task "GitPropertiesTask" 1> Task Parameter:GitDir=X:\Firmware\ 1> Git Properties: 1> Date=18.10.2018 1> Hash=530a981c4 1> Output Property: GitCommitDay=18 1> Output Property: GitCommitMonth=10 1> Output Property: GitCommitYear=2018 1> Output Property: GitCommitHash=530a981c4 1> Done executing task "GitPropertiesTask". 1> Task "Message" 1> Task Parameter:Text=Git Properties: 1> Date=18.10.2018 1> Hash=530a981c4 1> Task Parameter:Importance=high 1> Git Properties: 1> Date=18.10.2018 1> Hash=530a981c4 1> Done executing task "Message". 1>Done building target "GitPropertiesTarget" in project "Firmware.vcxproj". ... 1>Target "BuildCppObjectList" in file "C:\Program Files (x86)\Sysprogs\VisualGDB\MSBuild\Targets\gcc.targets": 1> Added Item(s): 1> Obj= 1> VisualGDB\Debug\eeprom.o ... 1> PreprocessorDefinitions=ARM_MATH_CM4;flash_layout;STM32F407VG;USE_USB_FS;STM32F407xx;FAST_SEMIHOSTING_BUFFER_SIZE=4096;FAST_SEMIHOSTING_BLOCKING_MODE=0;FAST_SEMIHOSTING_STDIO_DRIVER=1;FAST_SEMIHOSTING_PROFILER_DRIVER=1;PROFILER_STM32F4;SYSPROGS_PROFILER_DEBUGGER_CHECK_MODE=1;GIT_BUILD_ID=;GIT_YEAR=;GIT_MONTH=;GIT_DAY=;DEBUG=1;;DEBUG=1
To me it seems like the PreprocessorDefinitions get resolved before GitPropertiesTarget is triggered, as the variables seems to get set correctly, but not the PreprocessorDefinitions.
PS: I have attached you a shortened version of MSBuild.log (due to your upload-size limit)
- This reply was modified 6 years ago by SR.
October 22, 2018 at 12:27 #22383October 22, 2018 at 18:12 #22399supportKeymasterHi,
If the PreprocessorDefinitions macro gets resolved before the custom tool has a chance to run, please consider a slightly different approach. Remove the reference to your variable from the regular PreprocessorDefinitions and add the following code inside your <Target> element after the invocation of the custom tool (please update it to reference the actual variables):
<ItemDefinitionGroup> <ClCompile> <PreprocessorDefinitions>%(ClCompile.PreprocessorDefinitions);$(...)</PreprocessorDefinitions> </ClCompile> </ItemDefinitionGroup>
As long as the code above is inside the “target” element, it will get evaluated after the tool is invoked and hence the variables will be resolved properly.
October 23, 2018 at 08:40 #22408SRParticipantHi,
I actually tried just that yesterday, but it failed with error:
<ItemDefinitionGroup> is not allowed inside a target.
But with the help of some google I figured that this works as desired.
<ItemGroup> <ClCompile> <PreprocessorDefinitions>%(ClCompile.PreprocessorDefinitions);GIT_BUILD_ID="$(GitCommitHash)";GIT_YEAR=$(GitCommitYear);GIT_MONTH=$(GitCommitMonth);GIT_DAY=$(GitCommitDay);</PreprocessorDefinitions> </ClCompile> </ItemGroup>
Thank you very much for your help!
October 23, 2018 at 18:04 #22411supportKeymasterHi,
Sorry about that, it should indeed be ItemGroup. When placed inside a target, it will work the same as ItemDefinitionGroup works normally.
Good to know it works and let us know if you encounter any further issues.
-
AuthorPosts
- You must be logged in to reply to this topic.