Package: qgis
Version: 2.4.0-1~exp1
Severity: important
X-debbugs-cc: rossgam...@mail.dk

Ross Gammon wrote:
Hi Peter,

I am working in the Debian GIS Team and I am hoping you can help me with
a build failure on arm*:
                                            ^
(without having any detailed knowledge of the issue)

The issue is that on arm platforms with qt4 qreal is defined as float rather than double. You can safely assign between qreal and double because you can safely assign between float and double but more complex cases involving templates or pointers can give problems.

Since there is a lot of analysis in this message i'm turning this into a bug report so it doesn't get lost.
/«PKGBUILDDIR»/src/gui/qgscomposerview.cpp: In member function 'virtual
void QgsComposerView::mouseReleaseEvent(QMouseEvent*)':
/«PKGBUILDDIR»/src/gui/qgscomposerview.cpp:872:189: error: no matching
function for call to 'qMax(qreal, double)'
         newTable->setSceneRect( QRectF(
mRubberBandItem->transform().dx(), mRubberBandItem->transform().dy(),
mRubberBandItem->rect().width(), qMax( mRubberBandItem->rect().height(),
15.0 ) ) );


                                             ^
/«PKGBUILDDIR»/src/gui/qgscomposerview.cpp:872:189: note: candidate is:
In file included from /usr/include/qt4/QtCore/qnamespace.h:45:0,
                 from /usr/include/qt4/QtCore/qobjectdefs.h:45,
                 from /usr/include/qt4/QtCore/qobject.h:47,
                 from /usr/include/qt4/QtCore/qcoreapplication.h:45,
                 from /usr/include/qt4/QtGui/qapplication.h:45,
                 from /usr/include/qt4/QtGui/QApplication:1,
                 from /«PKGBUILDDIR»/src/gui/qgscomposerview.cpp:18:
/usr/include/qt4/QtCore/qglobal.h:1219:34: note: template<class T> const
T& qMax(const T&, const T&)
 Q_DECL_CONSTEXPR inline const T &qMax(const T &a, const T &b) { return
(a < b) ? b : a; }
                                  ^
/usr/include/qt4/QtCore/qglobal.h:1219:34: note:   template argument
deduction/substitution failed:
/«PKGBUILDDIR»/src/gui/qgscomposerview.cpp:872:189: note:   deduced
conflicting types for parameter 'const T' ('float' and 'double')
         newTable->setSceneRect( QRectF(
mRubberBandItem->transform().dx(), mRubberBandItem->transform().dy(),
mRubberBandItem->rect().width(), qMax( mRubberBandItem->rect().height(),
15.0 ) ) );
In this case qMax is a template. The result is it will work with arguments of any numeric type but the two arguments must be the same type. The literal 12.0 is type double. So on a platform where qreal is float qMax gets passed one float and one double and the compiler can't decide which to use for the template parameter and errors out. Easy enough to fix by casting the literal to qreal.


Unfortunately after fixing that the buidl fails later with
[ 94%] Generating analysis/sip_analysispart0.cpp, analysis/sip_analysispart1.cpp, analysis/sip_analysispart2.cpp, analysis/sip_analysispart3.cpp
cd /qgis-2.4.0/obj-arm-linux-gnueabihf/python && /usr/bin/cmake -E echo

cd /qgis-2.4.0/obj-arm-linux-gnueabihf/python && /usr/bin/cmake -E touch /qgis-2.4.0/obj-arm-linux-gnueabihf/python/analysis/sip_analysispart0.cpp /qgis-2.4.0/obj-arm-linux-gnueabihf/python/analysis/sip_analysispart1.cpp /qgis-2.4.0/obj-arm-linux-gnueabihf/python/analysis/sip_analysispart2.cpp /qgis-2.4.0/obj-arm-linux-gnueabihf/python/analysis/sip_analysispart3.cpp cd /qgis-2.4.0/obj-arm-linux-gnueabihf/python && /usr/bin/sip -w -e -x ANDROID -x HAVE_TOUCH -x MOBILITY_LOCATION -x QSETINT_CONVERSION -x QSETTYPE_CONVERSION -x VendorID -t WS_X11 -x PyQt_NoPrintRangeBug -x PyQt_qreal_double -t Qt_4_8_6 -x Py_v3 -g -o -a /qgis-2.4.0/obj-arm-linux-gnueabihf/python/qgis.analysis.api -j 4 -c /qgis-2.4.0/obj-arm-linux-gnueabihf/python/analysis -I /usr/share/sip/PyQt4 -I /qgis-2.4.0/python /qgis-2.4.0/python/analysis/analysis.sip sip: /qgis-2.4.0/python/core/composer/qgsatlascomposition.sip:165: QgsAtlasComposition::predefinedScales() unsupported function return type - provide %MethodCode and a C++ signature python/CMakeFiles/python_module_qgis__analysis.dir/build.make:305: recipe for target 'python/analysis/sip_analysispart0.cpp' failed
make[4]: *** [python/analysis/sip_analysispart0.cpp] Error 1
make[4]: Leaving directory '/qgis-2.4.0/obj-arm-linux-gnueabihf'
CMakeFiles/Makefile2:3415: recipe for target 'python/CMakeFiles/python_module_qgis__analysis.dir/all' failed make[3]: *** [python/CMakeFiles/python_module_qgis__analysis.dir/all] Error 2

