I'm writing a command line program in ANSI C to parse a Quake 2 map file to report how many entities and textures are being used. My development machine is MacBook. I'm testing on OS X Snow Leopard (32-bit), Windows XP (32-bit) and Vista (64-bit), and Ubuntu 9.10 (32-bit).
The code is flawless on the OS X and GCC 4.2. The other platforms, not so flawless.
Visual Studio 2005 complained about an array declaration in the middle of the main() block -- size info for the array isn't available until then--that should be declared at top. Fixed that by declaring a pointer at top and writing a function to create the array.
Dev-C++ and GCC (3.4) on Windows has no complaints.
Cygwin and GCC (4.4) on Windows complained about array subscript has type char. I added (int) casts to fix that.
Ubuntu and GCC (4.4) is complaining about ignoring the return value of fread. Although I read elsewhere that I might be a bug in the way Ubuntu packaged GCC. Seems like this one in the context I'm using fread in may be safe to ignore. The warning only appears with the -O3 flag.
Except for Visual Studio 2005, all the compilers that I tested with are some version of GCC. Chasing down all these errors and warnings is serious pain in the butt. Until now, I been using the following flags in my Makefile:
debug: -pedantic -Wall
release: -O3
Is th开发者_如何学Goere a set of GCC flags that I should be using to catch all the errors on my primary development machine? Or is write once and test everywhere a fact of life?
Irritatingly enough, the C dialect in Visual Studio (even the beta of Visual Studio 2010!) is old, and doesn't support all C99 features, and being able to mix declarations and executable statements is probably the most irritating of them all. The least evil option might be to compile as C++ instead on this platform, even if it requires some re-arranging of your code to make it both valid C++ and C.
Other than that, as Ken's comment said, "write-once-test-everywhere is a fact of life". Lint can be a good help (as Chris wrote), but to find all the incompatibilities in syntax and semantics you really need to compile and test your program on several compilers and systems. Doing this can actually help find errors and problems in your code, even if you don't intend to actually run the program on more than one system.
Get yourself a copy of Lint. Lint is a static analysis tool that will pretty much cover the full range of compiler errors and warning and then some. As someone who frequently writes code targeting different platforms and compilers ensuring that the code passes through Lint is a pretty good barometer for getting the code to run across all compilers.
The best set of gcc flags to approximate lint is something like:
-ansi -pedantic -W -Wall -Wundef -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wcast-qual -Wwrite-strings -Weffc++
I also often use
-Wno-long-longif I am going to be writing 64-bit code because many compilers complain that long long is not a c++ type.
*Edit: Fixing copy and paste error in command line options
Add -ansi
to the mix. The canonical set is -ansi -pedantic -Wall
.
That said, you will probably find other quirks with MSVC, because it's a different compiler altogether, with its own warnings - so you might have to tweak its options too.
You can save much time by using -Wall and Lint, because they will help you understand your code better. Rework your code to minimize the safe-to-ignore warnings. You will be less likely to agonize over a hard to reproduce run-time failure. Also, whoever maintains your code will find it easier to make changes.
When you are using Visual Studio, explore the compile options for Lint like tools. I forget where they are, and they slow down your build, but they are helpful.
精彩评论