diff --git a/Makefile.am b/Makefile.am index 0fb6c79..f85966b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,7 +8,7 @@ if ENABLE_MAN SUBDIRS += docs/libpsl endif endif -SUBDIRS += fuzz tests +SUBDIRS += fuzz tests msvc ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} diff --git a/configure.ac b/configure.ac index 72b136e..82af630 100644 --- a/configure.ac +++ b/configure.ac @@ -381,7 +381,10 @@ AC_CONFIG_FILES([Makefile fuzz/Makefile tests/Makefile docs/libpsl/Makefile docs/libpsl/version.xml - libpsl.pc:libpsl.pc.in]) + libpsl.pc:libpsl.pc.in + msvc/Makefile + msvc/config.h.win32 + msvc/config-msvc.mak]) AC_OUTPUT AC_MSG_NOTICE([Summary of build options: diff --git a/msvc/Makefile.am b/msvc/Makefile.am new file mode 100644 index 0000000..5d85a99 --- /dev/null +++ b/msvc/Makefile.am @@ -0,0 +1,13 @@ +EXTRA_DIST = \ + build-rules-msvc.mak \ + config.h.win32 \ + config-msvc.mak \ + create-lists.bat \ + create-lists-msvc.mak \ + detectenv-msvc.mak \ + generate-msvc.mak \ + install-msvc.mak \ + libpsl-pc.py \ + Makefile.vc \ + pc_base.py \ + replace.py diff --git a/msvc/Makefile.vc b/msvc/Makefile.vc new file mode 100644 index 0000000..722438e --- /dev/null +++ b/msvc/Makefile.vc @@ -0,0 +1,35 @@ +# NMake Makefile for building libpsl 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" + +# 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 + +all: $(PSL_LIB) $(PSL_UTILS) build-info + +tests: $(PSL_TEST_DATA) $(PSL_TESTS) build-info + +# 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 the Makefile portion that enables installing the build results +!include install-msvc.mak +!else +!error No CFG (or invalid CFG) value specified. Valid values are release or debug. +!endif \ No newline at end of file diff --git a/msvc/build-rules-msvc.mak b/msvc/build-rules-msvc.mak new file mode 100644 index 0000000..78923b7 --- /dev/null +++ b/msvc/build-rules-msvc.mak @@ -0,0 +1,110 @@ +# NMake Makefile portion for compilation rules +# Items in here should not need to be edited unless +# one is maintaining the NMake build files. The format +# of NMake Makefiles here are different from the GNU +# Makefiles. Please see the comments about these formats. + +# Inference rules for compiling the .obj files. +# Used for libs and programs with more than a single source file. +# Format is as follows +# (all dirs must have a trailing '\'): +# +# {$(srcdir)}.$(srcext){$(destdir)}.obj:: +# $(CC)|$(CXX) $(cflags) /Fo$(destdir) /c @<< +# $< +# << + +{..\src\}.c{$(CFG)\$(PLAT)\libpsl\}.obj:: + $(CC) $(BASE_CFLAGS) $(PSL_ADDITIONAL_CFLAGS) $(PSL_INCLUDES) /Fo$(CFG)\$(PLAT)\libpsl\ /c @<< +$< +<< + +{..\tools\}.c{$(CFG)\$(PLAT)\psl\}.obj:: + $(CC) $(BASE_CFLAGS) $(PSL_INCLUDES) /Fo$(CFG)\$(PLAT)\psl\ /c @<< +$< +<< + +# Make sure we generate suffixes_dafsa.c before trying to compile psl.c +$(CFG)\$(PLAT)\libpsl\psl.obj: $(CFG)\$(PLAT)\libpsl\suffixes_dafsa.c + +# Inference rules for building the test programs +# Used for programs with a single source file. +# Format is as follows +# (all dirs must have a trailing '\'): +# +# {$(srcdir)}.$(srcext){$(destdir)}.exe:: +# $(CC)|$(CXX) $(cflags) $< /Fo$*.obj /Fe$@ [/link $(linker_flags) $(dep_libs)] + +{..\tests\}.c{$(CFG)\$(PLAT)\}.exe: + @if not exist $(PSL_UTILS) $(MAKE) -f Makefile.vc $(PSL_MAKE_OPTIONS) $(PSL_UTILS) + @if not exist $(CFG)\$(PLAT)\tests $(MAKE) -f Makefile.vc $(PSL_MAKE_OPTIONS) $(CFG)\$(PLAT)\tests + $(CC) $(PSL_TEST_CFLAGS) $(PSL_INCLUDES) /Fo$(CFG)\$(PLAT)\tests\ /Fe$@ \ + $< /link $(LDFLAGS) $(PSL_LIB) $(PSL_ADDITIONAL_LIBS) + @if exist $@.manifest mt /manifest $@.manifest /outputresource:$@;1 + +# Rules for building .lib files +!ifdef STATIC +$(PSL_LIB): $(CFG)\$(PLAT)\libpsl ..\config.h $(libpsl_OBJS) + lib $(ARFLAGS) /out:$@ @<< +$(libpsl_OBJS) +<< + +!else +$(PSL_LIB): $(PSL_DLL) +!endif + +# Rules for linking DLLs +# Format is as follows (the mt command is needed for MSVC 2005/2008 builds): +# $(dll_name_with_path): $(dependent_libs_files_objects_and_items) +# link /DLL [$(linker_flags)] [$(dependent_libs)] [/def:$(def_file_if_used)] [/implib:$(lib_name_if_needed)] -out:$@ @<< +# $(dependent_objects) +# << +# @-if exist $@.manifest mt /manifest $@.manifest /outputresource:$@;2 + +$(PSL_DLL): ..\config.h $(libpsl_OBJS) + link $(LDFLAGS) $(PSL_ADDITIONAL_LIBS) /DLL /out:$@ @<< +$(libpsl_OBJS) +<< + @if exist $@.manifest mt /manifest $@.manifest /outputresource:$@;2 + +# Rules for linking Executables +# Format is as follows (the mt command is needed for MSVC 2005/2008 builds): +# $(dll_name_with_path): $(dependent_libs_files_objects_and_items) +# link [$(linker_flags)] [$(dependent_libs)] -out:$@ @<< +# $(dependent_objects) +# << +# @-if exist $@.manifest mt /manifest $@.manifest /outputresource:$@;1 + +$(CFG)\$(PLAT)\psl.exe: $(PSL_LIB) $(CFG)\$(PLAT)\psl $(psl_OBJS) + link $(LDFLAGS) $(PSL_LIB) $(PSL_ADDITIONAL_LIBS) /PDB:$(@R)-tool.pdb /out:$@ @<< +$(psl_OBJS) +<< + @if exist $@.manifest mt /manifest $@.manifest /outputresource:$@;1 + +# Show the build configuration for this build +build-info: + @echo ------------------------------- + @echo Build configuration for libpsl: + @echo ------------------------------- + @echo Configuration/Platform: $(CFG)/$(PLAT) + @echo Library Build Type: $(PSL_LIBTYPE) + @echo Enabled Runtime: $(ENABLED_RUNTIME) + @echo Enabled Builtin: $(ENABLED_BUILTIN) + @if not "$(ENABLED_BUILTIN)" == "none" echo PSL File: $(PSL_FILE) + +clean: + @if exist $(CFG)\$(PLAT)\psl.dafsa del $(CFG)\$(PLAT)\psl.dafsa + @if exist $(CFG)\$(PLAT)\psl_ascii.dafsa del $(CFG)\$(PLAT)\psl_ascii.dafsa + @if exist .\libpsl.pc del /f /q .\libpsl.pc + @-del /f /q $(CFG)\$(PLAT)\*.exe + @-del /f /q $(CFG)\$(PLAT)\*.lib + @-del /f /q $(CFG)\$(PLAT)\*.pdb + @-del /f /q $(CFG)\$(PLAT)\*.dll.manifest + @-del /f /q $(CFG)\$(PLAT)\*.dll + @-del /f /q $(CFG)\$(PLAT)\*.ilk + @-if exist $(CFG)\$(PLAT)\tests del /f /q $(CFG)\$(PLAT)\tests\*.obj + @-del /f /q $(CFG)\$(PLAT)\libpsl\*.obj + @-del /f /q $(CFG)\$(PLAT)\libpsl\suffixes_dafsa.c + @-del /f /q ..\config.h + @-del /f /q vc$(PDBVER)0.pdb + @-rmdir /s /q $(CFG)\$(PLAT) diff --git a/msvc/config-msvc.mak.in b/msvc/config-msvc.mak.in new file mode 100644 index 0000000..adf1eff --- /dev/null +++ b/msvc/config-msvc.mak.in @@ -0,0 +1,137 @@ +# NMake Makefile portion for enabling features for Windows builds + +# You may change these lines to customize various items + +!ifndef PSL_FILE +PSL_FILE=..\list\public_suffix_list.dat +!endif + +!ifndef PSL_TESTFILE +PSL_TESTFILE=..\list\tests\tests.txt +!endif + +PSL_FILE_INPUT = $(PSL_FILE:\=/) +PSL_TESTFILE_INPUT = $(PSL_TESTFILE:\=/) + +# We only support using the ICU runtime and/or builtin, or no runtime +# and/or builtin for Visual Studio builds +!if "$(CFG)" == "Release" || "$(CFG)" == "release" +ICUUC_LIB = icuuc.lib +!else +ICUUC_LIB = icuucd.lib +!endif + +ICONV_LIB = iconv.lib +GETTEXT_LIB = intl.lib + +# Please do not change anything beneath this line unless maintaining the NMake Makefiles +# Version info + +PACKAGE_NAME=@PACKAGE_NAME@ +PACKAGE_VERSION=@PACKAGE_VERSION@ +PACKAGE_URL=@PACKAGE_URL@ + +# Bare minimum features and sources built into libpsl on Windows + +!if "$(PLAT)" == "x64" +SSIZE_T_DEF = signed __int64 +!else +SSIZE_T_DEF = signed int +!endif + +PSL_ADDITIONAL_LIBS = ws2_32.lib +PSL_ADDITIONAL_CFLAGS = /DBUILDING_PSL + +BASE_CFLAGS = \ + $(CFLAGS) \ + /D_CRT_SECURE_NO_WARNINGS \ + /D_CRT_NONSTDC_NO_WARNINGS \ + /DHAVE_CONFIG_H \ + /Dssize_t="$(SSIZE_T_DEF)" + +PSL_INCLUDES = /I..\include /I.. /I$(CFG)\$(PLAT)\libpsl /I$(PREFIX)\include + +# We build the psl.dll or psl.lib at least, with the psl.exe utility +PSL_LIB = $(CFG)\$(PLAT)\psl.lib +PSL_UTILS = $(CFG)\$(PLAT)\psl.exe + +PSL_TESTS = \ + $(CFG)\$(PLAT)\test-is-public.exe \ + $(CFG)\$(PLAT)\test-is-public-all.exe \ + $(CFG)\$(PLAT)\test-is-cookie-domain-acceptable.exe + +PSL_TEST_DATA = \ + $(CFG)\$(PLAT)\psl.dafsa \ + $(CFG)\$(PLAT)\psl_ascii.dafsa + +PSL_MAKE_OPTIONS = CFG^=$(CFG) + +!ifndef STATIC +!ifdef USE_LIBTOOL_DLLNAME +PSL_DLL_PREFIX = lib +PSL_DLL_SUFFIX = -5 +PSL_MAKE_OPTIONS = $(PSL_MAKE_OPTIONS) USE_LIBTOOL_DLLNAME^=$(USE_LIBTOOL_DLLNAME) +!else +PSL_DLL_PREFIX = +PSL_DLL_SUFFIX = +!endif +!endif + +PSL_DLL = $(CFG)\$(PLAT)\$(PSL_DLL_PREFIX)psl$(PSL_DLL_SUFFIX).dll + +# ENABLE_RUNTIME_ICU and ENABLE_BUILTIN_ICU are currently dummy arguments to NMake +ENABLED_RUNTIME = +ENABLED_BUILTIN = + +!ifndef DISABLE_RUNTIME +BASE_CFLAGS = $(BASE_CFLAGS) /DWITH_LIBICU=1 +ENABLED_RUNTIME = libicu +!else +PSL_MAKE_OPTIONS = $(PSL_MAKE_OPTIONS) DISABLE_RUNTIME^=1 +ENABLED_RUNTIME = none +!endif + +!ifndef DISABLE_BUILTIN +BASE_CFLAGS = $(BASE_CFLAGS) /DBUILTIN_GENERATOR_LIBICU=1 +ENABLED_BUILTIN = libicu +!else +PSL_MAKE_OPTIONS = $(PSL_MAKE_OPTIONS) DISABLE_BUILTIN^=1 +ENABLED_BUILTIN = none +!endif + +!ifdef STATIC +BASE_CFLAGS = $(BASE_CFLAGS) /DPSL_STATIC +PSL_MAKE_OPTIONS = $(PSL_MAKE_OPTIONS) STATIC^=1 +PSL_LIBTYPE = static +!else +PSL_LIBTYPE = DLL +!endif + +!if "$(DISABLE_RUNTIME)" == "" || "$(DISABLE_BUILTIN)" == "" +PSL_ADDITIONAL_LIBS = $(PSL_ADDITIONAL_LIBS) $(ICUUC_LIB) +PSL_TESTS = \ + $(PSL_TESTS) \ + $(CFG)\$(PLAT)\test-is-public-builtin.exe \ + $(CFG)\$(PLAT)\test-registrable-domain.exe +!endif + +!ifdef USE_GETTEXT +USE_ICONV=1 +PSL_ADDITIONAL_LIBS = $(PSL_ADDITIONAL_LIBS) $(GETTEXT_LIB) +BASE_CFLAGS = $(BASE_CFLAGS) /DUSE_GETTEXT=1 +PSL_MAKE_OPTIONS = $(PSL_MAKE_OPTIONS) USE_GETTEXT^=1 +!endif + +!ifdef USE_ICONV +PSL_ADDITIONAL_LIBS = $(PSL_ADDITIONAL_LIBS) $(ICONV_LIB) +BASE_CFLAGS = $(BASE_CFLAGS) /DUSE_ICONV=1 +PSL_MAKE_OPTIONS = $(PSL_MAKE_OPTIONS) USE_ICONV^=1 +!endif + +PSL_TEST_CFLAGS = $(BASE_CFLAGS) /DPSL_TESTFILE=\"$(PSL_TESTFILE_INPUT)\" /DPSL_FILE=\"$(PSL_FILE_INPUT)\" + +# Visual Studio 2013 or earlier does not have snprintf(), +# so use _snprintf() which seems to be enough for our purposes +!if $(VSVER) < 14 +PSL_TEST_CFLAGS = $(PSL_TEST_CFLAGS) /Dsnprintf=_snprintf +!endif diff --git a/msvc/config.h.win32.in b/msvc/config.h.win32.in new file mode 100644 index 0000000..b1f2525 --- /dev/null +++ b/msvc/config.h.win32.in @@ -0,0 +1,169 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* generate PSL data using libicu */ +/* #undef BUILTIN_GENERATOR_LIBICU */ + +/* generate PSL data using libidn */ +/* #undef BUILTIN_GENERATOR_LIBIDN */ + +/* generate PSL data using libidn2 */ +/* #undef BUILTIN_GENERATOR_LIBIDN2 */ + +/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP + systems. This function is required for `alloca.c' support on those systems. + */ +/* #undef CRAY_STACKSEG_END */ + +/* Define to 1 if using `alloca.c'. */ +/* #undef C_ALLOCA */ + +/* Define to 1 if translation of program messages to the user's native + language is requested. */ +#ifdef USE_GETTEXT +# define ENABLE_NLS 1 +#endif + +/* Define to 1 if you have `alloca', as a function or macro. */ +#ifdef _MSC_VER +# define alloca _alloca +#endif +#define HAVE_ALLOCA 1 + +/* Define to 1 if you have and it should be used (not on Ultrix). + */ +/* #undef HAVE_ALLOCA_H */ + +/* Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the + CoreFoundation framework. */ +/* #undef HAVE_CFLOCALECOPYCURRENT */ + +/* Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in + the CoreFoundation framework. */ +/* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */ + +/* Define to 1 if you have the `clock_gettime' function. */ +#ifndef _MSC_VER +# define HAVE_CLOCK_GETTIME 1 +#endif + +/* Define if the GNU dcgettext() function is already present or preinstalled. + */ +#ifdef USE_GETTEXT +# define HAVE_DCGETTEXT 1 +#endif + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DLFCN_H */ + +/* Define to 1 if you have the `fmemopen' function. */ +/* #undef HAVE_FMEMOPEN */ + +/* Define if the GNU gettext() function is already present or preinstalled. */ +#ifdef USE_GETTEXT +# define HAVE_GETTEXT 1 +#endif + +/* Define if you have the iconv() function and it works. */ +#ifdef USE_ICONV +# define HAVE_ICONV 1 +#endif + +/* Define to 1 if you have the header file. */ +#if !defined (_MSC_VER) || (_MSC_VER >= 1800) +# define HAVE_INTTYPES_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the header file. */ +#if !defined (_MSC_VER) || (_MSC_VER >= 1600) +# define HAVE_STDINT_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#ifndef _MSC_VER +# define HAVE_STRINGS_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strndup' function. */ +/* #undef HAVE_STRNDUP */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#ifndef _MSC_VER +# define HAVE_UNISTD_H 1 +#endif + +/* Define to 1 or 0, depending whether the compiler supports simple visibility + declarations. */ +#ifndef _MSC_VER +# define HAVE_VISIBILITY 1 +#endif + +/* Define as const if the declaration of iconv() needs const. */ +/* #undef ICONV_CONST */ + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#define LT_OBJDIR ".libs/" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "@PACKAGE_NAME@" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "@PACKAGE_NAME@ @PACKAGE_VERSION@" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "@PACKAGE_TARNAME@" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "@PACKAGE_URL@" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "@PACKAGE_VERSION@" + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at runtime. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ +/* #undef STACK_DIRECTION */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* generate PSL data using libicu */ +/* #undef WITH_LIBICU */ + +/* generate PSL data using libidn */ +/* #undef WITH_LIBIDN */ + +/* generate PSL data using libidn2 */ +/* #undef WITH_LIBIDN2 */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +# if defined (_MSC_VER) && (_MSC_VER < 1900) +# define inline __inline +# endif +#endif + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ diff --git a/msvc/create-lists-msvc.mak b/msvc/create-lists-msvc.mak new file mode 100644 index 0000000..324cee5 --- /dev/null +++ b/msvc/create-lists-msvc.mak @@ -0,0 +1,61 @@ +# Convert the source listing to object (.obj) listing in +# another NMake Makefile module, include it, and clean it up. +# This is a "fact-of-life" regarding NMake Makefiles... +# This file does not need to be changed unless one is maintaining the NMake Makefiles + +# For those wanting to add things here: +# To add a list, do the following: +# # $(description_of_list) +# if [call create-lists.bat header $(makefile_snippet_file) $(variable_name)] +# endif +# +# if [call create-lists.bat file $(makefile_snippet_file) $(file_name)] +# endif +# +# if [call create-lists.bat footer $(makefile_snippet_file)] +# endif +# ... (repeat the if [call ...] lines in the above order if needed) +# !include $(makefile_snippet_file) +# +# (add the following after checking the entries in $(makefile_snippet_file) is correct) +# (the batch script appends to $(makefile_snippet_file), you will need to clear the file unless the following line is added) +#!if [del /f /q $(makefile_snippet_file)] +#!endif + +# In order to obtain the .obj filename that is needed for NMake Makefiles to build DLLs/static LIBs or EXEs, do the following +# instead when doing 'if [call create-lists.bat file $(makefile_snippet_file) $(file_name)]' +# (repeat if there are multiple $(srcext)'s in $(source_list), ignore any headers): +# !if [for %c in ($(source_list)) do @if "%~xc" == ".$(srcext)" @call create-lists.bat file $(makefile_snippet_file) $(intdir)\%~nc.obj] +# +# $(intdir)\%~nc.obj needs to correspond to the rules added in build-rules-msvc.mak +# %~xc gives the file extension of a given file, %c in this case, so if %c is a.cc, %~xc means .cc +# %~nc gives the file name of a given file without extension, %c in this case, so if %c is a.cc, %~nc means a + +NULL= + +# Include libpsl source files +!include ..\src\libpsl-srcs.mk + +# Create the list of .obj files +!if [call create-lists.bat header libpsl-msvc.mak libpsl_OBJS] +!endif + +!if [for %c in ($(LIBPSL_SRCS)) do @if "%~xc" == ".c" @call create-lists.bat file libpsl-msvc.mak ^$(CFG)\^$(PLAT)\libpsl\%~nc.obj] +!endif + +!if [call create-lists.bat footer libpsl-msvc.mak] +!endif + +!if [call create-lists.bat header libpsl-msvc.mak psl_OBJS] +!endif + +!if [for %c in (..\tools\*.c) do @call create-lists.bat file libpsl-msvc.mak ^$(CFG)\^$(PLAT)\psl\%~nc.obj] +!endif + +!if [call create-lists.bat footer libpsl-msvc.mak] +!endif + +!include libpsl-msvc.mak + +!if [del /f /q libpsl-msvc.mak] +!endif diff --git a/msvc/create-lists.bat b/msvc/create-lists.bat new file mode 100644 index 0000000..ef60d5c --- /dev/null +++ b/msvc/create-lists.bat @@ -0,0 +1,42 @@ +@echo off +rem Simple .bat script for creating the NMake Makefile snippets. + +if not "%1" == "header" if not "%1" == "file" if not "%1" == "footer" goto :error_cmd +if "%2" == "" goto error_no_destfile + +if "%1" == "header" goto :header +if "%1" == "file" goto :addfile +if "%1" == "footer" goto :footer + +:header +if "%3" == "" goto error_var +echo %3 = \>>%2 +goto done + +:addfile +if "%3" == "" goto error_file +echo. %3 \>>%2 +goto done + +:footer +echo. $(NULL)>>%2 +echo.>>%2 +goto done + +:error_cmd +echo Specified command '%1' was invalid. Valid commands are: header file footer. +goto done + +:error_no_destfile +echo Destination NMake snippet file must be specified +goto done + +:error_var +echo A name must be specified for using '%1'. +goto done + +:error_file +echo A file must be specified for using '%1'. +goto done + +:done \ No newline at end of file diff --git a/msvc/detectenv-msvc.mak b/msvc/detectenv-msvc.mak new file mode 100644 index 0000000..2ca74d5 --- /dev/null +++ b/msvc/detectenv-msvc.mak @@ -0,0 +1,152 @@ +# Change this (or specify PREFIX= when invoking this NMake Makefile) if +# necessary, so that the libs and headers of the dependent third-party +# libraries can be located. For instance, if building from GLib's +# included Visual Studio projects, this should be able to locate the GLib +# build out-of-the-box if they were not moved. GLib's headers will be +# found in $(GLIB_PREFIX)\include\glib-2.0 and +# $(GLIB_PREFIX)\lib\glib-2.0\include and its import library will be found +# in $(GLIB_PREFIX)\lib. + +!if "$(PREFIX)" == "" +PREFIX = ..\..\vs$(VSVER)\$(PLAT) +!endif + +# Location of the PERL interpretor, for running glib-mkenums. glib-mkenums +# needs to be found in $(PREFIX)\bin. Using either a 32-bit or x64 PERL +# interpretor are supported for either a 32-bit or x64 build. + +!if "$(PERL)" == "" +PERL = perl +!endif + +# Location of the Python interpretor, for building introspection. The complete set +# of Python Modules for introspection (the giscanner Python scripts and the _giscanner.pyd +# compiled module) needs to be found in $(PREFIX)\lib\gobject-introspection\giscanner, and +# the g-ir-scanner Python script and g-ir-compiler utility program needs to be found +# in $(PREFIX)\bin, together with any DLLs they will depend on, if those DLLs are not already +# in your PATH. +# Note that the Python interpretor and the introspection modules and utility progam must +# correspond to the build type (i.e. 32-bit Release for 32-bit Release builds, and so on). +# +# For introspection, currently only Python 2.7.x is supported. This may change when Python 3.x +# support is added upstream in gobject-introspection--when this happens, the _giscanner.pyd must +# be the one that is built against the release series of Python that is used here. + +!if "$(PYTHON)" == "" +PYTHON = python +!endif + +# Location of the pkg-config utility program, for building introspection. It needs to be able +# to find the pkg-config (.pc) files so that the correct libraries and headers for the needed libraries +# can be located, using PKG_CONFIG_PATH. Using either a 32-bit or x64 pkg-config are supported for +# either a 32-bit or x64 build. + +!if "$(PKG_CONFIG)" == "" +PKG_CONFIG = pkg-config +!endif + +# The items below this line should not be changed, unless one is maintaining +# the NMake Makefiles. The exception is for the CFLAGS_ADD line(s) where one +# could use his/her desired compiler optimization flags, if he/she knows what is +# being done. + +# Check to see we are configured to build with MSVC (MSDEVDIR, MSVCDIR or +# VCINSTALLDIR) or with the MS Platform SDK (MSSDK or WindowsSDKDir) +!if !defined(VCINSTALLDIR) && !defined(WINDOWSSDKDIR) +MSG = ^ +This Makefile is only for Visual Studio 2008 and later.^ +You need to ensure that the Visual Studio Environment is properly set up^ +before running this Makefile. +!error $(MSG) +!endif + +ERRNUL = 2>NUL +_HASH=^# + +!if ![echo VCVERSION=_MSC_VER > vercl.x] \ + && ![echo $(_HASH)if defined(_M_IX86) >> vercl.x] \ + && ![echo PLAT=Win32 >> vercl.x] \ + && ![echo $(_HASH)elif defined(_M_AMD64) >> vercl.x] \ + && ![echo PLAT=x64 >> vercl.x] \ + && ![echo $(_HASH)endif >> vercl.x] \ + && ![cl -nologo -TC -P vercl.x $(ERRNUL)] +!include vercl.i +!if ![echo VCVER= ^\> vercl.vc] \ + && ![set /a $(VCVERSION) / 100 - 6 >> vercl.vc] +!include vercl.vc +!endif +!endif +!if ![del $(ERRNUL) /q/f vercl.x vercl.i vercl.vc] +!endif + +!if $(VCVERSION) > 1499 && $(VCVERSION) < 1600 +VSVER = 9 +!elseif $(VCVERSION) > 1599 && $(VCVERSION) < 1700 +VSVER = 10 +!elseif $(VCVERSION) > 1699 && $(VCVERSION) < 1800 +VSVER = 11 +!elseif $(VCVERSION) > 1799 && $(VCVERSION) < 1900 +VSVER = 12 +!elseif $(VCVERSION) > 1899 && $(VCVERSION) < 1910 +VSVER = 14 +!elseif $(VCVERSION) > 1909 && $(VCVERSION) < 2000 +VSVER = 15 +!else +VSVER = 0 +!endif + +!if "$(VSVER)" == "0" +MSG = ^ +This NMake Makefile set supports Visual Studio^ +9 (2008) through 14 (2015). Your Visual Studio^ +version is not supported. +!error $(MSG) +!elseif $(VSVER) < 15 +PDBVER = $(VSVER) +!else +PDBVER = 14 +!endif + +VALID_CFGSET = FALSE +!if "$(CFG)" == "release" || "$(CFG)" == "debug" +VALID_CFGSET = TRUE +!endif + +# One may change these items, but be sure to test +# the resulting binaries +!if "$(CFG)" == "release" +CFLAGS_ADD = /MD /O2 /MP /GL +!if $(VSVER) > 9 && $(VSVER) < 14 +# Undocumented "enhance optimized debugging" switch. Became documented +# as "/Zo" in VS 2013 Update 3, and is turned on by default in VS 2015. +CFLAGS_ADD = $(CFLAGS_ADD) /d2Zi+ +!endif +!else +CFLAGS_ADD = /MDd /Od +!endif + +!if "$(PLAT)" == "x64" +LDFLAGS_ARCH = /machine:x64 +!elseif "$(PLAT)" == "arm" +LDFLAGS_ARCH = /machine:arm +CFLAGS_ADD = $(CFLAGS_ADD) /DWINAPI_FAMILY=3 +!else +LDFLAGS_ARCH = /machine:x86 +!endif + +!if "$(VALID_CFGSET)" == "TRUE" +CFLAGS = $(CFLAGS_ADD) /W3 /Zi + +!if "$(ADDITIONAL_LIB_DIR)" != "" +ADDITIONAL_LIB_ARG = /libpath:$(ADDITIONAL_LIB_DIR) +!endif +LDFLAGS_BASE = $(LDFLAGS_ARCH) /libpath:$(PREFIX)\lib $(ADDITIONAL_LIB_ARG) /DEBUG + +!if "$(CFG)" == "debug" +LDFLAGS = $(LDFLAGS_BASE) +ARFLAGS = $(LDFLAGS_ARCH) +!else +LDFLAGS = $(LDFLAGS_BASE) /opt:ref /LTCG +ARFLAGS = $(LDFLAGS_ARCH) /LTCG +!endif +!endif diff --git a/msvc/generate-msvc.mak b/msvc/generate-msvc.mak new file mode 100644 index 0000000..2fd7697 --- /dev/null +++ b/msvc/generate-msvc.mak @@ -0,0 +1,31 @@ +# NMake Makefile portion for code generation and +# intermediate build directory creation +# Items in here should not need to be edited unless +# one is maintaining the NMake build files. + +# Create the build directories +$(CFG)\$(PLAT)\libpsl \ +$(CFG)\$(PLAT)\psl \ +$(CFG)\$(PLAT)\tests: + @-md $@ + +$(CFG)\$(PLAT)\libpsl\suffixes_dafsa.c: $(CFG)\$(PLAT)\libpsl $(PSL_FILE) ..\src\psl-make-dafsa + @echo Generating $@ + $(PYTHON) ..\src\psl-make-dafsa --output-format=cxx+ "$(PSL_FILE_INPUT)" $@ + +$(CFG)\$(PLAT)\psl.dafsa: $(CFG)\$(PLAT)\tests + @echo Generating $@ + $(PYTHON) ..\src\psl-make-dafsa --output-format=binary "$(PSL_FILE_INPUT)" $@ + +$(CFG)\$(PLAT)\psl_ascii.dafsa: $(CFG)\$(PLAT)\tests + @echo Generating $@ + $(PYTHON) ..\src\psl-make-dafsa --output-format=binary --encoding=ascii "$(PSL_FILE_INPUT)" $@ + +libpsl.pc: ..\libpsl.pc.in + @echo Generating $@ + $(PYTHON) libpsl-pc.py --name=$(PACKAGE_NAME) \ + --version=$(PACKAGE_VERSION) --url=$(PACKAGE_URL) --prefix=$(PREFIX) + +..\config.h: config.h.win32 + @echo Generating $@ + @copy $** $@ diff --git a/msvc/install-msvc.mak b/msvc/install-msvc.mak new file mode 100644 index 0000000..7afa50e --- /dev/null +++ b/msvc/install-msvc.mak @@ -0,0 +1,14 @@ +# NMake Makefile snippet for copying the built libraries, utilities and headers to +# a path under $(PREFIX). + +install: all libpsl.pc build-info + @if not exist $(PREFIX)\bin\ mkdir $(PREFIX)\bin + @if not exist $(PREFIX)\lib\pkgconfig\ mkdir $(PREFIX)\lib\pkgconfig + @if not exist $(PREFIX)\include @mkdir $(PREFIX)\include + @copy /b $(CFG)\$(PLAT)\psl.exe $(PREFIX)\bin + @copy /b $(CFG)\$(PLAT)\psl-tool.pdb $(PREFIX)\bin + @if "$(PSL_LIBTYPE)" == "DLL" copy /b $(PSL_DLL) $(PREFIX)\bin + @if "$(PSL_LIBTYPE)" == "DLL" copy /b $(CFG)\$(PLAT)\psl.pdb $(PREFIX)\bin + @copy /b $(CFG)\$(PLAT)\psl.lib $(PREFIX)\lib + @copy libpsl.pc $(PREFIX)\lib\pkgconfig + @for %h in (..\include\*.h) do @copy %h $(PREFIX)\include\%~nxh diff --git a/msvc/libpsl-pc.py b/msvc/libpsl-pc.py new file mode 100644 index 0000000..d6f2958 --- /dev/null +++ b/msvc/libpsl-pc.py @@ -0,0 +1,32 @@ +# !/usr/env/python +# Simple script to generate libpsl.pc from libpsl.pc.in +# for Visual Studio builds + +import sys +import argparse + +from replace import replace_multi +from pc_base import BasePCItems + +def main(argv): + parser = argparse.ArgumentParser(description='Setup basic libpsl.pc file info') + parser.add_argument('--name', help='Name of package', required=True) + parser.add_argument('--url', help='Package Home Page URL', required=True) + + base_pc = BasePCItems() + base_pc.setup(argv, parser) + args = parser.parse_args() + + pc_replace_items = {'@PACKAGE_NAME@': args.name, + '@PACKAGE_VERSION@': args.version, + '@PACKAGE_URL@': args.url} + + pc_replace_items.update(base_pc.base_replace_items) + + # Generate libpsl.pc + replace_multi(base_pc.top_srcdir + '/libpsl.pc.in', + base_pc.srcdir + '/libpsl.pc', + pc_replace_items) + +if __name__ == '__main__': + sys.exit(main(sys.argv)) \ No newline at end of file diff --git a/msvc/pc_base.py b/msvc/pc_base.py new file mode 100644 index 0000000..285b6cd --- /dev/null +++ b/msvc/pc_base.py @@ -0,0 +1,124 @@ +#!/usr/bin/python +# +# Simple utility script to generate the basic info +# needed in a .pc (pkg-config) file, used especially +# for introspection purposes + +# This can be used in various projects where +# there is the need to generate .pc files, +# and is copied from GLib's $(srcroot)/build/win32 + +# Author: Fan, Chun-wei +# Date: March 10, 2016 + +import os +import sys +import argparse + +class BasePCItems: + def __init__(self): + self.base_replace_items = {} + self.exec_prefix = '' + self.includedir = '' + self.libdir = '' + self.prefix = '' + self.srcdir = os.path.dirname(__file__) + self.top_srcdir = self.srcdir + '\\..' + self.version = '' + + def setup(self, argv, parser=None): + if parser is None: + parser = argparse.ArgumentParser(description='Setup basic .pc file info') + parser.add_argument('--prefix', help='prefix of the installed library', + required=True) + parser.add_argument('--exec-prefix', + help='prefix of the installed programs, \ + if different from the prefix') + parser.add_argument('--includedir', + help='includedir of the installed library, \ + if different from ${prefix}/include') + parser.add_argument('--libdir', + help='libdir of the installed library, \ + if different from ${prefix}/lib') + parser.add_argument('--version', help='Version of the package', + required=True) + args = parser.parse_args() + + self.version = args.version + + # check whether the prefix and exec_prefix are valid + if not os.path.exists(args.prefix): + raise SystemExit('Specified prefix \'%s\' is invalid' % args.prefix) + + # use absolute paths for prefix + self.prefix = os.path.abspath(args.prefix).replace('\\','/') + + # check and setup the exec_prefix + if getattr(args, 'exec_prefix', None) is None: + exec_prefix_use_shorthand = True + self.exec_prefix = '${prefix}' + else: + if args.exec_prefix.startswith('${prefix}'): + exec_prefix_use_shorthand = True + input_exec_prefix = args.prefix + args.exec_prefix[len('${prefix}'):] + else: + exec_prefix_use_shorthand = False + input_exec_prefix = args.exec_prefix + if not os.path.exists(input_exec_prefix): + raise SystemExit('Specified exec_prefix \'%s\' is invalid' % + args.exec_prefix) + if exec_prefix_use_shorthand is True: + self.exec_prefix = args.exec_prefix.replace('\\','/') + else: + self.exec_prefix = os.path.abspath(input_exec_prefix).replace('\\','/') + + # check and setup the includedir + if getattr(args, 'includedir', None) is None: + self.includedir = '${prefix}/include' + else: + if args.includedir.startswith('${prefix}'): + includedir_use_shorthand = True + input_includedir = args.prefix + args.includedir[len('${prefix}'):] + else: + if args.includedir.startswith('${exec_prefix}'): + includedir_use_shorthand = True + input_includedir = input_exec_prefix + args.includedir[len('${exec_prefix}'):] + else: + includedir_use_shorthand = False + input_includedir = args.includedir + if not os.path.exists(input_includedir): + raise SystemExit('Specified includedir \'%s\' is invalid' % + args.includedir) + if includedir_use_shorthand is True: + self.includedir = args.includedir.replace('\\','/') + else: + self.includedir = os.path.abspath(input_includedir).replace('\\','/') + + # check and setup the libdir + if getattr(args, 'libdir', None) is None: + self.libdir = '${prefix}/lib' + else: + if args.libdir.startswith('${prefix}'): + libdir_use_shorthand = True + input_libdir = args.prefix + args.libdir[len('${prefix}'):] + else: + if args.libdir.startswith('${exec_prefix}'): + libdir_use_shorthand = True + input_libdir = input_exec_prefix + args.libdir[len('${exec_prefix}'):] + else: + libdir_use_shorthand = False + input_libdir = args.libdir + if not os.path.exists(input_libdir): + raise SystemExit('Specified libdir \'%s\' is invalid' % + args.libdir) + if libdir_use_shorthand is True: + self.libdir = args.libdir.replace('\\','/') + else: + self.libdir = os.path.abspath(input_libdir).replace('\\','/') + + # setup dictionary for replacing items in *.pc.in + self.base_replace_items.update({'@VERSION@': self.version}) + self.base_replace_items.update({'@prefix@': self.prefix}) + self.base_replace_items.update({'@exec_prefix@': self.exec_prefix}) + self.base_replace_items.update({'@libdir@': self.libdir}) + self.base_replace_items.update({'@includedir@': self.includedir}) diff --git a/msvc/replace.py b/msvc/replace.py new file mode 100644 index 0000000..3aeceb1 --- /dev/null +++ b/msvc/replace.py @@ -0,0 +1,115 @@ +#!/usr/bin/python +# +# Simple utility script to manipulate +# certain types of strings in a file + +# This can be used in various projects where +# there is the need to replace strings in files, +# and is copied from GLib's $(srcroot)/win32 + +# Author: Fan, Chun-wei +# Date: September 03, 2014 + +import os +import sys +import re +import string +import argparse + +valid_actions = ['remove-prefix', + 'replace-var', + 'replace-str', + 'remove-str'] + +def open_file(filename, mode): + if sys.version_info[0] < 3: + return open(filename, mode=mode) + else: + return open(filename, mode=mode, encoding='utf-8') + +def replace_multi(src, dest, replace_items): + with open_file(src, 'r') as s: + with open_file(dest, 'w') as d: + for line in s: + replace_dict = dict((re.escape(key), value) \ + for key, value in replace_items.items()) + replace_pattern = re.compile("|".join(replace_dict.keys())) + d.write(replace_pattern.sub(lambda m: \ + replace_dict[re.escape(m.group(0))], line)) + +def replace(src, dest, instring, outstring): + replace_item = {instring: outstring} + replace_multi(src, dest, replace_item) + +def check_required_args(args, params): + for param in params: + if getattr(args, param, None) is None: + raise SystemExit('%s: error: --%s argument is required' % (__file__, param)) + +def warn_ignored_args(args, params): + for param in params: + if getattr(args, param, None) is not None: + print('%s: warning: --%s argument is ignored' % (__file__, param)) + +def main(argv): + + parser = argparse.ArgumentParser(description='Process strings in a file.') + parser.add_argument('-a', + '--action', + help='Action to carry out. Can be one of:\n' + 'remove-prefix\n' + 'replace-var\n' + 'replace-str\n' + 'remove-str', + choices=valid_actions) + parser.add_argument('-i', '--input', help='Input file') + parser.add_argument('-o', '--output', help='Output file') + parser.add_argument('--instring', help='String to replace or remove') + parser.add_argument('--var', help='Autotools variable name to replace') + parser.add_argument('--outstring', + help='New String to replace specified string or variable') + parser.add_argument('--removeprefix', help='Prefix of string to remove') + + args = parser.parse_args() + + input_string = '' + output_string = '' + + # We must have action, input, output for all operations + check_required_args(args, ['action','input','output']) + + # Build the arguments by the operation that is to be done, + # to be fed into replace() + + # Get rid of prefixes from a string + if args.action == 'remove-prefix': + check_required_args(args, ['instring','removeprefix']) + warn_ignored_args(args, ['outstring','var']) + input_string = args.removeprefix + args.instring + output_string = args.instring + + # Replace an m4-style variable (those surrounded by @...@) + if args.action == 'replace-var': + check_required_args(args, ['var','outstring']) + warn_ignored_args(args, ['instring','removeprefix']) + input_string = '@' + args.var + '@' + output_string = args.outstring + + # Replace a string + if args.action == 'replace-str': + check_required_args(args, ['instring','outstring']) + warn_ignored_args(args, ['var','removeprefix']) + input_string = args.instring + output_string = args.outstring + + # Remove a string + if args.action == 'remove-str': + check_required_args(args, ['instring']) + warn_ignored_args(args, ['var','outstring','removeprefix']) + input_string = args.instring + output_string = '' + + replace(args.input, args.output, input_string, output_string) + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/src/Makefile.am b/src/Makefile.am index 089e27e..ae8474e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,3 +1,5 @@ +include libpsl-srcs.mk + # suffixes.c must be created before psl.c is compiled BUILT_SOURCES = suffixes_dafsa.c @@ -6,7 +8,7 @@ CLEANFILES = suffixes_dafsa.c lib_LTLIBRARIES = libpsl.la -libpsl_la_SOURCES = psl.c lookup_string_in_fixed_set.c +libpsl_la_SOURCES = $(LIBPSL_SRCS) libpsl_la_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include -DPSL_DISTFILE=\"$(PSL_DISTFILE)\" \ $(CFLAG_VISIBILITY) -DBUILDING_PSL libpsl_la_LIBADD = $(LTLIBICONV) $(LTLIBINTL) @INTL_MACOSX_LIBS@ diff --git a/src/libpsl-srcs.mk b/src/libpsl-srcs.mk new file mode 100644 index 0000000..8f22123 --- /dev/null +++ b/src/libpsl-srcs.mk @@ -0,0 +1 @@ +LIBPSL_SRCS = psl.c lookup_string_in_fixed_set.c \ No newline at end of file