From f9aa4a12cd245f8ae681c7d7eeec4a885d7dff9b Mon Sep 17 00:00:00 2001 From: Shahram Najm Date: Mon, 7 Jan 2019 16:13:48 +0000 Subject: [PATCH] Windows support: merge branch dtip-windows from Github --- CMakeLists.txt | 7 +- cmake/eccodes_test_endiness.cmake | 4 +- examples/C/bufr_keys_iterator.c | 2 +- examples/C/grib_keys_iterator.c | 7 +- examples/C/large_grib1.c | 4 +- memfs.py | 3 +- src/eccodes_windef.h | 1 + src/grib_accessor_class_codetable.c | 1 - src/grib_api.h | 1 - src/grib_api_internal.h | 1 - src/grib_jasper_encoding.c | 1 - src/grib_timer.c_off | 336 ---------------------------- tests/largefile.c | 3 + tests/multi_from_message.c | 3 + tests/values_to_ascii.c | 3 + tests/windows_testing.bashrc | 11 + tigge/tigge_check.c | 13 +- tigge/tigge_name.c | 8 +- tigge/tigge_split.c | 17 +- tigge/tigge_tools.c | 40 +++- tools/CMakeLists.txt | 12 +- tools/codes_info.c | 4 + tools/grib_options.c | 1 - tools/grib_to_netcdf.c | 5 + tools/wingetopt.h | 2 - 25 files changed, 132 insertions(+), 358 deletions(-) delete mode 100644 src/grib_timer.c_off create mode 100644 tests/windows_testing.bashrc diff --git a/CMakeLists.txt b/CMakeLists.txt index 2af9428da..97e995147 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -127,7 +127,7 @@ endif() ecbuild_add_option( FEATURE MEMFS DESCRIPTION "Memory based access to definitions/samples" DEFAULT OFF - CONDITION ECCODES_HAVE_FMEMOPEN OR ECCODES_HAVE_FUNOPEN + CONDITION ECCODES_HAVE_FMEMOPEN OR ECCODES_HAVE_FUNOPEN OR (EC_OS_NAME MATCHES "windows") REQUIRED_PACKAGES PythonInterp ) @@ -283,6 +283,11 @@ if( IEEE_LE ) set( IEEE_BE 0 ) endif() +# Symbols need to be explicitly exported on Windows so we can link to dlls. +if( EC_OS_NAME MATCHES "windows" ) + set( CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE ) +endif() + ############################################################################### # contents diff --git a/cmake/eccodes_test_endiness.cmake b/cmake/eccodes_test_endiness.cmake index 634de4227..0f1870d68 100644 --- a/cmake/eccodes_test_endiness.cmake +++ b/cmake/eccodes_test_endiness.cmake @@ -53,7 +53,7 @@ if( NOT DEFINED IEEE_BE ) endif() if( ECCODES_BIG_ENDIAN AND NOT IEEE_BE ) - ecbuild_critical("Failed to sanity check on endiness: OS should be Big-Endian but compiled code runs differently -- to ignore this pass -DIEEE_BE=0 to CMake/ecBuild") + ecbuild_critical("Failed to sanity check on endiness: OS should be Big-Endian but compiled code runs differently -- to ignore this pass -DIEEE_BE=1 to CMake/ecBuild") endif() if( NOT DEFINED IEEE_LE ) @@ -89,5 +89,5 @@ if( NOT DEFINED IEEE_LE ) endif() if( ECCODES_LITTLE_ENDIAN AND NOT IEEE_LE ) - ecbuild_critical("Failed to sanity check on endiness: OS should be Little-Endian but compiled code runs differently -- to ignore this pass -DIEEE_LE=0 to CMake/ecBuild") + ecbuild_critical("Failed to sanity check on endiness: OS should be Little-Endian but compiled code runs differently -- to ignore this pass -DIEEE_LE=1 to CMake/ecBuild") endif() diff --git a/examples/C/bufr_keys_iterator.c b/examples/C/bufr_keys_iterator.c index bea9615fa..69c6b1494 100644 --- a/examples/C/bufr_keys_iterator.c +++ b/examples/C/bufr_keys_iterator.c @@ -88,7 +88,7 @@ int main(int argc,char* argv[]) { /* not array */ vlen=MAX_VAL_LEN; - bzero(value,vlen); + memset(value, 0, vlen); codes_get_string(h,name,value,&vlen); printf("%s\n",value); } diff --git a/examples/C/grib_keys_iterator.c b/examples/C/grib_keys_iterator.c index 3fc6a38ed..0ef3a60f0 100644 --- a/examples/C/grib_keys_iterator.c +++ b/examples/C/grib_keys_iterator.c @@ -21,9 +21,12 @@ #include #include #include -#include #include +#if !(defined(_WIN32) && defined(_MSC_VER)) +#include +#endif + #include "eccodes.h" #define MAX_VAL_LEN 1024 @@ -82,7 +85,7 @@ int main(int argc, char *argv[]) { const char* name = codes_keys_iterator_get_name(kiter); vlen=MAX_VAL_LEN; - bzero(value,vlen); + memset(value, 0, vlen); CODES_CHECK(codes_get_string(h,name,value,&vlen),name); printf("%s = %s\n",name,value); diff --git a/examples/C/large_grib1.c b/examples/C/large_grib1.c index ee64bea19..2cfc88132 100644 --- a/examples/C/large_grib1.c +++ b/examples/C/large_grib1.c @@ -29,8 +29,8 @@ int main() } for (i=0; i #include #include +#include "eccodes_windef.h" struct entry { const char* path; @@ -173,7 +174,7 @@ static FILE* fmemopen(const char* buffer, size_t size, const char* mode){ return funopen(f, &read_mem, &write_mem, &seek_mem, &close_mem); } -#elif defined(_WIN32) +#elif defined(ECCODES_ON_WINDOWS) #include #include diff --git a/src/eccodes_windef.h b/src/eccodes_windef.h index 043c495a1..4f6992575 100644 --- a/src/eccodes_windef.h +++ b/src/eccodes_windef.h @@ -14,6 +14,7 @@ /* Microsoft Windows Visual Studio support */ #if defined(_WIN32) && defined(_MSC_VER) # define ECCODES_ON_WINDOWS +# define YY_NO_UNISTD_H #endif #endif diff --git a/src/grib_accessor_class_codetable.c b/src/grib_accessor_class_codetable.c index c0afc2e0d..8c3d7d86a 100644 --- a/src/grib_accessor_class_codetable.c +++ b/src/grib_accessor_class_codetable.c @@ -656,7 +656,6 @@ static int pack_string(grib_accessor* a, const char* buffer, size_t *len) #ifndef ECCODES_ON_WINDOWS cmpproc cmp = (a->flags & GRIB_ACCESSOR_FLAG_LOWERCASE) ? strcmp_nocase : strcmp; #else - /* Microsoft Windows Visual Studio support */ cmpproc cmp = (a->flags & GRIB_ACCESSOR_FLAG_LOWERCASE) ? stricmp : strcmp; #endif diff --git a/src/grib_api.h b/src/grib_api.h index 43061b002..a741aa43e 100644 --- a/src/grib_api.h +++ b/src/grib_api.h @@ -21,7 +21,6 @@ #include #include -/* Microsoft Windows Visual Studio support */ #include "eccodes_windef.h" #ifndef ECCODES_ON_WINDOWS diff --git a/src/grib_api_internal.h b/src/grib_api_internal.h index 3b108f8b3..b2be9291d 100644 --- a/src/grib_api_internal.h +++ b/src/grib_api_internal.h @@ -58,7 +58,6 @@ #include #include -/* Microsoft Windows Visual Studio support */ #include "eccodes_windef.h" #ifndef ECCODES_ON_WINDOWS diff --git a/src/grib_jasper_encoding.c b/src/grib_jasper_encoding.c index a7a46d490..965f8183f 100644 --- a/src/grib_jasper_encoding.c +++ b/src/grib_jasper_encoding.c @@ -164,7 +164,6 @@ int grib_jasper_encode(grib_context *c, j2k_encode_helper *helper) #ifndef ECCODES_ON_WINDOWS snprintf (opts, MAXOPTSSIZE, "mode=real\nrate=%f", 1.0/helper->compression); #else - /* Microsoft Windows Visual Studio support */ _snprintf(opts, MAXOPTSSIZE, "mode=real\nrate=%f", 1.0/helper->compression); #endif } diff --git a/src/grib_timer.c_off b/src/grib_timer.c_off deleted file mode 100644 index 3f28bda00..000000000 --- a/src/grib_timer.c_off +++ /dev/null @@ -1,336 +0,0 @@ -#include "grib_api_internal.h" -#include -#include -#include - - -static grib_timer *timers = NULL; -int false=0; -int true=1; -#define long64 long - -#define ROUND(a) ((long)((a)+0.5)) - -double proc_cpu() -{ - struct rusage rup; - - if(getrusage(RUSAGE_SELF,&rup) != -1) - { - return (rup.ru_utime.tv_sec + rup.ru_utime.tv_usec / 1000000.0 + - rup.ru_stime.tv_sec + rup.ru_stime.tv_usec / 1000000.0); - } - return clock()/(double)CLOCKS_PER_SEC; -} - -static char *timetext(char *pfx,double ds,char *text) -{ - long s = ROUND(ds); - long x = s; - long n; - char sec[20]; - char min[20]; - char hou[20]; - char day[20]; - - *text = *sec = *min = *hou = *day = 0; - if(s) - { - - if((n = x % 60) != 0) sprintf(sec,"%ld sec ",n); - x /= 60; - if((n = x % 60) != 0) sprintf(min,"%ld min ",n); - x /= 60; - if((n = x % 24) != 0) sprintf(hou,"%ld hour ",n); - x /= 24; - if((n = x) != 0) sprintf(day,"%ld day ",n); - - sprintf(text,"%s%s%s%s%s",pfx,day,hou,min,sec); - } - - return text; - -} - -char *timename(double t) -{ - static char buf[80]; - return timetext("",t,buf); -} - -grib_timer *grib_get_timer(grib_context* c,const char* name, const char *statname, int elapsed) -{ - grib_timer *t = timers; - if (!c) c=grib_context_get_default( ); - - while(t) - { - if(strcmp(name,t->name_) == 0) - return t; - t = t->next_; - } - - t = grib_context_malloc_clear(c,sizeof(grib_timer)); - t->name_ = (char*) name; - t->context =c; - t->active_ = false; - t->count_ = 0; - t->timer_ = 0; - t->total_ = 0; - - t->elapsed_ = elapsed; /* Whether to print CPU usage */ - t->cpu_ = 0; - t->total_cpu_ = 0; - - t->statname_ = 0; - if(statname) - t->statname_ = (char*)statname; - - t->next_ = timers; - timers = t; - - return t; -} - -int grib_timer_start(grib_timer* t) -{ - -#ifndef NOTIMER - int e = gettimeofday(&t->start_,NULL); - if(e != 0) - grib_context_log(t->context,GRIB_LOG_WARNING|GRIB_LOG_PERROR,"Error starting timer '%s'",t->name_?t->name_:"unnamed"); - t->active_ = true; - t->cpu_ = proc_cpu(); - return e; -#else - return 0; -#endif -} - -int grib_timer_stop(grib_timer* t, long total) -{ - -#ifndef NOTIMER - struct timeval stop, diff; - int e = gettimeofday(&stop,NULL); - double c = proc_cpu(); - - if(e != 0) - grib_context_log(t->context,GRIB_LOG_WARNING|GRIB_LOG_PERROR,"Error stopping timer '%s'",t->name_?t->name_:"unnamed"); - - if(!t->active_) - { - grib_context_log(t->context,GRIB_LOG_WARNING,"Stopping non-started timer '%s'",t->name_?t->name_:"unnamed"); - return 1; - } - - diff.tv_sec = stop.tv_sec - t->start_.tv_sec; - diff.tv_usec = stop.tv_usec - t->start_.tv_usec; - if (diff.tv_usec < 0) - { - diff.tv_sec--; - diff.tv_usec += 1000000; - } - - t->timer_ += (double)diff.tv_sec + ((double)diff.tv_usec / 1000000.); - t->total_ += total; - t->total_cpu_ += (c - t->cpu_); - - t->active_=false; - t->count_++; - - return e; - -#else - return 0; -#endif -} - -double grib_timer_value(grib_timer *t) -{ - return t->timer_; -} - -const char *bytename(double bytes) -{ - static char *names[] = { - "","K","M","G","T" }; - double x = bytes; - int n = 0; - static char buf[20]; - - while(x>=1024.0) - { - x /= 1024.0; - n++; - } - - sprintf(buf,"%.2f %s",x,names[n]); - - return buf; -} - -void grib_timer_print(grib_timer* t) -{ - char cpu[1024] = ""; - char *name = t->name_?t->name_:""; - if(t->timer_>=1) { - if(! t->elapsed_ && t->total_cpu_ >= 1.0) - sprintf(cpu,"cpu: %s",timename(t->total_cpu_)); - - if(t->total_ != 0) - { - double rate = (double)t->total_/t->timer_; - char bytes[80]; - sprintf(bytes,"%sbyte(s)",bytename(t->total_)); - grib_context_print(t->context,stdout," %s: %s in %s [%sbyte/sec] %s\n", - name,bytes,timename(t->timer_),bytename(rate),cpu); - } - else { - char* ctimename=timename(t->timer_); - grib_context_print(t->context,stdout," %s: wall: %s%s\n",name,ctimename,cpu); - } -/* - if(t->statname_) - log_statistics(t->statname_,"%ld",(long)t->timer_); - */ - } -} - -void grib_timer_partial_rate(grib_timer *t, double start, long total) -{ - double ptime = t->timer_ - start; - long ptotal = total; - char *name = t->name_?t->name_:""; - if(ptime>=1) - { - double rate = (double)ptotal/ptime; - char bytes[80]; - sprintf(bytes,"%sbyte(s)",bytename(ptotal)); - grib_context_log(t->context,GRIB_LOG_INFO," %s: %s in %s [%sbyte/sec]", - name,bytes,timename(ptime),bytename(rate)); - } -} - -void grib_print_all_timers() -{ - grib_timer *t = timers; - while(t) - { - grib_timer_print(t); - t = t->next_; - } -} - -void grib_reset_all_timers() -{ - grib_timer *t = timers; - while(t) - { - t->count_ = 0; - t->timer_ = 0; - t->active_ = 0; - t->total_ = 0; - t->total_cpu_ = 0; - t = t->next_; - } -} - - -/************************************************* -* Timed functions -**************************************************/ -/* -int timed_fread(char *buffer, int n, int length, FILE *f, grib_timer *t) -{ - int r = 0; - long total = 0; - timer_start(t); - if((r = fread(buffer,n,length,f)) > 0) - total = r*n; - - timer_stop(t,total); - - return r; -} - - -int timed_wind_next(wind* w, FILE *f, char *buffer, long *length, grib_timer *t) -{ - int r = 0; - long64 total = 0; - timer_start(t); - if((r = wind_next(w,f,buffer,length)) == 0) - total = *length; - - timer_stop(t,total); - - return r; -} - -int timed_fwrite(char *buffer, int n, int length, FILE *f, grib_timer *t) -{ - int r = 0; - long64 total = 0; - timer_start(t); - if((r = fwrite(buffer,n,length,f)) > 0) - total = r*n; - timer_stop(t,total); - - return r; -} - -int timed_fclose(FILE *f, grib_timer *t) -{ - int r = 0; - timer_start(t); - r = fclose(f); - timer_stop(t,0); - - return r; -} - -int timed_writetcp(void *data, char *buffer, int n, grib_timer *t) -{ - int r = 0; - long64 total = 0; - timer_start(t); - if((r = writetcp(data,buffer,n)) > 0) - total = r; - timer_stop(t,total); - - return r; -} - -int timed_readtcp(void *data, char *buffer, int n, grib_timer *t) -{ - int r = 0; - long64 total = 0; - timer_start(t); - if((r = readtcp(data,buffer,n)) > 0) - total = r; - timer_stop(t,total); - return r; -} - -int timed_readany(FILE *f, char *buffer, long *length, grib_timer *t) -{ - int e; - long original = *length; - long64 total = 0; - timer_start(t); - if(((e = _readany(f,buffer,length)) == NOERR) || (e == BUF_TO_SMALL)) - total = (e == BUF_TO_SMALL)?original:*length; - timer_stop(t,total); - - if(e != NOERR && e != BUF_TO_SMALL && e != EOF) - { - if(e == NOT_FOUND_7777) - marslog(LOG_WARN,"Group 7777 not found by readany",e); - else - marslog(LOG_WARN,"Error %d returned by readany",e); - } - - return e; -} -*/ diff --git a/tests/largefile.c b/tests/largefile.c index 8ff86ca81..9ad42affb 100644 --- a/tests/largefile.c +++ b/tests/largefile.c @@ -16,7 +16,10 @@ /* #include */ /* #include */ #include "grib_api_internal.h" + +#ifndef ECCODES_ON_WINDOWS #include +#endif void usage(char* prog) { printf("usage: %s filename\n",prog); diff --git a/tests/multi_from_message.c b/tests/multi_from_message.c index 5cff4ef7e..8023c3baa 100644 --- a/tests/multi_from_message.c +++ b/tests/multi_from_message.c @@ -15,7 +15,10 @@ #include "grib_api.h" #include #include + +#ifndef ECCODES_ON_WINDOWS #include +#endif static void usage(const char* prog) { printf("usage: %s [-m] file.grib\n",prog); diff --git a/tests/values_to_ascii.c b/tests/values_to_ascii.c index 7a1694c82..161edee05 100755 --- a/tests/values_to_ascii.c +++ b/tests/values_to_ascii.c @@ -10,7 +10,10 @@ #include #include + +#ifndef ECCODES_ON_WINDOWS #include +#endif #include "grib_api.h" diff --git a/tests/windows_testing.bashrc b/tests/windows_testing.bashrc new file mode 100644 index 000000000..f65068a8b --- /dev/null +++ b/tests/windows_testing.bashrc @@ -0,0 +1,11 @@ +# bashrc to be used for running tests on windows. +# In order for the functions to be usable by the tests, we need to use the -i option. +# Typical usage: +# bash --rcfile windows_testing.bashrc -ci "some/test/script.sh" + +# During testing we diff Windows files with Unix files => need to ignore the carriage +# return. +function diff { + command diff --strip-trailing-cr "$@" +} +export -f diff diff --git a/tigge/tigge_check.c b/tigge/tigge_check.c index 32b3b74d1..0ded67674 100755 --- a/tigge/tigge_check.c +++ b/tigge/tigge_check.c @@ -25,7 +25,18 @@ #include #include #include -#include + +#ifndef ECCODES_ON_WINDOWS + #include +#else + #include + #include + + #ifdef _MSC_VER + # define strcasecmp _stricmp + #endif +#endif + #include #include "tigge_tools.h" diff --git a/tigge/tigge_name.c b/tigge/tigge_name.c index b3a9837b9..e2878a915 100755 --- a/tigge/tigge_name.c +++ b/tigge/tigge_name.c @@ -25,9 +25,15 @@ #include #include #include -#include #include "tigge_tools.h" +#ifndef ECCODES_ON_WINDOWS + #include +#else + #include + #include +#endif + /* #define CHECK(a) check(#a,a) */ #define NUMBER(a) (sizeof(a)/sizeof(a[0])) diff --git a/tigge/tigge_split.c b/tigge/tigge_split.c index 7e69fd060..b634fbfbb 100755 --- a/tigge/tigge_split.c +++ b/tigge/tigge_split.c @@ -25,9 +25,22 @@ #include #include #include -#include -#include +#ifndef ECCODES_ON_WINDOWS + #include + #include +#else + #include + #include + + #ifndef F_OK + # define F_OK 0 + #endif + + #ifdef _MSC_VER + # define access(path,mode) _access(path,mode) + #endif +#endif #define CHECK(a) check(#a,a) diff --git a/tigge/tigge_tools.c b/tigge/tigge_tools.c index f6501a915..d33cc9bb2 100644 --- a/tigge/tigge_tools.c +++ b/tigge/tigge_tools.c @@ -13,14 +13,23 @@ */ #include "tigge_tools.h" +#include "eccodes_windef.h" #include #include -#include + +#ifndef ECCODES_ON_WINDOWS + #include +#else + #include + #include +#endif + #include extern void validate(const char* path); +#ifndef ECCODES_ON_WINDOWS void scan(const char* name) { DIR *dir; @@ -41,3 +50,32 @@ void scan(const char* name) validate(name); } } +#else +// based on similar code in grib_tools.c +static int isWinDir(const struct _finddata_t *fileinfo) +{ + if((fileinfo->attrib & 16) == 16) + return 1; + return 0; +} +void scan(const char* name) +{ + struct _finddata_t fileinfo; + intptr_t handle; + if((handle = _findfirst(name, &fileinfo)) != -1) + { + char tmp[1024]; + do { + if(isWinDir(&fileinfo)) + { + if(fileinfo.name[0] != '.') { + sprintf(tmp, "%s/%s", name, fileinfo.name); + scan(tmp); + } + } + } while(!_findnext(handle, &fileinfo)); + } + else + validate(name); +} +#endif diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index c1a0b528b..2fac9cda9 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -9,11 +9,21 @@ # nor does it submit to any jurisdiction. # +list( APPEND grib_tools_sources + grib_tools.c + grib_options.c + grib_tools.h + ) + +if( EC_OS_NAME MATCHES "windows" ) + list( APPEND grib_tools_sources wingetopt.c ) +endif() + # tools library ecbuild_add_library( TARGET grib_tools TYPE STATIC NOINSTALL - SOURCES grib_tools.c grib_options.c grib_tools.h + SOURCES ${grib_tools_sources} LIBS eccodes ) # tools binaries diff --git a/tools/codes_info.c b/tools/codes_info.c index 720aadccf..1f1f37a0a 100644 --- a/tools/codes_info.c +++ b/tools/codes_info.c @@ -13,6 +13,10 @@ extern char *optarg; extern int optind; +#ifdef ECCODES_ON_WINDOWS +#include "wingetopt.h" +#endif + static void usage_and_exit(const char* progname) { printf("\nUsage: %s [-v] [-d] [-s]\n",progname); exit(1); diff --git a/tools/grib_options.c b/tools/grib_options.c index e5116cea9..893208bc3 100644 --- a/tools/grib_options.c +++ b/tools/grib_options.c @@ -18,7 +18,6 @@ extern char *optarg; extern int optind; #ifdef ECCODES_ON_WINDOWS -/* Microsoft Windows Visual Studio support */ #include "wingetopt.h" #endif diff --git a/tools/grib_to_netcdf.c b/tools/grib_to_netcdf.c index 211be8026..2d78f921b 100644 --- a/tools/grib_to_netcdf.c +++ b/tools/grib_to_netcdf.c @@ -23,6 +23,11 @@ #include #include "grib_tools.h" +#include "eccodes_windef.h" + +#ifdef ECCODES_ON_WINDOWS +#include +#endif const char* grib_tool_description = "Convert a GRIB file to netCDF format."; const char* grib_tool_name = "grib_to_netcdf"; diff --git a/tools/wingetopt.h b/tools/wingetopt.h index 170676d1c..3e074ef6a 100644 --- a/tools/wingetopt.h +++ b/tools/wingetopt.h @@ -11,11 +11,9 @@ #ifndef WINGETOPT_H #define WINGETOPT_H -/* Microsoft Windows Visual Studio support */ #include "eccodes_windef.h" #ifdef ECCODES_ON_WINDOWS -/* Microsoft Windows Visual Studio support */ extern int optind, opterr; extern char *optarg; int getopt(int argc, char *argv[], const char *optstring);