Skip to content

Commit

Permalink
windows: integrate visibility attributes without conflicts
Browse files Browse the repository at this point in the history
When using a DLL in Windows, the function declarations (and definitions)
that are public are decorated with attributes but those declarations would
conflict with the ones that are selected when the compiler supports the
visibility feature.

Define instead a new macro that would be added to the corresponding
macros independently and while at it allow setting visibility with cmake.
  • Loading branch information
carenas committed May 15, 2023
1 parent 04fbb65 commit 4b3539d
Show file tree
Hide file tree
Showing 14 changed files with 90 additions and 123 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,19 @@ missing
pcre2-config
pcre2_dftables
pcre2_jit_test
pcre2_jit_test.exe
pcre2_jit_test.log
pcre2_jit_test.trs
pcre2posix_test
pcre2posix_test.exe
pcre2posix_test.log
pcre2posix_test.trs
pcre2demo
pcre2fuzzcheck
pcre2grep
pcre2grep.exe
pcre2test
pcre2test.exe
test-driver
test-suite.log
test3input
Expand Down
33 changes: 24 additions & 9 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,15 @@
# 2022-12-10 PH added support for pcre2posix_test
# 2023-01-15 Carlo added C99 as the minimum required

# Increased minimum to 2.8.5 to support GNUInstallDirs.
# Increased minimum to 3.1 to support imported targets.
CMAKE_MINIMUM_REQUIRED(VERSION 3.1)
# Increased minimum to 3.3 to support visibility.
CMAKE_MINIMUM_REQUIRED(VERSION 3.3)
PROJECT(PCRE2 C)
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED TRUE)

set(CMAKE_C_VISIBILITY_PRESET hidden)
cmake_policy(SET CMP0063 NEW)

# Set policy CMP0026 to avoid warnings for the use of LOCATION in
# GET_TARGET_PROPERTY. This should no longer be required.
# CMAKE_POLICY(SET CMP0026 OLD)
Expand Down Expand Up @@ -156,7 +158,7 @@ CHECK_SYMBOL_EXISTS(strerror "string.h" HAVE_STRERROR)
CHECK_C_SOURCE_COMPILES(
"#include <stdlib.h>
#include <limits.h>
int main(int c, char *v[]) { char buf[PATH_MAX]; realpath(v[1], buf); return 0; }"
int main(int c, char *v[]) { char buf[PATH_MAX]; realpath(v[c], buf); return 0; }"
HAVE_REALPATH
)

Expand All @@ -165,14 +167,28 @@ set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror")

CHECK_C_SOURCE_COMPILES(
"#include <stddef.h>
int main() { int a,b; size_t m; __builtin_mul_overflow(a,b,&m); return 0; }"
int main(void) { int a,b; size_t m; __builtin_mul_overflow(a,b,&m); return 0; }"
HAVE_BUILTIN_MUL_OVERFLOW
)

CHECK_C_SOURCE_COMPILES(
"int main() { char buf[128] __attribute__((uninitialized)); (void)buf; return 0; }"
"int main(void) { char buf[128] __attribute__((uninitialized)); (void)buf; return 0; }"
HAVE_ATTRIBUTE_UNINITIALIZED
)

CHECK_C_SOURCE_COMPILES([=[
extern __attribute__ ((visibility ("default"))) int f(void);
int main(void) { return f(); }
int f(void) { return 42; }
]=] HAVE_VISIBILITY
)

if (HAVE_VISIBILITY)
set(PCRE2_EXPORT [=[__attribute__ ((visibility ("default")))]=])
else()
set(PCRE2_EXPORT)
endif()

set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})

# Check whether Intel CET is enabled, and if so, adjust compiler flags. This
Expand All @@ -191,8 +207,6 @@ IF (INTEL_CET_ENABLED)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mshstk")
ENDIF(INTEL_CET_ENABLED)



# User-configurable options
#
# Note: CMakeSetup displays these in alphabetical order, regardless of
Expand Down Expand Up @@ -729,7 +743,6 @@ IF(PCRE2_BUILD_PCRE2_8)
VERSION ${LIBPCRE2_POSIX_VERSION}
SOVERSION ${LIBPCRE2_POSIX_SOVERSION})
TARGET_LINK_LIBRARIES(pcre2-posix-static pcre2-8-static)
TARGET_COMPILE_DEFINITIONS(pcre2-posix-static PUBLIC PCRE2_STATIC)
TARGET_INCLUDE_DIRECTORIES(pcre2-posix-static PUBLIC ${PROJECT_BINARY_DIR})
SET(targets ${targets} pcre2-posix-static)

