Windows support: merge branch dtip-windows from Github

This commit is contained in:
Shahram Najm 2019-01-07 16:13:48 +00:00
parent 1f6d8d3d52
commit f9aa4a12cd
25 changed files with 132 additions and 358 deletions

View File

@ -127,7 +127,7 @@ endif()
ecbuild_add_option( FEATURE MEMFS ecbuild_add_option( FEATURE MEMFS
DESCRIPTION "Memory based access to definitions/samples" DESCRIPTION "Memory based access to definitions/samples"
DEFAULT OFF 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 REQUIRED_PACKAGES PythonInterp
) )
@ -283,6 +283,11 @@ if( IEEE_LE )
set( IEEE_BE 0 ) set( IEEE_BE 0 )
endif() 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 # contents

View File

@ -53,7 +53,7 @@ if( NOT DEFINED IEEE_BE )
endif() endif()
if( ECCODES_BIG_ENDIAN AND NOT IEEE_BE ) 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() endif()
if( NOT DEFINED IEEE_LE ) if( NOT DEFINED IEEE_LE )
@ -89,5 +89,5 @@ if( NOT DEFINED IEEE_LE )
endif() endif()
if( ECCODES_LITTLE_ENDIAN AND NOT IEEE_LE ) 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() endif()

View File

@ -88,7 +88,7 @@ int main(int argc,char* argv[])
{ {
/* not array */ /* not array */
vlen=MAX_VAL_LEN; vlen=MAX_VAL_LEN;
bzero(value,vlen); memset(value, 0, vlen);
codes_get_string(h,name,value,&vlen); codes_get_string(h,name,value,&vlen);
printf("%s\n",value); printf("%s\n",value);
} }

View File

@ -21,9 +21,12 @@
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <unistd.h>
#include <string.h> #include <string.h>
#if !(defined(_WIN32) && defined(_MSC_VER))
#include <unistd.h>
#endif
#include "eccodes.h" #include "eccodes.h"
#define MAX_VAL_LEN 1024 #define MAX_VAL_LEN 1024
@ -82,7 +85,7 @@ int main(int argc, char *argv[])
{ {
const char* name = codes_keys_iterator_get_name(kiter); const char* name = codes_keys_iterator_get_name(kiter);
vlen=MAX_VAL_LEN; vlen=MAX_VAL_LEN;
bzero(value,vlen); memset(value, 0, vlen);
CODES_CHECK(codes_get_string(h,name,value,&vlen),name); CODES_CHECK(codes_get_string(h,name,value,&vlen),name);
printf("%s = %s\n",name,value); printf("%s = %s\n",name,value);

View File

@ -29,8 +29,8 @@ int main()
} }
for (i=0; i<ni*nj; i++) { for (i=0; i<ni*nj; i++) {
double rand = random(); double r = rand();
values[i] = 10*rand; values[i] = 10*r;
} }
h = codes_grib_handle_new_from_samples(0, "GRIB1"); h = codes_grib_handle_new_from_samples(0, "GRIB1");

View File

