Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fail to link if compiled as shared lib + inline with MinGW #288

Closed
SpaceIm opened this issue Mar 1, 2020 · 4 comments · Fixed by #298
Closed

Fail to link if compiled as shared lib + inline with MinGW #288

SpaceIm opened this issue Mar 1, 2020 · 4 comments · Fixed by #298

Comments

@SpaceIm
Copy link
Contributor

SpaceIm commented Mar 1, 2020

With MinGW on Windows, linker reports multiple definition of symbols when geos 3.8.0 is created as a shared lib and DISABLE_GEOS_INLINE is OFF.
There is no issue with others combination (shared lib + inline off, static with inline or not).

Click to expand log
[ 99%] Linking CXX shared library ..\bin\libgeos.dll
CMakeFiles\geos.dir/objects.a(inlines.cpp.obj):inlines.cpp:(.text+0x20): multiple definition of `geos::geom::LineSegment::~LineSegment()'
CMakeFiles\geos.dir/objects.a(MinimumDiameter.cpp.obj):MinimumDiameter.cpp:(.text$_ZN4geos4geom11LineSegmentD1Ev[_ZN4geos4geom11LineSegmentD1Ev]+0x0): first defined here
CMakeFiles\geos.dir/objects.a(inlines.cpp.obj):inlines.cpp:(.text+0x30): multiple definition of `geos::noding::BasicSegmentString::getCoordinate(unsigned long long) const'
CMakeFiles\geos.dir/objects.a(EdgeNodingValidator.cpp.obj):EdgeNodingValidator.cpp:(.text$_ZNK4geos6noding18BasicSegmentString13getCoordinateEy[_ZNK4geos6noding18BasicSegmentString13getCoordinateEy]+0x0): first defined here
CMakeFiles\geos.dir/objects.a(inlines.cpp.obj):inlines.cpp:(.text+0x40): multiple definition of `geos::noding::BasicSegmentString::getCoordinates() const'
CMakeFiles\geos.dir/objects.a(EdgeNodingValidator.cpp.obj):EdgeNodingValidator.cpp:(.text$_ZNK4geos6noding18BasicSegmentString14getCoordinatesEv[_ZNK4geos6noding18BasicSegmentString14getCoordinatesEv]+0x0): first defined here
CMakeFiles\geos.dir/objects.a(inlines.cpp.obj):inlines.cpp:(.text+0x50): multiple definition of `geos::geom::LineSegment::~LineSegment()'
CMakeFiles\geos.dir/objects.a(MinimumDiameter.cpp.obj):MinimumDiameter.cpp:(.text$_ZN4geos4geom11LineSegmentD0Ev[_ZN4geos4geom11LineSegmentD0Ev]+0x0): first defined here
CMakeFiles\geos.dir/objects.a(inlines.cpp.obj):inlines.cpp:(.text+0x60): multiple definition of `geos::geom::CoordinateArraySequenceFactory::create() const'
CMakeFiles\geos.dir/objects.a(CoordinateArraySequenceFactory.cpp.obj):CoordinateArraySequenceFactory.cpp:(.text$_ZNK4geos4geom30CoordinateArraySequenceFactory6createEv[_ZNK4geos4geom30CoordinateArraySequenceFactory6createEv]+0x0): first defined here
CMakeFiles\geos.dir/objects.a(inlines.cpp.obj):inlines.cpp:(.text+0xb0): multiple definition of `geos::geom::CoordinateArraySequenceFactory::create(std::vector<geos::geom::Coordinate, std::allocator<geos::geom::Coordinate> >*, unsigned long long) const'
CMakeFiles\geos.dir/objects.a(CoordinateArraySequenceFactory.cpp.obj):CoordinateArraySequenceFactory.cpp:(.text$_ZNK4geos4geom30CoordinateArraySequenceFactory6createEPSt6vectorINS0_10CoordinateESaIS3_EEy[_ZNK4geos4geom30CoordinateArraySequenceFactory6createEPSt6vectorINS0_10CoordinateESaIS3_EEy]+0x0): first defined here
CMakeFiles\geos.dir/objects.a(inlines.cpp.obj):inlines.cpp:(.text+0x100): multiple definition of `geos::geom::CoordinateArraySequenceFactory::create(std::vector<geos::geom::Coordinate, std::allocator<geos::geom::Coordinate> >&&, unsigned long long) const'
CMakeFiles\geos.dir/objects.a(CoordinateArraySequenceFactory.cpp.obj):CoordinateArraySequenceFactory.cpp:(.text$_ZNK4geos4geom30CoordinateArraySequenceFactory6createEOSt6vectorINS0_10CoordinateESaIS3_EEy[_ZNK4geos4geom30CoordinateArraySequenceFactory6createEOSt6vectorINS0_10CoordinateESaIS3_EEy]+0x0): first defined here
CMakeFiles\geos.dir/objects.a(inlines.cpp.obj):inlines.cpp:(.text+0x150): multiple definition of `geos::geom::CoordinateArraySequenceFactory::create(unsigned long long, unsigned long long) const'
CMakeFiles\geos.dir/objects.a(CoordinateArraySequenceFactory.cpp.obj):CoordinateArraySequenceFactory.cpp:(.text$_ZNK4geos4geom30CoordinateArraySequenceFactory6createEyy[_ZNK4geos4geom30CoordinateArraySequenceFactory6createEyy]+0x0): first defined here
CMakeFiles\geos.dir/objects.a(inlines.cpp.obj):inlines.cpp:(.text+0x1a0): multiple definition of `geos::geom::CoordinateArraySequenceFactory::create(geos::geom::CoordinateSequence const&) const'
CMakeFiles\geos.dir/objects.a(CoordinateArraySequenceFactory.cpp.obj):CoordinateArraySequenceFactory.cpp:(.text$_ZNK4geos4geom30CoordinateArraySequenceFactory6createERKNS0_18CoordinateSequenceE[_ZNK4geos4geom30CoordinateArraySequenceFactory6createERKNS0_18CoordinateSequenceE]+0x0): first defined here
CMakeFiles\geos.dir/objects.a(inlines.cpp.obj):inlines.cpp:(.text+0x200): multiple definition of `geos::noding::BasicSegmentString::isClosed() const'
CMakeFiles\geos.dir/objects.a(EdgeNodingValidator.cpp.obj):EdgeNodingValidator.cpp:(.text$_ZNK4geos6noding18BasicSegmentString8isClosedEv[_ZNK4geos6noding18BasicSegmentString8isClosedEv]+0x0): first defined here
CMakeFiles\geos.dir/objects.a(inlines.cpp.obj):inlines.cpp:(.text+0x1b90): multiple definition of `geos::geom::MultiLineString::clone() const'
CMakeFiles\geos.dir/objects.a(MultiLineString.cpp.obj):MultiLineString.cpp:(.text$_ZNK4geos4geom15MultiLineString5cloneEv[_ZNK4geos4geom15MultiLineString5cloneEv]+0x0): first defined here
CMakeFiles\geos.dir/objects.a(inlines.cpp.obj):inlines.cpp:(.text+0x1c20): multiple definition of `geos::geom::MultiPolygon::clone() const'
CMakeFiles\geos.dir/objects.a(MultiPolygon.cpp.obj):MultiPolygon.cpp:(.text$_ZNK4geos4geom12MultiPolygon5cloneEv[_ZNK4geos4geom12MultiPolygon5cloneEv]+0x0): first defined here
CMakeFiles\geos.dir/objects.a(inlines.cpp.obj):inlines.cpp:(.text+0x2330): multiple definition of `geos::geomgraph::Quadrant::quadrant(double, double)'
CMakeFiles\geos.dir/objects.a(EdgeEnd.cpp.obj):EdgeEnd.cpp:(.text$_ZN4geos9geomgraph8Quadrant8quadrantEdd[_ZN4geos9geomgraph8Quadrant8quadrantEdd]+0x0): first defined here
CMakeFiles\geos.dir/objects.a(inlines.cpp.obj):inlines.cpp:(.text+0x2a50): multiple definition of `geos::geomgraph::GeometryGraph::~GeometryGraph()'
CMakeFiles\geos.dir/objects.a(PointLocator.cpp.obj):PointLocator.cpp:(.text$_ZN4geos9geomgraph13GeometryGraphD1Ev[_ZN4geos9geomgraph13GeometryGraphD1Ev]+0x0): first defined here
CMakeFiles\geos.dir/objects.a(inlines.cpp.obj):inlines.cpp:(.text+0x2af0): multiple definition of `geos::geomgraph::GeometryGraph::~GeometryGraph()'
CMakeFiles\geos.dir/objects.a(PointLocator.cpp.obj):PointLocator.cpp:(.text$_ZN4geos9geomgraph13GeometryGraphD0Ev[_ZN4geos9geomgraph13GeometryGraphD0Ev]+0x0): first defined here
CMakeFiles\geos.dir/objects.a(MCIndexNoder.cpp.obj):MCIndexNoder.cpp:(.text$_ZNK4geos6noding12MCIndexNoder18getNodedSubstringsEv[_ZNK4geos6noding12MCIndexNoder18getNodedSubstringsEv]+0x0): multiple definition of `geos::noding::MCIndexNoder::getNodedSubstrings() const'
CMakeFiles\geos.dir/objects.a(inlines.cpp.obj):inlines.cpp:(.text+0x2a40): first defined here
CMakeFiles\geos.dir/objects.a(MaximalEdgeRing.cpp.obj):MaximalEdgeRing.cpp:(.text$_ZN4geos9operation7overlay15MinimalEdgeRing11setEdgeRingEPNS_9geomgraph12DirectedEdgeEPNS3_8EdgeRingE[_ZN4geos9operation7overlay15MinimalEdgeRing11setEdgeRingEPNS_9geomgraph12DirectedEdgeEPNS3_8EdgeRingE]+0x0): multiple definition of `geos::operation::overlay::MinimalEdgeRing::setEdgeRing(geos::geomgraph::DirectedEdge*, geos::geomgraph::EdgeRing*)'
CMakeFiles\geos.dir/objects.a(inlines.cpp.obj):inlines.cpp:(.text+0x0): first defined here
CMakeFiles\geos.dir/objects.a(MaximalEdgeRing.cpp.obj):MaximalEdgeRing.cpp:(.text$_ZN4geos9operation7overlay15MinimalEdgeRing7getNextEPNS_9geomgraph12DirectedEdgeE[_ZN4geos9operation7overlay15MinimalEdgeRing7getNextEPNS_9geomgraph12DirectedEdgeE]+0x0): multiple definition of `geos::operation::overlay::MinimalEdgeRing::getNext(geos::geomgraph::DirectedEdge*)'
CMakeFiles\geos.dir/objects.a(inlines.cpp.obj):inlines.cpp:(.text+0x10): first defined here
CMakeFiles\geos.dir/objects.a(MaximalEdgeRing.cpp.obj):MaximalEdgeRing.cpp:(.text$_ZN4geos9operation7overlay15MinimalEdgeRingD1Ev[_ZN4geos9operation7overlay15MinimalEdgeRingD1Ev]+0x0): multiple definition of `geos::operation::overlay::MinimalEdgeRing::~MinimalEdgeRing()'
CMakeFiles\geos.dir/objects.a(inlines.cpp.obj):inlines.cpp:(.text+0x680): first defined here
CMakeFiles\geos.dir/objects.a(MaximalEdgeRing.cpp.obj):MaximalEdgeRing.cpp:(.text$_ZN4geos9operation7overlay15MinimalEdgeRingD0Ev[_ZN4geos9operation7overlay15MinimalEdgeRingD0Ev]+0x0): multiple definition of `geos::operation::overlay::MinimalEdgeRing::~MinimalEdgeRing()'
CMakeFiles\geos.dir/objects.a(inlines.cpp.obj):inlines.cpp:(.text+0x820): first defined here
collect2.exe: error: ld returned 1 exit status

