[cfe-dev] Trying to use CLang / CLang Static Analyzer under Windows XP SP3 32-bit

TP wingusr at gmail.com
Thu Apr 15 07:29:01 PDT 2010


I've managed to get scan-build working on Windows XP Pro SP3 using a
Visual Studio 2008 built version of clang.exe. This post describes
what I had to do.

As others mentioned to my initial post, you have to use gcc (I was
under the mistaken impression that clang was a *replacement* for gcc).

First some things to note about trying to run the scan-build perl
script on Windows XP Pro SP3.

1). ActiveState perl doesn't work with scan-build.

The getpwuid function is unimplemented. Easy to get around by just faking it.
List form of pipe open not implemented, so it can't handle:

 # Query clang for analysis options.
 open(PIPE, "-|", $Clang, "-cc1", "-help") or
   DieDiag("Cannot execute '$Clang'\n");

Once I saw that error I gave up on trying to use ActiveState perl.

2). You can't run cygwin perl using the normal Windows XP command
prompt window (or JP Software's enhanced shell 4NT for that matter).
Things like `uname` or "system 'mkdir','-p',$NewDir;" don't work. You
have to use the cygwin bash shell.

3). In order to debug the perl fork() command (used inside
ccc-analyzer), you need to run perl -d inside an xterm window. This
means that you not only need xterm, but also X11. See
http://x.cygwin.com/ for installation instructions. Use the created
Start -> Cygwin-X -> XWin Server shortcut to start a resizable XTerm
window.

Then you can do the following:

 perl /cygdrive/c/llvm/tools/clang/tools/scan-build/scan-build gcc t.c

or:

 perl /cygdrive/c/llvm/tools/clang/tools/scan-build/scan-build gcc -v -v -v t.c

to get a bit more info on what's going on.

Once you get all that sorted out, you then will hit some bugs in
scan-build and ccc-analyzer.

First of all, it turns out that the following is *normal* for clean .c files:

 ANALYZE: t.c main
 scan-build: Removing directory '/tmp/scan-build-2010-04-15-3' because
it contains no reports.

So if there are no warnings or errors you see *nothing*. Therefore,
when first testing scan-build, make sure your small test file actually
has an error or two. Then you should see something like this:

 ANALYZE: t.c main
 t.c(7) :  warning: Value stored to 'c' is never read
   c = a + b;
   ^   ~~~~~
 t.c(7) :  warning: The left operand of '+' is a garbage value
   c = a + b;
       ~ ^
 2 warnings generated.
 scan-build: 2 bugs found.
 scan-build: Run 'scan-view /tmp/scan-build-2010-04-15-1' to examine
bug reports.

(where /tmp is actually c:\cygwin\tmp). I don't bother with scan-view,
I just open the index.html directly.

There are a number of problems in scan-build since it doesn't seem to
be in the place where it used to be (or maybe there's a symbolic link
that doesn't show up on Windows XP)?

Change:

 my $ClangSB = Cwd::realpath("$RealBin/bin/clang");

to:

 my $ClangSB = Cwd::realpath("$RealBin/../../../../bin/Debug/clang.exe");

(assuming you built a Debug version of clang with Visual Studio 2008)

Change:

 my $AbsRealBin = Cwd::realpath($RealBin);
 my $Cmd = "$AbsRealBin/libexec/ccc-analyzer";
 my $CmdCXX = "$AbsRealBin/libexec/c++-analyzer";

To:

 my $AbsRealBin = Cwd::realpath($RealBin);
 my $Cmd = "$AbsRealBin/ccc-analyzer";
 my $CmdCXX = "$AbsRealBin/c++-analyzer";

Change:

 my $ScanView = Cwd::realpath("$RealBin/scan-view");

To:

 my $ScanView = Cwd::realpath("$RealBin/../scan-view/scan-view");

in ccc-analyzer:

 in sub GetCCArgs()

  chomp $line;
  $line =~ s/^\s+//;
  my @items = quotewords('\s+', 0, $line);

should be changed to:

  chomp $line;
  $line =~ s/^\s+//;
  $line =~ s/\cM//; #%%%% remove trailing carriage return
  my @items = quotewords('\s+', 0, $line);

Otherwise you get the following error:

 Use of uninitialized value $CmdArgs[25] in exec at
/cygdrive/c/llvm/tools/clang/tools/scan-build/ccc-analyzer line 238.

The remaining problem is caused by sending cygwin style filenames to a
clang.exe built with Visual Studio 2008 (which doesn't understand such
things):

  if ($RunAnalyzer) {
    if (defined $ResultFile) {
      push @CmdArgs,'-o';
      push @CmdArgs, $ResultFile;
    }
    elsif (defined $HtmlDir) {
      push @CmdArgs,'-o';
      push @CmdArgs, $HtmlDir;
    }
  }

should be changed to:

  if ($RunAnalyzer) {
    if (defined $ResultFile) {
      push @CmdArgs,'-o';
      if ($ResultFile =~ m!^/cygdrive!) {
	$ResultFile =~ s!/cygdrive/(.)!$1:!i;
	}
      else {
	$ResultFile = "c:/cygwin$ResultFile";
	}

      push @CmdArgs, $ResultFile;
    }
    elsif (defined $HtmlDir) {
      push @CmdArgs,'-o';
      if ($HtmlDir =~ m!^/cygdrive!) {
	$HtmlDir =~ s!/cygdrive/(.)!$1:!i;
	}
      else {
	$HtmlDir = "c:/cygwin$HtmlDir";
	}
      push @CmdArgs, $HtmlDir;
    }
  }

Finally. I found that in order to debug ccc-analyzer, in scan-build's
RunBuildCommand(), I had to change:

    shift @$Args;
    unshift @$Args, $CCAnalyzer;

to:

    shift @$Args;
    unshift @$Args, $CCAnalyzer;
    unshift @$Args, "-d";
    unshift @$Args, "perl";

Then:

 $DB::single = 1;

will break wherever I want in ccc-analyzer. Without the above change,
perl -d scan-build will debug scan-build, but *doesn't* stop at
$DB::single=1; statements inside ccc-analyzer. This is presumably
because ccc-analyzer is started via:

  return (system(@$Args) >> 8);

so the debugger doesn't know to also debug it unless explicitly told to?



More information about the cfe-dev mailing list