Przeglądaj źródła

makepackage: install for multiple Python versions on Windows

See #441
rdb 7 lat temu
rodzic
commit
862906b86d
2 zmienionych plików z 289 dodań i 187 usunięć
  1. 272 170
      makepanda/installer.nsi
  2. 17 17
      makepanda/makepackage.py

+ 272 - 170
makepanda/installer.nsi

@@ -14,7 +14,7 @@
 ;
 ;   BUILT         - location of panda install tree.
 ;   SOURCE        - location of the panda source-tree if available, OR location of panda install tree.
-;   PYVER         - version of Python that Panda was built with (ie, "2.7")
+;   INCLUDE_PYVER - version of Python that Panda was built with (eg. "2.7", "3.5-32")
 ;   REGVIEW       - either 32 or 64, depending on the build architecture.
 ;
 
@@ -46,7 +46,9 @@ SetCompressor ${COMPRESSOR}
 !insertmacro MUI_PAGE_LICENSE "${SOURCE}/doc/LICENSE"
 !insertmacro MUI_PAGE_DIRECTORY
 
+!ifdef INCLUDE_PYVER
 !define MUI_PAGE_CUSTOMFUNCTION_LEAVE ConfirmPythonSelection
+!endif
 !insertmacro MUI_PAGE_COMPONENTS
 
 !insertmacro MUI_PAGE_INSTFILES
@@ -64,8 +66,9 @@ ShowUninstDetails hide
 
 LicenseData "${SOURCE}/doc/LICENSE"
 
-InstType "Full (Recommended)"
-InstType "Minimal"
+InstType "Auto (Recommended)"
+InstType "Full"
+InstType "Light"
 
 LangString DESC_SecCore ${LANG_ENGLISH} "The Panda3D core libraries, configuration files and models/textures that are needed to use Panda3D."
 LangString DESC_SecOpenGL ${LANG_ENGLISH} "The OpenGL graphics back-end is the most well-supported renderer."
@@ -78,8 +81,9 @@ LangString DESC_SecODE ${LANG_ENGLISH} "Support for the Open Dynamics Engine to
 LangString DESC_SecPhysX ${LANG_ENGLISH} "Support for NVIDIA PhysX to implement physics."
 LangString DESC_SecRocket ${LANG_ENGLISH} "Support for the libRocket GUI library.  This is an optional library that offers an HTML/CSS-like approach to creating user interfaces."
 LangString DESC_SecTools ${LANG_ENGLISH} "Useful tools and model converters to help with Panda3D development.  Recommended."
-LangString DESC_SecPyBindings ${LANG_ENGLISH} "Contains the Python modules that allow use of Panda3D using Python.  These will only work with a ${REGVIEW}-bit version of Python ${PYVER}."
-LangString DESC_SecPython ${LANG_ENGLISH} "Contains a ${REGVIEW}-bit copy of Python ${PYVER} preconfigured to make use of Panda3D."
+LangString DESC_SecGroupPython ${LANG_ENGLISH} "Contains modules that provide Python support for Panda3D."
+LangString DESC_SecPyShared ${LANG_ENGLISH} "Contains the common Python code used by the Panda3D Python bindings."
+LangString DESC_SecPython ${LANG_ENGLISH} "Contains a ${REGVIEW}-bit copy of Python ${INCLUDE_PYVER} preconfigured to make use of Panda3D."
 LangString DESC_SecHeadersLibs ${LANG_ENGLISH} "Headers and libraries needed for C++ development with Panda3D."
 LangString DESC_SecSamples ${LANG_ENGLISH} "The sample programs demonstrate how to make Python applications with Panda3D."
 LangString DESC_SecMaxPlugins ${LANG_ENGLISH} "Plug-ins for Autodesk 3ds Max (${REGVIEW}-bit) that can be used to export models to Panda3D."
@@ -112,26 +116,107 @@ var MANPAGE
 !insertmacro !defineifexist HAVE_ODE "${BUILT}\bin\libpandaode.dll"
 !insertmacro !defineifexist HAVE_PHYSX "${BUILT}\bin\libpandaphysx.dll"
 !insertmacro !defineifexist HAVE_ROCKET "${BUILT}\bin\libp3rocket.dll"
-!insertmacro !defineifexist HAVE_PYTHON "${BUILT}\python"
 !insertmacro !defineifexist HAVE_SAMPLES "${SOURCE}\samples"
 !insertmacro !defineifexist HAVE_MAX_PLUGINS "${BUILT}\plugins\*.dlo"
 !insertmacro !defineifexist HAVE_MAYA_PLUGINS "${BUILT}\plugins\*.mll"
 
+!macro RemovePythonPath PYVER
+    ReadRegStr $0 HKCU "Software\Python\PythonCore\${PYVER}\PythonPath\Panda3D" ""
+    StrCmp $0 "$INSTDIR" 0 +2
+    DeleteRegKey HKCU "Software\Python\PythonCore\${PYVER}\PythonPath\Panda3D"
+!macroend
+
+!macro PyBindingSection PYVER EXT_SUFFIX
+    LangString DESC_SecPyBindings${PYVER} ${LANG_ENGLISH} "Contains the Python modules that allow use of Panda3D using a ${REGVIEW}-bit version of Python ${PYVER}."
+
+    !insertmacro !defineifexist _present "${BUILT}\panda3d\core${EXT_SUFFIX}"
+    !ifdef _present
+    Section "${PYVER} bindings" SecPyBindings${PYVER}
+        !if "${PYVER}" == "${INCLUDE_PYVER}"
+            SectionIn 1 2 3
+        !else
+            !if "${PYVER}" == "2.7"
+                SectionIn 1 2
+            !else
+                ; See .onInit function where this is dynamically enabled.
+                SectionIn 2
+            !endif
+        !endif
+
+        SetDetailsPrint both
+        DetailPrint "Installing Panda3D bindings for Python ${PYVER}..."
+        SetDetailsPrint listonly
+
+        SetOutPath $INSTDIR\panda3d
+
+        File /nonfatal /r "${BUILT}\panda3d\core${EXT_SUFFIX}"
+        File /nonfatal /r "${BUILT}\panda3d\ai${EXT_SUFFIX}"
+        File /nonfatal /r "${BUILT}\panda3d\direct${EXT_SUFFIX}"
+        File /nonfatal /r "${BUILT}\panda3d\egg${EXT_SUFFIX}"
+        File /nonfatal /r "${BUILT}\panda3d\fx${EXT_SUFFIX}"
+        File /nonfatal /r "${BUILT}\panda3d\interrogatedb${EXT_SUFFIX}"
+        File /nonfatal /r "${BUILT}\panda3d\physics${EXT_SUFFIX}"
+        File /nonfatal /r "${BUILT}\panda3d\_rplight${EXT_SUFFIX}"
+        File /nonfatal /r "${BUILT}\panda3d\skel${EXT_SUFFIX}"
+        File /nonfatal /r "${BUILT}\panda3d\vision${EXT_SUFFIX}"
+        File /nonfatal /r "${BUILT}\panda3d\vrpn${EXT_SUFFIX}"
+
+        !ifdef HAVE_BULLET
+            SectionGetFlags ${SecBullet} $R0
+            IntOp $R0 $R0 & ${SF_SELECTED}
+            StrCmp $R0 ${SF_SELECTED} 0 SkipBulletPyd
+            File /nonfatal /r "${BUILT}\panda3d\bullet${EXT_SUFFIX}"
+            SkipBulletPyd:
+        !endif
+
+        !ifdef HAVE_ODE
+            SectionGetFlags ${SecODE} $R0
+            IntOp $R0 $R0 & ${SF_SELECTED}
+            StrCmp $R0 ${SF_SELECTED} 0 SkipODEPyd
+            File /nonfatal /r "${BUILT}\panda3d\ode${EXT_SUFFIX}"
+            SkipODEPyd:
+        !endif
+
+        !ifdef HAVE_PHYSX
+            SectionGetFlags ${SecPhysX} $R0
+            IntOp $R0 $R0 & ${SF_SELECTED}
+            StrCmp $R0 ${SF_SELECTED} 0 SkipPhysXPyd
+            File /nonfatal /r "${BUILT}\panda3d\physx${EXT_SUFFIX}"
+            SkipPhysXPyd:
+        !endif
+
+        !ifdef HAVE_ROCKET
+            SectionGetFlags ${SecRocket} $R0
+            IntOp $R0 $R0 & ${SF_SELECTED}
+            StrCmp $R0 ${SF_SELECTED} 0 SkipRocketPyd
+            File /nonfatal /r "${BUILT}\panda3d\rocket${EXT_SUFFIX}"
+            SkipRocketPyd:
+        !endif
+
+        SetOutPath $INSTDIR\pandac\input
+        File /r "${BUILT}\pandac\input\*"
+        SetOutPath $INSTDIR\Pmw
+        File /nonfatal /r /x CVS "${BUILT}\Pmw\*"
+
+        !ifdef REGVIEW
+        SetRegView ${REGVIEW}
+        !endif
+
+        ; Install a Panda3D path into the global PythonPath for this version
+        ; of Python.
+        WriteRegStr HKCU "Software\Python\PythonCore\${PYVER}\PythonPath\Panda3D" "" "$INSTDIR"
+    SectionEnd
+    !undef _present
+    !endif
+!macroend
+
 Function runFunction
     ExecShell "open" "$SMPROGRAMS\${TITLE}\Panda3D Manual.lnk"
 FunctionEnd
 
-Function .onInit
-    ${If} ${REGVIEW} = 64
-    ${AndIfNot} ${RunningX64}
-        MessageBox MB_OK|MB_ICONEXCLAMATION "You are attempting to install the 64-bit version of Panda3D on a 32-bit version of Windows.  Please download and install the 32-bit version of Panda3D instead."
-        Abort
-    ${EndIf}
-FunctionEnd
-
 SectionGroup "Panda3D Libraries"
     Section "Core Libraries" SecCore
