def main(): """Main program flow of Nuitka At this point, options will be parsed already, Nuitka will be executing in the desired version of Python with desired flags, and we just get to execute the task assigned. We might be asked to only re-compile generated C, dump only an XML representation of the internal node tree after optimization, etc. """ # Main has to fulfill many options, leading to many branches and statements # to deal with them. pylint: disable=too-many-branches,too-many-statements # In case we are in a PGO run, we read its information first, so it becomes # available for later parts. pgo_filename = getPythonPgoInput() if pgo_filename is not None: readPGOInputFile(pgo_filename) if not Options.shallDumpBuiltTreeXML(): general.info( "Starting Python compilation with Nuitka %r on Python %r commercial %r." % (getNuitkaVersion(), python_version_str, getCommercialVersion()) ) filename = Options.getPositionalArgs()[0] # Inform the importing layer about the main script directory, so it can use # it when attempting to follow imports. Importing.setMainScriptDirectory( main_dir=os.path.dirname(os.path.abspath(filename)) ) addIncludedDataFilesFromFileOptions() # Turn that source code into a node tree structure. try: main_module = _createNodeTree(filename=filename) except (SyntaxError, IndentationError) as e: handleSyntaxError(e) addIncludedDataFilesFromPackageOptions() if Options.shallDumpBuiltTreeXML(): # XML output only. for module in ModuleRegistry.getDoneModules(): dumpTreeXML(module) else: # Make the actual compilation. result, options = compileTree() # Exit if compilation failed. if not result: sys.exit(1) # Relaunch in case of Python PGO input to be produced. if Options.shallCreatePgoInput(): # Will not return. pgo_filename = OutputDirectories.getPgoRunInputFilename() general.info( "Restarting compilation using collected information from '%s'." % pgo_filename ) reExecuteNuitka(pgo_filename=pgo_filename) if Options.shallNotDoExecCCompilerCall(): if Options.isShowMemory(): MemoryUsage.showMemoryTrace() sys.exit(0) executePostProcessing() copyDataFiles() if Options.isStandaloneMode(): binary_filename = options["result_exe"] setMainEntryPoint(binary_filename) dist_dir = OutputDirectories.getStandaloneDirectoryPath() for module in ModuleRegistry.getDoneModules(): addIncludedEntryPoints(Plugins.considerExtraDlls(dist_dir, module)) copyDllsUsed( source_dir=OutputDirectories.getSourceDirectoryPath(), dist_dir=dist_dir, standalone_entry_points=getStandaloneEntryPoints(), ) Plugins.onStandaloneDistributionFinished(dist_dir) if Options.isOnefileMode(): packDistFolderToOnefile(dist_dir, binary_filename) if Options.isRemoveBuildDir(): general.info("Removing dist folder %r." % dist_dir) removeDirectory(path=dist_dir, ignore_errors=False) else: general.info( "Keeping dist folder %r for inspection, no need to use it." % dist_dir ) # Remove the source directory (now build directory too) if asked to. source_dir = OutputDirectories.getSourceDirectoryPath() if Options.isRemoveBuildDir(): general.info("Removing build directory %r." % source_dir) removeDirectory(path=source_dir, ignore_errors=False) assert not os.path.exists(source_dir) else: general.info("Keeping build directory %r." % source_dir) final_filename = OutputDirectories.getResultFullpath( onefile=Options.isOnefileMode() ) if Options.isStandaloneMode() and isMacOS(): general.info( "Created binary that runs on macOS %s (%s) or higher." % (options["macos_min_version"], options["macos_target_arch"]) ) Plugins.onFinalResult(final_filename) general.info("Successfully created %r." % final_filename) report_filename = Options.getCompilationReportFilename() if report_filename: writeCompilationReport(report_filename) # Execute the module immediately if option was given. if Options.shallExecuteImmediately(): run_filename = OutputDirectories.getResultRunFilename( onefile=Options.isOnefileMode() ) general.info("Launching %r." % run_filename) if Options.shallMakeModule(): executeModule( tree=main_module, clean_path=Options.shallClearPythonPathEnvironment(), ) else: executeMain( binary_filename=run_filename, clean_path=Options.shallClearPythonPathEnvironment(), )
def main(): """Main program flow of Nuitka At this point, options will be parsed already, Nuitka will be executing in the desired version of Python with desired flags, and we just get to execute the task assigned. We might be asked to only re-compile generated C, dump only an XML representation of the internal node tree after optimization, etc. """ # Main has to fulfill many options, leading to many branches and statements # to deal with them. pylint: disable=too-many-branches,too-many-statements if not Options.shallDumpBuiltTreeXML(): general.info("Starting Python compilation.") filename = Options.getPositionalArgs()[0] # Inform the importing layer about the main script directory, so it can use # it when attempting to follow imports. Importing.setMainScriptDirectory( main_dir=os.path.dirname(os.path.abspath(filename)) ) # Turn that source code into a node tree structure. try: main_module = _createNodeTree(filename=filename) except (SyntaxError, IndentationError) as e: handleSyntaxError(e) if Options.shallDumpBuiltTreeXML(): # XML output only. for module in ModuleRegistry.getDoneModules(): dumpTreeXML(module) else: # Make the actual compilation. result, options = compileTree() # Exit if compilation failed. if not result: sys.exit(1) if Options.shallNotDoExecCCompilerCall(): if Options.isShowMemory(): MemoryUsage.showMemoryTrace() sys.exit(0) executePostProcessing() if Options.shallMakeModule() and Options.shallCreatePyiFile(): pyi_filename = OutputDirectories.getResultBasepath() + ".pyi" putTextFileContents( filename=pyi_filename, contents="""\ # This file was generated by Nuitka and describes the types of the # created shared library. # At this time it lists only the imports made and can be used by the # tools that bundle libraries, including Nuitka itself. For instance # standalone mode usage of the created library will need it. # In the future, this will also contain type information for values # in the module, so IDEs will use this. Therefore please include it # when you make software releases of the extension module that it # describes. %(imports)s # This is not Python source even if it looks so. Make it clear for # now. This was decided by PEP 484 designers. __name__ = ... """ % { "imports": "\n".join( "import %s" % module_name for module_name in getImportedNames() ) }, ) if Options.isStandaloneMode(): binary_filename = options["result_exe"] setMainEntryPoint(binary_filename) dist_dir = OutputDirectories.getStandaloneDirectoryPath() for module in ModuleRegistry.getDoneModules(): addIncludedEntryPoints(Plugins.considerExtraDlls(dist_dir, module)) copyUsedDLLs( source_dir=OutputDirectories.getSourceDirectoryPath(), dist_dir=dist_dir, standalone_entry_points=getStandaloneEntryPoints(), ) copyDataFiles(dist_dir=dist_dir) Plugins.onStandaloneDistributionFinished(dist_dir) if Options.isOnefileMode(): packDistFolderToOnefile(dist_dir, binary_filename) if Options.isRemoveBuildDir(): general.info("Removing dist folder %r." % dist_dir) removeDirectory(path=dist_dir, ignore_errors=False) else: general.info( "Keeping dist folder %r for inspection, no need to use it." % dist_dir ) # Remove the source directory (now build directory too) if asked to. source_dir = OutputDirectories.getSourceDirectoryPath() if Options.isRemoveBuildDir(): general.info("Removing build directory %r." % source_dir) removeDirectory(path=source_dir, ignore_errors=False) assert not os.path.exists(source_dir) else: general.info("Keeping build directory %r." % source_dir) final_filename = OutputDirectories.getResultFullpath( onefile=Options.isOnefileMode() ) Plugins.onFinalResult(final_filename) general.info("Successfully created %r." % final_filename) # Execute the module immediately if option was given. if Options.shallExecuteImmediately(): general.info("Launching %r." % final_filename) if Options.shallMakeModule(): executeModule( tree=main_module, clean_path=Options.shallClearPythonPathEnvironment(), ) else: executeMain( binary_filename=final_filename, clean_path=Options.shallClearPythonPathEnvironment(), )