1

I want to use frama-c for static C code analysis. It already took me some effort to install it (hopefully) properly. The files are located at C:\CodeAnalysis\frama-c. I want to apply it via Windows console, e.g.:

C:\CodeAnalysis\frama-c\bin\frama-c hello.c

hello.c is just a simple hello-world-program (I am no C programmer btw and a newbie in programming)

#include <stdio.h>

main()
{
 printf("Hello World \n");
}

So when running the above command there is the following output:

[kernel] preprocessing with "gcc -C -E -I. hello.c"
C:/Strawberry/c/x86_64-w64-mingw32/include/stdio.h:141:[kernel] user error: syntax error
[kernel] user error: skipping file "hello.c" that has errors.
[kernel] Frama-C aborted: invalid user input

Yes, I have Perl installed but have no idea why Frama uses it. To me it seems that there is somehow something wrong with the stdio.h. Can this be? But I can compile my program successfully.

C:\Strawberry\c\bin\gcc hello.c produces a nicely working exe file.

When removing the include statement from the file, there is the following output:

[kernel] preprocessing with "gcc -C -E I. hello.c"
hello.c:5:[kernel] warning: Calling undeclared function printf. Old style K&R code?

So frama itself does work and this is the kind of output I expected to have.

I also have MinGW installed and tried to make Frama use this for compiling. So I removed the Strawberry entries in my Windows Path. After that calling frama-c produces the same output.

When completely uninstalling Strawberry Perl, frama doesn't work (stating gcc is an unknown command), although C:\MinGW\mingw64\bin is also added to my Windows Path, even as very first entry.

C:\MinGW\mingw64\bin\gcc hello.c works, gcc hello.c doesn't.

When Perl is installed gcc hello.c works, even when I delete the Strawberry parts from the Windows Path variable. Wtf?

How can I make things work properly?

