17db96d56Sopenharmony_ci#! /usr/bin/env python3
27db96d56Sopenharmony_ci
37db96d56Sopenharmony_ci"""Freeze a Python script into a binary.
47db96d56Sopenharmony_ci
57db96d56Sopenharmony_ciusage: freeze [options...] script [module]...
67db96d56Sopenharmony_ci
77db96d56Sopenharmony_ciOptions:
87db96d56Sopenharmony_ci-p prefix:    This is the prefix used when you ran ``make install''
97db96d56Sopenharmony_ci              in the Python build directory.
107db96d56Sopenharmony_ci              (If you never ran this, freeze won't work.)
117db96d56Sopenharmony_ci              The default is whatever sys.prefix evaluates to.
127db96d56Sopenharmony_ci              It can also be the top directory of the Python source
137db96d56Sopenharmony_ci              tree; then -P must point to the build tree.
147db96d56Sopenharmony_ci
157db96d56Sopenharmony_ci-P exec_prefix: Like -p but this is the 'exec_prefix', used to
167db96d56Sopenharmony_ci                install objects etc.  The default is whatever sys.exec_prefix
177db96d56Sopenharmony_ci                evaluates to, or the -p argument if given.
187db96d56Sopenharmony_ci                If -p points to the Python source tree, -P must point
197db96d56Sopenharmony_ci                to the build tree, if different.
207db96d56Sopenharmony_ci
217db96d56Sopenharmony_ci-e extension: A directory containing additional .o files that
227db96d56Sopenharmony_ci              may be used to resolve modules.  This directory
237db96d56Sopenharmony_ci              should also have a Setup file describing the .o files.
247db96d56Sopenharmony_ci              On Windows, the name of a .INI file describing one
257db96d56Sopenharmony_ci              or more extensions is passed.
267db96d56Sopenharmony_ci              More than one -e option may be given.
277db96d56Sopenharmony_ci
287db96d56Sopenharmony_ci-o dir:       Directory where the output files are created; default '.'.
297db96d56Sopenharmony_ci
307db96d56Sopenharmony_ci-m:           Additional arguments are module names instead of filenames.
317db96d56Sopenharmony_ci
327db96d56Sopenharmony_ci-a package=dir: Additional directories to be added to the package's
337db96d56Sopenharmony_ci                __path__.  Used to simulate directories added by the
347db96d56Sopenharmony_ci                package at runtime (eg, by OpenGL and win32com).
357db96d56Sopenharmony_ci                More than one -a option may be given for each package.
367db96d56Sopenharmony_ci
377db96d56Sopenharmony_ci-l file:      Pass the file to the linker (windows only)
387db96d56Sopenharmony_ci
397db96d56Sopenharmony_ci-d:           Debugging mode for the module finder.
407db96d56Sopenharmony_ci
417db96d56Sopenharmony_ci-q:           Make the module finder totally quiet.
427db96d56Sopenharmony_ci
437db96d56Sopenharmony_ci-h:           Print this help message.
447db96d56Sopenharmony_ci
457db96d56Sopenharmony_ci-x module     Exclude the specified module. It will still be imported
467db96d56Sopenharmony_ci              by the frozen binary if it exists on the host system.
477db96d56Sopenharmony_ci
487db96d56Sopenharmony_ci-X module     Like -x, except the module can never be imported by
497db96d56Sopenharmony_ci              the frozen binary.
507db96d56Sopenharmony_ci
517db96d56Sopenharmony_ci-E:           Freeze will fail if any modules can't be found (that
527db96d56Sopenharmony_ci              were not excluded using -x or -X).
537db96d56Sopenharmony_ci
547db96d56Sopenharmony_ci-i filename:  Include a file with additional command line options.  Used
557db96d56Sopenharmony_ci              to prevent command lines growing beyond the capabilities of
567db96d56Sopenharmony_ci              the shell/OS.  All arguments specified in filename
577db96d56Sopenharmony_ci              are read and the -i option replaced with the parsed
587db96d56Sopenharmony_ci              params (note - quoting args in this file is NOT supported)
597db96d56Sopenharmony_ci
607db96d56Sopenharmony_ci-s subsystem: Specify the subsystem (For Windows only.);
617db96d56Sopenharmony_ci              'console' (default), 'windows', 'service' or 'com_dll'
627db96d56Sopenharmony_ci
637db96d56Sopenharmony_ci-w:           Toggle Windows (NT or 95) behavior.
647db96d56Sopenharmony_ci              (For debugging only -- on a win32 platform, win32 behavior
657db96d56Sopenharmony_ci              is automatic.)
667db96d56Sopenharmony_ci
677db96d56Sopenharmony_ci-r prefix=f:  Replace path prefix.
687db96d56Sopenharmony_ci              Replace prefix with f in the source path references
697db96d56Sopenharmony_ci              contained in the resulting binary.
707db96d56Sopenharmony_ci
717db96d56Sopenharmony_ciArguments:
727db96d56Sopenharmony_ci
737db96d56Sopenharmony_ciscript:       The Python script to be executed by the resulting binary.
747db96d56Sopenharmony_ci
757db96d56Sopenharmony_cimodule ...:   Additional Python modules (referenced by pathname)
767db96d56Sopenharmony_ci              that will be included in the resulting binary.  These
777db96d56Sopenharmony_ci              may be .py or .pyc files.  If -m is specified, these are
787db96d56Sopenharmony_ci              module names that are search in the path instead.
797db96d56Sopenharmony_ci
807db96d56Sopenharmony_ciNOTES:
817db96d56Sopenharmony_ci
827db96d56Sopenharmony_ciIn order to use freeze successfully, you must have built Python and
837db96d56Sopenharmony_ciinstalled it ("make install").
847db96d56Sopenharmony_ci
857db96d56Sopenharmony_ciThe script should not use modules provided only as shared libraries;
867db96d56Sopenharmony_ciif it does, the resulting binary is not self-contained.
877db96d56Sopenharmony_ci"""
887db96d56Sopenharmony_ci
897db96d56Sopenharmony_ci
907db96d56Sopenharmony_ci# Import standard modules
917db96d56Sopenharmony_ci
927db96d56Sopenharmony_ciimport modulefinder
937db96d56Sopenharmony_ciimport getopt
947db96d56Sopenharmony_ciimport os
957db96d56Sopenharmony_ciimport sys
967db96d56Sopenharmony_ciimport sysconfig
977db96d56Sopenharmony_ci
987db96d56Sopenharmony_ci
997db96d56Sopenharmony_ci# Import the freeze-private modules
1007db96d56Sopenharmony_ci
1017db96d56Sopenharmony_ciimport checkextensions
1027db96d56Sopenharmony_ciimport makeconfig
1037db96d56Sopenharmony_ciimport makefreeze
1047db96d56Sopenharmony_ciimport makemakefile
1057db96d56Sopenharmony_ciimport parsesetup
1067db96d56Sopenharmony_ciimport bkfile
1077db96d56Sopenharmony_ci
1087db96d56Sopenharmony_ci
1097db96d56Sopenharmony_ci# Main program
1107db96d56Sopenharmony_ci
1117db96d56Sopenharmony_cidef main():
1127db96d56Sopenharmony_ci    # overridable context
1137db96d56Sopenharmony_ci    prefix = None                       # settable with -p option
1147db96d56Sopenharmony_ci    exec_prefix = None                  # settable with -P option
1157db96d56Sopenharmony_ci    extensions = []
1167db96d56Sopenharmony_ci    exclude = []                        # settable with -x option
1177db96d56Sopenharmony_ci    addn_link = []      # settable with -l, but only honored under Windows.
1187db96d56Sopenharmony_ci    path = sys.path[:]
1197db96d56Sopenharmony_ci    modargs = 0
1207db96d56Sopenharmony_ci    debug = 1
1217db96d56Sopenharmony_ci    odir = ''
1227db96d56Sopenharmony_ci    win = sys.platform[:3] == 'win'
1237db96d56Sopenharmony_ci    replace_paths = []                  # settable with -r option
1247db96d56Sopenharmony_ci    error_if_any_missing = 0
1257db96d56Sopenharmony_ci
1267db96d56Sopenharmony_ci    # default the exclude list for each platform
1277db96d56Sopenharmony_ci    if win: exclude = exclude + [
1287db96d56Sopenharmony_ci        'dos', 'dospath', 'mac', 'macfs', 'MACFS', 'posix', ]
1297db96d56Sopenharmony_ci
1307db96d56Sopenharmony_ci    fail_import = exclude[:]
1317db96d56Sopenharmony_ci
1327db96d56Sopenharmony_ci    # output files
1337db96d56Sopenharmony_ci    frozen_c = 'frozen.c'
1347db96d56Sopenharmony_ci    config_c = 'config.c'
1357db96d56Sopenharmony_ci    target = 'a.out'                    # normally derived from script name
1367db96d56Sopenharmony_ci    makefile = 'Makefile'
1377db96d56Sopenharmony_ci    subsystem = 'console'
1387db96d56Sopenharmony_ci
1397db96d56Sopenharmony_ci    # parse command line by first replacing any "-i" options with the
1407db96d56Sopenharmony_ci    # file contents.
1417db96d56Sopenharmony_ci    pos = 1
1427db96d56Sopenharmony_ci    while pos < len(sys.argv)-1:
1437db96d56Sopenharmony_ci        # last option can not be "-i", so this ensures "pos+1" is in range!
1447db96d56Sopenharmony_ci        if sys.argv[pos] == '-i':
1457db96d56Sopenharmony_ci            try:
1467db96d56Sopenharmony_ci                with open(sys.argv[pos+1]) as infp:
1477db96d56Sopenharmony_ci                    options = infp.read().split()
1487db96d56Sopenharmony_ci            except IOError as why:
1497db96d56Sopenharmony_ci                usage("File name '%s' specified with the -i option "
1507db96d56Sopenharmony_ci                      "can not be read - %s" % (sys.argv[pos+1], why) )
1517db96d56Sopenharmony_ci            # Replace the '-i' and the filename with the read params.
1527db96d56Sopenharmony_ci            sys.argv[pos:pos+2] = options
1537db96d56Sopenharmony_ci            pos = pos + len(options) - 1 # Skip the name and the included args.
1547db96d56Sopenharmony_ci        pos = pos + 1
1557db96d56Sopenharmony_ci
1567db96d56Sopenharmony_ci    # Now parse the command line with the extras inserted.
1577db96d56Sopenharmony_ci    try:
1587db96d56Sopenharmony_ci        opts, args = getopt.getopt(sys.argv[1:], 'r:a:dEe:hmo:p:P:qs:wX:x:l:')
1597db96d56Sopenharmony_ci    except getopt.error as msg:
1607db96d56Sopenharmony_ci        usage('getopt error: ' + str(msg))
1617db96d56Sopenharmony_ci
1627db96d56Sopenharmony_ci    # process option arguments
1637db96d56Sopenharmony_ci    for o, a in opts:
1647db96d56Sopenharmony_ci        if o == '-h':
1657db96d56Sopenharmony_ci            print(__doc__)
1667db96d56Sopenharmony_ci            return
1677db96d56Sopenharmony_ci        if o == '-d':
1687db96d56Sopenharmony_ci            debug = debug + 1
1697db96d56Sopenharmony_ci        if o == '-e':
1707db96d56Sopenharmony_ci            extensions.append(a)
1717db96d56Sopenharmony_ci        if o == '-m':
1727db96d56Sopenharmony_ci            modargs = 1
1737db96d56Sopenharmony_ci        if o == '-o':
1747db96d56Sopenharmony_ci            odir = a
1757db96d56Sopenharmony_ci        if o == '-p':
1767db96d56Sopenharmony_ci            prefix = a
1777db96d56Sopenharmony_ci        if o == '-P':
1787db96d56Sopenharmony_ci            exec_prefix = a
1797db96d56Sopenharmony_ci        if o == '-q':
1807db96d56Sopenharmony_ci            debug = 0
1817db96d56Sopenharmony_ci        if o == '-w':
1827db96d56Sopenharmony_ci            win = not win
1837db96d56Sopenharmony_ci        if o == '-s':
1847db96d56Sopenharmony_ci            if not win:
1857db96d56Sopenharmony_ci                usage("-s subsystem option only on Windows")
1867db96d56Sopenharmony_ci            subsystem = a
1877db96d56Sopenharmony_ci        if o == '-x':
1887db96d56Sopenharmony_ci            exclude.append(a)
1897db96d56Sopenharmony_ci        if o == '-X':
1907db96d56Sopenharmony_ci            exclude.append(a)
1917db96d56Sopenharmony_ci            fail_import.append(a)
1927db96d56Sopenharmony_ci        if o == '-E':
1937db96d56Sopenharmony_ci            error_if_any_missing = 1
1947db96d56Sopenharmony_ci        if o == '-l':
1957db96d56Sopenharmony_ci            addn_link.append(a)
1967db96d56Sopenharmony_ci        if o == '-a':
1977db96d56Sopenharmony_ci            modulefinder.AddPackagePath(*a.split("=", 2))
1987db96d56Sopenharmony_ci        if o == '-r':
1997db96d56Sopenharmony_ci            f,r = a.split("=", 2)
2007db96d56Sopenharmony_ci            replace_paths.append( (f,r) )
2017db96d56Sopenharmony_ci
2027db96d56Sopenharmony_ci    # modules that are imported by the Python runtime
2037db96d56Sopenharmony_ci    implicits = []
2047db96d56Sopenharmony_ci    for module in ('site', 'warnings', 'encodings.utf_8', 'encodings.latin_1'):
2057db96d56Sopenharmony_ci        if module not in exclude:
2067db96d56Sopenharmony_ci            implicits.append(module)
2077db96d56Sopenharmony_ci
2087db96d56Sopenharmony_ci    # default prefix and exec_prefix
2097db96d56Sopenharmony_ci    if not exec_prefix:
2107db96d56Sopenharmony_ci        if prefix:
2117db96d56Sopenharmony_ci            exec_prefix = prefix
2127db96d56Sopenharmony_ci        else:
2137db96d56Sopenharmony_ci            exec_prefix = sys.exec_prefix
2147db96d56Sopenharmony_ci    if not prefix:
2157db96d56Sopenharmony_ci        prefix = sys.prefix
2167db96d56Sopenharmony_ci
2177db96d56Sopenharmony_ci    # determine whether -p points to the Python source tree
2187db96d56Sopenharmony_ci    ishome = os.path.exists(os.path.join(prefix, 'Python', 'ceval.c'))
2197db96d56Sopenharmony_ci
2207db96d56Sopenharmony_ci    # locations derived from options
2217db96d56Sopenharmony_ci    version = '%d.%d' % sys.version_info[:2]
2227db96d56Sopenharmony_ci    if hasattr(sys, 'abiflags'):
2237db96d56Sopenharmony_ci        flagged_version = version + sys.abiflags
2247db96d56Sopenharmony_ci    else:
2257db96d56Sopenharmony_ci        flagged_version = version
2267db96d56Sopenharmony_ci    if win:
2277db96d56Sopenharmony_ci        extensions_c = 'frozen_extensions.c'
2287db96d56Sopenharmony_ci    if ishome:
2297db96d56Sopenharmony_ci        print("(Using Python source directory)")
2307db96d56Sopenharmony_ci        configdir = exec_prefix
2317db96d56Sopenharmony_ci        incldir = os.path.join(prefix, 'Include')
2327db96d56Sopenharmony_ci        config_h_dir = exec_prefix
2337db96d56Sopenharmony_ci        config_c_in = os.path.join(prefix, 'Modules', 'config.c.in')
2347db96d56Sopenharmony_ci        frozenmain_c = os.path.join(prefix, 'Python', 'frozenmain.c')
2357db96d56Sopenharmony_ci        makefile_in = os.path.join(exec_prefix, 'Makefile')
2367db96d56Sopenharmony_ci        if win:
2377db96d56Sopenharmony_ci            frozendllmain_c = os.path.join(exec_prefix, 'Pc\\frozen_dllmain.c')
2387db96d56Sopenharmony_ci    else:
2397db96d56Sopenharmony_ci        configdir = sysconfig.get_config_var('LIBPL')
2407db96d56Sopenharmony_ci        incldir = os.path.join(prefix, 'include', 'python%s' % flagged_version)
2417db96d56Sopenharmony_ci        config_h_dir = os.path.join(exec_prefix, 'include',
2427db96d56Sopenharmony_ci                                    'python%s' % flagged_version)
2437db96d56Sopenharmony_ci        config_c_in = os.path.join(configdir, 'config.c.in')
2447db96d56Sopenharmony_ci        frozenmain_c = os.path.join(configdir, 'frozenmain.c')
2457db96d56Sopenharmony_ci        makefile_in = os.path.join(configdir, 'Makefile')
2467db96d56Sopenharmony_ci        frozendllmain_c = os.path.join(configdir, 'frozen_dllmain.c')
2477db96d56Sopenharmony_ci    libdir = sysconfig.get_config_var('LIBDIR')
2487db96d56Sopenharmony_ci    supp_sources = []
2497db96d56Sopenharmony_ci    defines = []
2507db96d56Sopenharmony_ci    includes = ['-I' + incldir, '-I' + config_h_dir]
2517db96d56Sopenharmony_ci
2527db96d56Sopenharmony_ci    # sanity check of directories and files
2537db96d56Sopenharmony_ci    check_dirs = [prefix, exec_prefix, configdir, incldir]
2547db96d56Sopenharmony_ci    if not win:
2557db96d56Sopenharmony_ci        # These are not directories on Windows.
2567db96d56Sopenharmony_ci        check_dirs = check_dirs + extensions
2577db96d56Sopenharmony_ci    for dir in check_dirs:
2587db96d56Sopenharmony_ci        if not os.path.exists(dir):
2597db96d56Sopenharmony_ci            usage('needed directory %s not found' % dir)
2607db96d56Sopenharmony_ci        if not os.path.isdir(dir):
2617db96d56Sopenharmony_ci            usage('%s: not a directory' % dir)
2627db96d56Sopenharmony_ci    if win:
2637db96d56Sopenharmony_ci        files = supp_sources + extensions # extensions are files on Windows.
2647db96d56Sopenharmony_ci    else:
2657db96d56Sopenharmony_ci        files = [config_c_in, makefile_in] + supp_sources
2667db96d56Sopenharmony_ci    for file in supp_sources:
2677db96d56Sopenharmony_ci        if not os.path.exists(file):
2687db96d56Sopenharmony_ci            usage('needed file %s not found' % file)
2697db96d56Sopenharmony_ci        if not os.path.isfile(file):
2707db96d56Sopenharmony_ci            usage('%s: not a plain file' % file)
2717db96d56Sopenharmony_ci    if not win:
2727db96d56Sopenharmony_ci        for dir in extensions:
2737db96d56Sopenharmony_ci            setup = os.path.join(dir, 'Setup')
2747db96d56Sopenharmony_ci            if not os.path.exists(setup):
2757db96d56Sopenharmony_ci                usage('needed file %s not found' % setup)
2767db96d56Sopenharmony_ci            if not os.path.isfile(setup):
2777db96d56Sopenharmony_ci                usage('%s: not a plain file' % setup)
2787db96d56Sopenharmony_ci
2797db96d56Sopenharmony_ci    # check that enough arguments are passed
2807db96d56Sopenharmony_ci    if not args:
2817db96d56Sopenharmony_ci        usage('at least one filename argument required')
2827db96d56Sopenharmony_ci
2837db96d56Sopenharmony_ci    # check that file arguments exist
2847db96d56Sopenharmony_ci    for arg in args:
2857db96d56Sopenharmony_ci        if arg == '-m':
2867db96d56Sopenharmony_ci            break
2877db96d56Sopenharmony_ci        # if user specified -m on the command line before _any_
2887db96d56Sopenharmony_ci        # file names, then nothing should be checked (as the
2897db96d56Sopenharmony_ci        # very first file should be a module name)
2907db96d56Sopenharmony_ci        if modargs:
2917db96d56Sopenharmony_ci            break
2927db96d56Sopenharmony_ci        if not os.path.exists(arg):
2937db96d56Sopenharmony_ci            usage('argument %s not found' % arg)
2947db96d56Sopenharmony_ci        if not os.path.isfile(arg):
2957db96d56Sopenharmony_ci            usage('%s: not a plain file' % arg)
2967db96d56Sopenharmony_ci
2977db96d56Sopenharmony_ci    # process non-option arguments
2987db96d56Sopenharmony_ci    scriptfile = args[0]
2997db96d56Sopenharmony_ci    modules = args[1:]
3007db96d56Sopenharmony_ci
3017db96d56Sopenharmony_ci    # derive target name from script name
3027db96d56Sopenharmony_ci    base = os.path.basename(scriptfile)
3037db96d56Sopenharmony_ci    base, ext = os.path.splitext(base)
3047db96d56Sopenharmony_ci    if base:
3057db96d56Sopenharmony_ci        if base != scriptfile:
3067db96d56Sopenharmony_ci            target = base
3077db96d56Sopenharmony_ci        else:
3087db96d56Sopenharmony_ci            target = base + '.bin'
3097db96d56Sopenharmony_ci
3107db96d56Sopenharmony_ci    # handle -o option
3117db96d56Sopenharmony_ci    base_frozen_c = frozen_c
3127db96d56Sopenharmony_ci    base_config_c = config_c
3137db96d56Sopenharmony_ci    base_target = target
3147db96d56Sopenharmony_ci    if odir and not os.path.isdir(odir):
3157db96d56Sopenharmony_ci        try:
3167db96d56Sopenharmony_ci            os.mkdir(odir)
3177db96d56Sopenharmony_ci            print("Created output directory", odir)
3187db96d56Sopenharmony_ci        except OSError as msg:
3197db96d56Sopenharmony_ci            usage('%s: mkdir failed (%s)' % (odir, str(msg)))
3207db96d56Sopenharmony_ci    base = ''
3217db96d56Sopenharmony_ci    if odir:
3227db96d56Sopenharmony_ci        base = os.path.join(odir, '')
3237db96d56Sopenharmony_ci        frozen_c = os.path.join(odir, frozen_c)
3247db96d56Sopenharmony_ci        config_c = os.path.join(odir, config_c)
3257db96d56Sopenharmony_ci        target = os.path.join(odir, target)
3267db96d56Sopenharmony_ci        makefile = os.path.join(odir, makefile)
3277db96d56Sopenharmony_ci        if win: extensions_c = os.path.join(odir, extensions_c)
3287db96d56Sopenharmony_ci
3297db96d56Sopenharmony_ci    # Handle special entry point requirements
3307db96d56Sopenharmony_ci    # (on Windows, some frozen programs do not use __main__, but
3317db96d56Sopenharmony_ci    # import the module directly.  Eg, DLLs, Services, etc
3327db96d56Sopenharmony_ci    custom_entry_point = None  # Currently only used on Windows
3337db96d56Sopenharmony_ci    python_entry_is_main = 1   # Is the entry point called __main__?
3347db96d56Sopenharmony_ci    # handle -s option on Windows
3357db96d56Sopenharmony_ci    if win:
3367db96d56Sopenharmony_ci        import winmakemakefile
3377db96d56Sopenharmony_ci        try:
3387db96d56Sopenharmony_ci            custom_entry_point, python_entry_is_main = \
3397db96d56Sopenharmony_ci                winmakemakefile.get_custom_entry_point(subsystem)
3407db96d56Sopenharmony_ci        except ValueError as why:
3417db96d56Sopenharmony_ci            usage(why)
3427db96d56Sopenharmony_ci
3437db96d56Sopenharmony_ci
3447db96d56Sopenharmony_ci    # Actual work starts here...
3457db96d56Sopenharmony_ci
3467db96d56Sopenharmony_ci    # collect all modules of the program
3477db96d56Sopenharmony_ci    dir = os.path.dirname(scriptfile)
3487db96d56Sopenharmony_ci    path[0] = dir
3497db96d56Sopenharmony_ci    mf = modulefinder.ModuleFinder(path, debug, exclude, replace_paths)
3507db96d56Sopenharmony_ci
3517db96d56Sopenharmony_ci    if win and subsystem=='service':
3527db96d56Sopenharmony_ci        # If a Windows service, then add the "built-in" module.
3537db96d56Sopenharmony_ci        mod = mf.add_module("servicemanager")
3547db96d56Sopenharmony_ci        mod.__file__="dummy.pyd" # really built-in to the resulting EXE
3557db96d56Sopenharmony_ci
3567db96d56Sopenharmony_ci    for mod in implicits:
3577db96d56Sopenharmony_ci        mf.import_hook(mod)
3587db96d56Sopenharmony_ci    for mod in modules:
3597db96d56Sopenharmony_ci        if mod == '-m':
3607db96d56Sopenharmony_ci            modargs = 1
3617db96d56Sopenharmony_ci            continue
3627db96d56Sopenharmony_ci        if modargs:
3637db96d56Sopenharmony_ci            if mod[-2:] == '.*':
3647db96d56Sopenharmony_ci                mf.import_hook(mod[:-2], None, ["*"])
3657db96d56Sopenharmony_ci            else:
3667db96d56Sopenharmony_ci                mf.import_hook(mod)
3677db96d56Sopenharmony_ci        else:
3687db96d56Sopenharmony_ci            mf.load_file(mod)
3697db96d56Sopenharmony_ci
3707db96d56Sopenharmony_ci    # Add the main script as either __main__, or the actual module name.
3717db96d56Sopenharmony_ci    if python_entry_is_main:
3727db96d56Sopenharmony_ci        mf.run_script(scriptfile)
3737db96d56Sopenharmony_ci    else:
3747db96d56Sopenharmony_ci        mf.load_file(scriptfile)
3757db96d56Sopenharmony_ci
3767db96d56Sopenharmony_ci    if debug > 0:
3777db96d56Sopenharmony_ci        mf.report()
3787db96d56Sopenharmony_ci        print()
3797db96d56Sopenharmony_ci    dict = mf.modules
3807db96d56Sopenharmony_ci
3817db96d56Sopenharmony_ci    if error_if_any_missing:
3827db96d56Sopenharmony_ci        missing = mf.any_missing()
3837db96d56Sopenharmony_ci        if missing:
3847db96d56Sopenharmony_ci            sys.exit("There are some missing modules: %r" % missing)
3857db96d56Sopenharmony_ci
3867db96d56Sopenharmony_ci    # generate output for frozen modules
3877db96d56Sopenharmony_ci    files = makefreeze.makefreeze(base, dict, debug, custom_entry_point,
3887db96d56Sopenharmony_ci                                  fail_import)
3897db96d56Sopenharmony_ci
3907db96d56Sopenharmony_ci    # look for unfrozen modules (builtin and of unknown origin)
3917db96d56Sopenharmony_ci    builtins = []
3927db96d56Sopenharmony_ci    unknown = []
3937db96d56Sopenharmony_ci    mods = sorted(dict.keys())
3947db96d56Sopenharmony_ci    for mod in mods:
3957db96d56Sopenharmony_ci        if dict[mod].__code__:
3967db96d56Sopenharmony_ci            continue
3977db96d56Sopenharmony_ci        if not dict[mod].__file__:
3987db96d56Sopenharmony_ci            builtins.append(mod)
3997db96d56Sopenharmony_ci        else:
4007db96d56Sopenharmony_ci            unknown.append(mod)
4017db96d56Sopenharmony_ci
4027db96d56Sopenharmony_ci    # search for unknown modules in extensions directories (not on Windows)
4037db96d56Sopenharmony_ci    addfiles = []
4047db96d56Sopenharmony_ci    frozen_extensions = [] # Windows list of modules.
4057db96d56Sopenharmony_ci    if unknown or (not win and builtins):
4067db96d56Sopenharmony_ci        if not win:
4077db96d56Sopenharmony_ci            addfiles, addmods = \
4087db96d56Sopenharmony_ci                      checkextensions.checkextensions(unknown+builtins,
4097db96d56Sopenharmony_ci                                                      extensions)
4107db96d56Sopenharmony_ci            for mod in addmods:
4117db96d56Sopenharmony_ci                if mod in unknown:
4127db96d56Sopenharmony_ci                    unknown.remove(mod)
4137db96d56Sopenharmony_ci                    builtins.append(mod)
4147db96d56Sopenharmony_ci        else:
4157db96d56Sopenharmony_ci            # Do the windows thang...
4167db96d56Sopenharmony_ci            import checkextensions_win32
4177db96d56Sopenharmony_ci            # Get a list of CExtension instances, each describing a module
4187db96d56Sopenharmony_ci            # (including its source files)
4197db96d56Sopenharmony_ci            frozen_extensions = checkextensions_win32.checkextensions(
4207db96d56Sopenharmony_ci                unknown, extensions, prefix)
4217db96d56Sopenharmony_ci            for mod in frozen_extensions:
4227db96d56Sopenharmony_ci                unknown.remove(mod.name)
4237db96d56Sopenharmony_ci
4247db96d56Sopenharmony_ci    # report unknown modules
4257db96d56Sopenharmony_ci    if unknown:
4267db96d56Sopenharmony_ci        sys.stderr.write('Warning: unknown modules remain: %s\n' %
4277db96d56Sopenharmony_ci                         ' '.join(unknown))
4287db96d56Sopenharmony_ci
4297db96d56Sopenharmony_ci    # windows gets different treatment
4307db96d56Sopenharmony_ci    if win:
4317db96d56Sopenharmony_ci        # Taking a shortcut here...
4327db96d56Sopenharmony_ci        import winmakemakefile, checkextensions_win32
4337db96d56Sopenharmony_ci        checkextensions_win32.write_extension_table(extensions_c,
4347db96d56Sopenharmony_ci                                                    frozen_extensions)
4357db96d56Sopenharmony_ci        # Create a module definition for the bootstrap C code.
4367db96d56Sopenharmony_ci        xtras = [frozenmain_c, os.path.basename(frozen_c),
4377db96d56Sopenharmony_ci                 frozendllmain_c, os.path.basename(extensions_c)] + files
4387db96d56Sopenharmony_ci        maindefn = checkextensions_win32.CExtension( '__main__', xtras )
4397db96d56Sopenharmony_ci        frozen_extensions.append( maindefn )
4407db96d56Sopenharmony_ci        with open(makefile, 'w') as outfp:
4417db96d56Sopenharmony_ci            winmakemakefile.makemakefile(outfp,
4427db96d56Sopenharmony_ci                                         locals(),
4437db96d56Sopenharmony_ci                                         frozen_extensions,
4447db96d56Sopenharmony_ci                                         os.path.basename(target))
4457db96d56Sopenharmony_ci        return
4467db96d56Sopenharmony_ci
4477db96d56Sopenharmony_ci    # generate config.c and Makefile
4487db96d56Sopenharmony_ci    builtins.sort()
4497db96d56Sopenharmony_ci    with open(config_c_in) as infp, bkfile.open(config_c, 'w') as outfp:
4507db96d56Sopenharmony_ci        makeconfig.makeconfig(infp, outfp, builtins)
4517db96d56Sopenharmony_ci
4527db96d56Sopenharmony_ci    cflags = ['$(OPT)']
4537db96d56Sopenharmony_ci    cppflags = defines + includes
4547db96d56Sopenharmony_ci    libs = [os.path.join(libdir, '$(LDLIBRARY)')]
4557db96d56Sopenharmony_ci
4567db96d56Sopenharmony_ci    somevars = {}
4577db96d56Sopenharmony_ci    if os.path.exists(makefile_in):
4587db96d56Sopenharmony_ci        makevars = parsesetup.getmakevars(makefile_in)
4597db96d56Sopenharmony_ci        for key in makevars:
4607db96d56Sopenharmony_ci            somevars[key] = makevars[key]
4617db96d56Sopenharmony_ci
4627db96d56Sopenharmony_ci    somevars['CFLAGS'] = ' '.join(cflags) # override
4637db96d56Sopenharmony_ci    somevars['CPPFLAGS'] = ' '.join(cppflags) # override
4647db96d56Sopenharmony_ci    files = [base_config_c, base_frozen_c] + \
4657db96d56Sopenharmony_ci            files + supp_sources +  addfiles + libs + \
4667db96d56Sopenharmony_ci            ['$(MODLIBS)', '$(LIBS)', '$(SYSLIBS)']
4677db96d56Sopenharmony_ci
4687db96d56Sopenharmony_ci    with bkfile.open(makefile, 'w') as outfp:
4697db96d56Sopenharmony_ci        makemakefile.makemakefile(outfp, somevars, files, base_target)
4707db96d56Sopenharmony_ci
4717db96d56Sopenharmony_ci    # Done!
4727db96d56Sopenharmony_ci
4737db96d56Sopenharmony_ci    if odir:
4747db96d56Sopenharmony_ci        print('Now run "make" in', odir, end=' ')
4757db96d56Sopenharmony_ci        print('to build the target:', base_target)
4767db96d56Sopenharmony_ci    else:
4777db96d56Sopenharmony_ci        print('Now run "make" to build the target:', base_target)
4787db96d56Sopenharmony_ci
4797db96d56Sopenharmony_ci
4807db96d56Sopenharmony_ci# Print usage message and exit
4817db96d56Sopenharmony_ci
4827db96d56Sopenharmony_cidef usage(msg):
4837db96d56Sopenharmony_ci    sys.stdout = sys.stderr
4847db96d56Sopenharmony_ci    print("Error:", msg)
4857db96d56Sopenharmony_ci    print("Use ``%s -h'' for help" % sys.argv[0])
4867db96d56Sopenharmony_ci    sys.exit(2)
4877db96d56Sopenharmony_ci
4887db96d56Sopenharmony_ci
4897db96d56Sopenharmony_cimain()
490