blob: 0435a8adb1b9d2c78bcce57adf0086e348176fcc [file] [log] [blame]
Antoine Pitroue67f48c2012-06-19 22:29:35 +02001/* This is built as a stand-alone executable by the Makefile, and helps turn
2 Lib/importlib/_bootstrap.py into a frozen module in Python/importlib.h
3*/
4
5#include <Python.h>
6#include <marshal.h>
7
8#include <stdio.h>
9#include <sys/types.h>
10#include <sys/stat.h>
Martin v. Löwis96d97ec2012-07-28 20:46:52 +020011#ifndef MS_WINDOWS
Antoine Pitroue67f48c2012-06-19 22:29:35 +020012#include <unistd.h>
Martin v. Löwis96d97ec2012-07-28 20:46:52 +020013#endif
Antoine Pitroue67f48c2012-06-19 22:29:35 +020014
15
16/* To avoid a circular dependency on frozen.o, we create our own structure
17 of frozen modules instead, left deliberately blank so as to avoid
18 unintentional import of a stale version of _frozen_importlib. */
19
Benjamin Peterson7701e6e2013-03-13 14:06:39 -050020const static struct _frozen _PyImport_FrozenModules[] = {
Antoine Pitroue67f48c2012-06-19 22:29:35 +020021 {0, 0, 0} /* sentinel */
22};
23
Martin v. Löwisee365ac2012-07-28 21:55:20 +020024#ifndef MS_WINDOWS
25/* On Windows, this links with the regular pythonXY.dll, so this variable comes
26 from frozen.obj. In the Makefile, frozen.o is not linked into this executable,
27 so we define the variable here. */
Benjamin Peterson7701e6e2013-03-13 14:06:39 -050028const struct _frozen *PyImport_FrozenModules;
Martin v. Löwisee365ac2012-07-28 21:55:20 +020029#endif
30
Antoine Pitroue67f48c2012-06-19 22:29:35 +020031const char header[] = "/* Auto-generated by Modules/_freeze_importlib.c */";
32
33int
34main(int argc, char *argv[])
35{
36 char *inpath, *outpath;
37 FILE *infile, *outfile = NULL;
38 struct stat st;
39 size_t text_size, data_size, n;
Antoine Pitrou0ab5cf92012-06-25 17:32:43 +020040 char *text;
41 unsigned char *data;
Antoine Pitroue67f48c2012-06-19 22:29:35 +020042 PyObject *code, *marshalled;
43
Martin v. Löwis96d97ec2012-07-28 20:46:52 +020044 PyImport_FrozenModules = _PyImport_FrozenModules;
45
Antoine Pitroue67f48c2012-06-19 22:29:35 +020046 if (argc != 3) {
47 fprintf(stderr, "need to specify input and output paths\n");
48 return 2;
49 }
50 inpath = argv[1];
51 outpath = argv[2];
52 infile = fopen(inpath, "rb");
53 if (infile == NULL) {
54 fprintf(stderr, "cannot open '%s' for reading\n", inpath);
55 return 1;
56 }
57 if (fstat(fileno(infile), &st)) {
58 fclose(infile);
59 fprintf(stderr, "cannot fstat '%s'\n", inpath);
60 return 1;
61 }
62 text_size = st.st_size;
63 text = (char *) malloc(text_size + 1);
64 if (text == NULL) {
65 fclose(infile);
66 fprintf(stderr, "could not allocate %ld bytes\n", (long) text_size);
67 return 1;
68 }
69 n = fread(text, 1, text_size, infile);
70 fclose(infile);
71 infile = NULL;
72 if (n < text_size) {
73 fprintf(stderr, "read too short: got %ld instead of %ld bytes\n",
74 (long) n, (long) text_size);
75 return 1;
76 }
77 text[text_size] = '\0';
78
79 Py_NoUserSiteDirectory++;
80 Py_NoSiteFlag++;
81 Py_IgnoreEnvironmentFlag++;
82
83 Py_SetProgramName(L"./_freeze_importlib");
84 /* Don't install importlib, since it could execute outdated bytecode. */
85 _Py_InitializeEx_Private(1, 0);
86
87 code = Py_CompileStringExFlags(text, "<frozen importlib._bootstrap>",
88 Py_file_input, NULL, 0);
89 if (code == NULL)
90 goto error;
91 marshalled = PyMarshal_WriteObjectToString(code, Py_MARSHAL_VERSION);
92 Py_DECREF(code);
93 if (marshalled == NULL)
94 goto error;
95
96 assert(PyBytes_CheckExact(marshalled));
Antoine Pitrou0ab5cf92012-06-25 17:32:43 +020097 data = (unsigned char *) PyBytes_AS_STRING(marshalled);
Antoine Pitroue67f48c2012-06-19 22:29:35 +020098 data_size = PyBytes_GET_SIZE(marshalled);
99
Martin v. Löwis96d97ec2012-07-28 20:46:52 +0200100 /* Open the file in text mode. The hg checkout should be using the eol extension,
Martin v. Löwisee365ac2012-07-28 21:55:20 +0200101 which in turn should cause the EOL style match the C library's text mode */
102 outfile = fopen(outpath, "w");
Antoine Pitroue67f48c2012-06-19 22:29:35 +0200103 if (outfile == NULL) {
104 fprintf(stderr, "cannot open '%s' for writing\n", outpath);
105 return 1;
106 }
107 fprintf(outfile, "%s\n", header);
Benjamin Peterson7701e6e2013-03-13 14:06:39 -0500108 fprintf(outfile, "const unsigned char _Py_M__importlib[] = {\n");
Antoine Pitroue67f48c2012-06-19 22:29:35 +0200109 for (n = 0; n < data_size; n += 16) {
110 size_t i, end = Py_MIN(n + 16, data_size);
111 fprintf(outfile, " ");
112 for (i = n; i < end; i++) {
Antoine Pitrou0ab5cf92012-06-25 17:32:43 +0200113 fprintf(outfile, "%d,", (unsigned int) data[i]);
Antoine Pitroue67f48c2012-06-19 22:29:35 +0200114 }
115 fprintf(outfile, "\n");
116 }
117 fprintf(outfile, "};\n");
118
119 Py_DECREF(marshalled);
120
121 Py_Finalize();
122 if (infile)
123 fclose(infile);
124 if (outfile) {
125 if (ferror(outfile)) {
126 fprintf(stderr, "error when writing to '%s'\n", outpath);
127 fclose(outfile);
128 return 1;
129 }
130 fclose(outfile);
131 }
132 return 0;
133
134error:
135 PyErr_Print();
136 Py_Finalize();
137 if (infile)
138 fclose(infile);
139 if (outfile)
140 fclose(outfile);
141 return 1;
142}