-        SectionIn 1 2 RO
+        SectionIn 1 2 3 RO
 
         SetShellVarContext current
         SetOverwrite try
@@ -177,7 +262,7 @@ SectionGroup "Panda3D Libraries"
 
     !ifdef HAVE_GL
     Section "OpenGL" SecOpenGL
-        SectionIn 1 2 RO
+        SectionIn 1 2 3 RO
 
         SetOutPath "$INSTDIR\bin"
         File "${BUILT}\bin\libpandagl.dll"
@@ -186,7 +271,7 @@ SectionGroup "Panda3D Libraries"
 
     !ifdef HAVE_DX9
     Section "Direct3D 9" SecDirect3D9
-        SectionIn 1
+        SectionIn 1 2
 
         SetOutPath "$INSTDIR\bin"
         File "${BUILT}\bin\libpandadx9.dll"
@@ -196,7 +281,7 @@ SectionGroup "Panda3D Libraries"
 
     !ifdef HAVE_OPENAL
     Section "OpenAL Audio" SecOpenAL
-        SectionIn 1 2
+        SectionIn 1 2 3
 
         SetOutPath "$INSTDIR\bin"
         File "${BUILT}\bin\libp3openal_audio.dll"
@@ -207,7 +292,7 @@ SectionGroup "Panda3D Libraries"
 
     !ifdef HAVE_FMOD
     Section "FMOD Audio" SecFMOD
-        SectionIn 1
+        SectionIn 1 2
 
         SetOutPath "$INSTDIR\bin"
         File "${BUILT}\bin\libp3fmod_audio.dll"
@@ -217,7 +302,7 @@ SectionGroup "Panda3D Libraries"
 
     !ifdef HAVE_FFMPEG
     Section "FFMpeg" SecFFMpeg
-        SectionIn 1
+        SectionIn 1 2
 
         SetOutPath "$INSTDIR\bin"
         File "${BUILT}\bin\libp3ffmpeg.dll"
@@ -230,7 +315,7 @@ SectionGroup "Panda3D Libraries"
 
     !ifdef HAVE_BULLET
     Section "Bullet Physics" SecBullet
-        SectionIn 1
+        SectionIn 1 2
 
         SetOutPath "$INSTDIR\bin"
         File "${BUILT}\bin\libpandabullet.dll"
@@ -239,7 +324,7 @@ SectionGroup "Panda3D Libraries"
 
     !ifdef HAVE_ODE
     Section "ODE Physics" SecODE
-        SectionIn 1
+        SectionIn 1 2
 
         SetOutPath "$INSTDIR\bin"
         File "${BUILT}\bin\libpandaode.dll"
@@ -248,7 +333,8 @@ SectionGroup "Panda3D Libraries"
 
     !ifdef HAVE_PHYSX
     Section "NVIDIA PhysX" SecPhysX
-        SectionIn 1
+        ; Only enable in "Full"
+        SectionIn 2
 
         SetOutPath "$INSTDIR\bin"
         File "${BUILT}\bin\libpandaphysx.dll"
@@ -260,7 +346,7 @@ SectionGroup "Panda3D Libraries"
 
     !ifdef HAVE_ROCKET
     Section "libRocket GUI" SecRocket
-        SectionIn 1
+        SectionIn 1 2
 
         SetOutPath "$INSTDIR\bin"
         File "${BUILT}\bin\libp3rocket.dll"
@@ -272,7 +358,7 @@ SectionGroup "Panda3D Libraries"
 SectionGroupEnd
 
 Section "Tools and utilities" SecTools
-    SectionIn 1 2
+    SectionIn 1 2 3
 
     SetDetailsPrint both
     DetailPrint "Installing utilities..."
@@ -305,17 +391,14 @@ Section "Tools and utilities" SecTools
     WriteRegStr HKCU "Software\Classes\Panda3D.Multifile\shell\extract\command" "" '"$INSTDIR\bin\multify.exe" -xf "%1"'
 SectionEnd
 
-SectionGroup "Python support"
-    Section "Python bindings" SecPyBindings
-        SectionIn 1 2
+SectionGroup "Python modules" SecGroupPython
+    Section "Shared code" SecPyShared
+        SectionIn 1 2 3
 
         SetDetailsPrint both
-        DetailPrint "Installing Panda3D Python modules..."
+        DetailPrint "Installing Panda3D shared Python modules..."
         SetDetailsPrint listonly
 
-        SetOutPath "$INSTDIR\bin"
-        File /nonfatal /r "${BUILT}\bin\*.pyd"
-
         SetOutPath $INSTDIR\direct\directscripts
         File /r /x CVS /x Opt?-Win32 "${BUILT}\direct\directscripts\*"
         SetOutPath $INSTDIR\direct\filter
@@ -330,141 +413,133 @@ SectionGroup "Python support"
         File /r "${BUILT}\pandac\*.py"
         SetOutPath $INSTDIR\panda3d
         File /r "${BUILT}\panda3d\*.py"
+    SectionEnd
 
-        File /nonfatal /r "${BUILT}\panda3d\core${EXT_SUFFIX}"
-        File /nonfatal /r "${BUILT}\panda3d\ai${EXT_SUFFIX}"
-        File /nonfatal /r "${BUILT}\panda3d\direct${EXT_SUFFIX}"
-        File /nonfatal /r "${BUILT}\panda3d\egg${EXT_SUFFIX}"
-        File /nonfatal /r "${BUILT}\panda3d\fx${EXT_SUFFIX}"
-        File /nonfatal /r "${BUILT}\panda3d\interrogatedb${EXT_SUFFIX}"
-        File /nonfatal /r "${BUILT}\panda3d\physics${EXT_SUFFIX}"
-        File /nonfatal /r "${BUILT}\panda3d\_rplight${EXT_SUFFIX}"
-        File /nonfatal /r "${BUILT}\panda3d\skel${EXT_SUFFIX}"
-        File /nonfatal /r "${BUILT}\panda3d\vision${EXT_SUFFIX}"
-        File /nonfatal /r "${BUILT}\panda3d\vrpn${EXT_SUFFIX}"
-
-        !ifdef HAVE_BULLET
-            SectionGetFlags ${SecBullet} $R0
-            IntOp $R0 $R0 & ${SF_SELECTED}
-            StrCmp $R0 ${SF_SELECTED} 0 SkipBulletPyd
-            File /nonfatal /r "${BUILT}\panda3d\bullet${EXT_SUFFIX}"
-            SkipBulletPyd:
-        !endif
-
-        !ifdef HAVE_ODE
-            SectionGetFlags ${SecODE} $R0
-            IntOp $R0 $R0 & ${SF_SELECTED}
-            StrCmp $R0 ${SF_SELECTED} 0 SkipODEPyd
-            File /nonfatal /r "${BUILT}\panda3d\ode${EXT_SUFFIX}"
-            SkipODEPyd:
-        !endif
-
-        !ifdef HAVE_PHYSX
-            SectionGetFlags ${SecPhysX} $R0
-            IntOp $R0 $R0 & ${SF_SELECTED}
-            StrCmp $R0 ${SF_SELECTED} 0 SkipPhysXPyd
-            File /nonfatal /r "${BUILT}\panda3d\physx${EXT_SUFFIX}"
-            SkipPhysXPyd:
-        !endif
-
-        !ifdef HAVE_ROCKET
-            SectionGetFlags ${SecRocket} $R0
-            IntOp $R0 $R0 & ${SF_SELECTED}
-            StrCmp $R0 ${SF_SELECTED} 0 SkipRocketPyd
-            File /nonfatal /r "${BUILT}\panda3d\rocket${EXT_SUFFIX}"
-            SkipRocketPyd:
-        !endif
+    !insertmacro PyBindingSection 2.7 .pyd
+    !if "${REGVIEW}" == "32"
+        !insertmacro PyBindingSection 3.5-32 .cp35-win32.pyd
+        !insertmacro PyBindingSection 3.6-32 .cp36-win32.pyd
+        !insertmacro PyBindingSection 3.7-32 .cp37-win32.pyd
+        !insertmacro PyBindingSection 3.8-32 .cp38-win32.pyd
+        !insertmacro PyBindingSection 3.9-32 .cp39-win32.pyd
+    !else
+        !insertmacro PyBindingSection 3.5 .cp35-win_amd64.pyd
+        !insertmacro PyBindingSection 3.6 .cp36-win_amd64.pyd
+        !insertmacro PyBindingSection 3.7 .cp37-win_amd64.pyd
+        !insertmacro PyBindingSection 3.8 .cp38-win_amd64.pyd
+        !insertmacro PyBindingSection 3.9 .cp39-win_amd64.pyd
+    !endif
+SectionGroupEnd
 
-        SetOutPath $INSTDIR\pandac\input
-        File /r "${BUILT}\pandac\input\*"
-        SetOutPath $INSTDIR\Pmw
-        File /nonfatal /r /x CVS "${BUILT}\Pmw\*"
+!ifdef INCLUDE_PYVER
+Section "Python ${INCLUDE_PYVER}" SecPython
+    SectionIn 1 2 3
 
-        !ifdef REGVIEW
-        SetRegView ${REGVIEW}
-        !endif
+    !ifdef REGVIEW
+    SetRegView ${REGVIEW}
+    !endif
 
