Skip to content

Commit

Permalink
GooString: only export non-inline methods for MSVC builds, not the wh…
Browse files Browse the repository at this point in the history
…ole class

As noted in the comment of the patch, exporting the whole class causes
duplicated symbols to be exported, and other link issues as can be seen
in downstream GDAL project: OSGeo/gdal#5513.

The issue specifically appears on Windows Conda Poppler builds, that
build thee 'poppler' library as a shared one (cf
https://github.com/conda-forge/poppler-feedstock/blob/127ae45699e7442aee3be4b55f5d1e37fc166658/recipe/exportsymbols.patch#L10)

This patch (actually a slightly modified version that applies on top of
Popppler master) has been submitted to upstream Poppler project per:
https://gitlab.freedesktop.org/poppler/poppler/-/merge_requests/1134
  • Loading branch information
rouault committed Mar 25, 2022
1 parent 127ae45 commit 3b94b8e
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 0 deletions.
90 changes: 90 additions & 0 deletions recipe/goostring_22_01.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
diff --git a/goo/GooString.h b/goo/GooString.h
index aa68635c..01a2a7c3 100644
--- a/goo/GooString.h
+++ b/goo/GooString.h
@@ -49,7 +49,25 @@
# define GOOSTRING_FORMAT
#endif

-class POPPLER_PRIVATE_EXPORT GooString : private std::string
+
+// VC++ implicitly applies __declspec(dllexport) to template base classes
+// of classes marked with __declspec(dllexport).
+// Hence, if marked with POPPLER_PRIVATE_EXPORT, VC++ would export symbols for the specialization
+// of std::basic_string<char>, since it is a base class of GooString.
+// As a result, if an application linked both poppler and a static library that
+// (implicitly) instantiates std::string (almost all do!), then the linker would
+// emit an error concerning duplicate symbols for std::string.
+// The least intrusive solution is to not mark the whole class with
+// __declspec(dllexport) for VC++, but only its non-inline methods.
+#ifdef _MSC_VER
+#define POPPLER_PRIVATE_EXPORT_CLASS
+#define POPPLER_PRIVATE_EXPORT_METHOD POPPLER_PRIVATE_EXPORT
+#else
+#define POPPLER_PRIVATE_EXPORT_CLASS POPPLER_PRIVATE_EXPORT
+#define POPPLER_PRIVATE_EXPORT_METHOD
+#endif
+
+class POPPLER_PRIVATE_EXPORT_CLASS GooString : private std::string
{
public:
// Create an empty string.
@@ -138,8 +156,8 @@ public:
// t -- GooString *
// w -- blank space; arg determines width
// To get literal curly braces, use {{ or }}.
- static GooString *format(const char *fmt, ...) GOOSTRING_FORMAT;
- static GooString *formatv(const char *fmt, va_list argList);
+ POPPLER_PRIVATE_EXPORT_METHOD static GooString *format(const char *fmt, ...) GOOSTRING_FORMAT;
+ POPPLER_PRIVATE_EXPORT_METHOD static GooString *formatv(const char *fmt, va_list argList);

// Get length.
int getLength() const { return size(); }
@@ -188,8 +206,8 @@ public:
}

// Append a formatted string.
- GooString *appendf(const char *fmt, ...) GOOSTRING_FORMAT;
- GooString *appendfv(const char *fmt, va_list argList);
+ POPPLER_PRIVATE_EXPORT_METHOD GooString *appendf(const char *fmt, ...) GOOSTRING_FORMAT;
+ POPPLER_PRIVATE_EXPORT_METHOD GooString *appendfv(const char *fmt, va_list argList);

// Insert a character or string.
GooString *insert(int i, char c)
@@ -221,7 +239,7 @@ public:
}

// Convert string to all-lower case.
- GooString *lowerCase();
+ POPPLER_PRIVATE_EXPORT_METHOD GooString *lowerCase();

// Compare two strings: -1:< 0:= +1:>
int cmp(const GooString *str) const { return compare(*str); }
@@ -231,9 +249,9 @@ public:
int cmpN(const char *sA, int n) const { return compare(0, n, sA); }

// Return true if strings starts with prefix
- bool startsWith(const char *prefix) const;
+ POPPLER_PRIVATE_EXPORT_METHOD bool startsWith(const char *prefix) const;
// Return true if string ends with suffix
- bool endsWith(const char *suffix) const;
+ POPPLER_PRIVATE_EXPORT_METHOD bool endsWith(const char *suffix) const;

bool hasUnicodeMarker() const { return hasUnicodeMarker(*this); }
static bool hasUnicodeMarker(const std::string &s) { return s.size() >= 2 && s[0] == '\xfe' && s[1] == '\xff'; }
@@ -241,13 +259,13 @@ public:
static bool hasUnicodeMarkerLE(const std::string &s) { return s.size() >= 2 && s[0] == '\xff' && s[1] == '\xfe'; }
bool hasJustUnicodeMarker() const { return size() == 2 && hasUnicodeMarker(); }

- void prependUnicodeMarker();
+ POPPLER_PRIVATE_EXPORT_METHOD void prependUnicodeMarker();

// Sanitizes the string so that it does
// not contain any ( ) < > [ ] { } / %
// The postscript mode also has some more strict checks
// The caller owns the return value
- GooString *sanitizedName(bool psmode) const;
+ POPPLER_PRIVATE_EXPORT_METHOD GooString *sanitizedName(bool psmode) const;
};

#endif
3 changes: 3 additions & 0 deletions recipe/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ source:
# https://github.com/conda-forge/libtiff-feedstock/pull/51
- disable-libtiff-win32-io.patch # [win]
- includesystembeforejpeg.patch # [win]
# Poppler GooString.h extends std::string and exports the class, which
# cause duplicated symbols and build errors in downstream projects like GDAL
- goostring_22_01.patch # [win]

build:
number: 1
Expand Down

0 comments on commit 3b94b8e

Please sign in to comment.