[Qgis-developer] Some concerns about QGIS on OS X, part 1

Mac Programmer macpgmr at fastermac.net
Sat Feb 7 20:16:59 EST 2009


Out of curiosity, has anyone actually tried the C++ examples in the  
1.0 user guide, particularly on a Mac? I'm finding them pretty rough  
sledding.

Chapter 14, C++ plugin example:

The SVN sources for this example looked pretty old (2006), so I just  
copied and pasted step 1 into .pro, .h and .cpp files, then modified  
the .pro file as best I could figure for my system. Then what? Well,  
it doesn't say. After some googling, I tried running qmake and then  
make - nothing happened. More googling. Okay, apparently qmake  
creates an Xcode project, so I opened the .xcodeproj folder in Xcode.  
 From there I was able to build the library, although it ignored  
the .pro file's DEST setting and also gave a couple of warnings.  
However, looking at the resulting .dylib with otool -L and -h showed  
that the .dylib was linked differently from the other plugin .so  
files in /lib/qgis and was not a "bundle" (filetype 8). So I decided  
to go back to basics and compile and link the plugin myself.

By the way, here's what I had tried for a .pro file:

QGIS_DIR = /Users/phil/Desktop/qgis-1.0.0/qgis1.0.0.app/Contents/MacOs
TEMPLATE = lib
CONFIG = qt
QT += xml qt3support
unix:LIBS += -L$$QGIS_DIR/Lib
INCLUDEPATH += $$QGIS_DIR/include/qgis
SOURCES = qgspointconverterplugin.cpp
HEADERS = qgspointconverterplugin.h
DEST = pointconverterplugin.so
DEFINES += GUI_EXPORT= CORE_EXPORT=


Here's what I came up with:

#!/bin/sh
# Force Bourne shell in case tcsh is default.
#

BASE=~/Desktop/qgis-1.0.0/qgis1.0.0.app/Contents/MacOs

INCLUDE1=$BASE/include/qgis
INCLUDE2=/Library/Frameworks/QtCore.framework/Headers
INCLUDE3=/Library/Frameworks/QtGui.framework/Headers
INCLUDES="-I$INCLUDE1 -I$INCLUDE2 -I$INCLUDE3"

LINK1=$BASE/Lib/libqgis_core.dylib
LINK2=$BASE/Lib/libqgis_gui.dylib
LINK3=$BASE/Lib/QtCore.framework/Versions/4/QtCore
LINK4=$BASE/Lib/QtGui.framework/Versions/4/QtGui
LINKS="$LINK1 $LINK2 $LINK3 $LINK4"

DEFINES="-D GUI_EXPORT= -D CORE_EXPORT="

XLINKER="-Xlinker -executable_path -Xlinker $BASE"
PLUGIN=pointconverterplugin

if [ -e "$INCLUDE1" ]
then
   if [ -e "$INCLUDE2" ]
   then
     moc -o moc_qgs$PLUGIN.cpp qgs$PLUGIN.h
     CMD="g++ -mmacosx-version-min=10.4 $DEFINES $INCLUDES $LINKS qgs 
$PLUGIN.cpp -o lib$PLUGIN.so -fPIC -bundle $XLINKER"
     echo executing: $CMD
     $CMD
     otool -L lib$PLUGIN.so
   else
     echo "Can't find Qt frameworks -- need to install Qt"
     echo "Did not find: $INCLUDE2"
   fi
else
   echo "Can't find QGIS -- change location of QGIS in this script"
   echo "Did not find: $INCLUDE1"
fi

This script successfully compiled both the step 1 and step 2 source  
and the resulting .so loaded fine in QGIS once placed in lib/qgis.  
Note that since the Qt header files are not included with QGIS, I had  
to use header files from a separate installation of the Qt frameworks.

Also, something that really tripped me up for a long time was the  
need to create the "moc" file. I then had to insert this in the  
qgspointconverterplugin.cpp file:

   #include "moc_qgspointconverterplugin.cpp"

However, when I tried the script with the step 3 source, I got an  
error about a missing geos_c.h file. Searching my system for this  
file didn't turn up anything, so at that point I gave up.

Question: Did the folks who wrote and compiled the C++ plugins  
included with the OS X QGIS have a chance to review Chapter 14 in the  
user guide?



Chapter 16, C++ application example:

This time I started with the SVN sources, but the compile  
instructions on page 157 are not correct. There is no "cmake" on my  
system. So back to the drawing board. This is what I came up with:

#!/bin/sh
# Force Bourne shell in case tcsh is default.
#
APP=main
QTBASE=/Library/Frameworks
FWEXT=.framework

LIB1=Core
LIB2=Gui
LIB3=Xml

QGISBASE=~/Desktop/qgis-1.0.0/qgis1.0.0.app/Contents/MacOs
BASE1=$QTBASE/Qt$LIB1$FWEXT
BASE2=$QTBASE/Qt$LIB2$FWEXT
BASE3=$QTBASE/Qt$LIB3$FWEXT

INCLUDEQG=$QGISBASE/include/qgis
INCLUDE1=$BASE1/Headers
INCLUDE2=$BASE2/Headers
INCLUDE3=$BASE3/Headers

LINKQG1=$QGISBASE/Lib/libqgis_core.dylib
LINKQG2=$QGISBASE/Lib/libqgis_gui.dylib
LINK1=$QGISBASE/Lib/Qt$LIB1$FWEXT/Versions/4/Qt$LIB1
LINK2=$QGISBASE/Lib/Qt$LIB2$FWEXT/Versions/4/Qt$LIB2

DEFINES="-D GUI_EXPORT= -D CORE_EXPORT="

INCLUDES="-I. -I$INCLUDEQG -I$INCLUDE1 -I$INCLUDE2 -I$INCLUDE3"
LINKS="$LINKQG1 $LINKQG2 $LINK1 $LINK2"
XLINKER="-Xlinker -executable_path -Xlinker $QGISBASE"

if [ -e "$LINKQG1" ]
then
   CMD="g++ -mmacosx-version-min=10.4 $DEFINES $INCLUDES $LINKS  
main.cpp -o $APP $XLINKER"
   echo executing: $CMD
   $CMD
   otool -L $APP
else
# QGIS not in expected location or different version.
   echo "Can't find QGIS -- check location of QGIS in this script"
   echo "Did not find: $LINKQG1"
fi


The resulting compiled executable does work, but only if you create  
an app bundle for it and copy the QGIS libraries and Qt frameworks  
from the qgis1.0.0.app bundle, thus duplicating them on your system.

It seems like the C++ instructions in the user guide present good  
examples of the directions-to-the-wedding-reception paradox, where  
the directions only make sense to a local, who does not need them  
since he already knows the area. Same with these examples: anyone who  
can successfully compile them in short order probably doesn't need  
the instructions, whereas those who struggle need much more than what  
is in the user guide.

Thanks.

-Phil





More information about the Qgis-developer mailing list