From: Eric Biggers Date: Mon, 28 Nov 2016 03:19:41 +0000 (-0800) Subject: examples: C++ and Windows compatibility X-Git-Tag: v1.11.0~48 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=6fa3af89322f3bec1df1df7d283e76daca4a27e3 examples: C++ and Windows compatibility --- diff --git a/examples/applywim.c b/examples/applywim.c index ffcff149..cd6d3409 100644 --- a/examples/applywim.c +++ b/examples/applywim.c @@ -3,7 +3,7 @@ * * The following copying information applies to this specific source code file: * - * Written in 2013-2014 by Eric Biggers + * Written in 2013-2016 by Eric Biggers * * To the extent possible under law, the author(s) have dedicated all copyright * and related and neighboring rights to this software to the public domain @@ -21,6 +21,21 @@ #include #include +/* + * Windows compatibility defines for string encoding. Applications using wimlib + * that need to run on both UNIX and Windows will need to do something similar + * to this, whereas applications that only need to run on one or the other can + * just use their platform's convention directly. + */ +#ifdef _WIN32 +# define main wmain + typedef wchar_t tchar; +# define TS "ls" +#else + typedef char tchar; +# define TS "s" +#endif + #define TO_PERCENT(numerator, denominator) \ ((float)(((denominator) == 0) ? 0 : ((numerator) * 100 / (float)(denominator)))) @@ -40,12 +55,12 @@ extract_progress(enum wimlib_progress_msg msg, return WIMLIB_PROGRESS_STATUS_CONTINUE; } -int main(int argc, char **argv) +int main(int argc, tchar **argv) { int ret; WIMStruct *wim = NULL; - const char *wimpath; - const char *destdir; + const tchar *wimpath; + const tchar *destdir; /* Check for the correct number of arguments. */ if (argc != 3) { @@ -78,8 +93,8 @@ out: /* Check for error status. */ if (ret != 0) { - fprintf(stderr, "wimlib error %d: %s\n", - ret, wimlib_get_error_string(ret)); + fprintf(stderr, "wimlib error %d: %" TS"\n", + ret, wimlib_get_error_string((enum wimlib_error_code)ret)); } /* Free global memory (optional). */ diff --git a/examples/capturewim.c b/examples/capturewim.c index 2d89e51f..ae99acb4 100644 --- a/examples/capturewim.c +++ b/examples/capturewim.c @@ -3,7 +3,7 @@ * * The following copying information applies to this specific source code file: * - * Written in 2014 by Eric Biggers + * Written in 2014-2016 by Eric Biggers * * To the extent possible under law, the author(s) have dedicated all copyright * and related and neighboring rights to this software to the public domain @@ -21,6 +21,21 @@ #include #include +/* + * Windows compatibility defines for string encoding. Applications using wimlib + * that need to run on both UNIX and Windows will need to do something similar + * to this, whereas applications that only need to run on one or the other can + * just use their platform's convention directly. + */ +#ifdef _WIN32 +# define main wmain + typedef wchar_t tchar; +# define TS "ls" +#else + typedef char tchar; +# define TS "s" +#endif + #define TO_PERCENT(numerator, denominator) \ ((float)(((denominator) == 0) ? 0 : ((numerator) * 100 / (float)(denominator)))) @@ -40,12 +55,12 @@ write_progress(enum wimlib_progress_msg msg, return WIMLIB_PROGRESS_STATUS_CONTINUE; } -int main(int argc, char **argv) +int main(int argc, tchar **argv) { int ret; WIMStruct *wim = NULL; - const char *srcdir; - const char *wimpath; + const tchar *srcdir; + const tchar *wimpath; /* Check for the correct number of arguments. */ if (argc != 3) { @@ -88,8 +103,8 @@ out: /* Check for error status. */ if (ret != 0) { - fprintf(stderr, "wimlib error %d: %s\n", - ret, wimlib_get_error_string(ret)); + fprintf(stderr, "wimlib error %d: %" TS"\n", + ret, wimlib_get_error_string((enum wimlib_error_code)ret)); } /* Free global memory (optional). */ diff --git a/examples/compressfile.c b/examples/compressfile.c index bc7ed18a..7f1ca997 100644 --- a/examples/compressfile.c +++ b/examples/compressfile.c @@ -3,7 +3,7 @@ * * The following copying information applies to this specific source code file: * - * Written in 2014 by Eric Biggers + * Written in 2014-2016 by Eric Biggers * * To the extent possible under law, the author(s) have dedicated all copyright * and related and neighboring rights to this software to the public domain @@ -46,30 +46,80 @@ * chunks. A real format would need to have checksums and other metadata. */ -#define _GNU_SOURCE #define _FILE_OFFSET_BITS 64 +#if defined(_MSC_VER) && _MSC_VER < 1800 /* VS pre-2013? */ +# define PRIu64 "I64u" +# define PRIu32 "u" +#else +# define __STDC_FORMAT_MACROS 1 +# include +#endif + #include #include -#include #include -#include +#include #include #include -#include +#ifdef _WIN32 +# include +#else +# include +#endif + +/* + * Windows compatibility defines for string encoding. Applications using wimlib + * that need to run on both UNIX and Windows will need to do something similar + * to this, whereas applications that only need to run on one or the other can + * just use their platform's convention directly. + */ +#ifdef _WIN32 +# define main wmain + typedef wchar_t tchar; +# define _T(text) L##text +# define T(text) _T(text) +# define TS "ls" +# define topen _wopen +# define tstrcmp wcscmp +# define tstrtol wcstol +#else + typedef char tchar; +# define T(text) text +# define TS "s" +# define topen open +# define O_BINARY 0 +# define tstrcmp strcmp +# define tstrtol strtol +#endif + +static void +fatal_error(int err, const char *format, ...) +{ + va_list va; + + va_start(va, format); + vfprintf(stderr, format, va); + if (err != 0) + fprintf(stderr, ": %s\n", strerror(err)); + else + fputc('\n', stderr); + va_end(va); + exit(1); +} static void -do_compress(int in_fd, const char *in_filename, - int out_fd, const char *out_filename, +do_compress(int in_fd, const tchar *in_filename, + int out_fd, const tchar *out_filename, uint32_t chunk_size, struct wimlib_compressor *compressor) { - char *ubuf = malloc(chunk_size); - char *cbuf = malloc(chunk_size - 1); + char *ubuf = (char *)malloc(chunk_size); + char *cbuf = (char *)malloc(chunk_size - 1); uint64_t chunk_num; for (chunk_num = 1; ; chunk_num++) { - ssize_t bytes_read; + int32_t bytes_read; size_t csize; char *out_buf; uint32_t out_size; @@ -80,7 +130,8 @@ do_compress(int in_fd, const char *in_filename, if (bytes_read <= 0) { if (bytes_read == 0) break; - error(1, errno, "Error reading \"%s\"", in_filename); + fatal_error(errno, "Error reading \"%" TS"\"", + in_filename); } /* Compress the chunk. */ @@ -98,7 +149,7 @@ do_compress(int in_fd, const char *in_filename, out_size = usize; } - printf("Chunk %"PRIu64": %"PRIu32" => %"PRIu32" bytes\n", + printf("Chunk %" PRIu64" %" PRIu32" => %" PRIu32" bytes\n", chunk_num, usize, out_size); /* Output the uncompressed chunk size, the compressed chunk @@ -106,29 +157,30 @@ do_compress(int in_fd, const char *in_filename, * to output the chunk sizes in consistent endianness. */ if (write(out_fd, &usize, sizeof(uint32_t)) != sizeof(uint32_t) || write(out_fd, &out_size, sizeof(uint32_t)) != sizeof(uint32_t) || - write(out_fd, out_buf, out_size) != out_size) + write(out_fd, out_buf, out_size) != (int32_t)out_size) { - error(1, errno, "Error writing to \"%s\"", - out_filename); + fatal_error(errno, "Error writing to \"%" TS"\"", + out_filename); } } free(ubuf); free(cbuf); } -int main(int argc, char **argv) +int main(int argc, tchar **argv) { - const char *in_filename; - const char *out_filename; + const tchar *in_filename; + const tchar *out_filename; int in_fd; int out_fd; struct wimlib_compressor *compressor; - int ctype = WIMLIB_COMPRESSION_TYPE_LZX; + enum wimlib_compression_type ctype = WIMLIB_COMPRESSION_TYPE_LZX; + uint32_t ctype32; uint32_t chunk_size = 32768; int ret; if (argc < 3 || argc > 5) { - fprintf(stderr, "Usage: %s INFILE OUTFILE " + fprintf(stderr, "Usage: %" TS" INFILE OUTFILE " "[LZX | XPRESS | LZMS] [chunk size]\n", argv[0]); return 2; } @@ -138,41 +190,43 @@ int main(int argc, char **argv) /* Parse compression type (optional) */ if (argc >= 4) { - if (!strcmp(argv[3], "LZX")) + if (!tstrcmp(argv[3], T("LZX"))) ctype = WIMLIB_COMPRESSION_TYPE_LZX; - else if (!strcmp(argv[3], "XPRESS")) + else if (!tstrcmp(argv[3], T("XPRESS"))) ctype = WIMLIB_COMPRESSION_TYPE_XPRESS; - else if (!strcmp(argv[3], "LZMS")) + else if (!tstrcmp(argv[3], T("LZMS"))) ctype = WIMLIB_COMPRESSION_TYPE_LZMS; else - error(1, 0, "Unrecognized compression type \"%s\"", argv[3]); + fatal_error(0, + "Unrecognized compression type \"%" TS"\"", + argv[3]); } /* Parse chunk size (optional). */ if (argc >= 5) - chunk_size = atoi(argv[4]); + chunk_size = tstrtol(argv[4], NULL, 10); /* Open input file and output file. */ - in_fd = open(in_filename, O_RDONLY); + in_fd = topen(in_filename, O_RDONLY | O_BINARY); if (in_fd < 0) - error(1, errno, "Failed to open \"%s\"", in_filename); - out_fd = open(out_filename, O_WRONLY | O_TRUNC | O_CREAT, 0644); + fatal_error(errno, "Failed to open \"%" TS"\"", in_filename); + out_fd = topen(out_filename, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, + 0644); if (out_fd < 0) - error(1, errno, "Failed to open \"%s\"", out_filename); + fatal_error(errno, "Failed to open \"%" TS"s\"", out_filename); /* Create a compressor for the compression type and chunk size with the * default parameters. */ ret = wimlib_create_compressor(ctype, chunk_size, 0, &compressor); if (ret != 0) - error(1, 0, "Failed to create compressor: %s", - wimlib_get_error_string(ret)); + fatal_error(0, "Failed to create compressor: %" TS, + wimlib_get_error_string((enum wimlib_error_code)ret)); - uint32_t ctype32 = ctype; + ctype32 = (uint32_t)ctype; /* Write compression type and chunk size to the file. */ if (write(out_fd, &ctype32, sizeof(uint32_t)) != sizeof(uint32_t) || write(out_fd, &chunk_size, sizeof(uint32_t)) != sizeof(uint32_t)) { - error(1, errno, "Error writing to \"%s\"", - out_filename); + fatal_error(errno, "Error writing to \"%" TS"\"", out_filename); } /* Compress and write the data. */ @@ -182,7 +236,7 @@ int main(int argc, char **argv) /* Cleanup and return. */ if (close(out_fd)) - error(1, errno, "Error closing \"%s\"", out_filename); + fatal_error(errno, "Error closing \"%" TS"\"", out_filename); wimlib_free_compressor(compressor); return 0; } diff --git a/examples/decompressfile.c b/examples/decompressfile.c index cc2b758e..e5a03b44 100644 --- a/examples/decompressfile.c +++ b/examples/decompressfile.c @@ -3,7 +3,7 @@ * * The following copying information applies to this specific source code file: * - * Written in 2014 by Eric Biggers + * Written in 2014-2016 by Eric Biggers * * To the extent possible under law, the author(s) have dedicated all copyright * and related and neighboring rights to this software to the public domain @@ -44,31 +44,74 @@ * chunks. A real format would need to have checksums and other metadata. */ -#define _GNU_SOURCE #define _FILE_OFFSET_BITS 64 +#if defined(_MSC_VER) && _MSC_VER < 1800 /* VS pre-2013? */ +# define PRIu64 "I64u" +# define PRIu32 "u" +#else +# define __STDC_FORMAT_MACROS 1 +# include +#endif + #include #include -#include #include -#include +#include #include #include -#include +#ifdef _WIN32 +# include +#else +# include +#endif + +/* + * Windows compatibility defines for string encoding. Applications using wimlib + * that need to run on both UNIX and Windows will need to do something similar + * to this, whereas applications that only need to run on one or the other can + * just use their platform's convention directly. + */ +#ifdef _WIN32 +# define main wmain + typedef wchar_t tchar; +# define TS "ls" +# define topen _wopen +#else + typedef char tchar; +# define TS "s" +# define topen open +# define O_BINARY 0 +#endif static void -do_decompress(int in_fd, const char *in_filename, - int out_fd, const char *out_filename, +fatal_error(int err, const char *format, ...) +{ + va_list va; + + va_start(va, format); + vfprintf(stderr, format, va); + if (err != 0) + fprintf(stderr, ": %s\n", strerror(err)); + else + fputc('\n', stderr); + va_end(va); + exit(1); +} + +static void +do_decompress(int in_fd, const tchar *in_filename, + int out_fd, const tchar *out_filename, uint32_t chunk_size, struct wimlib_decompressor *decompressor) { uint64_t chunk_num; - char *ubuf = malloc(chunk_size); - char *cbuf = malloc(chunk_size - 1); + char *ubuf = (char *)malloc(chunk_size); + char *cbuf = (char *)malloc(chunk_size - 1); for (chunk_num = 1; ; chunk_num++) { - ssize_t bytes_read; + int32_t bytes_read; uint32_t usize; uint32_t csize; @@ -80,56 +123,61 @@ do_decompress(int in_fd, const char *in_filename, if (bytes_read != sizeof(uint32_t) || read(in_fd, &csize, sizeof(uint32_t)) != sizeof(uint32_t)) { - error(1, errno, "Error reading \"%s\"", in_filename); + fatal_error(errno, "Error reading \"%" TS"\"", + in_filename); } if (csize > usize || usize > chunk_size) - error(1, 0, "The data is invalid!"); + fatal_error(0, "The data is invalid!"); if (usize == csize) { - if (read(in_fd, ubuf, usize) != usize) { - error(1, errno, "Error reading \"%s\"", - in_filename); + if (read(in_fd, ubuf, usize) != (int32_t)usize) { + fatal_error(errno, "Error reading \"%" TS"\"", + in_filename); } } else { - if (read(in_fd, cbuf, csize) != csize) { - error(1, errno, "Error reading \"%s\"", - in_filename); + if (read(in_fd, cbuf, csize) != (int32_t)csize) { + fatal_error(errno, "Error reading \"%" TS"\"", + in_filename); } if (wimlib_decompress(cbuf, csize, ubuf, usize, decompressor)) { - error(1, 0, "The compressed data is invalid!"); + fatal_error(0, + "The compressed data is invalid!"); } } - printf("Chunk %"PRIu64": %"PRIu32" => %"PRIu32" bytes\n", + printf("Chunk %" PRIu64": %" PRIu32" => %" PRIu32" bytes\n", chunk_num, csize, usize); /* Output the uncompressed chunk size, the compressed chunk * size, then the chunk data. Note: a real program would need * to output the chunk sizes in consistent endianness. */ - if (write(out_fd, ubuf, usize) != usize) - error(1, errno, "Error writing to \"%s\"", out_filename); + if (write(out_fd, ubuf, usize) != (int32_t)usize) { + fatal_error(errno, "Error writing to \"%" TS"\"", + out_filename); + } } free(ubuf); free(cbuf); } -int main(int argc, char **argv) +int main(int argc, tchar **argv) { - const char *in_filename; - const char *out_filename; + const tchar *in_filename; + const tchar *out_filename; int in_fd; int out_fd; - uint32_t ctype; + uint32_t ctype32; + enum wimlib_compression_type ctype; uint32_t chunk_size; int ret; struct wimlib_decompressor *decompressor; if (argc != 3) { - fprintf(stderr, "Usage: %s INFILE OUTFILE\n", argv[0]); + fprintf(stderr, "Usage: %" TS" INFILE OUTFILE\n", argv[0]); return 2; } @@ -137,24 +185,26 @@ int main(int argc, char **argv) out_filename = argv[2]; /* Open input file and output file. */ - in_fd = open(in_filename, O_RDONLY); + in_fd = topen(in_filename, O_RDONLY | O_BINARY); if (in_fd < 0) - error(1, errno, "Failed to open \"%s\"", in_filename); - out_fd = open(out_filename, O_WRONLY | O_TRUNC | O_CREAT, 0644); + fatal_error(errno, "Failed to open \"%" TS"\"", in_filename); + out_fd = topen(out_filename, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, + 0644); if (out_fd < 0) - error(1, errno, "Failed to open \"%s\"", out_filename); + fatal_error(errno, "Failed to open \"%" TS"\"", out_filename); /* Get compression type and chunk size. */ - if (read(in_fd, &ctype, sizeof(uint32_t)) != sizeof(uint32_t) || + if (read(in_fd, &ctype32, sizeof(uint32_t)) != sizeof(uint32_t) || read(in_fd, &chunk_size, sizeof(uint32_t)) != sizeof(uint32_t)) - error(1, errno, "Error reading from \"%s\"", in_filename); + fatal_error(errno, "Error reading from \"%" TS"\"", in_filename); + ctype = (enum wimlib_compression_type)ctype32; /* Create a decompressor for the compression type and chunk size with * the default parameters. */ ret = wimlib_create_decompressor(ctype, chunk_size, &decompressor); if (ret != 0) - error(1, 0, "Failed to create decompressor: %s", - wimlib_get_error_string(ret)); + fatal_error(0, "Failed to create decompressor: %" TS, + wimlib_get_error_string((enum wimlib_error_code)ret)); /* Decompress and write the data. */ do_decompress(in_fd, in_filename, @@ -163,7 +213,7 @@ int main(int argc, char **argv) /* Cleanup and return. */ if (close(out_fd)) - error(1, errno, "Error closing \"%s\"", out_filename); + fatal_error(errno, "Error closing \"%" TS"\"", out_filename); wimlib_free_decompressor(decompressor); return 0; } diff --git a/examples/updatewim.c b/examples/updatewim.c index d46f24d2..0483d5e7 100644 --- a/examples/updatewim.c +++ b/examples/updatewim.c @@ -4,7 +4,7 @@ * * The following copying information applies to this specific source code file: * - * Written in 2014 by Eric Biggers + * Written in 2014-2016 by Eric Biggers * * To the extent possible under law, the author(s) have dedicated all copyright * and related and neighboring rights to this software to the public domain @@ -22,13 +22,29 @@ #include #include -int main(int argc, char **argv) +/* + * Windows compatibility defines for string encoding. Applications using wimlib + * that need to run on both UNIX and Windows will need to do something similar + * to this, whereas applications that only need to run on one or the other can + * just use their platform's convention directly. + */ +#ifdef _WIN32 +# define main wmain + typedef wchar_t tchar; +# define TS "ls" +#else + typedef char tchar; +# define TS "s" +#endif + +int main(int argc, tchar **argv) { int ret; - char *wimfile; - char *wim_target_path; - char *fs_source_path; + tchar *wimfile; + tchar *wim_target_path; + tchar *fs_source_path; WIMStruct *wim = NULL; + struct wimlib_update_command cmds[1]; /* Check for the correct number of arguments. */ if (argc != 4) { @@ -53,8 +69,6 @@ int main(int argc, char **argv) * sake of demonstration we will use the more general function * wimlib_update_image(). */ - struct wimlib_update_command cmds[1]; - memset(cmds, 0, sizeof(cmds)); /* Set up an "add" operation. @@ -99,8 +113,8 @@ out: /* Check for error status. */ if (ret != 0) { - fprintf(stderr, "wimlib error %d: %s\n", - ret, wimlib_get_error_string(ret)); + fprintf(stderr, "wimlib error %d: %" TS"\n", + ret, wimlib_get_error_string((enum wimlib_error_code)ret)); } /* Free global memory (optional). */ diff --git a/tools/msvc-test-examples.bat b/tools/msvc-test-examples.bat new file mode 100755 index 00000000..f95297b6 --- /dev/null +++ b/tools/msvc-test-examples.bat @@ -0,0 +1,56 @@ +REM +REM Try building and running the example programs on Windows with Visual Studio. +REM + +@echo off +setlocal EnableDelayedExpansion + +copy .libs\libwim.dll.a libwim.lib +copy .libs\libwim-15.dll libwim-15.dll +for %%a in (examples\*.c) do ( + cl %%a libwim.lib /Iinclude /link /opt:noref + if errorlevel 1 exit /b +) +call :do_test + + +cd examples +rename *.c *.cc +cd .. +for %%a in (examples\*.cc) do ( + cl %%a libwim.lib /Iinclude /link /opt:noref + if errorlevel 1 exit /b +) +call :do_test +cd examples +rename *.cc *.c +cd .. + +del *.exe *.obj *.dll *.lib + +exit /b 0 + +:do_test +.\applywim.exe j:\test.wim e:\tmp1 +if errorlevel 1 exit /b +.\capturewim.exe e:\tmp1 e:\tmp1.wim +if errorlevel 1 exit /b +REM Windows likes to give UAC prompts for programs with "update" in their name. +move /y updatewim.exe updat3wim.exe +.\updat3wim.exe e:\tmp1.wim examples examples +if errorlevel 1 exit /b + +.\compressfile.exe j:\testdata e:\testdata.lzx +if errorlevel 1 exit /b +.\decompressfile.exe e:\testdata.lzx e:\testdata.orig +if errorlevel 1 exit /b +fc /b j:\testdata e:\testdata.orig +if errorlevel 1 exit /b + +.\compressfile.exe j:\testdata e:\testdata.lzx XPRESS 16384 +if errorlevel 1 exit /b +.\decompressfile.exe e:\testdata.lzx e:\testdata.orig +if errorlevel 1 exit /b +fc /b j:\testdata e:\testdata.orig +if errorlevel 1 exit /b +goto :eof diff --git a/tools/test-examples b/tools/test-examples new file mode 100755 index 00000000..8e4ac66f --- /dev/null +++ b/tools/test-examples @@ -0,0 +1,57 @@ +#!/bin/sh +# +# Try building the example programs: in 32-bit and 64-bit mode, in C and C++ +# mode, and for Linux and for Windows. Also run the Linux versions to make sure +# they work. +# + +set -eu + +cd examples +make clean + +COMMON_FLAGS="-Wall -Wextra -Werror -Wundef -Wno-unused-parameter -Wvla" +COMMON_CFLAGS="$COMMON_FLAGS -std=gnu99 -Wdeclaration-after-statement -Wstrict-prototypes" +COMMON_CXXFLAGS="$COMMON_FLAGS" + +TEST_WIM="$HOME/data/test.wim" +TESTDATA="$HOME/data/testdata" + +tmpdir="$(mktemp -d)" +tmpfile="$(mktemp)" +tmpfile2="$(mktemp)" + +trap "rm -rf \"$tmpdir\" \"$tmpfile\" \"$tmpfile2\"" EXIT + +do_test() { + rm -rf "$tmpdir" + + ./applywim "$TEST_WIM" "$tmpdir" + ./capturewim "$tmpdir" "$tmpfile" + ./updatewim "$tmpfile" "examples" . + + ./compressfile "$TESTDATA" "$tmpfile" + ./decompressfile "$tmpfile" "$tmpfile2" + cmp "$tmpfile2" "$TESTDATA" + + ./compressfile "$TESTDATA" "$tmpfile" XPRESS 16384 + ./decompressfile "$tmpfile" "$tmpfile2" + cmp "$tmpfile2" "$TESTDATA" +} + +make CC=gcc CFLAGS="$COMMON_CFLAGS" +do_test +make clean +make CC=g++ CFLAGS="$COMMON_CXXFLAGS" +do_test +make clean + +make CC=i686-w64-mingw32-gcc CFLAGS="$COMMON_CFLAGS -I../include -municode" LDLIBS="-lwim-15" LDFLAGS="-L/j/wimlib" +make clean +make CC=i686-w64-mingw32-g++ CFLAGS="$COMMON_CXXFLAGS -I../include -municode" LDLIBS="-lwim-15" LDFLAGS="-L/j/wimlib" +make clean + +make CC=x86_64-w64-mingw32-gcc CFLAGS="$COMMON_CFLAGS -I../include -municode" LDLIBS="-lwim-15" LDFLAGS="-L/j/x64" +make clean +make CC=x86_64-w64-mingw32-g++ CFLAGS="$COMMON_CXXFLAGS -I../include -municode" LDLIBS="-lwim-15" LDFLAGS="-L/j/x64" +make clean