seesharp
  • 47
  • 11
  • Could you please precise which version of Frama-C you are using? Older versions require using something like `-cpp-extra-args="-I path/to/frama-c/share"` to enable usage of Frama-C's own stdlib, otherwise it will default to the system's version, leading to the behavior you observed. – anol Aug 18 '15 at 15:07
  • Just for information, there are [updated installation instructions](https://bts.frama-c.com/dokuwiki/doku.php?id=mantis:frama-c:compiling_from_sourcecompilation_steps) for Windows which should allow newer Frama-C versions to be installed. Still, they require some knowledge about command-line tools, and Frama-C itself does require some experience in order to provide useful feedback to the user. It does provide some powerful analyses, but it's not an entry-level tool. Newcomers to C might prefer other tools such as [AddressSanitizer](https://en.wikipedia.org/wiki/AddressSanitizer) or Valgrind. – anol Feb 04 '16 at 19:34

1 Answers1

2

There are several issues here, and we have to isolate them in order to fix things.

  1. Strawberry Perl installs its own gcc (based on MinGW), binutils, C headers, etc., by default on directory C:\Strawberry\c\bin. It adds this directory (among others) to the Windows Path variable. Frama-C expects gcc to be in the path, and it is Windows who decides which gcc to choose, if there are several directories in the path which contain a gcc binary. This is why Frama-C seems to use it.

  2. One common mistake (not Windows-specific, but which happens more often in Windows due to the nature of its graphical applications) is to modify environment variables and forget to restart the processes which still have old copies of them (such as Command Prompt). echo %path% should confirm which directories are present in the path for the current command prompt, if there are any doubts about its value.

  3. In case echo %path% contains the expected value, this is what might have happened (unfortunately I cannot reproduce your configuration to test it thoroughly): during installation of Frama-C, it may use the settings present during installation time to choose which directory contains gcc (in your case, C:\Strawberry\c\bin) and later hardcode this directory in its scripts.

    This could explain why, after uninstalling Strawberry Perl, even if another gcc was in the path, it was not considered by Frama-C. Ideally, reinstalling Frama-C with a single gcc in the path could allow it to find the right version this time. Note that this is just a hypothesis, I may be completely wrong here.

    In any case, the major problem you're having is not with gcc itself, but with the headers included with Strawberry Perl, as explained in the next item.

  4. Concerning the error message:

    C:/Strawberry/c/x86_64-w64-mingw32/include/stdio.h:141:[kernel] user error: syntax error
    [kernel] user error: skipping file "hello.c" that has errors.
    

    It is indeed not extremely informative and might change in future versions, but it does point to the source line which causes the error (file stdio.h, line 141):

    int __cdecl __mingw_vsscanf (const char * __restrict__ _Str,
        const char * __restrict__ Format,va_list argp);
    

    In particular, it seems that __restrict__ is the source of the error here (Frama-C Sodium accepts restrict and __restrict, but not __restrict__; this may change in future versions).

    Unfortunately, even fixing this (by adding e.g. #define __restrict__ restrict before #include <stdio.h> in your file) does not guarantee that the rest of the file will be parsed, since it seems to be a Windows-specific, C++-prone header that likely contains other C definitions/extensions that are not in the C99 standard, and possibly not accepted by Frama-C.

The best solution would be to ensure Frama-C uses its own stdio.h header, instead of Strawberry Perl's. It is usually installed in share/frama-c/libc (that is, it could be in C:\CodeAnalysis\frama-c\share\frama-c\libc in your installation), but depending on your configuration the headers might not have been found during execution, and Strawberry Perl's headers were included instead.

A quick hack for this specific case might be replacing:

#include <stdio.h>

with:

#include "C:\CodeAnalysis\frama-c\share\frama-c\libc\stdio.h"

But it is far from ideal and likely to lead to other errors.

If you manage to find out how to prevent Strawberry Perl's headers from being included, and ensure Frama-C's header files are included instead, you should be able to run Frama-C.

Note about Cygwin/MinGW path issues

I've had some issues when using a MinGW compiler and a Cygwin build (which is not necessarily a good idea), so here are some quick instructions on how to build Frama-C Sodium with a MinGW-based OCaml compiler using a Cygwin shell (but not a Cygwin-based OCaml compiler), in case it might help someone:

  1. When running ./configure, you'll need to specify a --prefix using a Windows-based path instead of a Cygwin-based one, such as:

    ./configure --prefix="C:/CodeAnalysis/build"

    If you don't, when running Frama-C (after make/make install) it will fail to find the libc/__fc_builtin_for_normalization.i file because it will try to use the Cygwin-based path, which will not work with the MinGW-based OCaml compiler.

    Note that you cannot use backslashes (\) when specifying the prefix path, since they will not be correctly converted later.

  2. I had to use the following command to ensure the makefile worked correctly:

    make FRAMAC_TOP_SRCDIR="$(cygpath -a -m $PWD)"

    Again, this is due to Cygwin paths not being recognized by the MinGW compiler (in particular, the absolute paths used by the plug-ins).

  3. The previous steps are sufficient to compile and run Frama-C (plus the GUI, if you have lablgtk and other dependencies installed). However, there are still some issues, e.g. absolute Windows filenames are not always handled correctly. This can often be avoided by specifying the file names directly in the command line with relative paths (e.g. frama-c-gui -val hello.c), but in the general case, MinGW+Cygwin is not a very robust combination and other issues may arise.

Overall, mixing Cygwin and MinGW is not a good idea due to path issues, but it is nevertheless possible to compile and run Frama-C in such conditions.

anol
  • 8,264
  • 3
  • 34
  • 78
  • anol, I noticed your reply, but can't take the time to deal with it thoroughly before the weekend. – seesharp Aug 21 '15 at 13:01
  • I've been able to compile the Sodium release via MinGW (as indicated in [this question](http://stackoverflow.com/questions/32091729/)), though due to the lack of a working OPAM installation (and because I didn't try to manually install it), there was no GUI. In that version, I didn't have to add any arguments to ensure Frama-C's stdlib was chosen. – anol Aug 21 '15 at 13:05
  • Well, I found some time. First I downloaded the most actual version and build it with wodi and all that stuff. Seriously, I don't remember exactly because I tried some other tools as well and each build / installation cost me quite some nerves. After I was done I accidentally discovered a Windows installer for Frama-C Boron and decided to use it. The outcome for both versions was the same. I re-installed it, having uninstalled Strawberry Perl first. Now Frama-C uses the MinGW library, but the error message is the same. – seesharp Aug 21 '15 at 13:32
  • However, I found out that calling Frama-C from Cygwin console works. As I need to call it from Windows console, and meanwhile found the -cpp-command flag: `C:\...frama-c hello.c -cpp-command "C:\cygwin64\bin\gcc -C -E"` works. So, I will see, how far I can go with it. And what I wanted to add in my first comment: You were absolutely right with your point 3, anol. Thanks a lot for your effort. – seesharp Aug 21 '15 at 14:07
  • Ah, I see, it must be some cygwin/minGW path issue. I also had some of them, e.g. due to my unorthodox configuration I had to tell Frama-C to make using a different path. I'll add some details in my answer. Note that there are some issues with Unicode characters on the Command Prompt, so the Cygwin terminal would be recommended if possible. – anol Aug 21 '15 at 14:17