Quick fix:

--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -224,7 +224,7 @@ add_subdirectory(src)

 if(BUILD_SHARED_LIBS)
   target_compile_definitions(geos
-    PRIVATE $<$<CXX_COMPILER_ID:MSVC>:GEOS_DLL_EXPORT>)
+    PRIVATE $<IF:$<CXX_COMPILER_ID:MSVC>,GEOS_DLL_EXPORT,DLL_EXPORT>)

   set_target_properties(geos PROPERTIES VERSION ${GEOS_VERSION})
   set_target_properties(geos PROPERTIES SOVERSION ${GEOS_VERSION})
@@ -238,7 +238,7 @@ target_link_libraries(geos_c PRIVATE geos)

 if(BUILD_SHARED_LIBS)
   target_compile_definitions(geos_c
-    PRIVATE $<$<CXX_COMPILER_ID:MSVC>:GEOS_DLL_EXPORT>)
+    PRIVATE $<IF:$<CXX_COMPILER_ID:MSVC>,GEOS_DLL_EXPORT,DLL_EXPORT>)

   set_target_properties(geos_c PROPERTIES VERSION ${CAPI_VERSION})
   if(NOT WIN32)

Therefore, inline.cpp is not compiled if MinGW + shared + inline (and we can make use of DLL_EXPORT which is not used or defined anywhere else in source code):

...
// Only do something if GEOS_INLINE is defined
// Otherwise we'll end up with duplicated symbols
#ifdef GEOS_INLINE

// If using Visual C++ with GEOS_INLINE, do not build inline.obj
// otherwise linker will complain "multiple definition" errors.
// If using MingW with GEOS_INLINE to build a DLL then MingW's gcc
// has already generated the stubs for the contents of this file.
// Hence we need to suppress it to avoid "multiple definition" errors
// during the final link phase
#if !defined(_MSC_VER) && (!defined(__MINGW32__) || defined(__MINGW32__) && !defined(GEOS_DLL_EXPORT) && !defined(DLL_EXPORT) )
...
@dbaston
Copy link
Member

dbaston commented Mar 2, 2020

@robe2 could you test this fix on your system, please?

@robe2
Copy link
Member

robe2 commented Mar 29, 2020

@dbaston okay will do and will report back

@robe2
Copy link
Member

robe2 commented Mar 29, 2020

Okay works on my mingw system. @SpaceIm can you provide this as a pull request so we can give you credit for it.

@SpaceIm
Copy link
Contributor Author

SpaceIm commented Mar 30, 2020

Sure, done ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants