Written by Cyrille Fauvel – Autodesk Developer Network (April 2013)
Updated by Chengxi Li and Lanh Hong - Autodesk Developer Network (December 2019)
Building SIP and PyQt for Maya 2020 is a python binding to the Qt library. Because Maya uses Qt internally, you can use the PyQt modules in Maya python scripts to create custom UI. PyQt does not have the same licensing as Maya, Qt, or Python. Please consult the PyQt website for information about licensing for PyQt [http://www.riverbankcomputing.com/].
Maya 2020 uses Qt5.12.5 which is binary compatible with the latest version of PyQt - 5.13.2 / SIP - 4.19.19
Use the Maya modified version of the Qt source code. A copy of the customized Qt 5.12.5 source is available from Autodesk's Open Source web-site [http://www.autodesk.com/lgplsource] and includes text files describing how to configure, build and install Qt for each platform supported by Maya.
Note: There is no need to build PySide since it comes with Maya by default, nor have to rebuild Qt since the main Qt tools to build PyQt are now included in the Maya distributions (i.e. qmake, moc, …). Also coming by default in the Maya include and lib folders are libxml, openSSL, OpenAL, python2.7, qt-5.12.5, and tbb so you do not need to rebuild any of those libraries unless you have a very specific need.
Instructions
Here are the instructions for building a copy of the PyQt5 modules for Maya 2020.
Follow the instructions from the Maya Documentation (Maya Developer Help > Setting up your build environment) to setup your Windows, macOS, or Linux build environment.
Since Maya 2020 ships without the devkit, you can get the Maya 2020 devkit from the Maya Develop Center [https://www.autodesk.com/developmaya]. Download the devkit and unzip the files. Make sure to read the instructions in the Maya Documentation to install the devkit properly on your system.
Download SIP and PyQt source. I downloaded 'sip-4.19.19' and 'PyQt5-5.13.2'.
PyQt5: https://www.riverbankcomputing.com/software/pyqt/download5
SIP: http://www.riverbankcomputing.com/software/sip/download
The next steps are specific to your environment so follow the instructions for Mac, Linux or Windows.
Note: The scripts used in this document are posted on Github.
Mac
Unzip SIP and PyQt into one local folder
(e.g. /Users/<username>/Maya2020/Scripts/).
/Users/<username>/Maya2020/Scripts/sip-4.19.19
/Users/<username>/Maya2020/Scripts/PyQt5-5.13.2
If you have multiple installation of Xcode and would like to use Xcode 10.X to compile it, backup /Applications/Xcode.app and use Xcode 10.X to replace it.
Use xcode-select to change active xcode like below:
sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer
The qt.conf file uses MAYA_LOCATION and DEVKIT_LOCATION to locate the expected header/library files. Therefore, you must set both environment variables before building PyQt5. Follow the Maya Documentation to properly set up your environment variables.
DEVKIT_LOCATION should point to the directory where the devkit include, mkspecs, cmake directories are located. Please make sure DEVKIT_LOCATION/devkit/bin/moc and qmake are executable.
Modify /devkit/bin/qt.conf as below:
qt.conf
[Paths]
Prefix=
Libraries=$(MAYA_LOCATION)/MacOS
Binaries=$(DEVKIT_LOCATION)/devkit/bin
Headers=$(DEVKIT_LOCATION)/include/Qt
ArchData=$(DEVKIT_LOCATION)
Data=$(DEVKIT_LOCATION)
HostData=$(DEVKIT_LOCATION)
HostBinaries=$(DEVKIT_LOCATION)/devkit/bin
HostLibraries=$(MAYA_LOCATION)/MacOS
Untar the /include/qt-5.12.5-include.tar.gz into /include/Qt.
Untar the /mkspecs/qt-5.12.5-mkspecs.tar.gz into /mkspecs.
You can update qconfig.pri to make the project compile only release by removing or replace debug flags with release.
Build Prerequisite for PyQt
You’ll need to build setuptools and enum34 before installing SIP. You can find the source in PyPI.
After extracting the source code, use the following command to install them individually.
sudo /Applications/Autodesk/Maya2020/maya.app/Contents/bin/mayapy setup.py install
Build & Install SIP
Save the script below into the same folder as the SIP and PyQt folders. Use the script to build and install SIP.
sip
#!/usr/bin/env bash
MAYAQTBUILD="`dirname \"$0\"`" # Relative
export MAYAQTBUILD="`( cd \"$MAYAQTBUILD\" && pwd )`" # Absolutized and normalized
pushd $MAYAQTBUILD
export SIPDIR=$MAYAQTBUILD/sip-4.19.19
export MAYA_LOCATION=/Applications/Autodesk/Maya2020
pushd $SIPDIR
$MAYA_LOCATION/Maya.app/Contents/bin/mayapy ./configure.py --arch=x86_64 --sip-module PyQt5.sip
make
sudo make install
popd
popd
Build & Install PyQt
Save the script below into the same folder as the SIP and PyQt folders. Use the script to build and install PyQt.
pyqt
#!/usr/bin/env bash
MAYAQTBUILD="`dirname \"$0\"`" # Relative
export MAYAQTBUILD="`( cd \"$MAYAQTBUILD\" && pwd )`" # Absolutized and normalized
pushd $MAYAQTBUILD
export MAYA_LOCATION=/Applications/Autodesk/Maya2020/Maya.app/Contents
export DEVKIT_LOCATION=/Applications/Autodesk/Maya2020
export QTDIR=$DEVKIT_LOCATION/devkit
export QMAKESPEC=$DEVKIT_LOCATION/mkspecs/macx-clang
export INCDIR_QT=$DEVKIT_LOCATION/include/Qt
export LIBDIR_QT=$MAYA_LOCATION/MacOS
error=0
if [ ! -f $QMAKESPEC/qmake.conf ];
then
echo "You need to install qt-5.12.5-mkspecs.tar.gz in $QTDIR/mkspecs !"
error=1
fi
if [ ! -f $INCDIR_QT/QtCore/qdir.h ];
then
echo "You need to uncompress $MAYA_LOCATION/devkit/include/qt-5.12.5-include.tar.gz in $INCDIR_QT !"
error=1
fi
# qt.conf - /Applications/Autodesk/Maya2020/Maya.app/Contents/Resources
if [ ! -f $QTDIR/bin/qt.conf ];
then
echo "You need to copy $QTDIR/Resources/qt.conf in $QTDIR/bin !"
error=1
fi
test=`grep 'Data=$(DEVKIT_LOCATION)' $QTDIR/bin/qt.conf`
if [ -z "$test" ];
then
echo "You need to edit $QTDIR/bin/qt.conf to use 'Data=\$(DEVKIT_LOCATION)'"
error=1
fi
test=`grep 'Headers=$(DEVKIT_LOCATION)/include/Qt' $QTDIR/bin/qt.conf`
if [ -z "$test" ];
then
echo "You need to edit $QTDIR/bin/qt.conf to use 'Headers=\$(DEVKIT_LOCATION)/include/Qt'"
error=1
fi
test=`grep 'Libraries=$(MAYA_LOCATION)/MacOS' $QTDIR/bin/qt.conf`
if [ -z "$test" ];
then
echo "You need to edit $QTDIR/bin/qt.conf to use 'Libraries=\$(MAYA_LOCATION)/MacOS'"
error=1
fi
if [ $error -eq 1 ];
then
exit
fi
export DYLD_LIBRARY_PATH=$MAYA_LOCATION/MacOS
export DYLD_FRAMEWORK_PATH=$MAYA_LOCATION/Frameworks
export SIPDIR=$MAYAQTBUILD/sip-4.19.19
export PYQTDIR=$MAYAQTBUILD/PyQt5-5.13.2
export SIP_EXE=$MAYA_LOCATION/Frameworks/Python.framework/Versions/2.7/bin/sip
export SIP_INCLUDE=$MAYA_LOCATION/Frameworks/Python.framework/Versions/2.7/include/python2.7
pushd $PYQTDIR
export PATH=$QTDIR/bin:$PATH
echo
echo Environment
echo -----------
set
echo -----------
echo QT Settings
echo -----------
qmake -query
echo -----------
echo
$MAYA_LOCATION/bin/mayapy ./configure.py QMAKE_MAC_SDK=macosx10.14 QMAKE_RPATHDIR+=$LIBDIR_QT --sip=$SIP_EXE --sip-incdir=$SIP_INCLUDE -w --no-designer-plugin
make -j 8
sudo make install
popd
popd
Note: I am compiling against Mac OS X SDK 10.14 which is same as the developer environment. If you want to compile against other versions, modify the script (macosx10.14).
You're done! Please check the testing paragraph at the end of the article.
Linux
Unzip SIP and PyQt into one local folder
(e.g. /home/<username>/Maya2020/Scripts/).
/home/<username>/Maya2020/Scripts/sip-4.19.19
/home/<username>/Maya2020/Scripts/PyQt5-5.13.2
The qt.conf file uses MAYA_LOCATION and DEVKIT_LOCATION to locate the expected header/library files. Therefore, users must set both environment variables before building the PyQt5. Follow the Maya Documentation to properly set up your environment variables.
DEVKIT_LOCATION should point to the directory where the devkit include, mkspecs, cmake directories are located.
Please backup your qt.conf first, you'll need to restore it after building PyQt5.
Replace …/bin/qt.conf with below:
qt.conf
[Paths]
Prefix=
Libraries=$(MAYA_LOCATION)/lib
Binaries=$(DEVKIT_LOCATION)/bin
Headers=$(DEVKIT_LOCATION)/include/Qt
ArchData=$(DEVKIT_LOCATION)
Data=$(DEVKIT_LOCATION)
HostData=$(DEVKIT_LOCATION)
HostBinaries=$(DEVKIT_LOCATION)/bin
Untar the /include/qt-5.12.5-include.tar.gz into /include/Qt.
Untar the /mkspecs/qt-5.12.5-mkspecs.tar.gz into /mkspecs.
Make qmake and moc into executables from the Maya bin directory.
sudo chmod aog+x /usr/autodesk/Maya2020/bin/moc
sudo chmod aog+x /usr/autodesk/Maya2020/bin/qmake
Build Prerequisite for PyQt
You’ll need to build setuptools and enum34 before installing SIP. You can find the source in PyPI.
After extracting the source code, use the following command to install them individually.
sudo /usr/autodesk/Maya2020/bin/mayapy setup.py install
Build & Install SIP
Save the script below into the same folder as the SIP and PyQt folders. Use the script to build and install SIP.
PyQt requires to build private sip module since 5.11. You’ll need to add “–sip-module PyQt5.sip” to the configuration.
In Maya2020 release, the include/Python2.7 folder has been renamed to Python, so we’ll create a softlink for it.
sudo ln -s /usr/autodesk/Maya2020/include/Python /usr/autodesk/Maya2020/include/python2.7
sip
#!/usr/bin/env bash
MAYAQTBUILD="`dirname \"$0\"`" # Relative
export MAYAQTBUILD="`( cd \"$MAYAQTBUILD\" && pwd )`" # Absolutized and normalized
pushd $MAYAQTBUILD
export SIPDIR=$MAYAQTBUILD/sip-4.19.19
export MAYA_LOCATION=/usr/autodesk/Maya2020
pushd $SIPDIR
$MAYA_LOCATION/bin/mayapy ./configure.py --sip-module PyQt5.sip
make
sudo make install
popd
popd
Build & Install PyQt
Save the script below into the same folder as the SIP and PyQt folders. Use the script to build and install PyQt. You’ll need to install OpenGL headers before compiling the PyQt. You could install it by installing mesa-libGL-devel or simply install glew and glew-devel to make sure nothing is missing.
pyqt
#!/usr/bin/env bash
MAYAQTBUILD="`dirname \"$0\"`" # Relative
export MAYAQTBUILD="`( cd \"$MAYAQTBUILD\" && pwd )`" # Absolutized and normalized
pushd $MAYAQTBUILD
export MAYA_LOCATION=/usr/autodesk/Maya2020
export QTDIR=$MAYA_LOCATION
export DEVKIT_LOCATION=$MAYA_LOCATION
export QMAKESPEC=$QTDIR/mkspecs/linux-g++-64
export INCDIR_QT=$MAYA_LOCATION/include/Qt
export LIBDIR_QT=$QTDIR/lib
error=0
if [ ! -f $QMAKESPEC/qmake.conf ];
then
echo "You need to install qt-5.12.5-mkspecs.tar.gz in $QTDIR/mkspecs !"
error=1
fi
if [ ! -f $INCDIR_QT/QtCore/qdir.h ];
then
echo "You need to uncompress $MAYA_LOCATION/include/qt-5.12.5-include.tar.gz in $INCDIR_QT !"
error=1
fi
# qt.conf - $QTDIR/bin/qt.conf
if [ ! -f $QTDIR/bin/qt.conf ];
then
echo "You need to copy $QTDIR/Resources/qt.conf in $QTDIR/bin !"
error=1
fi
# The grep string should be in single quote('), if it is in double quote (""),
# shell will expand the variable, hence the intension of the below grep will fail
test=`grep 'Headers=$(DEVKIT_LOCATION)/include/Qt' $QTDIR/bin/qt.conf`
if [ -z "$test" ];
then
echo "You need to edit $QTDIR/bin/qt.conf to use 'Headers=$(DEVKIT_LOCATION)/include/Qt'"
error=1
fi
if [ $error -eq 1 ];
then
exit
fi
export SIPDIR=$MAYAQTBUILD/sip-4.19.19
export PYQTDIR=$MAYAQTBUILD/PyQt5-5.13.2
pushd $PYQTDIR
export PATH=$QTDIR/bin:$PATH
$QTDIR/bin/mayapy ./configure.py LIBDIR_QT=$LIBDIR_QT INCDIR_QT=$INCDIR_QT MOC=$QTDIR/bin/moc -w --no-designer-plugin
#change 8 to the count of cores your computer
make -j 8
sudo make install
popd
popd
You're done! Please check the testing paragraph at the end of the article.
Windows
Unzip SIP and PyQt into one local folder
(e.g. C:\Users\<username>\Maya2020\Scripts\).
C:\Users\<username>\Maya2020\Scripts\sip-4.19.19
C:\Users\<username>\Maya2020\Scripts\yQt5-5.13.2
Please backup your qt.conf first, you'll need to restore it after building PyQt5.
Replace …\bin\qt.conf with below:
qt.conf
[Paths]
Prefix=$(MAYA_LOCATION)
Libraries=lib
Binaries=bin
Headers=include/Qt
Data=.
Plugins=qt-plugins
Translations=qt-translations
Qml2Imports=qml
Unzip the \include\qt-5.12.5-include.tar.gz into \include\Qt
Unzip the \mkspecs\qt-5.12.5-mkspecs.tar.gz into \mkspecs.
You can update qconfig.pri to make the project compile only release by removing or replace debug flags with release.
Modify \mkspecs\common\msvc-destop.conf. Find QMAKE_LIBS_QT_ENTRY and make sure it is assigned to -lqtmain -lshell32.
Rename the folder inside \include\Qt\QtNfc to QtNfc.disabled.
Run following build scripts with VS2017 x64 Native Tools Command Prompt. If your Maya is installed in folders that requires administrator privilege (e.g. Program files), please run the command prompt as Administrator.
Environment Setup
Save the script below into the same folder as the SIP and PyQt folders. Use the script to setup the environment.
setup.bat
@echo off
set MAYAVERSION=2020
set ADSKQTVERSION=5.12.5
set SIPVERSION=4.19.19
set PYQTVERSION=5.13.2
set MAYADRIVE=m:
set BUILDDRIVE=v:
if exist %MAYADRIVE%\nul subst %MAYADRIVE% /d
subst %MAYADRIVE% "C:\Program Files\Autodesk\Maya%MAYAVERSION%"
set MAYA_LOCATION=%MAYADRIVE%
set MAYAPYQTBUILD=%~dp0
rem Removing trailing \
set MAYAPYQTBUILD=%MAYAPYQTBUILD:~0,-1%
if exist %BUILDDRIVE%\nul subst %BUILDDRIVE% /d
subst %BUILDDRIVE% "%MAYAPYQTBUILD%"
set SIPDIR=%BUILDDRIVE%\sip-%SIPVERSION%
set PYQTDIR=%BUILDDRIVE%\PyQt5-%PYQTVERSION%
rem set ADSKQTDIR=%BUILDDRIVE%\qt-%ADSKQTVERSION%
set QTDIR=%MAYA_LOCATION%
set PATH=%QTDIR%\bin;%PATH%
set MSVC_VERSION=2017
set MSVC_DIR=C:\Program Files (x86)\Microsoft Visual Studio 14.0
set QMAKESPEC=%QTDIR%\mkspecs\win32-msvc
set _QMAKESPEC_=win32-msvc
if ["%LIBPATH%"]==[""] call "%MSVC_DIR%\VC\vcvarsall" amd64
set INCLUDE=%INCLUDE%;%MAYA_LOCATION%\include\python
set LIB=%LIB%;%MAYA_LOCATION%\lib
Build Prerequisite for PyQt
You’ll need to build setuptools and enum34 before installing SIP. You can find the source in PyPI.
After extracting the source code, use the following command with administrator privilege to install them individually.
"C:\Program Files\Autodesk\Maya2020\bin\mayapy.exe" setup.py install
Build & Install SIP
Save the script below into the same folder as the SIP and PyQt folders. Use the script to build and install SIP.
sip.bat
@echo off
set XXX=%~dp0
if ["%MAYAPYQTBUILD%"]==[""] call "%XXX%setup.bat"
pushd %SIPDIR%
rem "%MAYA_LOCATION%\bin\mayapy" configure-ng.py --spec %_QMAKESPEC_%
"%MAYA_LOCATION%\bin\mayapy" configure.py --sip-module PyQt5.sip
nmake
nmake install
popd
Build & Install PyQt
Save the script below into the same folder as the SIP and PyQt folders. Use the script to build and install PyQt.
pyqt.bat
@echo off
set XXX=%~dp0
if ["%MAYAPYQTBUILD%"]==[""] call "%XXX%setup.bat"
set QMAKESPEC=%QTDIR%\mkspecs\%_QMAKESPEC_%
if not exist "%QMAKESPEC%\qmake.conf" (
echo "You need to uncompress %MAYA_LOCATION%\mkspecs\qt-5.12.5-mkspecs.tar.gz !"
goto end
)
if not exist "%MAYA_LOCATION%\include\Qt\QtCore\qdir.h" (
echo "You need to uncompress %MAYA_LOCATION%\include\qt-5.12.5-include.tar.gz in %MAYA_LOCATION%\include\Qt !"
goto end
)
findstr /L /C:"Headers=include/Qt" "%MAYA_LOCATION%\bin\qt.conf" >nul 2>&1
if ERRORLEVEL 1 (
echo "You need to edit %MAYA_LOCATION%\bin\qt.conf to use 'Headers=include/Qt'"
goto end
)
findstr /L /C:"-lqtmain -lshell32" "%QTDIR%\mkspecs\common\msvc-desktop.conf" >nul 2>&1
if ERRORLEVEL 1 (
echo "You need to edit %QTDIR%\mkspecs\common\msvc-desktop.conf to use 'QMAKE_LIBS_QT_ENTRY = -lqtmain -lshell32'"
goto end
)
if not exist "%MAYA_LOCATION%\include\Qt\qtnfc.disabled" (
echo "You need to rename %MAYA_LOCATION%\include\Qt\qtnfc to %MAYA_LOCATION\include\Qt\qtnfc.disabled"
goto end
)
pushd %PYQTDIR%
"%MAYA_LOCATION%\bin\mayapy" configure.py --spec %QMAKESPEC% LIBDIR_QT="%QTDIR%\lib" INCDIR_QT="%QTDIR%\include\Qt" MOC="%QTDIR%\bin\moc.exe" --sip="%QTDIR%\Python\sip.exe" --sip-incdir="%QTDIR%\Python\include" -w --no-designer-plugin
nmake
nmake install
popd
:end
You're done! Please check the testing paragraph at the end of the article.
Testing
Copy and paste this example in the Maya Script Editor (in a Python tab), and execute the code:
import sys
from PyQt5.QtWidgets import (QWidget, QToolTip, QPushButton)
from PyQt5.QtGui import QFont
class Example(QWidget):
def __init__(self):
super(Example,self).__init__()
self.initUI()
def initUI(self):
QToolTip.setFont(QFont('SansSerif', 10))
self.setToolTip('This is a <b>QWidget</b> widget')
btn = QPushButton('Button', self)
btn.setToolTip('This is a <b>QPushButton</b> widget')
btn.resize(btn.sizeHint())
btn.move(50, 50)
self.setGeometry(300, 300, 300, 200)
self.setWindowTitle('Tooltips')
self.show()
ex = Example()
If you see the dialog showing, you are all set.
Comments
You can follow this conversation by subscribing to the comment feed for this post.