-        ; Check for a non-Panda3D system-wide Python installation.
-        ReadRegStr $0 HKLM "Software\Python\PythonCore\${PYVER}\InstallPath" ""
-        StrCmp $0 "$INSTDIR\python" UserExternalPthCheck 0
-        StrCmp $0 "" UserExternalPthCheck 0
-        IfFileExists "$0\ppython.exe" UserExternalPthCheck 0
-        IfFileExists "$0\python.exe" AskExternalPth UserExternalPthCheck
-
-        ; Check for a non-Panda3D user installation of Python.
-        UserExternalPthCheck:
-        ReadRegStr $0 HKCU "Software\Python\PythonCore\${PYVER}\InstallPath" ""
-        StrCmp $0 "$INSTDIR\python" SkipExternalPth 0
-        StrCmp $0 "" SkipExternalPth 0
-        IfFileExists "$0\ppython.exe" SkipExternalPth 0
-        IfFileExists "$0\python.exe" AskExternalPth SkipExternalPth
-
-        ; We're pretty sure this Python build is of the right architecture.
-        AskExternalPth:
-        MessageBox MB_YESNO|MB_ICONQUESTION \
-            "Your system already has a copy of Python ${PYVER} installed in:$\r$\n$0$\r$\nWould you like to configure it to be able to use the Panda3D libraries?$\r$\nIf you choose no, you will only be able to use Panda3D's own copy of Python." \
-            IDYES WriteExternalPth IDNO SkipExternalPth
-
-        WriteExternalPth:
-        ;FileOpen $1 "$0\Lib\site-packages\panda.pth" w
-        ;FileWrite $1 "$INSTDIR$\r$\n"
-        ;FileWrite $1 "$INSTDIR\bin$\r$\n"
-        ;FileClose $1
-
-        ; Actually, it looks like we can just do this instead:
-        WriteRegStr HKCU "Software\Python\PythonCore\${PYVER}\PythonPath\Panda3D" "" "$INSTDIR"
+    SetDetailsPrint both
+    DetailPrint "Installing Python ${INCLUDE_PYVER} interpreter (${REGVIEW}-bit)..."
+    SetDetailsPrint listonly
 
-        SkipExternalPth:
-    SectionEnd
+    SetOutPath "$INSTDIR\bin"
+    File /nonfatal "${BUILT}\bin\python*.dll"
 
-    !ifdef HAVE_PYTHON
-    Section "Python ${PYVER}" SecPython
-        SectionIn 1 2
+    SetOutPath "$INSTDIR\python"
+    File /r /x *.pdb "${BUILT}\python\*"
 
-        !ifdef REGVIEW
-        SetRegView ${REGVIEW}
-        !endif
+    SetDetailsPrint both
+    DetailPrint "Adding registry keys for Python..."
+    SetDetailsPrint listonly
 
-        SetDetailsPrint both
-        DetailPrint "Installing Python ${PYVER} (${REGVIEW}-bit)..."
-        SetDetailsPrint listonly
+    ; Check if a copy of Python is installed for this user.
+    ReadRegStr $0 HKCU "Software\Python\PythonCore\${INCLUDE_PYVER}\InstallPath" ""
+    StrCmp "$0" "$INSTDIR\python" RegPath 0
+    StrCmp "$0" "" SkipFileCheck 0
+    IfFileExists "$0\python.exe" AskRegPath 0
+    SkipFileCheck:
 
-        SetOutPath "$INSTDIR\bin"
-        File /nonfatal "${BUILT}\bin\python*.dll"
+    ; Check if a system-wide copy of Python is installed.
+    ReadRegStr $0 HKLM "Software\Python\PythonCore\${INCLUDE_PYVER}\InstallPath" ""
+    StrCmp "$0" "$INSTDIR\python" RegPath 0
+    StrCmp "$0" "" RegPath 0
+    IfFileExists "$0\python.exe" AskRegPath RegPath
 
-        SetOutPath "$INSTDIR\python"
-        File /r /x *.pdb "${BUILT}\python\*"
+    AskRegPath:
+    MessageBox MB_YESNO|MB_ICONQUESTION \
+        "You already have a copy of Python ${INCLUDE_PYVER} installed in:$\r$\n$0$\r$\n$\r$\nPanda3D installs its own copy of Python ${INCLUDE_PYVER}, which will install alongside your existing copy.  Would you like to make Panda's copy the default Python for your user account?" \
+        IDNO SkipRegPath
 
-        SetDetailsPrint both
-        DetailPrint "Adding registry keys for Python..."
-        SetDetailsPrint listonly
+    RegPath:
+    WriteRegStr HKCU "Software\Python\PythonCore\${INCLUDE_PYVER}\InstallPath" "" "$INSTDIR\python"
+    WriteRegStr HKCU "Software\Python\PythonCore\${INCLUDE_PYVER}\InstallPath" "ExecutablePath" "$INSTDIR\python\python.exe"
+    SkipRegPath:
 
-        ; Check if a copy of Python is installed for this user.
-        ReadRegStr $0 HKCU "Software\Python\PythonCore\${PYVER}\InstallPath" ""
-        StrCmp "$0" "$INSTDIR\python" RegPath 0
-        StrCmp "$0" "" SkipFileCheck 0
-        IfFileExists "$0\python.exe" AskRegPath 0
-        SkipFileCheck:
+SectionEnd
+!endif
 