Expand Down Expand Up @@ -759,6 +772,7 @@ IF(PCRE2_BUILD_PCRE2_8)
TARGET_LINK_LIBRARIES(pcre2-8-shared Threads::Threads)
ENDIF(REQUIRE_PTHREAD)
SET(targets ${targets} pcre2-8-shared)

ADD_LIBRARY(pcre2-posix-shared SHARED ${PCRE2POSIX_HEADERS} ${PCRE2POSIX_SOURCES})
TARGET_INCLUDE_DIRECTORIES(pcre2-posix-shared PUBLIC ${PROJECT_BINARY_DIR})
SET_TARGET_PROPERTIES(pcre2-posix-shared PROPERTIES
Expand All @@ -768,6 +782,7 @@ IF(PCRE2_BUILD_PCRE2_8)
VERSION ${LIBPCRE2_POSIX_VERSION}
SOVERSION ${LIBPCRE2_POSIX_SOVERSION}
OUTPUT_NAME pcre2-posix)
TARGET_COMPILE_DEFINITIONS(pcre2-posix-shared PUBLIC PCRE2POSIX_SHARED)
TARGET_LINK_LIBRARIES(pcre2-posix-shared pcre2-8-shared)
SET(targets ${targets} pcre2-posix-shared)
SET(dll_pdb_files ${PROJECT_BINARY_DIR}/pcre2-8.pdb ${dll_pdb_files})
Expand Down
9 changes: 4 additions & 5 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ src/pcre2.h.generic: src/pcre2.h.in configure.ac
# resulting config.h is munged by perl to put #ifdefs round any #defines for
# macros with values, and to #undef all boolean macros such as HAVE_xxx and
# SUPPORT_xxx. We also get rid of any gcc-specific visibility settings. Make
# sure that PCRE2_EXP_DEFN is unset (in case it has visibility settings).
# sure that PCRE2_EXP_DEFN is unset.

src/config.h.generic: configure.ac
rm -rf $@ _generic
Expand All @@ -305,8 +305,7 @@ src/config.h.generic: configure.ac
perl -n \
-e 'BEGIN{$$blank=0;}' \
-e 'if(/PCRE2_EXP_DEFN/){print"/* #undef PCRE2_EXP_DEFN */\n";$$blank=0;next;}' \
-e 'if(/to make a symbol visible/){next;}' \
-e 'if(/__attribute__ \(\(visibility/){next;}' \
-e 'if(/(.+?)\s*__attribute__ \(\(visibility/){print "$$1\n";next;}' \
-e 'if(/LT_OBJDIR/){print"/* This is ignored unless you are using libtool. */\n";}' \
-e 'if(/^#define\s((?:HAVE|SUPPORT|STDC)_\w+)/){print"/* #undef $$1 */\n";$$blank=0;next;}' \
-e 'if(/^#define\s(?!PACKAGE|VERSION)(\w+)/){print"#ifndef $$1\n$$_#endif\n";$$blank=0;next;}' \
Expand Down Expand Up @@ -518,7 +517,7 @@ if WITH_PCRE2_8
lib_LTLIBRARIES += libpcre2-posix.la
libpcre2_posix_la_SOURCES = src/pcre2posix.c
libpcre2_posix_la_CFLAGS = \
-DPCRE2_CODE_UNIT_WIDTH=8 \
-DPCRE2_CODE_UNIT_WIDTH=8 @PCRE2POSIX_CFLAG@ \
$(VISIBILITY_CFLAGS) $(AM_CFLAGS)
libpcre2_posix_la_LDFLAGS = $(EXTRA_LIBPCRE2_POSIX_LDFLAGS)
libpcre2_posix_la_LIBADD = libpcre2-8.la
Expand Down Expand Up @@ -570,7 +569,7 @@ if WITH_PCRE2_8
TESTS += pcre2posix_test
noinst_PROGRAMS += pcre2posix_test
pcre2posix_test_SOURCES = src/pcre2posix_test.c
pcre2posix_test_CFLAGS = $(AM_CFLAGS)
pcre2posix_test_CFLAGS = $(AM_CFLAGS) @PCRE2POSIX_CFLAG@
pcre2posix_test_LDADD = libpcre2-posix.la libpcre2-8.la
endif # WITH_PCRE2_8

Expand Down
3 changes: 2 additions & 1 deletion NON-AUTOTOOLS-BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,8 @@ example.
(7) If you want to build the POSIX wrapper functions (which apply only to the
8-bit library), ensure that you have the src/pcre2posix.h file and then
compile src/pcre2posix.c. Link the result (on its own) as the pcre2posix
library.
library. If targeting a DLL in Windows, make sure to include
-DPCRE2POSIX_SHARED with your compiler flags.

