This is a note to commemorate my hard time (about a week) with the installation of PyQt on my macbook. Thorough surfing the internet, I found many people suffered/are suffering the same trouble as I had. So I write my experience down here, hoping to give somebody a hint.

These days while doing a project of fetching online data with python, I need install the popular tool  PyQt on my MacBook. I went to the website, downloaded and tried to install it following the instructions. I thought there will be a easy process as I had under the Windows system before. However, this was the beginning of a whole bunch of troubles.

Prerequisites:

Modules: python2.7-dev, libxext-dev, qt4-dev-tools, pkg-config, etc.

SIP(4.15.2), Python(2.7.5), Qt(5.0.1) (offline version, I tried online version first, but failed), PyQt(4.10.3)

Note that Qt from 4.8.5 on, has only the 64-bit version on Mac OS. So former hints on 32-bit Qt are not applicable to my cases (actually most of former cases are of this kind).

Begin

After successfully installing above packages, I started to configure PyQt, change to the PyQt directory and type following in the terminal:

python configure.py

and success follows. Then I started to make file,

make $$ make install

but it turn out the following error:

rm -f libpyqt4.dylib
/usr/bin/clang++ -headerpad_max_install_names -arch x86_64 -single_module -dynamiclib -Xarch_x86_64 -mmacosx-version-min=10.8 -o libpyqt4.dylib pluginloader.o moc_pluginloader.o -F/opt/local/Library/Frameworks -F/opt/local/lib -L/Library/Frameworks/Python.framework/Versions/2.7/lib -lpython2.7 -F/opt/local/Library/Frameworks -F/opt/local/lib -L/opt/local/lib -framework QtScript -framework QtCore -framework QtXml -framework QtGui -framework QtDesigner
ld: warning: ignoring file /Library/Frameworks/Python.framework/Versions/2.7/lib/libpython2.7.dylib, missing required architecture x86_64 in file /Library/Frameworks/Python.framework/Versions/2.7/lib/libpython2.7.dylib (2 slices)
Undefined symbols for architecture x86_64:
"_PyDict_Next", referenced from:
PyCustomWidgets::PyCustomWidgets(QObject*) in pluginloader.o
"_PyErr_Print", referenced from:
PyCustomWidgets::PyCustomWidgets(QObject*) in pluginloader.o
PyCustomWidgets::getModuleAttr(char const*, char const*) in pluginloader.o
"_PyImport_ImportModule", referenced from:
PyCustomWidgets::PyCustomWidgets(QObject*) in pluginloader.o
PyCustomWidgets::getModuleAttr(char const*, char const*) in pluginloader.o
"_PyList_Append", referenced from:
PyCustomWidgets::PyCustomWidgets(QObject*) in pluginloader.o
"_PyLong_AsVoidPtr", referenced from:
PyCustomWidgets::PyCustomWidgets(QObject*) in pluginloader.o
"_PyModule_GetDict", referenced from:
PyCustomWidgets::PyCustomWidgets(QObject*) in pluginloader.o
"_PyObject_CallFunctionObjArgs", referenced from:
PyCustomWidgets::PyCustomWidgets(QObject*) in pluginloader.o
"_PyObject_CallObject", referenced from:
PyCustomWidgets::PyCustomWidgets(QObject*) in pluginloader.o
"_PyObject_GetAttrString", referenced from:
PyCustomWidgets::PyCustomWidgets(QObject*) in pluginloader.o
PyCustomWidgets::getModuleAttr(char const*, char const*) in pluginloader.o
"_PyString_FromString", referenced from:
PyCustomWidgets::PyCustomWidgets(QObject*) in pluginloader.o
"_PyType_IsSubtype", referenced from:
PyCustomWidgets::PyCustomWidgets(QObject*) in pluginloader.o
"_Py_Initialize", referenced from:
PyCustomWidgets::PyCustomWidgets(QObject*) in pluginloader.o
"_Py_IsInitialized", referenced from:
PyCustomWidgets::PyCustomWidgets(QObject*) in pluginloader.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[1]: *** [libpyqt4.dylib] Error 1
make: *** [all] Error 2

I see the error is about ‘Undefined symbols for architecture x86_64’. So I googled again and someone says the configure command of sip and PyQt should be followed by -arch=x86_64 and –use-arch=x86_64 respectively, to inform the system version to the complier. I was very exited when I read this, as if I had found the golden key to the problem.  However, when I tried again, the problem occurred once again.

Suffering

Then the following days I suffered the no-one-know error,  struggling against it after a number of trial/errors. I tried to install PyQt by Homebrew and MacPort, but they cannot go around the problem neither. MacPort is only able to install an older version of PyQt compatible to Python 2.6. Then I tried to add different parameters before configuring, and fail followed again (like this and this). But I was confident that I was on the right track and the problem will be finally solved. To sum up,  thought I was deeply frustrated, fortunately I gathered many clues about my situation during the process.

  • First of all, from 4.8.5 on Qt only support the 64-bit system. So former tips like configure sip and PyQt under i386 will no longer be available (like this and this).  Instead, the only way can we build Qt is in x86_64.
  • Secondly, for Homebrew cannot make my PyQt as well, the problem must be with my own system, rather than the supplemental packages. This is because Homebrew will install all the required packages correctly and automatically.
  • Finally, some discussing the python versions on Mac (framework and non-framework ) caught my eye and it is from those posts that I had some idea about my case. (1,2 and 3)

I checked the error report again and found the complier was searching the dynamic lib ‘/Library/Frameworks/Python.framework/Versions/2.7/lib/libpython2.7.dylib’ for the ‘libpython2.7.dylib’ for the ‘ x86_64 architecture’ . I see the directory points to the python 2.7.5 I installed before and there is something that the system is searching for. Specifically, I think it is something automatically generated during the configure process since I used -arch=x86_64 as the parameter during configuring. However, they cannot be found now.  Where are they? Is the complier searching at the right directory, since I have multiple pythons installed?

Another discovery is that each time I type ‘python’ in the terminal, the system work with the python 2.7.2 from the anacoda, rather than the python 2.7.5 installed by myself. Then I realized when I was configuring the sip and PyQt with ‘python’ command, actually the system was compiling with py2.7.2, rather than the 2.7.5 that complier later search ‘x86_64 architecture’ for.

So the problem turned clear now. Because I had several versions of pythons in my system, non-framework (2.7.2) and framework (2.7.5), they confused the system. When I configured sip and PyQt with py2.7.2 (non-framework python), everything went well and something (say the .86_64 architecture) that would be later required in making files were also created and stored in correspondent directories in py2.7.2. However, the compiler of PyQt is supposed to find those constituents from the framework python (2.7.5.). Therefore, it cannot find the files.

Solution and Summary

The solution is easy after realizing the cause. I just configure sip and PyQt by the framework python, with typing the following,

for sip

python2.7 configure.py -arch=x86_64

make && make install 

for PyQt

python2.7 configure.py --use-arch=x86_64

make && make install 

Then everything went well and I succeeded.

Let me conclude with some points to take away:

  • Different programs use different version of python, (framework and non-framework).  They can coexist in a system, but should be correctly managed.
  • Know which kind of python is required before running the configure of the python program.
  • Problems are difficult since we call them problem, but keep trying will be finally rewarded.
Advertisements