epics-base / pvDataCPP

pvDataCPP is an EPICS V4 C++ module
https://epics-base.github.io/pvDataCPP/
Other
6 stars 16 forks source link

Problem building pvDataCPP for win32-x86-mingw #42

Closed anjohnson closed 8 years ago

anjohnson commented 8 years ago

I recently introduced Mark Rivers to the wonders of the MinGW compiler tool-set, which permits cross-building of Windows binaries using gcc on a Linux host (it also has a native copy of gcc that runs on Windows so it can be used either way). He has now started using this target, and reported the following build issue to core-talk this morning:

I get the following error building pvData on win32-x86-mingw.

Cross-compiler running on Linux. Base 3.15.4 Version of pvData checked out by Andrew's pvPackage: git clone --recursive git@github.com:anjohnson/pvPackageCPP.git

make[2]: Entering directory `/usr/local/epics/pvPackageCPP-3.15/pvData/src/O.win32-x86-mingw'
/usr/bin/i686-pc-mingw32-g++              -D_MINGW     -O3   -Wall       -m32   -DEPICS_BUILD_DLL -DEPICS_CALL_DLL   -I. -I../O.Common -I. -I. -I.. -I../../src/misc -I../../src/pv -I../../src/factory -I../../src/property -I../../src/copy -I../../src/pvMisc -I../../src/monitor -I../../include/compiler/gcc -I../../include/os/WIN32 -I../../include    -I/corvette/usr/local/epics/base-3.15.4/include/compiler/gcc -I/corvette/usr/local/epics/base-3.15.4/include/os/WIN32 -I/corvette/usr/local/epics/base-3.15.4/include   -I/corvette/usr/local/epics/pvPackageCPP-3.15/pvDatabase/include   -I/corvette/usr/local/epics/pvPackageCPP-3.15/pvaSrv/include   -I/corvette/usr/local/epics/pvPackageCPP-3.15/pvaClient/include   -I/corvette/usr/local/epics/pvPackageCPP-3.15/pvAccess/include   -I/corvette/usr/local/epics/pvPackageCPP-3.15/normativeTypes/include   -I/corvette/usr/local/epics/pvPackageCPP-3.15/pvData/include   -I/corvette/usr/local/epics/pvPackageCPP-3.15/pvCommon/include        -o pvCopy.obj -c ../../src/copy/pvCopy.cpp
../pv/pvData.h: In member function 'epics::pvData::StructureConstPtr epics::pvData::PVCopy::createStructure(const epics::pvData::PVStructurePtr&, const epics::pvData::PVStructurePtr&)':
../pv/pvData.h:705:29: sorry, unimplemented: inlining failed in call to 'epics::pvData::PVFieldPtr epics::pvData::PVStructure::getSubField(const std::string&) const': function not inlinable
../../src/copy/pvCopy.cpp:401:67: sorry, unimplemented: called from here
make[2]: *** [pvCopy.obj] Error 1
make[2]: Leaving directory `/usr/local/epics/pvPackageCPP-3.15/pvData/src/O.win32-x86-mingw'
make[1]: *** [install.win32-x86-mingw] Error 2
make[1]: Leaving directory `/usr/local/epics/pvPackageCPP-3.15/pvData/src'
make: *** [src.install] Error 2
anjohnson commented 8 years ago

A comment on the MinGW tool-set: This uses gcc as the compiler, but defines _WIN32 since that macro indicates the OS interface, not the compiler. The issue may be related to some code looking at the wrong macro and assuming that _WIN32 means that the compiler is MS Visual Studio; I haven't actually checked pvData.h to see.

mdavidsaver commented 8 years ago

What GCC/mingw version?

On Aug 29, 2016 12:28 PM, "Andrew Johnson" notifications@github.com wrote:

I recently introduced Mark Rivers to the wonders of the MinGW compiler tool-set, which permits cross-building of Windows binaries using gcc on a Linux host (it also has a native copy of gcc that runs on Windows so it can be used either way). He has now started using this target, and reported the following build issue to core-talk this morning:

I get the following error building pvData on win32-x86-mingw.

Cross-compiler running on Linux. Base 3.15.4 Version of pvData checked out by Andrew's pvPackage: git clone --recursive git@github.com:anjohnson/pvPackageCPP.git

make[2]: Entering directory /usr/local/epics/pvPackageCPP-3.15/pvData/src/O.win32-x86-mingw' /usr/bin/i686-pc-mingw32-g++ -D_MINGW -O3 -Wall -m32 -DEPICS_BUILD_DLL -DEPICS_CALL_DLL -I. -I../O.Common -I. -I. -I.. -I../../src/misc -I../../src/pv -I../../src/factory -I../../src/property -I../../src/copy -I../../src/pvMisc -I../../src/monitor -I../../include/compiler/gcc -I../../include/os/WIN32 -I../../include -I/corvette/usr/local/epics/base-3.15.4/include/compiler/gcc -I/corvette/usr/local/epics/base-3.15.4/include/os/WIN32 -I/corvette/usr/local/epics/base-3.15.4/include -I/corvette/usr/local/epics/pvPackageCPP-3.15/pvDatabase/include -I/corvette/usr/local/epics/pvPackageCPP-3.15/pvaSrv/include -I/corvette/usr/local/epics/pvPackageCPP-3.15/pvaClient/include -I/corvette/usr/local/epics/pvPackageCPP-3.15/pvAccess/include -I/corvette/usr/local/epics/pvPackageCPP-3.15/normativeTypes/include -I/corvette/usr/local/epics/pvPackageCPP-3.15/pvData/include -I/corvette/usr/local/epics/pvPackageCPP-3.15/pvCommon/include -o pvCopy.obj -c ../../src/copy/pvCopy.cpp ../pv/pvData.h: In member function 'epics::pvData::StructureConstPtr epics::pvData::PVCopy::createStructure(const epics::pvData::PVStructurePtr&, const epics::pvData::PVStructurePtr&)': ../pv/pvData.h:705:29: sorry, unimplemented: inlining failed in call to 'epics::pvData::PVFieldPtr epics::pvData::PVStructure::getSubField(const std::string&) const': function not inlinable ../../src/copy/pvCopy.cpp:401:67: sorry, unimplemented: called from here make[2]: *** [pvCopy.obj] Error 1 make[2]: Leaving directory/usr/local/epics/pvPackageCPP-3.15/pvData/src/O.win32-x86-mingw' make[1]: * [install.win32-x86-mingw] Error 2 make[1]: Leaving directory `/usr/local/epics/pvPackageCPP-3.15/pvData/src' make: * [src.install] Error 2

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/epics-base/pvDataCPP/issues/42, or mute the thread https://github.com/notifications/unsubscribe-auth/AEOVn2Fiyp03nVK51bevtkAeznKeM-WKks5qkwibgaJpZM4Jvpg1 .