(8) The pcre2test program can be linked with any combination of the 8-bit,
16-bit and 32-bit libraries (depending on what you specfied in
Expand Down
2 changes: 1 addition & 1 deletion config-cmake.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#cmakedefine HAVE_BUILTIN_MUL_OVERFLOW 1
#cmakedefine HAVE_ATTRIBUTE_UNINITIALIZED 1
#cmakedefine HAVE_DIRENT_H 1
#cmakedefine HAVE_STRERROR 1
#cmakedefine HAVE_SYS_STAT_H 1
#cmakedefine HAVE_SYS_TYPES_H 1
#cmakedefine HAVE_UNISTD_H 1
Expand Down Expand Up @@ -40,6 +39,7 @@
#cmakedefine HEAP_MATCH_RECURSE 1
#cmakedefine NEVER_BACKSLASH_C 1

#define PCRE2_EXPORT @PCRE2_EXPORT@
#define LINK_SIZE @PCRE2_LINK_SIZE@
#define HEAP_LIMIT @PCRE2_HEAP_LIMIT@
#define MATCH_LIMIT @PCRE2_MATCH_LIMIT@
Expand Down
11 changes: 9 additions & 2 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,12 @@ if test "x$enable_shared" = "xno" ; then
fi
AC_SUBST(PCRE2_STATIC_CFLAG)

PCRE2POSIX_CFLAG=""
if test "x$enable_shared" = "xyes" ; then
PCRE2POSIX_CFLAG="-DPCRE2POSIX_SHARED"
fi
AC_SUBST(PCRE2POSIX_CFLAG)

# Here is where PCRE2-specific defines are handled

if test "$enable_pcre2_8" = "yes"; then
Expand Down Expand Up @@ -862,8 +868,9 @@ AH_VERBATIM([PCRE2_EXP_DEFN], [
Win32, and it needs some magic to be inserted before the definition
of a function that is exported by the library, define this macro to
contain the relevant magic. If you do not define this macro, a suitable
__declspec value is used for Windows systems; in other environments
"extern" is used for a C compiler and "extern C" for a C++ compiler.
__declspec value is used for Windows systems; in other environments
a compiler relevant "extern" is used with any "visibility" related
attributes from PCRE2_EXPORT included.
This macro apears at the start of every exported function that is part
of the external API. It does not appear on functions that are "external"
in the C sense, but which are internal to the library. */
Expand Down
9 changes: 7 additions & 2 deletions doc/pcre2posix.3
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.TH PCRE2POSIX 3 "26 April 2021" "PCRE2 10.37"
.TH PCRE2POSIX 3 "13 May 2023" "PCRE2 10.43"
.SH NAME
PCRE2 - Perl-compatible regular expressions (revised API)
.SH "SYNOPSIS"
Expand Down Expand Up @@ -44,7 +44,12 @@ can be accessed by adding \fB-lpcre2-posix\fP to the command for linking an
application. Because the POSIX functions call the native ones, it is also
necessary to add \fB-lpcre2-8\fP.
.P
Although they were not defined as protypes in \fBpcre2posix.h\fP, releases
On Windows systems, if you are linking to a DLL version of the library, it is
recommended that \fBPCRE2POSIX_SHARED\fP is defined before including the
\fBpcre2posix.h\fP header, as it will allow for a more efficient way to
invoke the functions by adding the \fB__declspec(dllimport)\fP decorator.
.P
Although they were not defined as prototypes in \fBpcre2posix.h\fP, releases
10.33 to 10.36 of the library contained functions with the POSIX names
\fBregcomp()\fP etc. These simply passed their arguments to the PCRE2
functions. These functions were provided for backwards compatibility with
Expand Down
2 changes: 1 addition & 1 deletion libpcre2-posix.pc.in
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ Name: libpcre2-posix
Description: Posix compatible interface to libpcre2-8
Version: @PACKAGE_VERSION@
Libs: -L${libdir} -lpcre2-posix@LIB_POSTFIX@
Cflags: -I${includedir} @PCRE2_STATIC_CFLAG@
Cflags: -I${includedir} @PCRE2POSIX_CFLAG@
Requires.private: libpcre2-8
7 changes: 3 additions & 4 deletions m4/pcre2_visibility.m4
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,9 @@ AC_DEFUN([PCRE2_VISIBILITY],
VISIBILITY_CFLAGS="-fvisibility=hidden"
VISIBILITY_CXXFLAGS="-fvisibility=hidden -fvisibility-inlines-hidden"
HAVE_VISIBILITY=1
AC_DEFINE(PCRE2_EXP_DECL, [extern __attribute__ ((visibility ("default")))], [to make a symbol visible])
AC_DEFINE(PCRE2_EXP_DEFN, [__attribute__ ((visibility ("default")))], [to make a symbol visible])
AC_DEFINE(PCRE2POSIX_EXP_DECL, [extern __attribute__ ((visibility ("default")))], [to make a symbol visible])
AC_DEFINE(PCRE2POSIX_EXP_DEFN, [extern __attribute__ ((visibility ("default")))], [to make a symbol visible])
AC_DEFINE(PCRE2_EXPORT, [__attribute__ ((visibility ("default")))], [to make a symbol visible])
else
AC_DEFINE(PCRE2_EXPORT, [], [to make a symbol visible])
fi
fi
AC_SUBST([VISIBILITY_CFLAGS])
Expand Down
14 changes: 9 additions & 5 deletions src/config.h.generic
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ sure both macros are undefined; an emulation function will then be used. */
#define PACKAGE_NAME "PCRE2"

/* Define to the full name and version of this package. */
#define PACKAGE_STRING "PCRE2 10.42"
#define PACKAGE_STRING "PCRE2 10.43-DEV"

/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "pcre2"
Expand All @@ -248,7 +248,7 @@ sure both macros are undefined; an emulation function will then be used. */
#define PACKAGE_URL ""

/* Define to the version of this package. */
#define PACKAGE_VERSION "10.42"
#define PACKAGE_VERSION "10.43-DEV"

/* The value of PARENS_NEST_LIMIT specifies the maximum depth of nested
parentheses (of any kind) in a pattern. This limits the amount of system
Expand Down Expand Up @@ -278,12 +278,16 @@ sure both macros are undefined; an emulation function will then be used. */
/* Define to any value to include debugging code. */
/* #undef PCRE2_DEBUG */

/* to make a symbol visible */
#define PCRE2_EXPORT

/* If you are compiling for a system other than a Unix-like system or
Win32, and it needs some magic to be inserted before the definition
of a function that is exported by the library, define this macro to
contain the relevant magic. If you do not define this macro, a suitable
__declspec value is used for Windows systems; in other environments
"extern" is used for a C compiler and "extern C" for a C++ compiler.
__declspec value is used for Windows systems; in other environments
a compiler relevant "extern" is used with any "visibility" related
attributes from PCRE2_EXPORT included.
This macro apears at the start of every exported function that is part
of the external API. It does not appear on functions that are "external"
in the C sense, but which are internal to the library. */
Expand Down Expand Up @@ -441,7 +445,7 @@ sure both macros are undefined; an emulation function will then be used. */
#endif

/* Version number of package */
#define VERSION "10.42"
#define VERSION "10.43-DEV"

/* Number of bits in a file offset, on hosts where this is settable. */
/* #undef _FILE_OFFSET_BITS */
Expand Down
13 changes: 4 additions & 9 deletions src/config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -252,25 +252,20 @@ sure both macros are undefined; an emulation function will then be used. */
allows for the buffering of "before" and "after" lines. */
#undef PCRE2GREP_MAX_BUFSIZE

/* to make a symbol visible */
#undef PCRE2POSIX_EXP_DECL

/* to make a symbol visible */
#undef PCRE2POSIX_EXP_DEFN

/* Define to any value to include debugging code. */
#undef PCRE2_DEBUG

/* to make a symbol visible */
#undef PCRE2_EXP_DECL
#undef PCRE2_EXPORT


/* If you are compiling for a system other than a Unix-like system or
Win32, and it needs some magic to be inserted before the definition
of a function that is exported by the library, define this macro to
contain the relevant magic. If you do not define this macro, a suitable
__declspec value is used for Windows systems; in other environments
"extern" is used for a C compiler and "extern C" for a C++ compiler.
__declspec value is used for Windows systems; in other environments
a compiler relevant "extern" is used with any "visibility" related
attributes from PCRE2_EXPORT included.
This macro apears at the start of every exported function that is part
of the external API. It does not appear on functions that are "external"
in the C sense, but which are internal to the library. */
Expand Down
10 changes: 3 additions & 7 deletions src/pcre2_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,17 +122,13 @@ only if it is not already set. */
# define PCRE2_EXP_DECL extern __declspec(dllexport)
# define PCRE2_EXP_DEFN __declspec(dllexport)
# else
# define PCRE2_EXP_DECL extern
# define PCRE2_EXP_DECL extern PCRE2_EXPORT
# define PCRE2_EXP_DEFN
# endif
# else
# ifdef __cplusplus
# define PCRE2_EXP_DECL extern "C"
# else
# define PCRE2_EXP_DECL extern
# endif
# define PCRE2_EXP_DECL extern PCRE2_EXPORT
# ifndef PCRE2_EXP_DEFN
# define PCRE2_EXP_DEFN PCRE2_EXP_DECL
# define PCRE2_EXP_DEFN
# endif
# endif
#endif
Expand Down
Loading

0 comments on commit 4b3539d

Please sign in to comment.