-        ; Check if a system-wide copy of Python is installed.
-        ReadRegStr $0 HKLM "Software\Python\PythonCore\${PYVER}\InstallPath" ""
-        StrCmp "$0" "$INSTDIR\python" RegPath 0
-        StrCmp "$0" "" RegPath 0
-        IfFileExists "$0\python.exe" AskRegPath RegPath
+!macro MaybeEnablePyBindingSection PYVER
+    !if "${INCLUDE_PYVER}" != "${PYVER}"
+        !ifdef SecPyBindings${PYVER}
+            ; Check if a copy of Python is installed for this user.
+            Push $0
+            ReadRegStr $0 HKCU "Software\Python\PythonCore\${PYVER}\InstallPath" ""
+            StrCmp "$0" "" +2 0
+            IfFileExists "$0\python.exe" Py${PYVER}Exists 0
+
+            ; Check if a system-wide copy of Python is installed.
+            ReadRegStr $0 HKLM "Software\Python\PythonCore\${PYVER}\InstallPath" ""
+            StrCmp "$0" "" Py${PYVER}ExistsNot 0
+            IfFileExists "$0\python.exe" Py${PYVER}Exists Py${PYVER}ExistsNot
+
+            Py${PYVER}Exists:
+            SectionSetFlags ${SecPyBindings${PYVER}} ${SF_SELECTED}
+            SectionSetInstTypes ${SecPyBindings${PYVER}} 3
+
+            Py${PYVER}ExistsNot:
+            Pop $0
+        !endif
+    !endif
+!macroend
 
-        AskRegPath:
-        MessageBox MB_YESNO|MB_ICONQUESTION \
-            "You already have a copy of Python ${PYVER} installed in:$\r$\n$0$\r$\n$\r$\nPanda3D installs its own copy of Python ${PYVER}, which will install alongside your existing copy.  Would you like to make Panda's copy the default Python for your user account?" \
-            IDNO SkipRegPath
+Function .onInit
+    ${If} ${REGVIEW} = 64
+    ${AndIfNot} ${RunningX64}
+        MessageBox MB_OK|MB_ICONEXCLAMATION "You are attempting to install the 64-bit version of Panda3D on a 32-bit version of Windows.  Please download and install the 32-bit version of Panda3D instead."
+        Abort
+    ${EndIf}
 
-        RegPath:
-        WriteRegStr HKCU "Software\Python\PythonCore\${PYVER}\InstallPath" "" "$INSTDIR\python"
-        SkipRegPath:
+    !ifdef REGVIEW
+    SetRegView ${REGVIEW}
+    !endif
 
-    SectionEnd
+    ; We never check for 2.7; it is always enabled in Auto mode
+    !if "${REGVIEW}" == "32"
+        !insertmacro MaybeEnablePyBindingSection 3.5-32
+        !insertmacro MaybeEnablePyBindingSection 3.6-32
+        !insertmacro MaybeEnablePyBindingSection 3.7-32
+        !insertmacro MaybeEnablePyBindingSection 3.8-32
+        !insertmacro MaybeEnablePyBindingSection 3.9-32
+    !else
+        !insertmacro MaybeEnablePyBindingSection 3.5
+        !insertmacro MaybeEnablePyBindingSection 3.6
+        !insertmacro MaybeEnablePyBindingSection 3.7
+        !insertmacro MaybeEnablePyBindingSection 3.8
+        !insertmacro MaybeEnablePyBindingSection 3.9
     !endif
-SectionGroupEnd
+FunctionEnd
+
+Function .onSelChange
+    ; If someone selects any Python version, the "shared modules" must be on.
+    ${If} ${SectionIsPartiallySelected} ${SecGroupPython}
+        SectionGetFlags ${SecPyShared} $R0
+        IntOp $R0 $R0 | ${SF_SELECTED}
+        SectionSetFlags ${SecPyShared} $R0
+    ${EndIf}
+FunctionEnd
 
+!ifdef INCLUDE_PYVER
 Function ConfirmPythonSelection
     ; Check the current state of the "Python" section selection.
     SectionGetFlags ${SecPython} $R0
@@ -474,16 +549,14 @@ Function ConfirmPythonSelection
     StrCmp $R1 ${SF_SELECTED} SkipCheck 0
 
     ; Maybe the user just doesn't want Python support at all?
-    SectionGetFlags ${SecPyBindings} $R1
-    IntOp $R1 $R1 & ${SF_SELECTED}
-    StrCmp $R1 ${SF_SELECTED} 0 SkipCheck
+    !insertmacro SectionFlagIsSet ${SecGroupPython} ${SF_PSELECTED} 0 SkipCheck
 
     !ifdef REGVIEW
     SetRegView ${REGVIEW}
     !endif
 
     ; Check for a user installation of Python.
-    ReadRegStr $0 HKCU "Software\Python\PythonCore\${PYVER}\InstallPath" ""
+    ReadRegStr $0 HKCU "Software\Python\PythonCore\${INCLUDE_PYVER}\InstallPath" ""
     StrCmp $0 "$INSTDIR\python" CheckSystemWidePython 0
     StrCmp $0 "" CheckSystemWidePython 0
     IfFileExists "$0\ppython.exe" CheckSystemWidePython 0
@@ -491,7 +564,7 @@ Function ConfirmPythonSelection
 
     ; Check for a system-wide Python installation.
     CheckSystemWidePython:
-    ReadRegStr $0 HKLM "Software\Python\PythonCore\${PYVER}\InstallPath" ""
+    ReadRegStr $0 HKLM "Software\Python\PythonCore\${INCLUDE_PYVER}\InstallPath" ""
     StrCmp $0 "$INSTDIR\python" AskConfirmation 0
     StrCmp $0 "" AskConfirmation 0
     IfFileExists "$0\ppython.exe" AskConfirmation 0
@@ -501,7 +574,7 @@ Function ConfirmPythonSelection
     ; of a different Panda3D build.)  Ask the user if he's sure about this.
     AskConfirmation:
     MessageBox MB_YESNO|MB_ICONQUESTION \
-        "You do not appear to have a ${REGVIEW}-bit version of Python ${PYVER} installed.  Are you sure you don't want Panda to install a compatible copy of Python?$\r$\n$\r$\nIf you choose Yes, you will not be able to do Python development with Panda3D until you install a ${REGVIEW}-bit version of Python ${PYVER} and manually configure it to be able to use Panda3D." \
+        "You do not appear to have a ${REGVIEW}-bit version of Python ${INCLUDE_PYVER} installed.  Are you sure you don't want Panda to install a compatible copy of Python?$\r$\n$\r$\nIf you choose Yes, you will not be able to do Python development with Panda3D until you install a ${REGVIEW}-bit version of Python and install the bindings for this version." \
         IDYES SkipCheck
 
     ; User clicked no, so re-enable the select box and abort.
@@ -511,9 +584,10 @@ Function ConfirmPythonSelection
 
     SkipCheck:
 FunctionEnd
+!endif
 
 Section "C++ support" SecHeadersLibs
-    SectionIn 1
+    SectionIn 1 2
 
     SetDetailsPrint both
     DetailPrint "Installing header files..."
@@ -532,7 +606,7 @@ SectionEnd
 
 !ifdef HAVE_SAMPLES
 Section "Sample programs" SecSamples
-    SectionIn 1
+    SectionIn 1 2
 
     ; Necessary for proper start menu shortcut installation
     SetShellVarContext current
@@ -599,7 +673,7 @@ SectionEnd
 
 !ifdef HAVE_MAX_PLUGINS
 Section "3ds Max plug-ins" SecMaxPlugins
-    SectionIn 1 3
+    SectionIn 1 2
 
     SetDetailsPrint both
     DetailPrint "Installing Autodesk 3ds Max plug-ins..."
@@ -614,7 +688,7 @@ SectionEnd
 
 !ifdef HAVE_MAYA_PLUGINS
 Section "Maya plug-ins" SecMayaPlugins
-    SectionIn 1 3
+    SectionIn 1 2
 
     SetDetailsPrint both
     DetailPrint "Installing Autodesk Maya plug-ins..."
@@ -737,17 +811,30 @@ Section Uninstall
     DeleteRegKey HKCU "Software\Classes\Panda3D.Multifile\DefaultIcon"
     DeleteRegKey HKCU "Software\Classes\Panda3D.Multifile\shell"
 
-    ReadRegStr $0 HKLM "Software\Python\PythonCore\${PYVER}\InstallPath" ""
-    StrCmp $0 "$INSTDIR\python" 0 +2
-    DeleteRegKey HKLM "Software\Python\PythonCore\${PYVER}"
+    !ifdef INCLUDE_PYVER
+        ReadRegStr $0 HKLM "Software\Python\PythonCore\${INCLUDE_PYVER}\InstallPath" ""
+        StrCmp $0 "$INSTDIR\python" 0 +2
+        DeleteRegKey HKLM "Software\Python\PythonCore\${INCLUDE_PYVER}"
 
-    ReadRegStr $0 HKCU "Software\Python\PythonCore\${PYVER}\InstallPath" ""
-    StrCmp $0 "$INSTDIR\python" 0 +2
-    DeleteRegKey HKCU "Software\Python\PythonCore\${PYVER}"
+        ReadRegStr $0 HKCU "Software\Python\PythonCore\${INCLUDE_PYVER}\InstallPath" ""
+        StrCmp $0 "$INSTDIR\python" 0 +2
+        DeleteRegKey HKCU "Software\Python\PythonCore\${INCLUDE_PYVER}"
+    !endif
 
-    ReadRegStr $0 HKCU "Software\Python\PythonCore\${PYVER}\PythonPath\Panda3D" ""
-    StrCmp $0 "$INSTDIR" 0 +2
-    DeleteRegKey HKCU "Software\Python\PythonCore\${PYVER}\PythonPath\Panda3D"
+    !insertmacro RemovePythonPath 2.7
+    !if "${REGVIEW}" == "32"
+        !insertmacro RemovePythonPath 3.5-32
+        !insertmacro RemovePythonPath 3.6-32
+        !insertmacro RemovePythonPath 3.7-32
+        !insertmacro RemovePythonPath 3.8-32
+        !insertmacro RemovePythonPath 3.9-32
+    !else
+        !insertmacro RemovePythonPath 3.5
+        !insertmacro RemovePythonPath 3.6
+        !insertmacro RemovePythonPath 3.7
+        !insertmacro RemovePythonPath 3.8
+        !insertmacro RemovePythonPath 3.9
+    !endif
 
     SetDetailsPrint both
     DetailPrint "Deleting files..."
