Sort Visual Studio build log in "Build Order" style - visual-studio

There is a "Show output from" dropdown list in Visual Studio 2008 "Output" window, which allows viewing build events ordered by thread (Build Order). This is very useful when building big solutions on multi-core machines, as the log entries from those come unsynchronized.
Our organization has the automated build process, where solution(s) are compiled in a batch mode, using something like:
devenv Solution.sln /USEENV /build Release /out buildlog.txt
This will load Solution.sln, buld it in Release configuration and output build log into buildlog.txt.
Problem is: buildlog.txt is an output resembling "Build" output, not "Build Order", and therefore, it is pretty hard to read. Is there a command-line filter or something, which would convert output to "Build Order" format?

Use simple filter, something like that:
static void Main(string[] args)
{
var lines = new Dictionary<int, StringBuilder>();
var line = Console.In.ReadLine();
while (line != null)
{
int process = 0;
var re = new Regex(#"^(?<process>\d+)\>.*$");
if (re.IsMatch(line))
{
var match = re.Match(line);
process = Convert.ToInt32(match.Groups["process"].Value);
}
if (!lines.ContainsKey(process))
{
lines[process] = new StringBuilder();
}
lines[process].AppendLine(line);
line = Console.In.ReadLine();
}
foreach (var i in lines.Keys)
{
Console.Write(lines[i]);
}
}

I don't know whether this will solve the formatting issue, but you could try using msbuild instead of devenv, with a command line such as:
msbuild Solution.sln /p:Configuration=Release /logger:XMLLogger,C:\Loggers\MyLogger.dll;OutputAsHTML
See the documentation for msbuild for information on the logging options. You may find that this will give you the ability to have a more sensible output.

I don't think Walter's answer works for all the situation, because I've seen the problem when building C# projects and VS prints the Compile results withouth any process ID! such as
1>------ Build started: Project: MyProj, Configuration: Debug Any CPU ------
Compile complete -- 1 errors, 0 warnings
Please note that I removed most of other outputs but imagine you're building a lot of projects and Compile complete line is not inserted right after the correct project, how would you find which project Compile complete belongs?

Related

How can I stop a sub-project from getting built?

I have a large-ish Qt project that has multiple subprojects.
One of the sub-projects is intentionally unbuildable, and I don't want QtCreator to try to build it. I still want all its source files visible in the project tree, however.
How can I prevent a project from getting built?
Is there a TEMPLATE = NONE or TARGET = PLZ_DONT_BUILD?
The hacky solution I've come up with is wrapping all my source files with:
DisableBuild {
SOURCES = DummyMain.cpp
} else {
SOURCES = main.cpp \
...many other files...
} #...at the bottom of the .pro file.
DummyMain.cpp just contains an empty int main() function, so the compiler doesn't complain about empty entry points.
If there is a better solution, I'd like to hear it!

Should GetEnvironmentVariable work in xUnit tests?

If I set environment variables for a .Net Core web project in Visual Studio 2017 using the project properties page, I can read the value of the variable using Environment.GetEnvironmentVariable; however, when I set the environment variable for my xUnit testing project and then debug the test, Environment.GetEnvironmentVariable always returns null. Is there something about the fact that it is a testing project that should prevent the variable from being used the same as with the web project? If so, is there a way that I can set the environment variables for a test project? Thank you.
The GetEnvironmentVariable works fine in xUnit tests. The problem is to properly set a variable. If you set the variable at Properties -> Debug page, then the variable is written to Properties\launchSettings.json and Visual Studio makes all work to launch an application with the selected profile. As you could see, launchSettings.json even isn't copied to output folder by default. It's impossible to pass this file as argument to dotnet run or dotnet test, that leads to obvious problem if tests are run automatically on a CI server. So it is not surprising that launchSettings.json isn't considered by a test runner.
Solution: there are a lot of ways to setup a test environment in xUnit:
Constructor
Base class
Fixture
For example, this collection fixture sets up all environment variables from launchSettings.json:
public class LaunchSettingsFixture : IDisposable
{
public LaunchSettingsFixture()
{
using (var file = File.OpenText("Properties\\launchSettings.json"))
{
var reader = new JsonTextReader(file);
var jObject = JObject.Load(reader);
var variables = jObject
.GetValue("profiles")
//select a proper profile here
.SelectMany(profiles => profiles.Children())
.SelectMany(profile => profile.Children<JProperty>())
.Where(prop => prop.Name == "environmentVariables")
.SelectMany(prop => prop.Value.Children<JProperty>())
.ToList();
foreach (var variable in variables)
{
Environment.SetEnvironmentVariable(variable.Name, variable.Value.ToString());
}
}
}
public void Dispose()
{
// ... clean up
}
}
Set Copy to output directory: Always for launchSettings.json to make the file accessible from tests.
A solution for using environment variables in unit tests, for either mstest or xunittest, is through the ".runsettings" file provided for the platform:
UPDATE:
This works only for mstest.
Add a file with .runsettings extension in the project:
Configure environment variables in file "xxx.runsettings" created:
<!-- File name extension must be .runsettings -->
<RunSettings>
<RunConfiguration>
<EnvironmentVariables>
<!-- List of environment variables we want to set-->
<VARIABLE_XXXX>value X</VARIABLE_XXXX>
<VARIABLE_YYYY>value Y</VARIABLE_YYYY>
</EnvironmentVariables>
</RunConfiguration>
</RunSettings>
Add RunSettingsFilePath tag in test .csproj pointing to the .runsettings file.
Important: the path is absolute.
Using $(MSBuildProjectDirectory) variable will return the absolute path to the project diretory.
Another options to use .runsettings are in link below:
https://learn.microsoft.com/pt-br/visualstudio/test/configure-unit-tests-by-using-a-dot-runsettings-file?view=vs-2019
Great thread helped me find the adapted solution for me.
I needed something that works well for local dev / tests (using VS code) JSON file works fine.
I also needed something that can be used with CI/CD and deployment; environment variables were needed.
My fixture class needs the environment variable to be able to run the tests in the different environments.
I'm using the same principle #Ilya Chumakov except with System.Text.Json (in 2022 using .NET 6...)
I thought that sharing it might help save other people some time:
if (File.Exists(Directory.GetCurrentDirectory()+"/local.settings.json")){
using var file = File.Open(Directory.GetCurrentDirectory()+ "/local.settings.json",FileMode.Open);
var document = JsonDocument.Parse(file);
var variables = document.RootElement.EnumerateObject();
foreach(var variable in variables){
Environment.SetEnvironmentVariable(variable.Name, variable.Value.ToString());
}
}
All the needed variables are at the root of the local.settings.json. adapt if you use it for a lot of things, easy to add an "env" property which contains all your environment variable and just read from it.
For those who use VS code like me. Don't forget to add to your .csproj:
<ItemGroup>
<Content Include="local.settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
Took me also a bit of tinkering to find that out.

Can't get Gradle OpenCover plugin to produce coverage results

I'm not getting any results from opencover. My nunit tests all run and pass, just no coverage results. the problem seems to be opencover filters, but we aren't setting any. Any suggestions?
The CodeCoverage.xml file contains a group of lines like the following which indicate that the plugin is telling opencover to filter out the DLLs we are trying to measure.
<Module hash="A3-F0-3A-1A-FF-38-D7-EF-A2-55-C9-8B-84-37-CF-CF-00-80-70-23" skippedDueTo="Filter">
<FullName>C:\gitlab-runner\builds\83ebc972\0\active\scrpt\output\Scrpt.Core.dll</FullName>
<ModuleName>Scrpt.Core</ModuleName>
<Classes/></Module>
which has the correct path for the dll file, but I don't see why it is skipped due to filtering. The unit tests are contained in a dll called Scrpt.Test.dll and the rest of the code is in other DLLs all of which are being filtered out.
I'm using the following plugins
plugins {
id 'com.ullink.msbuild' version '2.15'
id 'com.ullink.nunit' version '1.8'
id 'com.ullink.opencover-nunit' version '1.6'
}
and the plugin definitions for nunit and opencover are:
nunit {
testAssemblies = [file('output/Scrpt.Tests.dll')]
shadowCopy = false
useX86 = true
ignoreFailures = false
}
opencover {
targetAssemblies = [file('output/Scrpt.dll'),file('output/Scrpt.Core.dll'),file('output/Scrpt.SourceCitations.dll'),file('output/ScrptUtilLib.dll')]
ignoreFailures = false
}
Thank you for your help,
-herb
You need to set an opencover filter. Open cover filter works off of inclusive and exclusive filters.
The first filter should always be something like :
+[*]*
meaning include every assembly and every class.
then add in your exclusive filters:
+[*]* -[AssemblyName]* -[*AnotherName]*
It's very simple. just add in the universal inclusive filter first, get your results, then start to incrementally exclude stuff in your filter one by one.
This was answered thru the help of Francois Valdy over at https://github.com/Ullink/gradle-opencover-plugin/issues/17
The problem turned out to be that the opencover plugin was not generating the coverage.xml results. There was an error message in the xml saying that the files I was interested in were skipped because of filters, but I couldn't find what filters were causing that.
I ended up replacing the opencover plugin with a task that does the same thing. Not sure why the plugin didn't work, but the replacement is essentially the same thing in that it calls nunit, creates the output coverage xml which sonarqube then uploads. Plus doing it this way gives you more control over where the files end up.
A bit awkward, but it work. The following replaced the opencover block in my original question.
task opencover(type:Exec) {
executable 'C:\\Program Files (x86)\\OpenCover\\OpenCover.Console.exe'
workingDir file('output')
args "-target:c:\\Program Files (x86)\\NUnit 2.6.4\\bin\\nunit-console-x86.exe", "-targetargs:c:\\gitlab-runner\\builds\\83ebc972\\0\\active\\scrpt\\output\\scrpt.tests.dll /noshadow", '-output:coverage.xml', '-filter:+[*]*'
}
btw, I did try replacing the file() uses in the targetAssemblies for the opencover gradle plugin, but that had no effect. From what I've read, the following should've worked.
opencover {
targetAssemblies = ['output/Scrpt.dll','output/Scrpt.Core.dll','output/Scrpt.SourceCitations.dll','output/ScrptUtilLib.dll']
ignoreFailures = false
}

Project (bin) folder path at compile time?

Is there a way to find out the project path at compile time?
I want to create a unit test that tests if the configurartion in the default web.config (the one in the project folder). Mainly to reduce human error.
I cannot rely on assembly locations at runtime (for the test), so I need to know where the project folder is to access web.config there.
I need a "generic" solution since I'd like to use the same (base) test code for multiple projects, and the physical location is different anyway for most development machines.
Thanks.
Based on rkb's answer,
As it sounds like you've got a C# project, use this post build step.
echo namespace ProjectPath { static public class ProjectPath { public static readonly string Path = #"$(ProjectDir)";} } > $(ProjectDir)path.cs
Then include path.cs as an existing item to your test project. Then you can access it via:
string path = ProjectPath.ProjectPath.Path;
If you want the Visual Studio project path, at compile time, you could use a Pre-Build Event (see the Project Properties dialog) to run a command line that will create a source file used in your project.
The source file will contain some code, say a variable definition. Your testing code uses this variable. The value of the variable will come from VS; when it runs your Pre-Build Event command, it substitutes project properties for certain macros. The macro you want is probably ProjectDir.
So in the end, you have something like this for your Pre-Build Event's command:
echo 'const char * PROJECT_PATH = "$(ProjectDir)";' > source.cpp
Not sure what language you're using, so adjust accordingly.
To improve the solution slightly, instead of using the Post Build Event Command Line, you can run the command as an MSbuild Exec Task in the BeforeBuild Target of the project.

Can clang be told not to analyze certain files?

I'm trying to use clang to profile a project I'm working on. The project includes a rather large static library that is included in Xcode as a dependency.
I would really like clang to not analyze the dependencies' files, as it seems to make clang fail. Is this possible? I've been reading the clang documentation, and I haven't found it.
As a last resort, there is a brute force option.
Add this to the beginning of a file:
// Omit from static analysis.
#ifndef __clang_analyzer__
Add this to the end:
#endif // not __clang_analyzer__
and clang --analyze won't see the contents of the file.
reference: Controlling Static Analyzer Diagnostics
So, this isn't really an answer, but it worked well enough.
What I ended up doing was building the static library ahead of time, and then building the project using scan-build. Since there was already an up-to-date build of the static library, it wasn't rebuilt and thus wasn't scanned.
I'd still love to have a real answer for this, though.
Finally, in 2018 the option was implemented.
Use --exclude <path> [1] [2] option
--exclude
Do not run static analyzer against files found in this directory
(You can specify this option multiple times). Could be useful when
project contains 3rd party libraries.
I don't use XCode, but using scan-build in linux the following works for me. I my case, I want to run the static analysis on all first party, non-generated code. However, I want to avoid running it on third_party code and generated code.
On the command line, clang-analyzer is hooked into the build when scan-build sets CC and CXX environment variables to ccc-analyzer and c++-analyzer locations. I wrote two simple scripts called ccc-analyzer.py and c++-analyzer.py and hooked them in to the compile in place of the default. In these wrapper scripts, I simply looked at the path of the file being compiled and then run either the raw compiler directly (if I wish to avoid static analysis) or the c*-analyzer (if I wish for static analysis to occur). My script is in python and tied to my specific build system, but as an example that needs modification:
import subprocess
import sys
def main(argv):
is_third_party_code = False
for i in range(len(argv)):
arg = argv[i]
if arg == '-c':
file_to_compile = argv[i + 1]
if '/third_party/' in file_to_compile or \
file_to_compile.startswith('gen/'):
is_third_party_code = True
break
if is_third_party_code:
argv[0] = '/samegoal/bin/clang++'
else:
argv[0] = '/samegoal/scan-build/c++-analyzer'
return subprocess.call(argv)
if __name__ == '__main__':
sys.exit(main(sys.argv))
For Xcode users, you can exclude individual files from static analyzer by adding the following flags in the Target -> Build Phases -> Compile Sources section: -Xanalyzer -analyzer-disable-all-checks

Resources