Build fixes for Windows/Visual C++
authorPetteri Aimonen <jpa@git.mail.kapsi.fi>
Tue, 10 Sep 2013 14:44:32 +0000 (17:44 +0300)
committerPetteri Aimonen <jpa@git.mail.kapsi.fi>
Tue, 10 Sep 2013 14:53:07 +0000 (17:53 +0300)
13 files changed:
compat/pb_syshdr.h
tests/SConstruct
tests/alltypes/SConscript
tests/alltypes/encode_alltypes.c
tests/basic_buffer/SConscript
tests/basic_buffer/decode_buffer.c
tests/basic_buffer/encode_buffer.c
tests/common/test_helpers.h [new file with mode: 0644]
tests/cxx_main_program/SConscript
tests/decode_unittests/SConscript
tests/decode_unittests/decode_unittests.c
tests/encode_unittests/SConscript
tests/site_scons/site_init.py

index c170c8d..b69a167 100644 (file)
@@ -12,6 +12,9 @@
 #define _PB_SYSHDR_H_
 
 /* stdint.h subset */
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#else
 /* You will need to modify these to match the word size of your platform. */
 typedef signed char int8_t;
 typedef unsigned char uint8_t;
@@ -21,8 +24,13 @@ typedef signed int int32_t;
 typedef unsigned int uint32_t;
 typedef signed long long int64_t;
 typedef unsigned long long uint64_t;
+#endif
 
 /* stddef.h subset */
+#ifdef HAVE_STDDEF_H
+#include <stddef.h>
+#else
+
 typedef uint32_t size_t;
 #define offsetof(st, m) ((size_t)(&((st *)0)->m))
 
@@ -30,12 +38,26 @@ typedef uint32_t size_t;
 #define NULL 0
 #endif
 
+#endif
+
 /* stdbool.h subset */
+#ifdef HAVE_STDBOOL_H
+#include <stdbool.h>
+#else
+
+#ifndef __cplusplus
 typedef int bool;
 #define false 0
 #define true 1
+#endif
+
+#endif
 
 /* string.h subset */
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+
 /* Implementations are from the Public Domain C Library (PDCLib). */
 static size_t strlen( const char * s )
 {
@@ -67,5 +89,6 @@ static void * memset( void * s, int c, size_t n )
     }
     return s;
 }
+#endif
 
 #endif
index a690aff..8bbb31d 100644 (file)
@@ -1,4 +1,5 @@
-env = DefaultEnvironment()
+import os
+env = Environment(ENV = {'PATH': os.environ['PATH']})
 
 # Add the builders defined in site_init.py
 add_nanopb_builders(env)
@@ -7,18 +8,49 @@ add_nanopb_builders(env)
 env.Append(CPPPATH = ["#../", "#common"])
 
 # Path for finding nanopb.proto
-env.Append(PROTOCPATH = ['#../generator', '/usr/include', '.'])
+env.Append(PROTOCPATH = '#../generator')
 
-# Define the include path to find nanopb.proto
-env.Append(PROTOCPATH = ['#../generator', '/usr/include', '.'])
+# Check the compilation environment, unless we are just cleaning up.
+if not env.GetOption('clean'):
+    conf = Configure(env)
 
