diff --git a/app/Makefile b/app/Makefile index ba463ce..d2bcd33 100644 --- a/app/Makefile +++ b/app/Makefile @@ -150,6 +150,11 @@ ifneq ($(LDFLAGS_JQ),) CFLAGS+= -DUSE_JQ endif +STATIC_LIB_FLAGS= +ifneq ($(STATIC_LIBS),) + STATIC_LIB_FLAGS=-static ${STATIC_LIBS} +endif + STANDALONE_PFX=${BUILD_DIR}/bin/zsv_ TARGETS=$(addprefix ${STANDALONE_PFX},$(addsuffix ${EXE},${SOURCES})) ${CLI} @@ -279,7 +284,7 @@ ${CLI_APP_OBJECT} ${CLI_OBJECTS}: ${CLI_OBJ_PFX}%.o: %.c ${UTF8PROC_SRC}/utf8pro ${CLI}: cli_internal.c.in cli_internal.h cli_internal.h.in ${CLI_APP_OBJECT} ${CLI_OBJECTS} ${OBJECTS} ${UTF8PROC_OBJECT} cli_ini.c ${INIH_OBJECT} ${LIBZSV_INSTALL} ${MORE_OBJECTS} @mkdir -p `dirname "$@"` - ${CC} ${CFLAGS} ${CFLAGS_EXE} -I${INCLUDE_DIR} -o $@ ${CLI_APP_OBJECT} ${CLI_OBJECTS} ${OBJECTS} ${UTF8PROC_OBJECT} ${INIH_OBJECT} -L${LIBDIR} -lzsv ${LDFLAGS} ${LDFLAGS_OPT} ${MORE_OBJECTS} ${MORE_SOURCE} ${MORE_LIBS} + ${CC} ${CFLAGS} ${CFLAGS_EXE} -I${INCLUDE_DIR} -o $@ ${CLI_APP_OBJECT} ${CLI_OBJECTS} ${OBJECTS} ${UTF8PROC_OBJECT} ${INIH_OBJECT} -L${LIBDIR} -lzsv ${LDFLAGS} ${LDFLAGS_OPT} ${MORE_OBJECTS} ${MORE_SOURCE} ${MORE_LIBS} ${STATIC_LIB_FLAGS} @echo Built $@ # cli_internal: cli_internal.c.in cli_internal.h cli_internal.h.in @@ -328,7 +333,7 @@ ${CLI} ${STANDALONE_PFX}jq${EXE}: MORE_LIBS+=${LDFLAGS_JQ} ${STANDALONE_PFX}%${EXE}: %.c ${OBJECTS} ${MORE_OBJECTS} ${LIBZSV_INSTALL} ${UTF8PROC_OBJECT} @mkdir -p `dirname "$@"` - ${CC} ${CFLAGS} -I${INCLUDE_DIR} -o $@ $< ${OBJECTS} ${MORE_OBJECTS} ${MORE_SOURCE} -L${LIBDIR} -lzsv ${UTF8PROC_OBJECT} ${LDFLAGS} ${LDFLAGS_OPT} ${MORE_LIBS} + ${CC} ${CFLAGS} -I${INCLUDE_DIR} -o $@ $< ${OBJECTS} ${MORE_OBJECTS} ${MORE_SOURCE} -L${LIBDIR} -lzsv ${UTF8PROC_OBJECT} ${LDFLAGS} ${LDFLAGS_OPT} ${MORE_LIBS} ${STATIC_LIB_FLAGS} ${BUILD_DIR}/external/sqlite3/sqlite3_and_csv_vtab.o: ${BUILD_DIR}/external/%.o : external/%.c @mkdir -p `dirname "$@"` diff --git a/app/cli.c b/app/cli.c index 2fda47c..54e78de 100644 --- a/app/cli.c +++ b/app/cli.c @@ -400,8 +400,8 @@ char havearg(const char *arg, if(len > min_len1) min_len1 = len; - if(!zsv_strincmp((const unsigned char *)arg, min_len1, - (const unsigned char *)form1, min_len1)) + if(!zsv_strincmp_ascii((const unsigned char *)arg, min_len1, + (const unsigned char *)form1, min_len1)) return 1; if(form2) { @@ -409,8 +409,8 @@ char havearg(const char *arg, min_len2 = strlen(form2); if(len > min_len2) min_len2 = len; - if(!zsv_strincmp((const unsigned char *)arg, min_len2, - (const unsigned char *)form2, min_len2)) + if(!zsv_strincmp_ascii((const unsigned char *)arg, min_len2, + (const unsigned char *)form2, min_len2)) return 1; } return 0; diff --git a/app/external/jq.diff b/app/external/jq.diff new file mode 100644 index 0000000..a604349 --- /dev/null +++ b/app/external/jq.diff @@ -0,0 +1,35 @@ +diff --git a/src/jv.c b/src/jv.c +index e1fb209..69c18fc 100644 +--- a/src/jv.c ++++ b/src/jv.c +@@ -333,6 +333,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, + } + } + ++#if !defined(HAVE_PTHREAD_KEY_CREATE) + int + pthread_key_create(pthread_key_t *key, void (*dtor)(void *)) + { +@@ -491,6 +492,9 @@ pthread_getspecific(pthread_key_t key) + #else + #include + #endif ++#else ++#include ++#endif + + static pthread_key_t dec_ctx_key; + static pthread_key_t dec_ctx_dbl_key; +diff --git a/src/jv_thread.h b/src/jv_thread.h +index a34cd08..c06ff6b 100644 +--- a/src/jv_thread.h ++++ b/src/jv_thread.h +@@ -1,7 +1,7 @@ + #ifndef JV_THREAD_H + #define JV_THREAD_H + +-#ifdef WIN32 ++#if defined(WIN32) && !defined(HAVE_PTHREAD_KEY_CREATE) + #include + #include + #include diff --git a/app/utils/string.c b/app/utils/string.c index 566709a..57940cb 100644 --- a/app/utils/string.c +++ b/app/utils/string.c @@ -24,13 +24,13 @@ static utf8proc_int32_t utf8proc_tolower1(utf8proc_int32_t codepoint, void *data } static unsigned char *utf8proc_tolower_str(const unsigned char *str, size_t *len) { + // note: for some unknown reason, this func intermittently can fail on win (compiled w mingw64) when called in a tight loop + // may be related to realloc() utf8proc_uint8_t *output; - utf8proc_option_t options; + utf8proc_option_t options = { 0 }; /* options = UTF8PROC_COMPOSE | UTF8PROC_COMPAT | UTF8PROC_CASEFOLD | UTF8PROC_IGNORE | UTF8PROC_STRIPMARK | UTF8PROC_STRIPCC | UTF8PROC_STRIPNA; */ - memset(&options, 0, sizeof(options)); - // utf8proc_map_custom allocates new mem options = UTF8PROC_STRIPNA; *len = (size_t) utf8proc_map_custom((const utf8proc_uint8_t *)str, (utf8proc_ssize_t)*len, &output, @@ -85,19 +85,7 @@ int zsv_stricmp(const unsigned char *s1, const unsigned char *s2) { return zsv_strincmp(s1, strlen((const char *)s1), s2, strlen((const char *)s2)); } -int zsv_strincmp(const unsigned char *s1, size_t len1, const unsigned char *s2, size_t len2) { -#ifndef NO_UTF8PROC - unsigned char *lc1 = zsv_strtolowercase(s1, &len1); - unsigned char *lc2 = zsv_strtolowercase(s2, &len2); - int result; - if(VERY_UNLIKELY(!lc1 || !lc2)) - fprintf(stderr, "Out of memory!\n"), result = -2; - else - result = strcmp((char *)lc1, (char *)lc2); - free(lc1); - free(lc2); - return result; -#else +int zsv_strincmp_ascii(const unsigned char *s1, size_t len1, const unsigned char *s2, size_t len2) { while(len1) { if(!*s1) return *s2 == 0 ? 0 : -1; @@ -111,6 +99,22 @@ int zsv_strincmp(const unsigned char *s1, size_t len1, const unsigned char *s2, return c1 < c2 ? -1 : 1; } return 0; +} + +int zsv_strincmp(const unsigned char *s1, size_t len1, const unsigned char *s2, size_t len2) { +#ifndef NO_UTF8PROC + unsigned char *lc1 = zsv_strtolowercase(s1, &len1); + unsigned char *lc2 = zsv_strtolowercase(s2, &len2); + int result; + if(VERY_UNLIKELY(!lc1 || !lc2)) + fprintf(stderr, "Out of memory!\n"), result = -2; + else + result = strcmp((char *)lc1, (char *)lc2); + free(lc1); + free(lc2); + return result; +#else + return zsv_strincmp_ascii(s1, len1, s2, len2); #endif } diff --git a/configure b/configure index 85c7a00..26929d0 100755 --- a/configure +++ b/configure @@ -544,7 +544,11 @@ if [ "$usejq" = "yes" ] || [ "$usejq" = "auto" ] ; then if ! [ "$LDFLAGS_JQ" = "" ] ; then tryldflag LDFLAGS_JQ -lm tryldflag LDFLAGS_JQ -lshlwapi - tryldflag LDFLAGS_JQ -pthread + if [ "$MINGW" = "1" ]; then + tryldflag LDFLAGS_TMP -pthread && STATIC_LIBS="$STATIC_LIBS -pthread" + else + tryldflag LDFLAGS_JQ -pthread + fi fi fi @@ -603,6 +607,7 @@ CFLAGS_OPT = $CFLAGS_OPT LDFLAGS_OPT = $LDFLAGS_OPT LDFLAGS_TERMCAP = $LDFLAGS_TERMCAP LDFLAGS_JQ = $LDFLAGS_JQ +STATIC_LIBS = $STATIC_LIBS CFLAGS_AUTO = $CFLAGS_AUTO CFLAGS_LTO = $CFLAGS_LTO LDFLAGS_AUTO = $LDFLAGS_AUTO diff --git a/include/zsv/utils/string.h b/include/zsv/utils/string.h index 3d66ec1..039fd4b 100644 --- a/include/zsv/utils/string.h +++ b/include/zsv/utils/string.h @@ -25,6 +25,7 @@ const unsigned char *zsv_strstr(const unsigned char *hay, const unsigned char *n /* * zsv_stricmp, zsv_strincmp(): case-insensitive comparison (unicode-compatible if built with utf8proc) + * zsv_strincmp_ascii: ascii case-insensitive comparison * * @param s1 string to convert * @param len1 length of s1 @@ -35,6 +36,7 @@ const unsigned char *zsv_strstr(const unsigned char *hay, const unsigned char *n */ int zsv_stricmp(const unsigned char *s1, const unsigned char *s2); int zsv_strincmp(const unsigned char *s1, size_t len1, const unsigned char *s2, size_t len2); +int zsv_strincmp_ascii(const unsigned char *s1, size_t len1, const unsigned char *s2, size_t len2); unsigned char *zsv_strtrim(unsigned char * restrict s, size_t *lenp); diff --git a/scripts/ci-install-libjq.sh b/scripts/ci-install-libjq.sh index a1acf47..8ba62bb 100755 --- a/scripts/ci-install-libjq.sh +++ b/scripts/ci-install-libjq.sh @@ -6,6 +6,15 @@ echo "[INF] Running $0" echo "[INF] Building and installing jq (libjq)" +echo "[INF] Will apply a patch to jq so that when compiling with mingw64," +echo "[INF] jq will not create its own functions that conflict with pthread functions" +echo "[INF] and which in turn prevent mingw64 from statically linking libwinpthread-1.dll" +echo "[INF] If you are building on your target system, this is not necessary, and the" +echo "[INF] standard jq distro can be used" + +THIS_SCRIPT_PATH=$(dirname "$0") +THIS_SCRIPT_PATH=$(cd "$THIS_SCRIPT_PATH" && pwd) +JQ_PATCH="$THIS_SCRIPT_PATH/../app/external/jq.diff" JQ_GIT_URL='https://github.com/stedolan/jq.git' JQ_GIT_COMMIT='cff5336' JQ_DIR="$PWD/jq" @@ -15,6 +24,7 @@ JQ_LIB_DIR="$JQ_PREFIX/lib" echo "[INF] PWD: $PWD" echo "[INF] CC: $CC" +echo "[INF] JQ_PATCH: $JQ_PATCH" echo "[INF] JQ_GIT_URL: $JQ_GIT_URL" echo "[INF] JQ_GIT_COMMIT: $JQ_GIT_COMMIT" echo "[INF] JQ_DIR: $JQ_DIR" @@ -27,6 +37,8 @@ rm -rf "$JQ_DIR" git clone "$JQ_GIT_URL" cd jq git checkout "$JQ_GIT_COMMIT" +echo "[INF] Applying patch" +git apply "$JQ_PATCH" || exit 1 echo "[INF] Configuring" autoreconf -fi @@ -39,7 +51,6 @@ if [ "$CC" = 'x86_64-w64-mingw32-gcc' ]; then --disable-docs \ --disable-shared \ --enable-static \ - --target=win64-x86_64 \ --host=x86_64-w64-mingw32 else CFLAGS='-O3' ./configure \