Panda3D

mayaWrapper.cxx

00001 ///////////////////////////////////////////////////////////////////////
00002 //
00003 // When multiple versions of maya are installed, maya2egg can
00004 // accidentally use the wrong version of the OpenMaya libraries.
00005 // This small wrapper program alters your PATH, MAYA_LOCATION, etc
00006 // environment variables in order to ensure that maya2egg finds the
00007 // right ligraries.
00008 //
00009 // To use this wrapper, maya2egg must be renamed to maya2egg-wrapped.
00010 // Then, this wrapper program must be installed as maya2egg.
00011 //
00012 ///////////////////////////////////////////////////////////////////////
00013 
00014 
00015 #ifndef MAYAVERSION
00016 #error You must define the symbol MAYAVERSION when compiling mayawrapper.
00017 #endif
00018 
00019 #define QUOTESTR(x) #x
00020 #define TOSTRING(x) QUOTESTR(x)
00021 
00022 #define _CRT_SECURE_NO_DEPRECATE 1
00023 
00024 #ifdef _WIN32
00025   #include <windows.h>
00026   #include <winuser.h>
00027   #include <process.h>
00028 #else
00029   #include <string.h>
00030   #include <sys/types.h>
00031   #include <sys/stat.h>
00032   #include <unistd.h>
00033   #define _putenv putenv
00034 #endif
00035 #ifdef __APPLE__
00036   #include <sys/malloc.h>
00037 #else
00038   #include <malloc.h>
00039 #endif
00040 #include <stdlib.h>
00041 #include <stdio.h>
00042 #include <signal.h>
00043 #include <limits.h>
00044 #define PATH_MAX 1024
00045 
00046 #ifdef __APPLE__
00047   // This is for _NSGetExecutablePath().
00048   #include <mach-o/dyld.h>
00049 #endif
00050 
00051 struct { char *ver, *key; } maya_versions[] = {
00052   { "MAYA6",    "6.0" },
00053   { "MAYA65",   "6.5" },
00054   { "MAYA7",    "7.0" },
00055   { "MAYA8",    "8.0" },
00056   { "MAYA85",   "8.5" },
00057   { "MAYA2008", "2008" },
00058   { "MAYA2009", "2009" },
00059   { "MAYA2010", "2010" },
00060   { "MAYA2011", "2011"},
00061   { 0, 0 },
00062 };
00063 
00064 char *getVersionNumber(char *ver) {
00065   for (int i=0; maya_versions[i].ver != 0; i++) {
00066     if (strcmp(maya_versions[i].ver, ver)==0) {
00067       return maya_versions[i].key;
00068     }
00069   }
00070   return 0;
00071 }
00072 
00073 #if defined(_WIN32)
00074 void getMayaLocation(char *ver, char *loc)
00075 {
00076   char fullkey[1024], *developer;
00077   HKEY hkey; DWORD size, dtype; LONG res; int dev, hive;
00078 
00079   for (dev=0; dev<3; dev++) {
00080     switch (dev) {
00081     case 0: developer="Alias|Wavefront"; break;
00082     case 1: developer="Alias"; break;
00083     case 2: developer="Autodesk"; break;
00084     }
00085     sprintf(fullkey, "SOFTWARE\\%s\\Maya\\%s\\Setup\\InstallPath", developer, ver);
00086     for (hive=0; hive<2; hive++) {
00087       loc[0] = 0;
00088       res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, fullkey, 0, KEY_READ | (hive ? 256:0), &hkey);
00089       if (res == ERROR_SUCCESS) {
00090         size=1024;
00091         res = RegQueryValueEx(hkey, "MAYA_INSTALL_LOCATION", NULL, &dtype, (LPBYTE)loc, &size);
00092         if ((res == ERROR_SUCCESS)&&(dtype == REG_SZ)) {
00093           loc[size] = 0;
00094           return;
00095         } else {
00096           loc[0] = 0;
00097         }
00098         RegCloseKey(hkey);
00099       }
00100     }
00101   }
00102 }
00103 
00104 void getWrapperName(char *prog)
00105 {
00106   DWORD res;
00107   res = GetModuleFileName(NULL, prog, 1000);
00108   if (res == 0) {
00109     prog[0] = 0;
00110     return;
00111   }
00112   int len = strlen(prog);
00113   if (_stricmp(prog+len-4, ".exe")) {
00114     prog[0] = 0;
00115     return;
00116   }
00117   prog[len-4] = 0;
00118 }
00119 
00120 #elif defined(__APPLE__)
00121 void getMayaLocation(char *ver, char *loc)
00122 {
00123   char mpath[64];
00124   sprintf(mpath, "/Applications/Autodesk/maya%s/Maya.app/Contents", ver);
00125   struct stat st;
00126   if(stat(mpath, &st) == 0) {
00127     strcpy(loc, mpath);
00128   } else {
00129     loc[0] = 0;
00130   }
00131 }
00132 
00133 void getWrapperName(char *prog)
00134 {
00135   char *pathbuf = new char[PATH_MAX];
00136   uint32_t bufsize = PATH_MAX;
00137   if (_NSGetExecutablePath(pathbuf, &bufsize) == 0) {
00138     strcpy(prog, pathbuf);
00139   } else {
00140     prog[0] = 0;
00141   }
00142   delete[] pathbuf;
00143 }
00144 
00145 #else
00146 void getMayaLocation(char *ver, char *loc)
00147 {
00148   char mpath[64];
00149 #if __WORDSIZE == 64
00150   sprintf(mpath, "/usr/autodesk/maya%s-x64", ver);
00151 #else
00152   sprintf(mpath, "/usr/autodesk/maya%s", ver);
00153 #endif
00154   struct stat st;
00155   if(stat(mpath, &st) == 0) {
00156     strcpy(loc, mpath);
00157   } else {
00158 #if __WORDSIZE == 64
00159     sprintf(mpath, "/usr/aw/maya%s-x64", ver);
00160 #else
00161     sprintf(mpath, "/usr/aw/maya%s", ver);
00162 #endif
00163     if(stat(mpath, &st) == 0) {
00164       strcpy(loc, mpath);
00165     } else {
00166       loc[0] = 0;
00167     }
00168   }
00169 }
00170 
00171 void getWrapperName(char *prog)
00172 {
00173   char readlinkbuf[PATH_MAX];
00174   int pathlen = readlink("/proc/self/exe", readlinkbuf, PATH_MAX-1);
00175   if (pathlen > 0) {
00176     readlinkbuf[pathlen] = 0;
00177     strcpy(prog, readlinkbuf);
00178   } else {
00179     prog[0] = 0;
00180   }
00181 }
00182 #endif
00183 
00184 int main(int argc, char **argv)
00185 {
00186   char loc[PATH_MAX], prog[PATH_MAX];
00187   char *key, *path, *env1, *env2, *env3, *env4;
00188   int nLocLen;
00189   
00190   key = getVersionNumber(TOSTRING(MAYAVERSION));
00191   if (key == 0) {
00192     printf("MayaWrapper: unknown maya version %s\n", TOSTRING(MAYAVERSION));
00193     exit(1);
00194   }
00195   
00196   getMayaLocation(key, loc);
00197   if (loc[0]==0) {
00198     printf("Cannot locate %s - it does not appear to be installed\n", TOSTRING(MAYAVERSION));
00199     exit(1);
00200   }
00201   
00202   getWrapperName(prog);
00203   if (prog[0]==0) {
00204     printf("mayaWrapper cannot determine its own filename (bug)\n");
00205     exit(1);
00206   }  
00207   
00208 #ifdef _WIN32
00209   strcat(prog, "-wrapped.exe");
00210 #else
00211   strcat(prog, "-wrapped");
00212 #endif
00213 
00214   // "loc" == MAYA_LOCATION
00215   // Now set PYTHONHOME & PYTHONPATH.  Maya requires this to be
00216   // set and pointing within MAYA_LOCATION, or it might get itself
00217   // confused with another Python installation (e.g. Panda's).
00218   // Finally, prepend PATH with MAYA_LOCATION\bin; as well.
00219 
00220 // As of Sept. 2009, at least some WIN32 platforms had 
00221 // much difficulty with Maya 2009 egging, e.g., see forums:
00222 // http://www.panda3d.org/phpbb2/viewtopic.php?p=42790 
00223 // 
00224 // Historically:
00225 // http://www.panda3d.org/phpbb2/viewtopic.php?t=3842 
00226 // http://www.panda3d.org/phpbb2/viewtopic.php?t=6468 
00227 // http://www.panda3d.org/phpbb2/viewtopic.php?t=6533 
00228 // http://www.panda3d.org/phpbb2/viewtopic.php?t=5070 
00229 // 
00230 // Hoped solution:  carry over code that was in mayapath.cxx 
00231 // and use that here to set 4 important environment variables:
00232 // MAYA_LOCATION
00233 // PYTHONPATH
00234 // PYTHONHOME
00235 // PATH (add Maya bin to start of this)
00236 // BUT... mayapath.cxx makes use of FILENAME and other code
00237 // from the rest of the Panda build, so for now, to keep this
00238 // wrapper thinner, just correct/verify that the latter 3 environment
00239 // variables are set properly (as they are in mayapath.cxx)
00240 // for use with Maya under WIN32.
00241 // FIRST TRY, keeping PYTHONPATH simple, as just loc\Python, failed.
00242 // SECOND TRY, as coded formerly here (in mayaWrapper.cxx), also fails:
00243 //   PYTHONPATH=%s\\bin;%s\\Python;%s\\Python\\DLLs;%s\\Python\\lib;%s\\Python\\lib\\site-packages
00244 // Eventually, solution was found that has AT MOST this (which does NOT match mayapath.cxx....):
00245 //   PYTHONPATH=%s\\bin\\python25.zip;%s\\Python\\DLLs;%s\\Python\\lib;%s\\Python\\lib\\plat-win;%s\\Python\\lib\\lib-tk;%s\\bin;%s\\Python;%s\\Python\\lib\\site-packages", loc, loc, loc, loc, loc, loc, loc, loc);
00246 // One attempt to thin down to just the .zip file and the site-packages file works!  This seems to be minimum needed 
00247 // as removing the .zip file mentioned first will then break again with the dreaded:
00248 // "Invalid Python Environment: Python is unable to find Maya's Python modules"
00249 // Again, this minimal necessary set (for Maya 2009 32-bit at least) does NOT match mayapath.cxx....):
00250 //   PYTHONPATH=%s\\bin\\python25.zip;%s\\Python\\lib\\site-packages", loc, loc);
00251 // 
00252 
00253 #ifdef _WIN32
00254   // Not sure of non-WIN32 environments, but for WIN32,
00255   // verify that terminating directory/folder separator
00256   // character \ is NOT found at end of "loc" string:
00257   nLocLen = strlen(loc);
00258   if (nLocLen > 0 && loc[nLocLen - 1] == '\\')
00259   {
00260     loc[nLocLen - 1] = '\0';
00261   }
00262   path = getenv("PATH");
00263   if (path == 0) path = "";
00264   env1 = (char*)malloc(100 + strlen(loc) + strlen(path));
00265   sprintf(env1, "PATH=%s\\bin;%s", loc, path);
00266   env2 = (char*)malloc(100 + strlen(loc));
00267   sprintf(env2, "MAYA_LOCATION=%s", loc);
00268   env3 = (char*)malloc(100 + strlen(loc));
00269   sprintf(env3, "PYTHONHOME=%s\\Python", loc);
00270   env4 = (char*)malloc(100 + 2*strlen(loc));
00271   // FYI,  background on what does Maya (e.g., Maya 2009) expect
00272   // in PYTHONPATH by doing a check of sys.paths in Python
00273   // as discussed in 
00274   // http://www.rtrowbridge.com/blog/2008/11/27/maya-python-import-scripts/
00275   // gives this:
00276   // C:\Program Files\Autodesk\Maya2009\bin\python25.zip
00277   // C:\Program Files\Autodesk\Maya2009\Python\DLLs
00278   // C:\Program Files\Autodesk\Maya2009\Python\lib
00279   // C:\Program Files\Autodesk\Maya2009\Python\lib\plat-win
00280   // C:\Program Files\Autodesk\Maya2009\Python\lib\lib-tk
00281   // C:\Program Files\Autodesk\Maya2009\bin
00282   // C:\Program Files\Autodesk\Maya2009\Python
00283   // C:\Program Files\Autodesk\Maya2009\Python\lib\site-packages
00284   // ...
00285   // Experimenting and a check of 
00286   // http://www.panda3d.org/phpbb2/viewtopic.php?t=3842
00287   // leads to these 2 items being necessary and hopefully sufficient:
00288   // bin\python25.zip (within loc)
00289   // Python\lib\site-packages (within loc)
00290   // ...so set PYTHONPATH accordingly:
00291   if (strcmp(key, "2011") == 0) {
00292     //Maya 2011 is built against Python 2.6 so look for that one instead
00293     sprintf(env4, "PYTHONPATH=%s\\bin\\python26.zip;%s\\Python\\lib\\site-packages", loc, loc);
00294   } else {
00295     sprintf(env4, "PYTHONPATH=%s\\bin\\python25.zip;%s\\Python\\lib\\site-packages", loc, loc);
00296   }
00297   // Set environment variables MAYA_LOCATION, PYTHONHOME, PYTHONPATH, PATH
00298   _putenv(env2);
00299   _putenv(env3);
00300   _putenv(env4);
00301   _putenv(env1);
00302 #else
00303 #ifdef __APPLE__
00304   path = getenv("DYLD_LIBRARY_PATH");
00305   if (path == 0) path = "";
00306   env1 = (char*)malloc(100 + strlen(loc) + strlen(path));
00307   sprintf(env1, "DYLD_LIBRARY_PATH=%s/MacOS:%s", loc, path);
00308   env3 = (char*)malloc(100 + strlen(loc));
00309   sprintf(env3, "PYTHONHOME=%s/Frameworks/Python.framework/Versions/Current", loc);
00310   _putenv(env3);
00311 #else
00312   path = getenv("LD_LIBRARY_PATH");
00313   if (path == 0) path = "";
00314   env1 = (char*)malloc(100 + strlen(loc) + strlen(path));
00315   sprintf(env1, "LD_LIBRARY_PATH=%s/lib:%s", loc, path);
00316 #endif // __APPLE__
00317   env2 = (char*)malloc(100 + strlen(loc));
00318   sprintf(env2, "MAYA_LOCATION=%s", loc);
00319   
00320   _putenv(env1);
00321   _putenv(env2);
00322 #endif // _WIN32
00323 
00324   // When this is set, Panda3D will try not to use any functions from the
00325   // CPython API.  This is necessary because Maya links with its own copy
00326   // of Python, which may be incompatible with ours.
00327   _putenv("PANDA_INCOMPATIBLE_PYTHON=1");
00328   
00329 #ifdef _WIN32
00330   STARTUPINFO si; PROCESS_INFORMATION pi;
00331   char *cmd;
00332   
00333   cmd = GetCommandLine();
00334   memset(&si, 0, sizeof(si));
00335   si.cb = sizeof(STARTUPINFO);
00336   if (CreateProcess(prog, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
00337     WaitForSingleObject(pi.hProcess, INFINITE);
00338     exit(0);
00339   } else {
00340     printf("Could not launch %s\n", prog);
00341     exit(1);
00342   }
00343 #else
00344   if (execvp(prog, argv) == 0) {
00345     exit(0);
00346   } else {
00347     printf("Could not launch %s\n", prog);
00348     exit(1);
00349   }
00350 #endif
00351 }
00352 
 All Classes Functions Variables Enumerations