-# If the platform doesn't support C99, use our own header file instead.
-conf = Configure(env)
-if not conf.CheckCHeader('stdbool.h'):
-       conf.env.Append(CPPDEFINES = {'PB_SYSTEM_HEADER': '\\"pb_syshdr.h\\"'})
-       conf.env.Append(CPPPATH = "#../compat")
-env = conf.Finish()
+    # If the platform doesn't support C99, use our own header file instead.
+    stdbool = conf.CheckCHeader('stdbool.h')
+    stdint = conf.CheckCHeader('stdint.h')
+    stddef = conf.CheckCHeader('stddef.h')
+    string = conf.CheckCHeader('string.h')
+    if not stdbool or not stdint or not stddef or not string:
+        conf.env.Append(CPPDEFINES = {'PB_SYSTEM_HEADER': '\\"pb_syshdr.h\\"'})
+        conf.env.Append(CPPPATH = "#../compat")
+        
+        if stdbool: conf.env.Append(CPPDEFINES = {'HAVE_STDBOOL_H': 1})
+        if stdint: conf.env.Append(CPPDEFINES = {'HAVE_STDINT_H': 1})
+        if stddef: conf.env.Append(CPPDEFINES = {'HAVE_STDDEF_H': 1})
+        if string: conf.env.Append(CPPDEFINES = {'HAVE_STRING_H': 1})
+        
+    # Check if we can use pkg-config to find protobuf include path
+    status, output = conf.TryAction('pkg-config protobuf --variable=includedir > $TARGET')
+    if status:
+        conf.env.Append(PROTOCPATH = output.strip())
+    else:
+        conf.env.Append(PROTOCPATH = '/usr/include')
+        
+    # End the config stuff
+    env = conf.Finish()
 
+# Initialize the CCFLAGS according to the compiler
+if 'cl' in env['CC']:
+    # Microsoft Visual C++
+    
+    # Debug info on, warning level 2 for tests, warnings as errors
+    env.Append(CCFLAGS = '/Zi /W2 /WX')
+    env.Append(LINKFLAGS = '/DEBUG')
+    
+    # PB_RETURN_ERROR triggers C4127 because of while(0)
+    env.Append(CCFLAGS = '/wd4127')
+    
+    
+    
 # Now include the SConscript files from all subdirectories
 SConscript(Glob('*/SConscript'), exports = 'env')
 
index 3c8adc4..8aa45b6 100644 (file)
@@ -4,9 +4,9 @@
 Import("env")
 
 env.NanopbProto("alltypes")
-env.Program(["encode_alltypes.c", "alltypes.pb.c", "#common/pb_encode.o"])
-env.Program(["decode_alltypes.c", "alltypes.pb.c", "#common/pb_decode.o"])
+enc = env.Program(["encode_alltypes.c", "alltypes.pb.c", "#common/pb_encode.o"])
+dec = env.Program(["decode_alltypes.c", "alltypes.pb.c", "#common/pb_decode.o"])
 
-env.RunTest("encode_alltypes")
-env.RunTest(["decode_alltypes", "encode_alltypes.output"])
+env.RunTest(enc)
+env.RunTest([dec, "encode_alltypes.output"])
 
index 982ad3c..802e157 100644 (file)
@@ -113,18 +113,20 @@ int main(int argc, char **argv)
     
     alltypes.end = 1099;
     
-    uint8_t buffer[1024];
-    pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
-    
-    /* Now encode it and check if we succeeded. */
-    if (pb_encode(&stream, AllTypes_fields, &alltypes))
-    {
-        fwrite(buffer, 1, stream.bytes_written, stdout);
-        return 0; /* Success */
-    }
-    else
     {
-        fprintf(stderr, "Encoding failed: %s\n", PB_GET_ERROR(&stream));
-        return 1; /* Failure */
+        uint8_t buffer[1024];
+        pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
+        
+        /* Now encode it and check if we succeeded. */
+        if (pb_encode(&stream, AllTypes_fields, &alltypes))
+        {
+            fwrite(buffer, 1, stream.bytes_written, stdout);
+            return 0; /* Success */
+        }
+        else
+        {
+            fprintf(stderr, "Encoding failed: %s\n", PB_GET_ERROR(&stream));
+            return 1; /* Failure */
+        }
     }
 }
index 5b85e13..349fb14 100644 (file)
@@ -2,11 +2,11 @@
 
 Import("env")
 
