> -----Original Message----- > From: cmake-developers [mailto:[email protected]] > On Behalf Of Brad King > Sent: Thursday, October 22, 2015 15:43 > To: [email protected] > Subject: Re: [cmake-developers] Fragile behaviour of msbuild when using > Visual Studio solution/project generators > > > We seem to use <CustomBuild>'s <Command> rather than <Exec> > > We use that because it is what the IDE uses when creating a project file so > using it makes the command visible in the IDE properties. It also handles all > the dependencies and such instead of always executing, and is the only way > to get proper semantics we've found. If no setting is available then I think > the solution is "don't do that" :( > > > internals of msbuild and I couldn't find any obvious documentation for > > <CustomBuild>. > > I'm not very familiar with it either. I see something that looks like a definition > of the CustomBuild target type in files like these: > > c:/Program Files > (x86)/MSBuild/Microsoft.Cpp/v4.0/Microsoft.CppCommon.targets > c:/Program Files > (x86)/MSBuild/Microsoft.Cpp/v4.0/V110/Microsoft.CppCommon.targets > c:/Program Files > (x86)/MSBuild/Microsoft.Cpp/v4.0/V120/Microsoft.CppCommon.targets > c:/Program Files > (x86)/MSBuild/Microsoft.Cpp/v4.0/V140/Microsoft.CppCommon.targets
Summary: I think there is a solution but it isn't the prettiest; see below: Ultimately, the VC tasks derive from Microsoft.Build.Utilities.ToolTask. I examined MSBuild 4.0 (newer versions may offer more flexibility): 1. Private ToolTask.LogMessagesFromStandardError is called whenever the process emits something on standard error. It's a one liner function that calls private LogMessagesFromStandardErrorOrOutput. 2. ToolTask.LogMessagesFromStandardErrorOrOutput calls protected virtual LogEventsFromTextOutput with the error/output line. 3. ToolTask's virtual LogEventsFromTextOutput implementation calls base class Task.Log.LogMessageFromText. Task.Log is a TaskLoggingHelper type property. It itself is a read-only property so that a user can't swap out that variable. 4. Public TaskLoggingHelper.LogMessageFromText is where it starts getting interesting. It calls CanonicalError.Parse, which checks for magic "error" and "warning" strings. If either string is found, a regex is used and if it's a match, then the function returns information about the parsed error/warning. There isn't a way to skip it that I can see. If Parse indicates that it parsed an error, you're guaranteed to have LogError called instead of the normal LogMessage. So as far as I can tell, anyone making an MSBuild task derived from ToolTask (very common) is guaranteed to get this error parsing capability by default whether they like it or not. Unless they override virtual LogEventsFromTextOutput. Which is what the Exec task does. Exec overrides LogEventsFromTextOutput so that it can honor the IgnoreStandardErrorWarningFormat property, which is specific to the Exec task. If the user doesn't set that property, it will call base.Log.LogMessageFromText (see above). If they do set it, they always just log it as a Message and do not try to parse it. Unfortunately, the CustomBuild task and all of its base classes between CustomBuild and ToolTask do not override LogEventsFromTextOutput. So CustomBuild will get the default ToolTask error parsing capability that can't be flipped off any other way. CustomBuild is totally unrelated to and independent of Exec task, other than that both of them derive from ToolTask. It looks like somebody else discusses it here: http://aschultz.us/blog/archives/316 I'm not sure why MSBuild team put IgnoreStandardErrorWarningFormat in Exec task instead of the base ToolTask class. (Or at least provide protected members to easily allow derived classes to control the behavior without having to completely reimplement the functionality in LogEventsFromTextOutput). It doesn't seem like a smart design. Maybe somebody can encourage the MSBuild team to rectify this problem - e.g. by adding something similar to IgnoreStandardErrorWarningFormat to ToolTask would seem like a simple enough thing to do that won't break compatibility... In the meantime, probably the only way to use CustomBuild and dodge this error parsing behavior is to write a new MSBuild task that derives from CustomBuild and then overrides LogEventsFromTextOutput. Normally MSBuild tasks require a precompiled .NET assembly to be available like in the .targets files Brad pointed out. However in MSBuild 4 I guess there is a way to put the task implementation inline in the project file: " MSBuild Inline Tasks " https://msdn.microsoft.com/en-us/library/dd722601.aspx ---- however this solution might have some downsides and somebody would have to experiment to see if they are tolerable: (1) how will the IDE project properties, etc. react to the proposed "CMakeCustomBuild" task derived from CustomBuild instead of "CustomBuild" directly? E.g. will it let you view/set the task properties like normal still from the IDE? (2) the IDE might give some annoying security warnings when opening the project since the project file is basically executing arbitrary C# code, (3) adds complexity to the CMake generator. Best regards, James Johnston -- Powered by www.kitware.com Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Kitware offers various services to support the CMake community. For more information on each offering, please visit: CMake Support: http://cmake.org/cmake/help/support.html CMake Consulting: http://cmake.org/cmake/help/consulting.html CMake Training Courses: http://cmake.org/cmake/help/training.html Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Follow this link to subscribe/unsubscribe: http://public.kitware.com/mailman/listinfo/cmake-developers