I changed double to qreal in the .sip file in a couple of places and that made the file build but I wasn't sure if it was a correct fix or not. In particular I wasn't sure if there is some corresponding peice of native code that needs to be changed to match.

Then it failed with

/qgis-2.4.0/obj-arm-linux-gnueabihf/python/core/sip_corepart2.cpp:12735:67: error: no matching function for call to 'QVector<float>::QVector(const QVector<double>&)'
                sipRaiseUnknownException();
                                                                  ^
/qgis-2.4.0/obj-arm-linux-gnueabihf/python/core/sip_corepart2.cpp:12735:67: note: candidates are:
In file included from /usr/include/qt4/QtGui/qbrush.h:47:0,
                from /usr/include/qt4/QtGui/qgraphicseffect.h:49,
                from /usr/include/qt4/QtGui/QGraphicsEffect:1,
from /qgis-2.4.0/python/../src/core/composer/qgscomposereffect.h:21, from /qgis-2.4.0/python/../src/core/composer/qgscomposeritem.h:21, from /qgis-2.4.0/python/../src/core/composer/qgspaperitem.h:21,
                from /qgis-2.4.0/python/core/composer/qgspaperitem.sip:21:
/usr/include/qt4/QtCore/qvector.h:123:12: note: QVector<T>::QVector(const QVector<T>&) [with T = float] inline QVector(const QVector<T> &v) : d(v.d) { d->ref.ref(); if (!d->sharable) detach_helper(); }
           ^
/usr/include/qt4/QtCore/qvector.h:123:12: note: no known conversion for argument 1 from 'const QVector<double>' to 'const QVector<float>&' /usr/include/qt4/QtCore/qvector.h:429:1: note: QVector<T>::QVector(int, const T&) [with T = float]
QVector<T>::QVector(int asize, const T &t)
^
/usr/include/qt4/QtCore/qvector.h:429:1: note: candidate expects 2 arguments, 1 provided /usr/include/qt4/QtCore/qvector.h:411:1: note: QVector<T>::QVector(int) [with T = float]
QVector<T>::QVector(int asize)
^
/usr/include/qt4/QtCore/qvector.h:411:1: note: no known conversion for argument 1 from 'const QVector<double>' to 'int' /usr/include/qt4/QtCore/qvector.h:120:12: note: QVector<T>::QVector() [with T = float]
    inline QVector() : d(&QVectorData::shared_null) { d->ref.ref(); }
           ^
/usr/include/qt4/QtCore/qvector.h:120:12: note: candidate expects 0 arguments, 1 provided /qgis-2.4.0/obj-arm-linux-gnueabihf/python/core/sip_corepart2.cpp: In function 'PyObject* meth_QgsAtlasComposition_setPredefinedScales(PyObject*, PyObject*)': /qgis-2.4.0/obj-arm-linux-gnueabihf/python/core/sip_corepart2.cpp:12774:44: error: no matching function for call to 'QgsAtlasComposition::setPredefinedScales(const QVector<float>&)' sipReleaseType(const_cast<QVector<qreal> *>(a0),sipType_QVector_2200,a0State);
                                           ^
/qgis-2.4.0/obj-arm-linux-gnueabihf/python/core/sip_corepart2.cpp:12774:44: note: candidate is: In file included from /qgis-2.4.0/python/../src/core/composer/qgscomposition.h:34:0, from /qgis-2.4.0/python/core/composer/qgscomposition.sip:10: /qgis-2.4.0/python/../src/core/composer/qgsatlascomposition.h:194:10: note: void QgsAtlasComposition::setPredefinedScales(const QVector<double>&)
    void setPredefinedScales( const QVector<double>& scales );
         ^