MarkRivers commented 8 years ago

i686-pc-mingw32-gcc (GCC) 4.5.3 20110428 (Fedora MinGW 4.5.3-1.fc15)

MarkRivers commented 8 years ago

What is the minimum version of GCC required by EPICS V4?

mdavidsaver commented 8 years ago

I'd expect 4.5 to work, but mingw building DLLs was a bit of a special case until recently. Can you try a buiild w/ static linking? gcc/mingw 4.9.1 (debian 8) builds for me w/o DLLs.

MarkRivers commented 8 years ago

I have created a new architecture in my 3.15.4 base/configure/os, win32-x86-mingw-static so that I can easily build both statically and dynamically.

Indeed the static build of pvData succeeds, while the dynamic build fails.

This is the static build. It has some warnings but no errors:

corvette:epics/pvPackageCPP-3.15/pvData>make -sj clean.win32-x86-mingw-static
corvette:epics/pvPackageCPP-3.15/pvData>make -sj install.win32-x86-mingw-static
../../src/factory/FieldCreateFactory.cpp: In member function 'virtual std::string epics::pvData::BoundedScalarArray::getID() const':
../../src/factory/FieldCreateFactory.cpp:294:76: warning: unknown conversion type character 'z' in format
../../src/factory/FieldCreateFactory.cpp:294:76: warning: too many arguments for format
../../src/factory/FieldCreateFactory.cpp: In member function 'virtual std::string epics::pvData::FixedScalarArray::getID() const':
../../src/factory/FieldCreateFactory.cpp:316:76: warning: unknown conversion type character 'z' in format
../../src/factory/FieldCreateFactory.cpp:316:76: warning: too many arguments for format
../../testApp/pv/testPVType.cpp: In function 'int main(int, char**)':
../../testApp/pv/testPVType.cpp:61:46: warning: unknown conversion type character 'l' in format
../../testApp/pv/testPVType.cpp:61:46: warning: too many arguments for format
../../testApp/pv/testPVType.cpp:64:44: warning: unknown conversion type character 'l' in format
../../testApp/pv/testPVType.cpp:64:44: warning: too many arguments for format
../../testApp/misc/testTimeStamp.cpp: In function 'void testTimeStampInternal()':
../../testApp/misc/testTimeStamp.cpp:39:45: warning: unknown conversion type character 'l' in format
../../testApp/misc/testTimeStamp.cpp:39:45: warning: format '%i' expects type 'int', but argument 2 has type 'epics::pvData::int64'
../../testApp/misc/testTimeStamp.cpp:39:45: warning: unknown conversion type character 'l' in format
../../testApp/misc/testTimeStamp.cpp:39:45: warning: too many arguments for format
../../testApp/misc/testTimeStamp.cpp:55:45: warning: unknown conversion type character 'l' in format
../../testApp/misc/testTimeStamp.cpp:55:45: warning: format '%i' expects type 'int', but argument 2 has type 'epics::pvData::int64'
../../testApp/misc/testTimeStamp.cpp:55:45: warning: unknown conversion type character 'l' in format
../../testApp/misc/testTimeStamp.cpp:55:45: warning: too many arguments for format    

This is the dynamic build:

corvette:epics/pvPackageCPP-3.15/pvData>make -sj clean.win32-x86-mingw
corvette:epics/pvPackageCPP-3.15/pvData>make -sj install.win32-x86-mingw
../../src/factory/FieldCreateFactory.cpp: In member function 'virtual std::string epics::pvData::BoundedScalarArray::getID() const':
../../src/factory/FieldCreateFactory.cpp:294:76: warning: unknown conversion type character 'z' in format
../../src/factory/FieldCreateFactory.cpp:294:76: warning: too many arguments for format
../../src/factory/FieldCreateFactory.cpp: In member function 'virtual std::string epics::pvData::FixedScalarArray::getID() const':
../../src/factory/FieldCreateFactory.cpp:316:76: warning: unknown conversion type character 'z' in format
../../src/factory/FieldCreateFactory.cpp:316:76: warning: too many arguments for format
../pv/pvData.h: In member function 'epics::pvData::StructureConstPtr epics::pvData::PVCopy::createStructure(const epics::pvData::PVStructurePtr&, const epics::pvData::PVStructurePtr&)':
../pv/pvData.h:705:29: sorry, unimplemented: inlining failed in call to 'epics::pvData::PVFieldPtr epics::pvData::PVStructure::getSubField(const std::string&) const': function not inlinable
../../src/copy/pvCopy.cpp:401:67: sorry, unimplemented: called from here
make[2]: *** [pvCopy.obj] Error 1
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [install.win32-x86-mingw] Error 2
make: *** [src.install.win32-x86-mingw] Error 2
mdavidsaver commented 8 years ago

Did a quick grep through the gcc source. "inlining failed in call to" means that __attribute__((always_inline)) is used in a place where it can't be honored. The reason "function not inlinable" is however less clear as this is a binary flag which is set in many places.

Best guess, this is some issue with having getSubField() and getSubField<T>() as distinct functions. One is out-of-line and the other is always inline. I believe the MS compiler warns about this, and I've wondered if this would result in some name mangling ambiguity.

@MarkRivers In src/misc/pv/templateMeta.h as a workaround, you can change the logic around the definition of FORCE_INLINE so that the always_inline isn't used for mingw w/ DLL. This should at least avoid the explicit error. I haven't tried this, so it might just result in some mysterious linker error (mingw w/ DLLs is good at this).

MarkRivers commented 8 years ago

@mdavidsaver suggestion worked. Here is my change

corvette:epics/pvPackageCPP-3.15/pvData>git diff
diff --git a/src/misc/pv/templateMeta.h b/src/misc/pv/templateMeta.h
index cd82f48..6c12c5f 100644
--- a/src/misc/pv/templateMeta.h 
+++ b/src/misc/pv/templateMeta.h
@@ -11,7 +11,9 @@
 // gently nudge the compiler to inline our wrappers
 // Warning: Only use this when the template body is *small*.
 //          You have been warned!
-#if defined(__GNUC__) && __GNUC__>=3
+#if defined(__MINGW32__) 
+# define FORCE_INLINE inline
+#elif defined(__GNUC__) && __GNUC__>=3
 # define FORCE_INLINE __attribute__((always_inline)) inline
 #elif defined(_MSC_VER)
 # define FORCE_INLINE __forceinline

With this change pvData and all of EPICS V4 cross-compiles OK both statically and dynamically for me.

anjohnson commented 8 years ago

The macro __MINGW32__ that Mark is using above will not be present on 64-bit MinGW builds, and according to this page it doesn't look like there is a single macro suitable for both 32- and 64-bit MinGW builds. I suggest we use the _MINGW macro that the EPICS build system defines for all MinGW builds instead.

Mark also suggested that this fix should only be done when compiling dynamically; I agree, but the macros that the build system defines for signalling that are different between the 3.14 and 3.15 build rules, so please check both.

A fix for this issue should be included in the final V4.6.0 release if possible. I'm assigning the issue to @dhickin as the pvDataCPP module owner, but @mdavidsaver may want to develop the fix.

MarkRivers commented 8 years ago

Several sites I found say that -MINGW32 is defined even for 64-bit builds. http://mingw.5.n7.nabble.com/Macros-MINGW32-AND-MINGW64-td26319.html

However using _MINGW is probably better since it is clearer and under our control.

mdavidsaver commented 8 years ago

On 08/31/2016 02:34 PM, Andrew Johnson wrote:

The macro |MINGW32| that Mark is using above will not be present on 64-bit MinGW builds, and according to this page https://sourceforge.net/p/predef/wiki/Compilers/ it doesn't look like there is a single macro suitable for both 32- and 64-bit MinGW builds.

By my reading this table does say MINGW32 is defined for all three variants. A quick test shows that this is the case for mingw 4.9.1.

$ touch empty.c
$ x86_64-w64-mingw32-cpp -dM empty.c |grep MINGW
#define __MINGW32__ 1
#define __MINGW64__ 1
$ x86_64-w64-mingw32-cpp --version
x86_64-w64-mingw32-cpp (GCC) 4.9.1
mdavidsaver commented 8 years ago

For completeness

$ i686-w64-mingw32-cpp -dM empty.c |grep MINGW
#define __MINGW32__ 1