-env.Program(["encode_buffer.c", "#common/person.pb.c", "#common/pb_encode.o"])
-env.Program(["decode_buffer.c", "#common/person.pb.c", "#common/pb_decode.o"])
+enc = env.Program(["encode_buffer.c", "#common/person.pb.c", "#common/pb_encode.o"])
+dec = env.Program(["decode_buffer.c", "#common/person.pb.c", "#common/pb_decode.o"])
 
-env.RunTest("encode_buffer")
-env.RunTest(["decode_buffer", "encode_buffer.output"])
+env.RunTest(enc)
+env.RunTest([dec, "encode_buffer.output"])
 env.Decode(["encode_buffer.output", "#common/person.proto"], MESSAGE = "Person")
 env.Compare(["decode_buffer.output", "encode_buffer.decoded"])
 
index 56bbd8f..d231c91 100644 (file)
@@ -9,6 +9,7 @@
 #include <stdio.h>
 #include <pb_decode.h>
 #include "person.pb.h"
+#include "test_helpers.h"
 
 /* This function is called once from main(), it handles
    the decoding and printing. */
@@ -59,9 +60,13 @@ bool print_person(pb_istream_t *stream)
 
 int main()
 {
-    /* Read the data into buffer */
     uint8_t buffer[512];
-    size_t count = fread(buffer, 1, sizeof(buffer), stdin);
+    pb_istream_t stream;
+    size_t count;
+    
+    /* Read the data into buffer */
+    SET_BINARY_MODE(stdin);
+    count = fread(buffer, 1, sizeof(buffer), stdin);
     
     if (!feof(stdin))
     {
@@ -70,7 +75,7 @@ int main()
     }
     
     /* Construct a pb_istream_t for reading from the buffer */
-    pb_istream_t stream = pb_istream_from_buffer(buffer, count);
+    stream = pb_istream_from_buffer(buffer, count);
     
     /* Decode and print out the stuff */
     if (!print_person(&stream))
index 742c99f..d3e4f6e 100644 (file)
@@ -6,9 +6,13 @@
 #include <stdio.h>
 #include <pb_encode.h>
 #include "person.pb.h"
+#include "test_helpers.h"
 
 int main()
 {
+    uint8_t buffer[512];
+    pb_ostream_t stream;
+    
     /* Initialize the structure with constants */
     Person person = {"Test Person 99", 99, true, "test@person.com",
         3, {{"555-12345678", true, Person_PhoneType_MOBILE},
@@ -16,12 +20,13 @@ int main()
             {"1234-5678", true, Person_PhoneType_WORK},
         }};
 
-    uint8_t buffer[512];
-    pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
+    stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
     
     /* Now encode it and check if we succeeded. */
     if (pb_encode(&stream, Person_fields, &person))
-    {
+    {    
+        /* Write the result data to stdout */
+        SET_BINARY_MODE(stdout);
         fwrite(buffer, 1, stream.bytes_written, stdout);
         return 0; /* Success */
     }
diff --git a/tests/common/test_helpers.h b/tests/common/test_helpers.h
new file mode 100644 (file)
index 0000000..f77760a
--- /dev/null
@@ -0,0 +1,17 @@
+/* Compatibility helpers for the test programs. */
+
+#ifndef _TEST_HELPERS_H_
+#define _TEST_HELPERS_H_
+
+#ifdef _WIN32
+#include <io.h>
+#include <fcntl.h>
+#define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
+
+#else
+#define SET_BINARY_MODE(file)
+
+#endif
+
+
+#endif
index b548231..0d0a25c 100644 (file)
@@ -13,8 +13,8 @@ Command("encode_alltypes.cxx", "#alltypes/encode_alltypes.c", c)
 Command("decode_alltypes.cxx", "#alltypes/decode_alltypes.c", c)
 
 # Now build and run the test normally.
-env.Program(["encode_alltypes.cxx", "alltypes.pb.cxx", "pb_encode.cxx"])
-env.Program(["decode_alltypes.cxx", "alltypes.pb.cxx", "pb_decode.cxx"])
+enc = env.Program(["encode_alltypes.cxx", "alltypes.pb.cxx", "pb_encode.cxx"])
+dec = env.Program(["decode_alltypes.cxx", "alltypes.pb.cxx", "pb_decode.cxx"])
 
-env.RunTest("encode_alltypes")
-env.RunTest(["decode_alltypes", "encode_alltypes.output"])
+env.RunTest(enc)
+env.RunTest([dec, "encode_alltypes.output"])
index 860d773..5e0f840 100644 (file)
@@ -1,4 +1,4 @@
 Import('env')
-env.Program(["decode_unittests.c", "#common/unittestproto.pb.c", "#common/pb_decode.o"])
-env.RunTest('decode_unittests')
+p = env.Program(["decode_unittests.c", "#common/unittestproto.pb.c", "#common/pb_decode.o"])
+env.RunTest(p)
 
index 6ad05f0..9c447a5 100644 (file)
@@ -291,7 +291,7 @@ int main()
     
     {
         pb_istream_t s;
-        IntegerContainer dest = {};
+        IntegerContainer dest = {{0}};
         
         COMMENT("Testing pb_decode_delimited")
         TEST((s = S("\x09\x0A\x07\x0A\x05\x01\x02\x03\x04\x05"),
index 0864a91..6a5ffcf 100644 (file)
@@ -1,5 +1,5 @@
 # Build and run the stand-alone unit tests for the nanopb encoder part.
 
 Import('env')
-env.Program(["encode_unittests.c", "#common/unittestproto.pb.c", "#common/pb_encode.o"])
-env.RunTest('encode_unittests')
+p = env.Program(["encode_unittests.c", "#common/unittestproto.pb.c", "#common/pb_encode.o"])
+env.RunTest(p)
index 1383067..b69db64 100644 (file)
@@ -1,6 +1,13 @@
 import subprocess
 import sys
 
+try:
+    # Make terminal colors work on windows
+    import colorama
+    colorama.init()
+except ImportError:
+    pass
+
 def add_nanopb_builders(env):
     '''Add the necessary builder commands for nanopb tests.'''
     
@@ -14,6 +21,7 @@ def add_nanopb_builders(env):
                                  src_suffix = '.proto')
     env.Append(BUILDERS = {'Proto': proto_file_builder})
     env.SetDefault(PROTOC = 'protoc')
+    env.SetDefault(PROTOCPATH = ['.'])
 
     # Build command for running nanopb generator
     import os.path
@@ -50,9 +58,9 @@ def add_nanopb_builders(env):
                                 stderr = sys.stderr)
         result = pipe.wait()
         if result == 0:
-            print '\033[92m[ OK ]\033[0m   Ran ' + str(source[0])
+            print '\033[32m[ OK ]\033[0m   Ran ' + str(source[0])
         else:
-            print '\033[91m[FAIL]\033[0m   Program ' + str(source[0]) + ' returned ' + str(result)
+            print '\033[31m[FAIL]\033[0m   Program ' + str(source[0]) + ' returned ' + str(result)
         return result
         
     run_test_builder = Builder(action = run_test,
@@ -73,10 +81,10 @@ def add_nanopb_builders(env):
         data1 = open(str(source[0]), 'rb').read()
         data2 = open(str(source[1]), 'rb').read()
         if data1 == data2:
-            print '\033[92m[ OK ]\033[0m   Files equal: ' + str(source[0]) + ' and ' + str(source[1])
+            print '\033[32m[ OK ]\033[0m   Files equal: ' + str(source[0]) + ' and ' + str(source[1])
             return 0
         else:
-            print '\033[91m[FAIL]\033[0m   Files differ: ' + str(source[0]) + ' and ' + str(source[1])
+            print '\033[31m[FAIL]\033[0m   Files differ: ' + str(source[0]) + ' and ' + str(source[1])
             return 1
 
     compare_builder = Builder(action = compare_files,