diff --git a/ChangeLog b/ChangeLog index bf558e0..8207f68 100644 --- a/ChangeLog +++ b/ChangeLog @@ -281,6 +281,44 @@ * data/tdict-science.txt: - Fix typo "อัลลอยด์" -> "อัลลอย". +2020-03-23 Ross Burton + + configure.ac: remove duplicate AC_CONFIG_MACRO_DIR + + Autoconf 2.70 will fatally error out if AC_CONFIG_MACRO_DIR is called + more than once: + + | configure.ac:25: error: AC_CONFIG_MACRO_DIR can only be used once + + * configure.ac: + - Remove duplicate AC_CONFIG_MACRO_DIR +2020-02-14 Chun-wei Fan + + Add a set of NMake Makefiles + * configure.ac: + * Makefile.am: + * win32/*: + - Add a set of NMake Makefiles for Visual Studio 2008 and later, + for building libthai as a DLL as well as the pkg-config file. + Buliding the dictionary file and tests are also supported. + +2020-02-14 Chun-wei Fan + Make libthai relocatable on native Windows + + * src/thbrk/brk-common.c: + - Deduce location of DLL or statically-linked EXE and construct + path dynamically where thbrk.tri can be loaded. + +2020-02-14 Chun-wei Fan + + Don't use __attribute__((destructor)) on MSVC builds + + * src/libthai.c: + * src/thbrk/brk-common.c: + - Instead define a DLLMain that does the same thing when libthai + is built as a DLL, on DLL_PROCESS_DETACH. Ensure that tests + builds as well since src/thbrk/brk-common.c is also used. + 2020-03-23 Ross Burton configure.ac: remove duplicate AC_CONFIG_MACRO_DIR diff --git a/Makefile.am b/Makefile.am index 8eba43a..5a89cca 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = include src data tests doc +SUBDIRS = include src data tests doc win32 EXTRA_DIST = \ build-aux/git-version-gen \ diff --git a/configure.ac b/configure.ac index 9492c84..ba26d55 100644 --- a/configure.ac +++ b/configure.ac @@ -152,6 +152,8 @@ AC_CONFIG_FILES([libthai.pc tests/Makefile doc/Makefile doc/Doxyfile + win32/Makefile + win32/config-msvc.mak ]) AC_OUTPUT diff --git a/src/libthai.c b/src/libthai.c index 8065c1f..ab2613c 100644 --- a/src/libthai.c +++ b/src/libthai.c @@ -90,7 +90,11 @@ #include "thbrk/thbrk-priv.h" -__attribute__ ((destructor)) void + +#if defined (__GNUC__) || defined (__clang__) +__attribute__((destructor)) +#endif +void _libthai_on_unload () { brk_free_shared_brk (); diff --git a/src/thbrk/brk-common.c b/src/thbrk/brk-common.c index fedb1bf..7a261b6 100644 --- a/src/thbrk/brk-common.c +++ b/src/thbrk/brk-common.c @@ -33,6 +33,108 @@ #include "thbrk-utils.h" #include "brk-common.h" +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN 1 +#include + +#if !defined (__GNUC__) && !defined (__clang__) +#ifdef MSVC_BUILD_LIBTHAI_TESTS +/* Externally refer to brk_free_shared_brk() when building the tests for + * Visual Studio so that we do not need to depend on $(srcroot)\src\libthai.c + * to build the tests + */ +extern void brk_free_shared_brk (); +#define _libthai_on_unload brk_free_shared_brk + +#else +extern void _libthai_on_unload (); +#endif /* MSVC_BUILD_LIBTHAI_TESTS */ +#endif /* !__GNUC__ && !__clang__ */ + +/* This way, we can use the current directory where the .exe is if no DLL is built, such as in tests */ +static HMODULE libthai_dll = NULL; + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, + DWORD fdwReason, + LPVOID lpvReserved); + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, + DWORD fdwReason, + LPVOID lpvReserved) +{ + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + libthai_dll = hinstDLL; + break; + +#if !defined (__GNUC__) && !defined (__clang__) + /* fallback for lack of GCC's __attribute__((destructor)) */ + case DLL_PROCESS_DETACH: + _libthai_on_unload (); + break; +#endif + } + + return TRUE; +} + +/* + * modelled around GLib's g_win32_get_package_installation_directory_of_module() + * without Cygwin support + */ +#ifndef __CYGWIN__ +char * +libthai_get_installdir (HMODULE hmodule) +{ + char *retval; + char *filename; + char *p; + wchar_t wc_fn[MAX_PATH]; + size_t length; + size_t converted = 0; + + /* NOTE: it relies that GetModuleFileNameW returns only canonical paths */ + if (!GetModuleFileNameW (hmodule, wc_fn, MAX_PATH)) + return NULL; + + length = wcslen(wc_fn); + filename = (char *)malloc (sizeof(char) * (length * 2 + 1)); + wcstombs_s(&converted, filename, length * 2, wc_fn, _TRUNCATE); + + if ((p = strrchr (filename, '\\')) != NULL) + *p = '\0'; + + retval = (char *)malloc (sizeof(char) * (length * 2 + 1)); + memcpy (retval, filename, strlen(filename)); + + do + { + p = strrchr (retval, '\\'); + if (p == NULL) + break; + + *p = '\0'; + + if (_stricmp (p + 1, "bin") == 0 || + _stricmp (p + 1, "lib") == 0) + break; + } + while (p != NULL); + + if (p == NULL) + { + free (retval); + retval = filename; + } + else + free (filename); + + return retval; +} +#endif /* !__CYGWIN__ */ +#endif /* _WIN32 */ + #define DICT_NAME "thbrk" static char * @@ -58,9 +160,20 @@ brk_load_default_dict () free (path); } - /* Then, fall back to default DICT_DIR macro */ + /* Then, fall back to default DICT_DIR macro or relative $(datadir)\share\libthai for native Windows DLL */ if (!dict_trie) { +#if defined (_WIN32) && !defined (__CYGWIN__) + char *basedir = libthai_get_installdir (libthai_dll); + const char *sharedir = "share\\libthai\\" DICT_NAME ".tri"; + size_t total_len = strlen (basedir) + strlen (sharedir) + 1; /* '+ 1' for the '\\' that we are using below */ + char *filepath = (char *) malloc (sizeof (char) * (total_len + 1)); + sprintf (filepath, "%s\\%s", basedir, sharedir); + dict_trie = trie_new_from_file (filepath); + free (filepath); + free (basedir); +#else dict_trie = trie_new_from_file (DICT_DIR "/" DICT_NAME ".tri"); +#endif } return dict_trie; diff --git a/win32/Makefile.am b/win32/Makefile.am new file mode 100644 index 0000000..b2cbbdf --- /dev/null +++ b/win32/Makefile.am @@ -0,0 +1,13 @@ +EXTRA_DIST = \ + build-rules-msvc.mak \ + config-msvc.mak \ + create-lists-msvc.mak \ + create-lists.bat \ + create-pc.bat \ + detectenv-msvc.mak \ + generate-msvc.mak \ + info-msvc.mak \ + install.mak \ + Makefile.vc \ + README.txt \ + $(NULL) diff --git a/win32/Makefile.vc b/win32/Makefile.vc new file mode 100644 index 0000000..b5268dd --- /dev/null +++ b/win32/Makefile.vc @@ -0,0 +1,45 @@ +# NMake Makefile for building libthai on Windows + +# The items below this line should not be changed, unless one is maintaining +# the NMake Makefiles. Customizations can be done in the following NMake Makefile +# portions (please see comments in the these files to see what can be customized): +# +# detectenv-msvc.mak +# config-msvc.mak + +!include detectenv-msvc.mak + +# Include the Makefile portion that enables features based on user input +!include config-msvc.mak + +!if "$(VALID_CFGSET)" == "TRUE" + + +all: $(LIBTHAI_LIBS) $(LIBTHAI_DATA) all-build-info + +# Include the Makefile portion to convert the source and header lists +# into the lists we need for compilation and introspection +!include create-lists-msvc.mak + +tests: all $(libthai_tests_EXES) + @for %x in (ctype cell inp rend str wchar) do vs$(PDBVER)\$(CFG)\$(PLAT)\test_th%x.exe + vs$(PDBVER)\$(CFG)\$(PLAT)\thsort.exe ..\tests\sorttest.txt vs$(PDBVER)\$(CFG)\$(PLAT)\libthai-tests\out.txt + @fc ..\tests\sorted.txt vs$(PDBVER)\$(CFG)\$(PLAT)\libthai-tests\out.txt + @del vs$(PDBVER)\$(CFG)\$(PLAT)\libthai-tests\out.txt + @if "$(LIB_ONLY)" == "" @(for %x in (brk wbrk) do (set LIBTHAI_DICTDIR=$(MAKEDIR)\vs$(PDBVER)\$(CFG)\$(PLAT)\) & (vs$(PDBVER)\$(CFG)\$(PLAT)\test_th%x.exe)) + +# Include the build rules for sources, DLLs and executables +!include build-rules-msvc.mak + +# Include the rules for build directory creation and code generation +!include generate-msvc.mak + +!include install.mak + +!else # "$(VALID_CFGSET)" == "TRUE" +all: help + @echo You need to specify a valid configuration, via + @echo CFG=release or CFG=debug +!endif # "$(VALID_CFGSET)" == "TRUE" + +!include info-msvc.mak diff --git a/win32/README.txt b/win32/README.txt new file mode 100644 index 0000000..ebd708b --- /dev/null +++ b/win32/README.txt @@ -0,0 +1,54 @@ +Instructions for building libthai on Visual Studio +================================================== +Building the libthai on Windows is now supported using Visual Studio. + +You will need the following items to build libthai using Visual Studio: +-libiconv (including the libcharset headers and libraries) if building trietool.exe + +Invoke the build by issuing the command: +nmake /f Makefile.vc CFG=[release|debug] [PREFIX=...] +where: + +CFG: Required. Choose from a release or debug build. Note that + all builds generate a .pdb file for each .dll and .exe built--this refers + to the C/C++ runtime that the build uses. + +PREFIX: Optional. Base directory of where the third-party headers, libraries + and needed tools can be found, i.e. headers in $(PREFIX)\include, + libraries in $(PREFIX)\lib and tools in $(PREFIX)\bin. If not + specified, $(PREFIX) is set as $(srcroot)\..\vs$(X)\$(platform), where + $(platform) is win32 for 32-bit builds or x64 for 64-bit builds, and + $(X) is the short version of the Visual Studio used, as follows: + 2008: 9 + 2010: 10 + 2012: 11 + 2013: 12 + 2015, 2017, 2019: 14 + +Explanation of options, set by