Example #1
0
int pyi_utils_set_environment(const ARCHIVE_STATUS *status)
{
    int rc = 0;

#ifdef __APPLE__
    /* On Mac OS X we do not use environment variables DYLD_LIBRARY_PATH
     * or others to tell OS where to look for dynamic libraries.
     * There were some issues with this approach. In some cases some
     * system libraries were trying to load incompatible libraries from
     * the dist directory. For instance this was experienced with macprots
     * and PyQt4 applications.
     *
     * To tell the OS where to look for dynamic libraries we modify
     * .so/.dylib files to use relative paths to other dependend
     * libraries starting with @executable_path.
     *
     * For more information see:
     * http://blogs.oracle.com/dipol/entry/dynamic_libraries_rpath_and_mac
     * http://developer.apple.com/library/mac/#documentation/DeveloperTools/  \
     *     Conceptual/DynamicLibraries/100-Articles/DynamicLibraryUsageGuidelines.html
     */
    /* For environment variable details see 'man dyld'. */
	pyi_unsetenv("DYLD_FRAMEWORK_PATH");
	pyi_unsetenv("DYLD_FALLBACK_FRAMEWORK_PATH");
	pyi_unsetenv("DYLD_VERSIONED_FRAMEWORK_PATH");
	pyi_unsetenv("DYLD_LIBRARY_PATH");
	pyi_unsetenv("DYLD_FALLBACK_LIBRARY_PATH");
	pyi_unsetenv("DYLD_VERSIONED_LIBRARY_PATH");
	pyi_unsetenv("DYLD_ROOT_PATH");

#else
    /* Set library path to temppath. This is only for onefile mode.*/
    if (status->temppath[0] != PYI_NULLCHAR) {
        rc = set_dynamic_library_path(status->temppath);
    }
    /* Set library path to homepath. This is for default onedir mode.*/
    else {
        rc = set_dynamic_library_path(status->homepath);
    }
#endif

    return rc;
}
Example #2
0
int pyi_main(int argc, char * argv[])
{
    /*  archive_status contain status information of the main process. */
    ARCHIVE_STATUS *archive_status = NULL;
    char executable[PATH_MAX];
    char homepath[PATH_MAX];
    char archivefile[PATH_MAX];
    int rc = 0;
    char *extractionpath = NULL;
    wchar_t * dllpath_w;

    int i = 0;

#ifdef _MSC_VER
    /* Visual C runtime incorrectly buffers stderr */
    setbuf(stderr, (char *)NULL);
#endif /* _MSC_VER */

    VS("PyInstaller Bootloader 3.x\n");

    // TODO create special function to allocate memory for archive status pyi_arch_status_alloc_memory(archive_status);
    archive_status = (ARCHIVE_STATUS *) calloc(1,sizeof(ARCHIVE_STATUS));
    if (archive_status == NULL) {
        FATALERROR("Cannot allocate memory for ARCHIVE_STATUS\n");
        return -1;

    }

    pyi_path_executable(executable, argv[0]);
    pyi_path_archivefile(archivefile, executable);
    pyi_path_homepath(homepath, executable);

    /* For the curious:
     * On Windows, the UTF-8 form of MEIPASS2 is passed to pyi_setenv, which
     * decodes to UTF-16 before passing it to the Windows API. So the var's value
     * is full unicode.
     *
     * On OS X/Linux, the MEIPASS2 value is passed as the bytes received from the OS.
     * Only Python will care about its encoding, and it is passed to Python using
     * PyUnicode_DecodeFSDefault.
     */

    extractionpath = pyi_getenv("_MEIPASS2");

    /* If the Python program we are about to run invokes another PyInstaller
     * one-file program as subprocess, this subprocess must not be fooled into
     * thinking that it is already unpacked. Therefore, PyInstaller deletes
     * the _MEIPASS2 variable from the environment.
     */

    pyi_unsetenv("_MEIPASS2");

    VS("LOADER: _MEIPASS2 is %s\n", (extractionpath ? extractionpath : "NULL"));

    if (pyi_arch_setup(archive_status, homepath, &executable[strlen(homepath)])) {
        if (pyi_arch_setup(archive_status, homepath, &archivefile[strlen(homepath)])) {
            FATALERROR("Cannot open self %s or archive %s\n",
                    executable, archivefile);
            return -1;
        }
    }

    /* These are used only in pyi_pylib_set_sys_argv, which converts to wchar_t */
    archive_status->argc = argc;
    archive_status->argv = argv;


#ifdef _WIN32
    /* On Windows use single-process for --onedir mode. */
    if (!extractionpath && !pyi_launch_need_to_extract_binaries(archive_status)) {
        VS("LOADER: No need to extract files to run; setting extractionpath to homepath\n");
        extractionpath = homepath;
    }
    if(extractionpath) {
        /* Add extraction folder to DLL search path */
        dllpath_w = pyi_win32_utils_from_utf8(NULL, extractionpath, 0);
        SetDllDirectory(dllpath_w);
        VS("LOADER: SetDllDirectory(%s)\n", extractionpath);
        free(dllpath_w);
    }
#endif
    if (extractionpath) {
        VS("LOADER: Already in the child - running user's code.\n");
        /*  If binaries were extracted to temppath,
         *  we pass it through status variable
         */
        if (strcmp(homepath, extractionpath) != 0) {
            strcpy(archive_status->temppath, extractionpath);
            /*
             * Temp path exits - set appropriate flag and change
             * status->mainpath to point to temppath.
             */
            archive_status->has_temp_directory = true;
            strcpy(archive_status->mainpath, archive_status->temppath);
        }

        /* Main code to initialize Python and run user's code. */
        pyi_launch_initialize(archive_status);
        rc = pyi_launch_execute(archive_status);
        pyi_launch_finalize(archive_status);

    } else {

        /* status->temppath is created if necessary. */
        if (pyi_launch_extract_binaries(archive_status)) {
            VS("LOADER: temppath is %s\n", archive_status->temppath);
            VS("LOADER: Error extracting binaries\n");
            return -1;
        }

        /* Run the 'child' process, then clean up. */

        VS("LOADER: Executing self as child\n");
        pyi_setenv("_MEIPASS2", archive_status->temppath[0] != 0 ? archive_status->temppath : homepath);

        VS("LOADER: set _MEIPASS2 to %s\n", pyi_getenv("_MEIPASS2"));

        if (pyi_utils_set_environment(archive_status) == -1)
            return -1;

	/* Transform parent to background process on OSX only. */
	pyi_parent_to_background();

        /* Run user's code in a subprocess and pass command line arguments to it. */
        rc = pyi_utils_create_child(executable, argc, argv);

        VS("LOADER: Back to parent (RC: %d)\n", rc);

        VS("LOADER: Doing cleanup\n");
        if (archive_status->has_temp_directory == true)
            pyi_remove_temp_path(archive_status->temppath);
        pyi_arch_status_free_memory(archive_status);
        if (extractionpath != NULL)
            free(extractionpath);
    }
    return rc;
}
Example #3
0
/*
 * Start python - return 0 on success
 */
