diff --git a/CMakeLists.txt b/CMakeLists.txt index c681fc5..0497ef2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,9 @@ endif() include(${BLT_SOURCE_DIR}/SetupBLT.cmake) add_subdirectory(src) +if (BUILD_TESTING) +add_subdirectory(tests) +endif() include(CMakePackageConfigHelpers) diff --git a/include/adiak.h b/include/adiak.h index 62557f0..ac2efdd 100644 --- a/include/adiak.h +++ b/include/adiak.h @@ -8,6 +8,12 @@ #include +#if defined(_MSC_VER) +#include +#else +#include +#endif + #if defined(__cplusplus) extern "C" { #endif diff --git a/include/adiak_internal.hpp b/include/adiak_internal.hpp index 659dc23..c795ed3 100644 --- a/include/adiak_internal.hpp +++ b/include/adiak_internal.hpp @@ -203,7 +203,7 @@ namespace adiak return false; } element_type::set(*value, valarray); - dtype->num_elements = c.size(); + dtype->num_elements = (int) c.size(); return true; } }; @@ -281,9 +281,9 @@ namespace adiak template struct set_tuple_type { - static void settype(adiak_datatype_t **dtypes) { + static void settype(adiak_datatype_t ** /*dtypes*/) { } - static bool setvalue(T &c, adiak_value_t *values, adiak_datatype_t *dtype) { + static bool setvalue(T & /*c*/, adiak_value_t * /*values*/ , adiak_datatype_t * /*dtype*/) { return true; } }; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b2694d1..a2c07f1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,8 +5,13 @@ set(adiak_public_headers ../include/adiak.h ../include/adiak.hpp ../include/adia if (APPLE) set(adiak_sys_sources adksys_posix.c adksys_unix.c adksys_osx.c) +set(adiak_sys_depends) elseif (UNIX) set(adiak_sys_sources adksys_glibc.c adksys_posix.c adksys_procfs.c adksys_unix.c) +set(adiak_sys_depends dl) +elseif (WIN32) +set(adiak_sys_sources adksys_windows.c) +set(adiak_sys_depends Secur32 Ws2_32) endif () if (MPI_FOUND) @@ -21,7 +26,7 @@ endif() blt_add_library( NAME adiak HEADERS ${adiak_public_headers} SOURCES adiak.c ${adiak_sys_sources} ${adiak_mpi_source} - DEPENDS_ON ${adiak_mpi_depends}) + DEPENDS_ON ${adiak_mpi_depends} ${adiak_sys_depends}) install(FILES ${adiak_public_headers} diff --git a/src/adiak.c b/src/adiak.c index d110f9a..848bc2d 100644 --- a/src/adiak.c +++ b/src/adiak.c @@ -3,6 +3,10 @@ // // SPDX-License-Identifier: MIT +#if defined(_MSC_VER) +#pragma warning(disable : 4996) +#endif + #include #include #include @@ -354,7 +358,7 @@ static adiak_datatype_t *parse_typestr(const char *typestr, va_list *ap) int end = 0; int len; - len = strlen(typestr); + len = (int) strlen(typestr); return parse_typestr_helper(typestr, 0, len, ap, &end); } @@ -768,6 +772,12 @@ int adiak_launchday() return 0; } +#if defined(_MSC_VER) +#define FILESEP '\\' +#else +#define FILESEP '/' +#endif + int adiak_executable() { char path[MAX_PATH_LEN+1]; @@ -778,7 +788,7 @@ int adiak_executable() if (result == -1) return -1; - filepart = strrchr(path, '/'); + filepart = strrchr(path, FILESEP); if (!filepart) filepart = path; else @@ -966,9 +976,9 @@ int adiak_hostlist() { char **hostlist_array = NULL; int num_hosts = 0, result = -1; - char *name_buffer = NULL; - + #if defined(USE_MPI) + char* name_buffer = NULL; if (adiak_config->use_mpi) result = adksys_hostlist(&hostlist_array, &num_hosts, &name_buffer, adiak_config->report_on_all_ranks); #endif @@ -985,9 +995,9 @@ int adiak_num_hosts() { char **hostlist_array = NULL; int num_hosts = 0, result = -1; - char *name_buffer = NULL; - + #if defined(USE_MPI) + char* name_buffer = NULL; if (adiak_config->use_mpi) result = adksys_hostlist(&hostlist_array, &num_hosts, &name_buffer, adiak_config->report_on_all_ranks); #endif @@ -1002,9 +1012,10 @@ int adiak_num_hosts() int adiak_job_size() { - int result = -1, size = 1; + int size = 1; #if defined(USE_MPI) + int result = -1; if (adiak_config->use_mpi) result = adksys_jobsize(&size); if (result == -1) @@ -1123,7 +1134,7 @@ static int adiak_type_string_helper(adiak_datatype_t *t, char *str, int len, int if (!size_calc_only) result = snprintf(str + pos, len - pos, "%s", simple); else - result = strlen(simple); + result = (int) strlen(simple); if (result != -1) pos += result; } @@ -1131,7 +1142,7 @@ static int adiak_type_string_helper(adiak_datatype_t *t, char *str, int len, int if (!size_calc_only) result = snprintf(str + pos, len - pos, "%s", lbracket); else - result = strlen(lbracket); + result = (int) strlen(lbracket); if (result > 0) pos += result; for (i = 0; i < t->num_subtypes; i++) { pos += adiak_type_string_helper(t->subtype[i], str, len, pos, long_form, size_calc_only); @@ -1146,7 +1157,7 @@ static int adiak_type_string_helper(adiak_datatype_t *t, char *str, int len, int if (!size_calc_only) result = snprintf(str + pos, len - pos, "%s", rbracket); else - result = strlen(rbracket); + result = (int) strlen(rbracket); if (result > 0) pos += result; } return pos - start_pos; @@ -1164,8 +1175,8 @@ char *adiak_type_to_string(adiak_datatype_t *t, int long_form) buffer = (char *) malloc(len + 1); len2 = adiak_type_string_helper(t, buffer, len+1, 0, long_form, 0); - assert(len == len2); - buffer[len] = '\0'; + assert(len == len2); (void) len2; + buffer[len] = '\0'; return buffer; } diff --git a/src/adksys.h b/src/adksys.h index b2dccf2..f1ace4e 100644 --- a/src/adksys.h +++ b/src/adksys.h @@ -6,7 +6,7 @@ #if !defined(ADKSYS_H_) #define ADKSYS_H_ -#include /* struct timeval */ +#include "adiak.h" int adksys_get_libraries(char ***libraries, int *libraries_size, int *libnames_need_free); int adksys_hostlist(char ***out_hostlist_array, int *out_num_hosts, char **out_name_buffer, int all_ranks); diff --git a/src/adksys_mpi.c b/src/adksys_mpi.c index c6d9f41..785ba7b 100644 --- a/src/adksys_mpi.c +++ b/src/adksys_mpi.c @@ -135,6 +135,7 @@ static int gethostlist(char **hostlist, int *num_hosts, int *max_hostlen, int al *hostlist = (char *) malloc(hostlist_size); MPI_Bcast(*hostlist, hostlist_size, MPI_CHAR, 0, adiak_communicator); + (void) all_ranks; return 0; } diff --git a/src/adksys_windows.c b/src/adksys_windows.c new file mode 100644 index 0000000..1b27ab9 --- /dev/null +++ b/src/adksys_windows.c @@ -0,0 +1,244 @@ +#include "adksys.h" +#include +#include +#include +#include + +#define SECURITY_WIN32 +#include + +#if defined(_MSC_VER) +#pragma warning(disable : 4996) +#endif + +int adksys_get_libraries(char*** libraries, int* libraries_size, int* libnames_need_free) +{ + BOOL result; + HMODULE *module_handles = NULL; + HANDLE proc; + int fresult = -1, libs_size = 0, nresult; + DWORD bytes_needed = 0; + char** lib_names = NULL, lib_name_buffer[4096]; + + proc = GetCurrentProcess(); + if (!proc) + goto done; + + result = EnumProcessModules(proc, NULL, 0, &bytes_needed); + if (!result) + goto done; + + module_handles = (HMODULE *) malloc(bytes_needed); + if (!module_handles) + goto done; + + result = EnumProcessModules(proc, module_handles, bytes_needed, &bytes_needed); + if (!result) + goto done; + + libs_size = bytes_needed / sizeof(HMODULE); + lib_names = (char**) malloc(libs_size * sizeof(char*)); + if (!lib_names) + goto done; + + memset(lib_names, 0, libs_size * sizeof(char*)); + + for (int i = 0; i < libs_size; i++) { + nresult = GetModuleFileName(module_handles[i], lib_name_buffer, sizeof(lib_name_buffer)); + if (!nresult) + goto done; + lib_names[i] = strdup(lib_name_buffer); + } + + *libraries = lib_names; + *libraries_size = libs_size; + *libnames_need_free = 1; + + fresult = 0; +done: + if (module_handles) + free(module_handles); + + if (fresult == -1 && lib_names) { + for (int i = 0; i < libs_size; i++) { + if (lib_names[i]) + free(lib_names[i]); + } + free(lib_names); + } + + return fresult; + +} + +#define EPOCH_DIFFERENCE 11644473600UL +static void filetime_to_timeval(FILETIME ft, struct timeval* tv, BOOL calendar_time) +{ + unsigned long long tmp; + + tmp = (((unsigned long long) ft.dwHighDateTime) << 32) | ft.dwLowDateTime; + tv->tv_sec = (unsigned long) (tmp / 10000000); + tv->tv_usec = (unsigned long) (tmp % 10000000) / 10; + if (calendar_time) + tv->tv_sec = (unsigned long) (tv->tv_sec - EPOCH_DIFFERENCE); +} + +int adksys_get_times(struct timeval* sys, struct timeval* cpu) +{ + HANDLE proc; + FILETIME creation_time, exit_time, user_time, sys_time; + BOOL result; + + proc = GetCurrentProcess(); + + result = GetProcessTimes(proc, &creation_time, &exit_time, &sys_time, &user_time); + if (!result) + return -1; + + if (sys) + filetime_to_timeval(sys_time, sys, FALSE); + if (cpu) + filetime_to_timeval(user_time, cpu, FALSE); + + return 0; +} + +int adksys_curtime(struct timeval* tm) +{ + FILETIME curtime; + GetSystemTimeAsFileTime(&curtime); + filetime_to_timeval(curtime, tm, TRUE); + return 0; +} + +int adksys_hostname(char* outbuffer, int buffer_size) +{ + static char* hostname = NULL; + static int err_ret = 0; + WSADATA unused; + int result; + + if (hostname || err_ret) { + if (err_ret) + return err_ret; + strncpy(outbuffer, hostname, buffer_size); + outbuffer[buffer_size - 1] = '\0'; + return 0; + } + + result = WSAStartup(MAKEWORD(1, 0), &unused); + if (result != 0) { + err_ret = -1; + return -1; + } + result = gethostname(outbuffer, buffer_size); + if (result != 0) { + err_ret = -1; + return -1; + } + outbuffer[buffer_size - 1] = '\0'; + + hostname = strdup(outbuffer); + err_ret = 0; + + WSACleanup(); + + return 0; +} + +int adksys_starttime(struct timeval* tv) +{ + HANDLE proc; + FILETIME creation_time, exit_time, user_time, sys_time; + BOOL result; + + proc = GetCurrentProcess(); + + result = GetProcessTimes(proc, &creation_time, &exit_time, &sys_time, &user_time); + if (!result) + return -1; + + filetime_to_timeval(creation_time, tv, TRUE); + return 0; +} + +int adksys_get_executable(char* outpath, size_t outpath_size) +{ + HANDLE proc; + int result; + + proc = GetCurrentProcess(); + result = GetProcessImageFileName(proc, outpath, (int) outpath_size); + if (!result) + return -1; + return 0; +} + +int adksys_get_cmdline_buffer(char** output_buffer, int* output_size) +{ + LPWSTR cmdline; + LPWSTR *argv; + char* buffer; + int argc, buffer_size = 0, pos = 0, bytes_written; + + cmdline = GetCommandLineW(); + argv = CommandLineToArgvW(cmdline, &argc); + + for (int i = 0; i < argc; i++) { + buffer_size += WideCharToMultiByte(CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL); + buffer_size++; + } + + buffer = (char *) malloc(buffer_size); + for (int i = 0; i < argc; i++) { + bytes_written = WideCharToMultiByte(CP_UTF8, 0, argv[i], -1, buffer + pos, buffer_size - pos, NULL, NULL); + pos += bytes_written; + } + assert(pos <= buffer_size); + LocalFree(argv); + + *output_buffer = buffer; + *output_size = pos; + + return 0; +} + +int adksys_get_names(char** uid, char** user) +{ + BOOL result; + char localname[4096]; + unsigned long lname_size = sizeof(localname); + + if (user) { + result = GetUserNameEx(NameDisplay, localname, &lname_size); + if (!result) + return -1; + *user = strdup(localname); + } + + if (uid) { + lname_size = sizeof(localname); + result = GetUserNameEx(NameCanonical, localname, &lname_size); + if (!result) { + free(*user); + return -1; + } + *uid = strdup(localname); + } + + return 0; +} + +int adksys_get_cwd(char* cwd, size_t max_size) +{ + char* p; + p = getcwd(cwd, (int) max_size); + if (!p) + return -1; + return 0; +} + +void* adksys_get_public_adiak_symbol() +{ + return NULL; +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..97b1ac2 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,17 @@ +include_directories(../include) + +if (MPI_FOUND) +add_definitions("-DUSE_MPI") +endif() + +blt_add_library(NAME testlib + SOURCES testlib.c + DEPENDS_ON adiak) + +blt_add_executable(NAME adiakctest + SOURCES testapp.c + DEPENDS_ON adiak testlib) + +blt_add_executable(NAME adiakcxxtest + SOURCES testapp.cpp + DEPENDS_ON adiak testlib) diff --git a/tests/testapp.c b/tests/testapp.c index 78f7538..34d9b36 100644 --- a/tests/testapp.c +++ b/tests/testapp.c @@ -1,18 +1,20 @@ +#if defined(_MSC_VER) +#pragma warning(disable : 4100) +#pragma warning(disable : 4996) +#endif + #include "adiak.h" -#include "testlib.c" #include #include -#include #include #if defined(USE_MPI) #include #endif -void dowork(struct timeval start) +void dowork() { int result; - struct timeval end; double gridarray[4] = { 4.5, 1.18, 0.24, 8.92 }; @@ -66,25 +68,25 @@ void dowork(struct timeval start) if (result != 0) printf("return: %d\n\n", result); #endif - gettimeofday(&end, NULL); - struct timeval *timerange[2]; - timerange[0] = &start; - timerange[1] = &end; - result = adiak_namevalue("computetime", adiak_performance, NULL, "<%t>", &timerange); - result = adiak_flush("stdout"); if (result != 0) printf("return: %d\n\n", result); } -int main(int argc, char *argv[]) -{ -#if defined(USE_MPI) - MPI_Comm world = MPI_COMM_WORLD; +extern void onload(); + +#if defined(_MSC_VER) +static volatile int call_onload_manually = 1; +#else +static volatile int call_onload_manually = 0; #endif - struct timeval start; - gettimeofday(&start, NULL); + +int main(int argc, char* argv[]) +{ + if (call_onload_manually) + onload(); #if defined(USE_MPI) + MPI_Comm world = MPI_COMM_WORLD; MPI_Init(&argc, &argv); adiak_init(&world); #else @@ -92,8 +94,8 @@ int main(int argc, char *argv[]) #endif - dowork(start); - dowork(start); + dowork(); + dowork(); adiak_clean(); diff --git a/tests/testapp.cpp b/tests/testapp.cpp index 9b03da9..dc0c95b 100644 --- a/tests/testapp.cpp +++ b/tests/testapp.cpp @@ -1,9 +1,13 @@ +#if defined(_MSC_VER) +#pragma warning(disable : 4100) +#pragma warning(disable : 4996) +#endif + #include "adiak.hpp" #include #include #include #include -#include #if defined(USE_MPI) @@ -12,10 +16,9 @@ using namespace std; -void dowork(struct timeval start) +void dowork() { bool result; - struct timeval end; vector grid; grid.push_back(4.5); @@ -132,10 +135,6 @@ void dowork(struct timeval start) if (!result) printf("return: %d\n\n", result); #endif -/* gettimeofday(&end, NULL); - result = adiak::value("computetime", &start, &end); - if (!result) printf("return: %d\n\n", result);*/ - array floatar; floatar[0] = 0.01f; floatar[1] = 0.02f; @@ -144,23 +143,28 @@ void dowork(struct timeval start) if (!result) printf("return: %d\n\n", result); } +extern "C" { void onload(); } + +#if defined(_MSC_VER) +static volatile bool call_onload_manually = true; +#else +static volatile bool call_onload_manually = false; +#endif + int main(int argc, char *argv[]) { -#if defined(USE_MPI) - MPI_Comm world = MPI_COMM_WORLD; -#endif - struct timeval start; + if (call_onload_manually) + onload(); - dowork(start); - - gettimeofday(&start, NULL); #if defined(USE_MPI) + MPI_Comm world = MPI_COMM_WORLD; MPI_Init(&argc, &argv); adiak::init(&world); #else adiak::init(NULL); #endif + dowork(); adiak::fini(); adiak::clean(); diff --git a/tests/testlib.c b/tests/testlib.c index a658975..c38961a 100644 --- a/tests/testlib.c +++ b/tests/testlib.c @@ -1,14 +1,22 @@ +#if defined(_MSC_VER) +#pragma warning(disable : 4100) +#pragma warning(disable : 4996) +#endif + #include "adiak_tool.h" #include #include -#include #include #include #define XSTR(S) #S #define STR(S) XSTR(S) +#if !defined(TOOLNAME) +#define TOOLNAME tool +#endif + static void print_value(adiak_value_t *val, adiak_datatype_t *t) { if (!t) @@ -35,7 +43,14 @@ static void print_value(adiak_value_t *val, adiak_datatype_t *t) case adiak_date: { char datestr[512]; signed long seconds_since_epoch = (signed long) val->v_long; +#if defined(_MSC_VER) + __time64_t s = (__time64_t) seconds_since_epoch; + struct tm *loc, loc_tmp; + _localtime64_s(&loc_tmp, &s); + loc = &loc_tmp; +#else struct tm *loc = localtime(&seconds_since_epoch); +#endif strftime(datestr, sizeof(datestr), "%a, %d %b %Y %T %z", loc); printf("%s", datestr); break; @@ -117,6 +132,9 @@ static void print_nameval(const char *name, int category, const char *subcategor printf("%s - %s: ", STR(TOOLNAME), name); print_value(value, t); printf("\n"); + (void) category; + (void) subcategory; + (void) opaque_value; } static void print_on_flush(const char *name, int category, const char *subcategory, adiak_value_t *value, adiak_datatype_t *t, void *opaque_value) @@ -124,11 +142,17 @@ static void print_on_flush(const char *name, int category, const char *subcatego if (strcmp(name, "fini") != 0) return; adiak_list_namevals(1, adiak_category_all, print_nameval, NULL); + (void) category; + (void) subcategory; + (void) value; + (void) t; + (void) opaque_value; } - -static void onload() __attribute__((constructor)); -static void onload() +#if !defined(_MSC_VER) +void onload() __attribute__((constructor)); +#endif +void onload() { if (strcmp(STR(TOOLNAME), "TOOL3") == 0) adiak_register_cb(1, adiak_control, print_on_flush, 0, NULL);