/qgis-2.4.0/python/../src/core/composer/qgsatlascomposition.h:194:10: note: no known conversion for argument 1 from 'const QVector<float>' to 'const QVector<double>&' python/CMakeFiles/python_module_qgis__core.dir/build.make:330: recipe for target 'python/CMakeFiles/python_module_qgis__core.dir/core/sip_corepart2.cpp.o' failed make[4]: *** [python/CMakeFiles/python_module_qgis__core.dir/core/sip_corepart2.cpp.o] Error 1

So it seems the .sip file is used to generate native code and the types in the native code generated from the sip file not matching the types used in the native code caused a build failure.

I attempted to fix this by adding versions of the getter and setter that took a QVector<float> and performed conversions but then found that was not possible due to C++ not allowing overloading based on return type. So I decided to try outright changing the type to qreal, fortunately it looks like the API in question is totally new in 2.4 so this shouldn't break too much third party stuff. There were some knockon impacts within the qgis source but nothing massive.

My changes make the package build but I would certainly want to discuss it with upstream before applying to check that the lower precision isn't likely to be a problem (or at least not any more of a problem than it already is in other places), to check if upstream can think of any other knockon impacts the change might have and also because if upstream decides to fix it in a different way (e.g. by finding some way to make sip accept qvector<double> on arm) it could leave us ABI-incompatible with upstream.

Debdiff attatched, no intent to NMU and as I stated above I would strongly advise discussion with upstream before uploading.
diff -Nru qgis-2.4.0/debian/changelog qgis-2.4.0/debian/changelog
--- qgis-2.4.0/debian/changelog 2014-07-08 05:04:52.000000000 +0000
+++ qgis-2.4.0/debian/changelog 2014-09-04 23:49:23.000000000 +0000
@@ -1,3 +1,9 @@
+qgis (2.4.0-1~exp1+plugwash1) UNRELEASED; urgency=medium
+
+  * Experimental arm fix, do not upload without further review
+
+ -- do <not@upload.without.review>  Thu, 04 Sep 2014 23:48:11 +0000
+
 qgis (2.4.0-1~exp1) experimental; urgency=medium
 
   [ Jürgen E. Fischer ]