int startPython(ARCHIVE_STATUS *status, int argc, char *argv[])
{
    /* Set PYTHONPATH so dynamic libs will load.
     * PYTHONHOME for function Py_SetPythonHome() should point
     * to a zero-terminated character string in static storage. */
	static char pypath[2*PATH_MAX + 14];
	int pathlen = 1;
	int i;
	char cmd[PATH_MAX+1+80];
	char tmp[PATH_MAX+1];
	PyObject *py_argv;
	PyObject *val;
	PyObject *sys;

    /* Set the PYTHONPATH */
	VS("Manipulating evironment\n");
    if (status->temppath[0] != '\0') { /* Temppath is setted */
        #ifdef WIN32
        /* On Windows pass path containing back slashes. */
        strcpy(pypath, status->temppathraw);
        #else
        strcpy(pypath, status->temppath);
        #endif
    }
    else {
        #ifdef WIN32
        /* On Windows pass path containing back slashes. */
        strcpy(pypath, status->homepathraw);
        #else
        strcpy(pypath, status->homepath);
        #endif
    }

	/* don't chop off SEP if root directory */
#ifdef WIN32
	if (strlen(pypath) > 14)
#else
	if (strlen(pypath) > 12)
#endif
		pypath[strlen(pypath)-1] = '\0';

	pyi_setenv("PYTHONPATH", pypath);
	VS("PYTHONPATH=%s\n", pypath);


	/* Clear out PYTHONHOME to avoid clashing with any Python installation. */
	pyi_unsetenv("PYTHONHOME");

    /* Set PYTHONHOME by using function from Python C API. */
    if (status->temppath[0] != '\0') {
        /* Use temppath as home. This is only for onefile mode. */
        #ifdef WIN32
        /* On Windows pass path containing back slashes. */
        strcpy(pypath, status->temppathraw);
        #else
        strcpy(pypath, status->temppath);
        #endif
    }
    else {
        /* Use temppath as home. This is for default onedir mode.*/
        #ifdef WIN32
        /* On Windows pass path containing back slashes. */
        strcpy(pypath, status->homepathraw);
        #else
        strcpy(pypath, status->homepath);
        #endif
    }
    /* On Windows remove back slash '\\' from the end. */
    // TODO remove this hook when path handling is fixed in bootloader.
    #ifdef WIN32
    /* Remove trailing slash in directory path. */
    pypath[strlen(pypath)-1] = '\0';
    #endif
    PI_Py_SetPythonHome(pypath);
	VS("PYTHONHOME=%s\n", pypath);


	/* Start python. */
	/* VS("Loading python\n"); */
	*PI_Py_NoSiteFlag = 1;	/* maybe changed to 0 by setRuntimeOptions() */
    *PI_Py_FrozenFlag = 1;
	setRuntimeOptions(status);
	PI_Py_SetProgramName(status->archivename); /*XXX*/
	PI_Py_Initialize();

	/* Set sys.path */
	/* VS("Manipulating Python's sys.path\n"); */
	PI_PyRun_SimpleString("import sys\n");
	PI_PyRun_SimpleString("del sys.path[:]\n");
    if (status->temppath[0] != '\0') {
        strcpy(tmp, status->temppath);
	    tmp[strlen(tmp)-1] = '\0';
	    sprintf(cmd, "sys.path.append(r\"%s\")", tmp);
        PI_PyRun_SimpleString(cmd);
    }

	strcpy(tmp, status->homepath);
	tmp[strlen(tmp)-1] = '\0';
	sprintf(cmd, "sys.path.append(r\"%s\")", tmp);
	PI_PyRun_SimpleString (cmd);

	/* Set argv[0] to be the archiveName */
	py_argv = PI_PyList_New(0);
	val = PI_Py_BuildValue("s", status->archivename);
	PI_PyList_Append(py_argv, val);
	for (i = 1; i < argc; ++i) {
		val = PI_Py_BuildValue ("s", argv[i]);
		PI_PyList_Append (py_argv, val);
	}
	sys = PI_PyImport_ImportModule("sys");
	/* VS("Setting sys.argv\n"); */
	PI_PyObject_SetAttrString(sys, "argv", py_argv);

	/* Check for a python error */
	if (PI_PyErr_Occurred())
	{
		FATALERROR("Error detected starting Python VM.");
		return -1;
	}

	return 0;
}