@ -86,6 +86,7 @@ print("""
#include <stdlib.h> #include <stdlib.h>
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include "eccodes_windef.h"
struct entry { struct entry {
const char* path; 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); return funopen(f, &read_mem, &write_mem, &seek_mem, &close_mem);
} }
#elif defined(_WIN32) #elif defined(ECCODES_ON_WINDOWS)
#include <io.h> #include <io.h>
#include <fcntl.h> #include <fcntl.h>

View File

@ -14,6 +14,7 @@
/* Microsoft Windows Visual Studio support */ /* Microsoft Windows Visual Studio support */
#if defined(_WIN32) && defined(_MSC_VER) #if defined(_WIN32) && defined(_MSC_VER)
# define ECCODES_ON_WINDOWS # define ECCODES_ON_WINDOWS
# define YY_NO_UNISTD_H
#endif #endif
#endif #endif

View File

@ -656,7 +656,6 @@ static int pack_string(grib_accessor* a, const char* buffer, size_t *len)
#ifndef ECCODES_ON_WINDOWS #ifndef ECCODES_ON_WINDOWS
cmpproc cmp = (a->flags & GRIB_ACCESSOR_FLAG_LOWERCASE) ? strcmp_nocase : strcmp; cmpproc cmp = (a->flags & GRIB_ACCESSOR_FLAG_LOWERCASE) ? strcmp_nocase : strcmp;
#else #else
/* Microsoft Windows Visual Studio support */
cmpproc cmp = (a->flags & GRIB_ACCESSOR_FLAG_LOWERCASE) ? stricmp : strcmp; cmpproc cmp = (a->flags & GRIB_ACCESSOR_FLAG_LOWERCASE) ? stricmp : strcmp;
#endif #endif

View File

@ -21,7 +21,6 @@
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
/* Microsoft Windows Visual Studio support */
#include "eccodes_windef.h" #include "eccodes_windef.h"
#ifndef ECCODES_ON_WINDOWS #ifndef ECCODES_ON_WINDOWS

View File

@ -58,7 +58,6 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
/* Microsoft Windows Visual Studio support */
#include "eccodes_windef.h" #include "eccodes_windef.h"
#ifndef ECCODES_ON_WINDOWS #ifndef ECCODES_ON_WINDOWS

View File

@ -164,7 +164,6 @@ int grib_jasper_encode(grib_context *c, j2k_encode_helper *helper)
#ifndef ECCODES_ON_WINDOWS #ifndef ECCODES_ON_WINDOWS
snprintf (opts, MAXOPTSSIZE, "mode=real\nrate=%f", 1.0/helper->compression); snprintf (opts, MAXOPTSSIZE, "mode=real\nrate=%f", 1.0/helper->compression);
#else #else
/* Microsoft Windows Visual Studio support */
_snprintf(opts, MAXOPTSSIZE, "mode=real\nrate=%f", 1.0/helper->compression); _snprintf(opts, MAXOPTSSIZE, "mode=real\nrate=%f", 1.0/helper->compression);
#endif #endif
} }

View File

@ -1,336 +0,0 @@
#include "grib_api_internal.h"
#include <sys/time.h>
#include <time.h>
#include <sys/resource.h>
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;
}
*/

View File

@ -16,7 +16,10 @@
/* #include <errno.h> */ /* #include <errno.h> */
/* #include <string.h> */ /* #include <string.h> */
#include "grib_api_internal.h" #include "grib_api_internal.h"
#ifndef ECCODES_ON_WINDOWS
#include <unistd.h> #include <unistd.h>
#endif
void usage(char* prog) { void usage(char* prog) {
printf("usage: %s filename\n",prog); printf("usage: %s filename\n",prog);

View File

@ -15,7 +15,10 @@
#include "grib_api.h" #include "grib_api.h"
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#ifndef ECCODES_ON_WINDOWS
#include <unistd.h> #include <unistd.h>
#endif
static void usage(const char* prog) { static void usage(const char* prog) {
printf("usage: %s [-m] file.grib\n",prog); printf("usage: %s [-m] file.grib\n",prog);

View File

@ -10,7 +10,10 @@
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
#ifndef ECCODES_ON_WINDOWS
#include <unistd.h> #include <unistd.h>
#endif
#include "grib_api.h" #include "grib_api.h"

View File

@ -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

View File

@ -25,7 +25,18 @@
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include <sys/types.h> #include <sys/types.h>
#ifndef ECCODES_ON_WINDOWS
#include <dirent.h> #include <dirent.h>
#else
#include <direct.h>
#include <io.h>
#ifdef _MSC_VER
# define strcasecmp _stricmp
#endif
#endif
#include <assert.h> #include <assert.h>
#include "tigge_tools.h" #include "tigge_tools.h"

View File

@ -25,9 +25,15 @@
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include <sys/types.h> #include <sys/types.h>
#include <dirent.h>
#include "tigge_tools.h" #include "tigge_tools.h"
#ifndef ECCODES_ON_WINDOWS
#include <dirent.h>
#else
#include <direct.h>
#include <io.h>
#endif
/* #define CHECK(a) check(#a,a) */ /* #define CHECK(a) check(#a,a) */
#define NUMBER(a) (sizeof(a)/sizeof(a[0])) #define NUMBER(a) (sizeof(a)/sizeof(a[0]))

View File

@ -25,9 +25,22 @@
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include <sys/types.h> #include <sys/types.h>
#ifndef ECCODES_ON_WINDOWS
#include <dirent.h> #include <dirent.h>
#include <unistd.h> #include <unistd.h>
#else
#include <direct.h>
#include <io.h>
#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) #define CHECK(a) check(#a,a)

View File

@ -13,14 +13,23 @@
*/ */
#include "tigge_tools.h" #include "tigge_tools.h"
#include "eccodes_windef.h"
#include <stdlib.h> #include <stdlib.h>
#include <sys/types.h> #include <sys/types.h>
#ifndef ECCODES_ON_WINDOWS
#include <dirent.h> #include <dirent.h>
#else
#include <direct.h>
#include <io.h>
#endif
#include <stdio.h> #include <stdio.h>
extern void validate(const char* path); extern void validate(const char* path);
#ifndef ECCODES_ON_WINDOWS
void scan(const char* name) void scan(const char* name)
{ {
DIR *dir; DIR *dir;
@ -41,3 +50,32 @@ void scan(const char* name)
validate(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

View File

@ -9,11 +9,21 @@
# nor does it submit to any jurisdiction. # 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 # tools library
ecbuild_add_library( TARGET grib_tools ecbuild_add_library( TARGET grib_tools
TYPE STATIC TYPE STATIC
NOINSTALL NOINSTALL
SOURCES grib_tools.c grib_options.c grib_tools.h SOURCES ${grib_tools_sources}
LIBS eccodes ) LIBS eccodes )
# tools binaries # tools binaries

View File

@ -13,6 +13,10 @@
extern char *optarg; extern char *optarg;
extern int optind; extern int optind;
#ifdef ECCODES_ON_WINDOWS
#include "wingetopt.h"
#endif
static void usage_and_exit(const char* progname) { static void usage_and_exit(const char* progname) {
printf("\nUsage: %s [-v] [-d] [-s]\n",progname); printf("\nUsage: %s [-v] [-d] [-s]\n",progname);
exit(1); exit(1);

View File

@ -18,7 +18,6 @@ extern char *optarg;
extern int optind; extern int optind;
#ifdef ECCODES_ON_WINDOWS #ifdef ECCODES_ON_WINDOWS
/* Microsoft Windows Visual Studio support */
#include "wingetopt.h" #include "wingetopt.h"
#endif #endif

View File

@ -23,6 +23,11 @@
#include <netcdf.h> #include <netcdf.h>
#include "grib_tools.h" #include "grib_tools.h"
#include "eccodes_windef.h"
#ifdef ECCODES_ON_WINDOWS
#include <stdint.h>
#endif
const char* grib_tool_description = "Convert a GRIB file to netCDF format."; const char* grib_tool_description = "Convert a GRIB file to netCDF format.";
const char* grib_tool_name = "grib_to_netcdf"; const char* grib_tool_name = "grib_to_netcdf";

View File

@ -11,11 +11,9 @@
#ifndef WINGETOPT_H #ifndef WINGETOPT_H
#define WINGETOPT_H #define WINGETOPT_H
/* Microsoft Windows Visual Studio support */
#include "eccodes_windef.h" #include "eccodes_windef.h"
#ifdef ECCODES_ON_WINDOWS #ifdef ECCODES_ON_WINDOWS
/* Microsoft Windows Visual Studio support */
extern int optind, opterr; extern int optind, opterr;
extern char *optarg; extern char *optarg;
int getopt(int argc, char *argv[], const char *optstring); int getopt(int argc, char *argv[], const char *optstring);