@@ -812,8 +899,23 @@ SectionEnd
     !insertmacro MUI_DESCRIPTION_TEXT ${SecRocket} $(DESC_SecRocket)
   !endif
   !insertmacro MUI_DESCRIPTION_TEXT ${SecTools} $(DESC_SecTools)
-  !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings} $(DESC_SecPyBindings)
-  !ifdef HAVE_PYTHON
+  !insertmacro MUI_DESCRIPTION_TEXT ${SecGroupPython} $(DESC_SecGroupPython)
+  !insertmacro MUI_DESCRIPTION_TEXT ${SecPyShared} $(DESC_SecPyShared)
+  !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings2.7} $(DESC_SecPyBindings2.7)
+  !if "${REGVIEW}" == "32"
+    !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.5-32} $(DESC_SecPyBindings3.5-32)
+    !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.6-32} $(DESC_SecPyBindings3.6-32)
+    !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.7-32} $(DESC_SecPyBindings3.7-32)
+    !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.8-32} $(DESC_SecPyBindings3.8-32)
+    !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.9-32} $(DESC_SecPyBindings3.9-32)
+  !else
+    !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.5} $(DESC_SecPyBindings3.5)
+    !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.6} $(DESC_SecPyBindings3.6)
+    !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.7} $(DESC_SecPyBindings3.7)
+    !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.8} $(DESC_SecPyBindings3.8)
+    !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.9} $(DESC_SecPyBindings3.9)
+  !endif
+  !ifdef INCLUDE_PYVER
     !insertmacro MUI_DESCRIPTION_TEXT ${SecPython} $(DESC_SecPython)
   !endif
   !insertmacro MUI_DESCRIPTION_TEXT ${SecHeadersLibs} $(DESC_SecHeadersLibs)

+ 17 - 17
makepanda/makepackage.py

@@ -168,17 +168,10 @@ def MakeInstallerNSIS(version, file, title, installdir, runtime=False, compresso
     elif os.path.isdir(file):
         shutil.rmtree(file)
 
-    if "PYTHONVERSION" in SDK:
-        pyver = SDK["PYTHONVERSION"][6:9]
-    else:
-        pyver = "%d.%d" % (sys.version_info[:2])
-
     if GetTargetArch() == 'x64':
         regview = '64'
     else:
         regview = '32'
-        if int(pyver[0]) == 3 and int(pyver[2]) >= 5:
-            pyver += '-32'
 
     if runtime:
         # Invoke the make_installer script.
@@ -211,11 +204,22 @@ def MakeInstallerNSIS(version, file, title, installdir, runtime=False, compresso
         'OUTFILE'   : '..\\' + file,
         'BUILT'     : '..\\' + outputdir,
         'SOURCE'    : '..',
-        'PYVER'     : pyver,
         'REGVIEW'   : regview,
-        'EXT_SUFFIX': GetExtensionSuffix(),
     }
 
+    # Are we shipping a version of Python?
+    if os.path.isfile(os.path.join(outputdir, "python", "python.exe")):
+        py_dlls = glob.glob(os.path.join(outputdir, "python", "python[0-9][0-9].dll")) \
+                + glob.glob(os.path.join(outputdir, "python", "python[0-9][0-9]_d.dll"))
+        assert py_dlls
+        py_dll = os.path.basename(py_dlls[0])
+        pyver = py_dll[6] + "." + py_dll[7]
+
+        if GetTargetArch() != 'x64':
+            pyver += '-32'
+
+        nsis_defs['INCLUDE_PYVER'] = pyver
+
     if GetHost() == 'windows':
         cmd = os.path.join(GetThirdpartyBase(), 'win-nsis', 'makensis') + ' /V2'
         for item in nsis_defs.items():
@@ -651,7 +655,7 @@ def MakeInstallerOSX(version, runtime=False, python_versions=[], **kwargs):
     dist.write('        <line choice="base"/>\n')
     if python_versions:
         dist.write('        <line choice="pythoncode">\n')
-        for version_info in python_versions:
+        for version_info in sorted(python_versions, key=lambda info:info["version"], reverse=True):
             dist.write('            <line choice="pybindings%s"/>\n' % (version_info["version"]))
         dist.write('        </line>\n')
     dist.write('        <line choice="tools"/>\n')
@@ -978,13 +982,9 @@ def MakeInstaller(version, **kwargs):
 
         fn += version
 
-        if "PYTHONVERSION" in SDK:
-            pyver = SDK["PYTHONVERSION"][6:9]
-        else:
-            pyver = "%d.%d" % (sys.version_info[:2])
-
-        if not runtime and pyver != "2.7":
-            fn += '-py' + pyver
+        python_versions = kwargs.get('python_versions', [])
+        if not runtime and len(python_versions) == 1 and python_versions[0]["version"] != "2.7":
+            fn += '-py' + python_versions[0]["version"]
 
         if GetOptimize() <= 2:
             fn += "-dbg"