blob: f630c03a91f027ebebb7b06fa9e62b3d03a75f2c [file] [log] [blame]
Win32 C++ builds of Avro-C
*****************************
April 2, 2012
These instructions describe some of the changes required to allow
Avro-C to compile under the Microsoft Visual C++ 2008 compiler, as
well as some limitations of the Windows build.
Status of the Windows Build:
****************************
The Windows build of Avro-C compiles under Microsoft Visual C++
2008. You can use C-Make to create the solution file (AvroC.sln) for
the build. The solution file contains projects for the build as well
as projects for the tests. All the tests are run and pass when the
project RUN_TESTS is built from within MS Visual C++ 2008.
Limitations of Windows Build:
******************************
1. The Windows build of Avro-C is compiled using Microsoft's C++
compiler and not Microsoft's C compiler. This is done using the /TP
flag in the MSVC++ compiler. This flag is automatically set using
CMakeLists.txt
The reason to compile Win32 under C++ instead of C is that there
are lots of places where variables are declared after statements,
the Microsoft C compiler does not support declarations after
statements. It is possible, that if all the declarations after
statements were removed, that Avro-C would compile under
Microsoft's C compiler also. I have not tried this.
2. The shared library, i.e. DLL, for avro has not been built. There
are instructions on how to build DLLs using CMake at
http://www.cmake.org/Wiki/BuildingWinDLL
3. Currently avropipe.c and avromod.c do not compile under Windows. In
order for them to compile we would have to either port getopt() to
Windows, or remove their dependency on getopt().
4. Windows cannot run version.sh to generate the version
number. Currently, LIBAVRO_VERSION is hard coded to "22:0:0" for
the Windows build, in the top level CMakeLists.txt.
5. Found two bugs related to improper return values under error
conditions in Avro. These bugs were marked with #warnings in the
code.
Instructions for Maintenance
*****************************
1. Instructions to check name mangling in Visual C++:
In a DOS prompt go to "C:\Program Files(x86)\Microsoft Visual Studio 9.0\VC\"
Run the program vcvarsall.bat . This will set up environment variables.
Now go to the avro_c\build_win32\src\Debug\ directory.
Run the command
dumpbin /ALL avro.lib > tmp.txt
View tmp.txt in your favorite editor. This will allow you to see
which names are mangled and which names are not mangled.
Every header file should start with
#ifndef HEADER_FILE_NAME_H
#define HEADER_FILE_NAME_H
#ifdef __cplusplus
extern "C" {
#define CLOSE_EXTERN }
#else
#define CLOSE_EXTERN
#endif
and end with
CLOSE_EXTERN
#endif /* HEADER_FILE_NAME_H */
This will ensure that all exported (public) functions are mangled
using C name mangling instead of C++ name mangling.
2. All file I/O operations should have "b" for binary in the fopen
statements. Otherwise Windows will replace LF with CRLF in binary
data.
3. Windows does not allow writing to a file with exclusive access
using the mode "wbx". Use the non-exclusive mode "wb" instead.
4. If the hashtable from st.c is used, the functions in the struct
st_hash_type should be cast to HASH_FUNCTION_CAST.
5. Do not use "%zu" to print size_t. Use '"%" PRIsz' without the
single quotes, instead.
6. MS Visual C++ 2008 does not properly expand variadic preprocessor
macros by default. It is possible to "trick" MSVC++ to properly
expand variadic preprocessor macros by using an extra (dummy)
preprocessor macro, whose only purpose is to properly expand its
input. This method is described here:
http://stackoverflow.com/questions/2575864/the-problem-about-different-treatment-to-va-args-when-using-vs-2008-and-gcc
See the solution described by monkeyman.
This method is used in the macro expand_args(...) in test_avro_values.c.
7. Web site describing how to debug macro expansion in Visual C++:
http://fneep.fiffa.net/?p=66
8. Sometimes it is necessary to declare a struct at the top of a file
and define it at the bottom of a file. An example is
AVRO_DATUM_VALUE_CLASS in src/datum_value.c. A C++ compiler will
complain that the struct is defined twice. To avoid this, declare
the struct with the modifier "extern" at the top of the file, and
then define it at the bottom of the file. Note that it cannot be
defined as "static" because Win32 does not like an extern struct
mapping to a static struct.
9. Use __FUNCTION__ instead of __func__ for generating the function
name.
10. All variables need to be explicitly cast when calling functions
with differing function signatures
11. All pointers need to be explicitly cast when assigning to other
pointers of a different type.
12. Do not perform pointer arithmetic on void * pointers. Cast the
pointers to char * before performing pointer arithmetic.
13. The executable names of any examples and tests need to be set
explicitly to include the "Debug/" directory in the path, and the
".exe" ending. See the CMakeLists.txt in the examples and the
tests directory to see how this is done.
14. Do not include the headers inttypes.h or unistd.h or
stdint.h. Instead include avro/platform.h in your C files.
15. Do not include dirent.h in your tests. When _WIN32 is defined
include msdirent.h. See example in test_avro_schema.c.
16. If _WIN32 is defined, define snprintf() to_snprintf(), which MS
Visual C++ recognizes.
17. MSVC++ does not recognize strtoll(). Define it to _strtoi64()
instead.
18. Old-style C function declarations are not allowed in C++. See the
changes in st.c and st.h -- which were converted to new-style
function declarations.
19. Structures cannot be initialized using the .element notation for
Win32. For example if we have a struct test_t:
typedef struct
{
int a;
int b;
} test_t;
Then we can initialize the struct using the syntax:
test_t t1 = { 0, 0 };
But we cannot use the syntax:
test_t t2 = { .a = 0, . b = 0 };
because Win32 does not support it.