blob: 052209b84cff58401a511926a714720e14d30412 [file] [log] [blame]
Deepak Panickal9b35cf52014-07-01 17:57:19 +00001""" SWIG creates Python C++ Script Bridge wrapper code Windows/LINUX/OSX platform
2
3 --------------------------------------------------------------------------
4 File: buildSwigWrapperClasses.py
5
6 Overview: Python script(s) to build the SWIG Python C++ Script
7 Bridge wrapper code on the Windows/LINUX/OSX platform.
8 The Python scripts are equivalent to the shell script (.sh)
9 files.
10 For each scripting language lib lldb supports, we need to
11 create the appropriate Script Bridge wrapper classes for
12 that language so that users can call Script Bridge
13 functions from within the script interpreter.
14 We use SWIG to help create the appropriate wrapper
15 classes/functions for the scripting language. In some
16 cases the file generated by SWIG may need some tweaking
17 before it is completely ready to use.
18
19 Environment: OS: Windows Vista or newer,LINUX,OSX.
20 IDE: Visual Studio 2013 Plugin Python Tools (PTVS)
21 Script: Python 2.6/2.7.5 x64
22 Other: SWIG 2.0.11
23
24 Gotchas: For Windows OS it is assumed the SWIG executable can be
25 found in the %PATH% environmental variable.
26
27 Copyright: None.
28 --------------------------------------------------------------------------
29
30"""
31
32# Python modules:
33import sys # Provide argument parsing
34import os # Provide directory and file handling
35
36# Third party modules:
37
38# In-house modules:
39import utilsArgsParse # Parse and validate this script's input arguments
40import utilsOsType # Determine the OS type this script is running on
41import utilsDebug # Debug Python scripts
42
43# Instantiations:
44gbDbgVerbose = False; # True = Turn on script function tracing, False = off.
45gbDbgFlag = False; # Global debug mode flag, set by input parameter
46 # --dbgFlag. True = operate in debug mode.
47gbMakeFileFlag = False; # True = yes called from makefile system, False = not.
48gbSwigGenDepFileFlag = False; # True = SWIG generate a dependency file.
49
50# User facing text:
51strMsgErrorNoMain = "Program called by another Python script not allowed";
52strExitMsgSuccess = "Program successful";
53strExitMsgError = "Program error: ";
54strParameter = "Parameter: ";
55strMsgErrorOsTypeUnknown = "Unable to determine OS type"
56strSwigFileFound = "Found the \'lldb.swig\' file\n";
57strSwigFileFoundNotFound = "Unable to locate the file \'%s\'"
58strSwigExeFileNotFound = "Unable to locate the SWIG executable file \'swig\'";
59strSwigScriptDirNotFound = "Unable to locate the SWIG script directory \'/script\'";
60strSwigScriptNotFound = "Unable to locate the SWIG script file \'%s\' in \'%s\'. Is it a script directory?";
61strSwigScriptLangFound = "Found \'%s\' build script.";
62strSwigScriptLangsFound = "Found the following script languages:";
63strSwigExecuteMsg = "Executing \'%s\' build script...";
64strSwigExecuteError = "Executing \'%s\' build script failed: ";
65strHelpInfo = "\
66Python script(s) to build the SWIG Python C++ Script \n\
67Bridge wrapper code on various platforms. The Python \n\
68scripts are equivalent to the shell script (.sh) files \n\
69run on others platforms.\n\
70Args: -h (optional) Print help information on this program.\n\
71 -d (optional) Determines whether or not this script\n\
72 outputs additional information when running.\n\
73 -m (optional) Specify called from Makefile system.\n\
74 -M (optional) Specify want SWIG to generate a dependency \n\
75 file.\n\
76 --srcRoot= The root of the lldb source tree.\n\
77 --targetDir= Where the lldb framework/shared library gets put.\n\
78 --cfgBldDir= (optional) Where the build-swig-Python-LLDB.py program \n\
79 will put the lldb.py file it generated from running\n\
80 SWIG.\n\
81 --prefix= (optional) Is the root directory used to determine where\n\
82 third-party modules for scripting languages should\n\
83 be installed. Where non-Darwin systems want to put\n\
84 the .py and .so files so that Python can find them\n\
85 automatically. Python install directory.\n\
86 --argsFile= The args are read from a file instead of the\n\
87 command line. Other command line args are ignored.\n\
88\n\
89Usage:\n\
90 buildSwigWrapperClasses.py --srcRoot=ADirPath --targetDir=ADirPath\n\
91 --cfgBldDir=ADirPath --prefix=ADirPath -m -d\n\
92\n\
93"; #TAG_PROGRAM_HELP_INFO
94strHelpInfoExtraWindows = "\
95On the Windows platform the PATH environmental variable needs to be \n\
96extended to include the installed SWIG executable path so it can be \n\
97be found by this Python script. The SWIG executable name is 'swig'."
98strHelpInfoExtraNonWindows = "\
99This Python script looks for the SWIG executable 'swig' in the following \n\
100directories '/usr/bin', '/usr/local/bin'. If not found the script will \n\
101abort.";
102
103#++---------------------------------------------------------------------------
104# Details: Retrieve the script -h help information based on the OS currently.
105# Args: None.
106# Returns: Str - Help Text.
107# Throws: None.
108#--
109def get_help_information():
110 strHelpMsg = strHelpInfo;
111
112 eOSType = utilsOsType.determine_os_type();
113 if eOSType == utilsOsType.EnumOsType.Windows:
114 strHelpMsg += strHelpInfoExtraWindows;
115 else:
116 strHelpMsg += strHelpInfoExtraNonWindows;
117
118 return strHelpMsg;
119
120#++---------------------------------------------------------------------------
121# Details: Exit the program on success. Called on program successfully done
122# its work. Returns a status result to the caller.
123# Args: vnResult - (R) 0 or greater indicating success.
124# vMsg - (R) Success message if any to show success to user.
125# Returns: None.
126# Throws: None.
127#--
128def program_exit_success( vnResult, vMsg ):
129 strMsg = "";
130
131 if vMsg.__len__() == 0:
132 strMsg = "%s (%d)" % (strExitMsgSuccess, vnResult);
133 else:
134 strMsg = "%s: %s (%d)" % (strExitMsgSuccess, vMsg, vnResult);
135 print strMsg;
136
137 sys.exit( vnResult );
138
139#++---------------------------------------------------------------------------
140# Details: Exit the program with error. Called on exit program failed its
141# task. Returns a status result to the caller.
142# Args: vnResult - (R) A negative number indicating error condition.
143# vMsg - (R) Error message to show to user.
144# Returns: None.
145# Throws: None.
146#--
147def program_exit_on_failure( vnResult, vMsg ):
148 print "%s%s (%d)" % (strExitMsgError, vMsg, vnResult);
149 sys.exit( vnResult );
150
151#++---------------------------------------------------------------------------
152# Details: Exit the program return a exit result number and print a message.
153# Positive numbers and zero are returned for success other error
154# occurred.
155# Args: vnResult - (R) A -ve (an error), 0 or +ve number (ok or status).
156# vMsg - (R) Error message to show to user.
157# Returns: None.
158# Throws: None.
159#--
160def program_exit( vnResult, vMsg ):
161 if vnResult >= 0:
162 program_exit_success( vnResult, vMsg );
163 else:
164 program_exit_on_failure( vnResult, vMsg );
165
166#++---------------------------------------------------------------------------
167# Details: Dump input parameters.
168# Args: vDictArgs - (R) Map of input args to value.
169# Returns: None.
170# Throws: None.
171#--
172def print_out_input_parameters( vDictArgs ):
173 for arg, val in vDictArgs.iteritems():
174 strEqs = "";
175 strQ = "";
176 if val.__len__() != 0:
177 strEqs = " =";
178 strQ = "\"";
179 print "%s%s%s %s%s%s\n" % (strParameter, arg, strEqs, strQ, val, strQ);
180
181#++---------------------------------------------------------------------------
182# Details: Locate the lldb.swig file. No checking for path correctness is
183# done here as assumed all values checked already. Path is adapted
184# to be compatible with the platform file system.
185# Args: vstrSrcRoot - (R) Directory path to the lldb source root.
186# veOSType - (R) Current OS type enumeration.
187# Returns: Bool - True = Success.
188# - False = Failure file not found.
189# Str - Error message.
190# Throws: None.
191#--
192def check_lldb_swig_file_exists( vstrSrcRoot, veOSType ):
193 dbg = utilsDebug.CDebugFnVerbose( "check_lldb_swig_file_exists()" );
194 bOk = True;
195 strStatusMsg = "";
196 strSwigFilePathName = "/scripts/lldb.swig";
197
198 strFullPath = os.path.normcase( vstrSrcRoot + strSwigFilePathName );
199 bOk = os.path.isfile( strFullPath );
200 if bOk:
201 if gbDbgFlag:
202 print strSwigFileFound;
203 else:
204 strStatusMsg = strSwigFileFoundNotFound % strFullPath;
205
206 return (bOk, strStatusMsg);
207
208#++---------------------------------------------------------------------------
209# Details: Locate SWIG sub script language directory and the script within
210# and execute SWIG for that script language.
211# Args: vStrScriptLang - (R) Name of the script language to build.
212# vSwigBuildFileName - (R) Prefix file name to build full name.
213# vDictArgs - (R) Program input parameters.
214# Returns: Int - 0 = Success, < 0 some error condition.
215# Str - Error message.
216# Throws: None.
217#--
218def run_swig( vStrScriptLang, vSwigBuildFileName, vDictArgs ):
219 dbg = utilsDebug.CDebugFnVerbose( "run_swig()" );
220 nResult = 0;
221 strStatusMsg = "";
222 strScriptFile = vSwigBuildFileName % vStrScriptLang;
223 strScriptFileDir = "%s%s/%s" % (vDictArgs[ "--srcRoot" ], "/scripts",
224 vStrScriptLang);
225 strScriptFilePath = "%s/%s" % (strScriptFileDir, strScriptFile);
226
227 # Check for the existence of the script file
228 strPath = os.path.normcase( strScriptFilePath );
229 bOk = os.path.exists( strPath );
230 if bOk == False:
231 strDir = os.path.normcase( strScriptFileDir );
232 strStatusMsg = strSwigScriptNotFound % (strScriptFile, strDir);
233 return (-9, strStatusMsg);
234
235 if gbDbgFlag:
236 print strSwigScriptLangFound % vStrScriptLang;
237 print strSwigExecuteMsg % vStrScriptLang;
238
239 # Change where Python looks for our modules
240 strDir = os.path.normcase( strScriptFileDir );
241 sys.path.append( strDir );
242
243 # Execute the specific language script
244 dictArgs = vDictArgs; # Remove any args not required before passing on
245 strModuleName = strScriptFile[ : strScriptFile.__len__() - 3 ];
246 module = __import__( strModuleName );
247 nResult, strStatusMsg = module.main( dictArgs );
248
249 # Revert sys path
250 sys.path.remove( strDir );
251
252 return (nResult, strStatusMsg);
253
254#++---------------------------------------------------------------------------
255# Details: Step through each SWIG sub directory script language supported
256# type and execute SWIG to build wrapper code based on that language.
257# If an error occurs for a build this function will return with an
258# error and not continue with proceed script builds.
259# For each scripting language, make sure the build script for that
260# language exists.
261# For now the only language we support is Python, but we expect this
262# to change.
263# Args: vDictArgs - (R) Program input parameters.
264# Returns: Int - 0 = Success, < 0 some error condition.
265# Str - Error message.
266# Throws: None.
267#--
268def run_swig_for_each_script_supported( vDictArgs ):
269 dbg = utilsDebug.CDebugFnVerbose( "run_swig_for_each_script_supported()" );
270 nResult = 0;
271 strStatusMsg = "";
272 strSwigScriptDir = vDictArgs[ "--srcRoot" ] + "/scripts";
273 strSwigBuildFileName = "buildSwig%s.py";
274
275 # Check for the existence of the SWIG scripts folder
276 strScriptsDir = os.path.normcase( strSwigScriptDir );
277 bOk = os.path.exists( strScriptsDir );
278 if bOk == False:
279 return (-8, strSwigScriptDirNotFound);
280
281 # Look for any script language directories to build for
282 listDirs = [];
283 nDepth = 1;
284 for strPath, listDirs, listFiles in os.walk( strSwigScriptDir ):
285 nDepth = nDepth - 1;
286 if nDepth == 0:
287 break;
288
289 if gbDbgFlag:
290 print strSwigScriptLangsFound,
291 for dir in listDirs:
292 print dir,
293 print "\n";
294
295 # Iterate script directory find any script language directories
296 for scriptLang in listDirs:
297 dbg.dump_text( "Executing language script for \'%s\'" % scriptLang );
298 nResult, strStatusMsg = run_swig( scriptLang, strSwigBuildFileName,
299 vDictArgs );
300 if nResult < 0:
301 break;
302
303 if nResult < 0:
304 strTmp = strSwigExecuteError % scriptLang;
305 strTmp += strStatusMsg;
306 strStatusMsg = strTmp;
307
308 return (nResult, strStatusMsg);
309
310#++---------------------------------------------------------------------------
311# Details: Dummy function - system unknown. Function should not be called.
312# Args: vDictArgs - (R) Program input parameters.
313# Returns: Bool - False = Program logic error.
314# Str - Error message.
315# Throws: None.
316#--
317def check_lldb_swig_executable_file_exists_Unknown( vDictArgs ):
318 dbg = utilsDebug.CDebugFnVerbose( "check_lldb_swig_executable_file_exists_Unknown()" );
319 # Do nothing
320 return (False, strMsgErrorOsTypeUnknown);
321
322#++---------------------------------------------------------------------------
323# Details: Locate the SWIG executable file in a Windows system. Several hard
324# coded predetermined possible file path locations are searched.
325# (This is good candidate for a derived class object)
326# Args: vDictArgs - (W) Program input parameters.
327# Returns: Bool - True = Success.
328# - False = Failure file not found.
329# Str - Error message.
330# Throws: None.
331#--
332def check_lldb_swig_executable_file_exists_windows( vDictArgs ):
333 dbg = utilsDebug.CDebugFnVerbose( "check_lldb_swig_executable_file_exists_windows()" );
334
335 # Will always be true as it assumed the path to SWIG executable will be
336 # in the OS system environmental variable %PATH%. Easier this way as the
337 # user may have renamed the directory and or custom path installation.
338 bExeFileFound = True;
339 vDictArgs[ "--swigExePath" ] = "";
340 vDictArgs[ "--swigExeName" ] = "swig.exe";
341 return (bExeFileFound, None);
342
343#++---------------------------------------------------------------------------
344# Details: Locate the SWIG executable file in a Linux system. Several hard
345# coded predetermined possible file path locations are searched.
346# (This is good candidate for a derived class object)
347# Args: vDictArgs - (W) Program input parameters.
348# Returns: Bool - True = Success.
349# - False = Failure file not found.
350# Str - Error message.
351# Throws: None.
352#--
353def check_lldb_swig_executable_file_exists_Linux( vDictArgs ):
354 dbg = utilsDebug.CDebugFnVerbose( "check_lldb_swig_executable_file_exists_Linux()" );
355 bExeFileFound = False;
356
357 strSwigExe = "swig";
358 strSwigExePath = "/usr/bin";
359 strExe = os.path.normcase( "%s/%s" % (strSwigExePath, strSwigExe) );
360 if os.path.isfile( strExe ) and os.access( strExe, os.X_OK ):
361 bExeFileFound = True;
362 vDictArgs[ "--swigExePath" ] = os.path.normcase( strSwigExePath );
363 vDictArgs[ "--swigExeName" ] = strSwigExe;
364 return (bExeFileFound, None);
365
366 strSwigExePath = "/usr/local/bin";
367 strExe = os.path.normcase( "%s/%s" % (strSwigExePath, strSwigExe) );
368 if os.path.isfile( strExe ) and os.access( strExe, os.X_OK ):
369 bExeFileFound = True;
370 vDictArgs[ "--swigExePath" ] = os.path.normcase( strSwigExePath );
371 vDictArgs[ "--swigExeName" ] = strSwigExe;
372 return (bExeFileFound, None);
373
374 return (bExeFileFound, strSwigExeFileNotFound);
375
376#++---------------------------------------------------------------------------
377# Details: Locate the SWIG executable file in a OSX system. Several hard
378# coded predetermined possible file path locations are searched.
379# (This is good candidate for a derived class object)
380# Args: vDictArgs - (W) Program input parameters.
381# Returns: Bool - True = Success.
382# - False = Failure file not found.
383# Str - Error message.
384# Throws: None.
385#--
386def check_lldb_swig_executable_file_exists_Darwin( vDictArgs ):
387 dbg = utilsDebug.CDebugFnVerbose( "check_lldb_swig_executable_file_exists_Darwin()" );
388 bExeFileFound = False;
389 # ToDo: Find the SWIG executable and add the path to the args dictionary
390 #vDictArgs.[ "--swigExePath" ] = "/usr/bin/swig";
391 strStatusMsg = "Sorry function 'check_lldb_swig_executable_file_exists_Darwin()' is not implemented";
392
393 return (bExeFileFound, strStatusMsg);
394
395#++---------------------------------------------------------------------------
396# Details: Locate the SWIG executable file. Several hard coded predetermined
397# possible file path locations are searched.
398# Args: vDictArgs - (RW) Program input parameters.
399# veOSType - (R) Current OS type enumeration.
400# Returns: Bool - True = Success.
401# - False = Failure file not found.
402# Str - Error message.
403# Throws: None.
404#--
405def check_lldb_swig_executable_file_exists( vDictArgs, veOSType ):
406 dbg = utilsDebug.CDebugFnVerbose( "check_lldb_swig_executable_file_exists()" );
407 bExeFileFound = False;
408 strStatusMsg = "";
409
410 switch = { 0 : check_lldb_swig_executable_file_exists_Unknown,
411 1 : check_lldb_swig_executable_file_exists_windows,
412 2 : check_lldb_swig_executable_file_exists_Linux,
413 3 : check_lldb_swig_executable_file_exists_Darwin }
414 bExeFileFound, strStatusMsg = switch[ veOSType ]( vDictArgs );
415
416 return (bExeFileFound, strStatusMsg);
417
418#++---------------------------------------------------------------------------
419# Details: Validate the arguments passed to the program. This function exits
420# the program should error with the arguments be found.
421# Args: vArgv - (R) List of arguments and values.
422# Returns: Int - 0 = success, -ve = some failure.
423# Dict - Map of arguments names to argument values
424# Throws: None.
425#--
426def validate_arguments( vArgv ):
427 dbg = utilsDebug.CDebugFnVerbose( "validate_arguments()" );
428 strMsg = "";
429 dictArgs = {};
430 nResult = 0;
431 strListArgs = "hdmM"; # Format "hiox:" = -h -i -o -x <arg>
432 listLongArgs = ["srcRoot=", "targetDir=", "cfgBldDir=", "prefix=",
433 "argsFile"];
434 dictArgReq = { "-h": "o", # o = optional, m = mandatory
435 "-d": "o",
436 "-m": "o",
437 "-M": "o",
438 "--srcRoot": "m",
439 "--targetDir": "m",
440 "--cfgBldDir": "o",
441 "--prefix": "o",
442 "--argsFile": "o" };
443 strHelpInfo = get_help_information();
444
445 # Check for mandatory parameters
446 nResult, dictArgs, strMsg = utilsArgsParse.parse( vArgv, strListArgs,
447 listLongArgs,
448 dictArgReq,
449 strHelpInfo );
450 if nResult < 0:
451 program_exit_on_failure( nResult, strMsg );
452
453 # User input -h for help
454 if nResult == 1:
455 program_exit_success( 0, strMsg );
456
457 return (nResult, dictArgs);
458
459#++---------------------------------------------------------------------------
460# Details: Program's main() with arguments passed in from the command line.
461# Program either exits normally or with error from this function -
462# top most level function.
463# Args: vArgv - (R) List of arguments and values.
464# Returns: None
465# Throws: None.
466#--
467def main( vArgv ):
468 dbg = utilsDebug.CDebugFnVerbose( "main()" );
469 bOk = False;
470 dictArgs = {};
471 nResult = 0;
472 strMsg = "";
473
474 # The validate arguments fn will exit the program if tests fail
475 nResult, dictArgs = validate_arguments( vArgv );
476
477 eOSType = utilsOsType.determine_os_type();
478 if eOSType == utilsOsType.EnumOsType.Unknown:
479 program_exit( -4, strMsgErrorOsTypeUnknown );
480
481 global gbDbgFlag;
482 gbDbgFlag = dictArgs.has_key( "-d" );
483 if gbDbgFlag:
484 print_out_input_parameters( dictArgs );
485
486 # Check to see if we were called from the Makefile system. If we were, check
487 # if the caller wants SWIG to generate a dependency file.
488 # Not used in this program, but passed through to the language script file
489 # called by this program
490 global gbMakeFileFlag;
491 global gbSwigGenDepFileFlag;
492 gbMakeFileFlag = dictArgs.has_key( "-m" );
493 gbSwigGenDepFileFlag = dictArgs.has_key( "-M" );
494
495 bOk, strMsg = check_lldb_swig_file_exists( dictArgs[ "--srcRoot" ], eOSType );
496 if bOk == False:
497 program_exit( -3, strMsg );
498
499 bOk, strMsg = check_lldb_swig_executable_file_exists( dictArgs, eOSType );
500 if bOk == False:
501 program_exit( -6, strMsg );
502
503 nResult, strMsg = run_swig_for_each_script_supported( dictArgs );
504
505 program_exit( nResult, strMsg );
506
507#-----------------------------------------------------------------------------
508#-----------------------------------------------------------------------------
509#-----------------------------------------------------------------------------
510
511#TAG_PROGRAM_HELP_INFO
512""" Details: Program main entry point.
513
514 --------------------------------------------------------------------------
515 Args: -h (optional) Print help information on this program.
516 -d (optional) Determines whether or not this script
517 outputs additional information when running.
518 -m (optional) Specify called from Makefile system. If given locate
519 the LLDBWrapPython.cpp in --srcRoot/source folder
520 else in the --targetDir folder.
521 -M (optional) Specify want SWIG to generate a dependency file.
522 --srcRoot= The root of the lldb source tree.
523 --targetDir= Where the lldb framework/shared library gets put.
524 --cfgBldDir= Where the buildSwigPythonLLDB.py program will
525 (optional) put the lldb.py file it generated from running
526 SWIG.
527 --prefix= Is the root directory used to determine where
528 (optional) third-party modules for scripting languages should
529 be installed. Where non-Darwin systems want to put
530 the .py and .so files so that Python can find them
531 automatically. Python install directory.
532 --argsFile= The args are read from a file instead of the
533 command line. Other command line args are ignored.
534 Usage:
535 buildSwigWrapperClasses.py --srcRoot=ADirPath --targetDir=ADirPath
536 --cfgBldDir=ADirPath --prefix=ADirPath -m -d
537
538 Results: 0 Success
539 -1 Error - invalid parameters passed.
540 -2 Error - incorrect number of mandatory parameters passed.
541 -3 Error - unable to locate lldb.swig file.
542 -4 Error - unable to determine OS type.
543 -5 Error - program called by another Python script not allowed.
544 -6 Error - unable to locate the swig executable file.
545 -7 Error - SWIG script execution failed.
546 -8 Error - unable to locate the SWIG scripts folder.
547 -9 Error - unable to locate the SWIG language script file.
548 -100+ - Error messages from the SWIG language script file.
549 -200+ - 200 +- the SWIG exit result.
550 --------------------------------------------------------------------------
551
552"""
553
554# Called using "__main__" when not imported i.e. from the command line
555if __name__ == "__main__":
556 utilsDebug.CDebugFnVerbose.bVerboseOn = gbDbgVerbose;
557 dbg = utilsDebug.CDebugFnVerbose( "__main__" );
558 main( sys.argv[ 1: ] );
559else:
560 program_exit( -5, strMsgErrorNoMain );
561