diff -Nru qgis-2.4.0/debian/patches/arm-qreal.patch 
qgis-2.4.0/debian/patches/arm-qreal.patch
--- qgis-2.4.0/debian/patches/arm-qreal.patch   1970-01-01 00:00:00.000000000 
+0000
+++ qgis-2.4.0/debian/patches/arm-qreal.patch   2014-09-04 23:48:02.000000000 
+0000
@@ -0,0 +1,109 @@
+Description: Fix qreal VS double issues.
+ This patch fixes qreal VS double issues
+ 
+ There are two seperate issues, the first is trivial just a typecast on
+ a const.
+
+ The second is however less-trivial and should be discussed with
+ upstream before uploading. sip doesn't seem to like the type
+ QVector<double> on platforms where qreal is float but changing
+ the type to qreal has knock-on impacts on the native code.
+
+Author: Peter Michael Green <plugw...@debian.org>
+--- qgis-2.4.0.orig/python/core/composer/qgsatlascomposition.sip
++++ qgis-2.4.0/python/core/composer/qgsatlascomposition.sip
+@@ -155,7 +155,7 @@ public:
+      * @see setPredefinedScales
+      * @see QgsComposerMap::atlasScalingMode
+     */
+-    const QVector<double>& predefinedScales() const;
++    const QVector<qreal>& predefinedScales() const;
+ 
+     /**Sets the list of predefined scales for the atlas. This is used
+      * for maps which are set to the predefined atlas scaling mode.
+@@ -163,7 +163,7 @@ public:
+      * @see predefinedScales
+      * @see QgsComposerMap::atlasScalingMode
+      */
+-    void setPredefinedScales( const QVector<double>& scales );
++    void setPredefinedScales( const QVector<qreal>& scales );
+ 
+     /** Begins the rendering. Returns true if successful, false if no 
matching atlas
+       features found.*/
+--- qgis-2.4.0.orig/src/app/composer/qgscomposer.cpp
++++ qgis-2.4.0/src/app/composer/qgscomposer.cpp
+@@ -3594,7 +3594,7 @@ void QgsComposer::loadAtlasPredefinedSca
+     return;
+   }
+   QgsAtlasComposition& atlasMap = mComposition->atlasComposition();
+-  QVector<double> pScales;
++  QVector<qreal> pScales;
+   // first look at project's scales
+   QStringList scales( QgsProject::instance()->readListEntry( "Scales", 
"/ScalesList" ) );
+   bool hasProjectScales( QgsProject::instance()->readBoolEntry( "Scales", 
"/useProjectScales" ) );
+--- qgis-2.4.0.orig/src/core/composer/qgsatlascomposition.cpp
++++ qgis-2.4.0/src/core/composer/qgsatlascomposition.cpp
+@@ -491,7 +491,7 @@ void QgsAtlasComposition::prepareMap( Qg
+       // choose one of the predefined scales
+       double newWidth = mOrigExtent.width();
+       double newHeight = mOrigExtent.height();
+-      const QVector<double>& scales = mPredefinedScales;
++      const QVector<qreal>& scales = mPredefinedScales;
+       for ( int i = 0; i < scales.size(); i++ )
+       {
+         double ratio = scales[i] / originalScale;
+@@ -747,13 +747,13 @@ bool QgsAtlasComposition::evalFeatureFil
+   return true;
+ }
+ 
+-void QgsAtlasComposition::setPredefinedScales( const QVector<double>& scales )
++void QgsAtlasComposition::setPredefinedScales( const QVector<qreal>& scales )
+ {
+   mPredefinedScales = scales;
+   // make sure the list is sorted
+   qSort( mPredefinedScales.begin(), mPredefinedScales.end() );
+ }
+ 
+ Q_NOWARN_DEPRECATED_PUSH
+ bool QgsAtlasComposition::fixedScale() const
+ {
+--- qgis-2.4.0.orig/src/core/composer/qgsatlascomposition.h
++++ qgis-2.4.0/src/core/composer/qgsatlascomposition.h
+@@ -183,7 +186,7 @@ class CORE_EXPORT QgsAtlasComposition :
+      * @see setPredefinedScales
+      * @see QgsComposerMap::atlasScalingMode
+     */
+-    const QVector<double>& predefinedScales() const { return 
mPredefinedScales; }
++    const QVector<qreal>& predefinedScales() const { return 
mPredefinedScales; }
+ 
+     /**Sets the list of predefined scales for the atlas. This is used
+      * for maps which are set to the predefined atlas scaling mode.
+@@ -191,7 +194,7 @@ class CORE_EXPORT QgsAtlasComposition :
+      * @see predefinedScales
+      * @see QgsComposerMap::atlasScalingMode
+      */
+-    void setPredefinedScales( const QVector<double>& scales );
++    void setPredefinedScales( const QVector<qreal>& scales );
+ 
+     /** Begins the rendering. Returns true if successful, false if no 
matching atlas
+       features found.*/
+@@ -320,7 +325,7 @@ class CORE_EXPORT QgsAtlasComposition :
+     void computeExtent( QgsComposerMap *map );
+ 
+     //list of predefined scales
+-    QVector<double> mPredefinedScales;
++    QVector<qreal> mPredefinedScales;
+ };
+ 
+ #endif
+--- qgis-2.4.0.orig/src/gui/qgscomposerview.cpp
++++ qgis-2.4.0/src/gui/qgscomposerview.cpp
+@@ -869,7 +869,7 @@ void QgsComposerView::mouseReleaseEvent(
+       else
+       {
+         QgsComposerAttributeTable* newTable = new QgsComposerAttributeTable( 
composition() );
+-        newTable->setSceneRect( QRectF( mRubberBandItem->transform().dx(), 
mRubberBandItem->transform().dy(), mRubberBandItem->rect().width(), qMax( 
mRubberBandItem->rect().height(), 15.0 ) ) );
++        newTable->setSceneRect( QRectF( mRubberBandItem->transform().dx(), 
mRubberBandItem->transform().dy(), mRubberBandItem->rect().width(), qMax( 
mRubberBandItem->rect().height(), (qreal)15.0 ) ) );
+         QList<const QgsComposerMap*> mapItemList = 
composition()->composerMapItems();
+         if ( mapItemList.size() > 0 )
+         {
diff -Nru qgis-2.4.0/debian/patches/series qgis-2.4.0/debian/patches/series
--- qgis-2.4.0/debian/patches/series    2014-07-08 05:04:52.000000000 +0000
+++ qgis-2.4.0/debian/patches/series    2014-09-04 23:42:42.000000000 +0000
@@ -2,3 +2,4 @@
 python-env.patch
 disable-doxygen.patch
 0001-oracle-provider-fix-closing-of-iterator-in-case-of-e.patch
+arm-qreal.patch

Reply via email to