blob: fb4a64a97182bdea59d08a822fd1c6cbd650c0ae [file] [log] [blame]
Stefan Krahf398a942012-05-17 00:21:57 +02001#include <windows.h>
2#include <sys/types.h>
3#include <sys/stat.h>
4#include <stdio.h>
5#include <io.h>
6
7#define CMD_SIZE 500
8
9/* This file creates the getbuildinfo.o object, by first
10 invoking subwcrev.exe (if found), and then invoking cl.exe.
11 As a side effect, it might generate PCBuild\getbuildinfo2.c
12 also. If this isn't a subversion checkout, or subwcrev isn't
13 found, it compiles ..\\..\\Modules\\getbuildinfo.c instead.
14
15 Currently, subwcrev.exe is found from the registry entries
16 of TortoiseSVN.
17
18 No attempt is made to place getbuildinfo.o into the proper
19 binary directory. This isn't necessary, as this tool is
20 invoked as a pre-link step for pythoncore, so that overwrites
21 any previous getbuildinfo.o.
22
23 However, if a second argument is provided, this will be used
24 as a temporary directory where any getbuildinfo2.c and
25 getbuildinfo.o files are put. This is useful if multiple
26 configurations are being built in parallel, to avoid them
27 trampling each other's files.
28
29*/
30
31int make_buildinfo2(const char *tmppath)
32{
33 struct _stat st;
34 HKEY hTortoise;
35 char command[CMD_SIZE+1];
36 DWORD type, size;
37 if (_stat(".svn", &st) < 0)
38 return 0;
39 /* Allow suppression of subwcrev.exe invocation if a no_subwcrev file is present. */
40 if (_stat("no_subwcrev", &st) == 0)
41 return 0;
42 if (RegOpenKey(HKEY_LOCAL_MACHINE, "Software\\TortoiseSVN", &hTortoise) != ERROR_SUCCESS &&
43 RegOpenKey(HKEY_CURRENT_USER, "Software\\TortoiseSVN", &hTortoise) != ERROR_SUCCESS)
44 /* Tortoise not installed */
45 return 0;
46 command[0] = '"'; /* quote the path to the executable */
47 size = sizeof(command) - 1;
48 if (RegQueryValueEx(hTortoise, "Directory", 0, &type, command+1, &size) != ERROR_SUCCESS ||
49 type != REG_SZ)
50 /* Registry corrupted */
51 return 0;
52 strcat_s(command, CMD_SIZE, "bin\\subwcrev.exe");
53 if (_stat(command+1, &st) < 0)
54 /* subwcrev.exe not part of the release */
55 return 0;
56 strcat_s(command, CMD_SIZE, "\" ..\\.. ..\\..\\Modules\\getbuildinfo.c \"");
57 strcat_s(command, CMD_SIZE, tmppath); /* quoted tmppath */
58 strcat_s(command, CMD_SIZE, "getbuildinfo2.c\"");
59
60 puts(command); fflush(stdout);
61 if (system(command) < 0)
62 return 0;
63 return 1;
64}
65
66const char DELIMS[] = { " \n" };
67
68int get_mercurial_info(char * hgbranch, char * hgtag, char * hgrev, int size)
69{
70 int result = 0;
71 char filename[CMD_SIZE];
72 char cmdline[CMD_SIZE];
73
74 strcpy_s(filename, CMD_SIZE, "tmpXXXXXX");
75 if (_mktemp_s(filename, CMD_SIZE) == 0) {
76 int rc;
77
78 strcpy_s(cmdline, CMD_SIZE, "hg id -bit > ");
79 strcat_s(cmdline, CMD_SIZE, filename);
80 rc = system(cmdline);
81 if (rc == 0) {
82 FILE * fp;
83
84 if (fopen_s(&fp, filename, "r") == 0) {
85 char * cp = fgets(cmdline, CMD_SIZE, fp);
86
87 if (cp) {
88 char * context = NULL;
89 char * tp = strtok_s(cp, DELIMS, &context);
90 if (tp) {
91 strcpy_s(hgrev, size, tp);
92 tp = strtok_s(NULL, DELIMS, &context);
93 if (tp) {
94 strcpy_s(hgbranch, size, tp);
95 tp = strtok_s(NULL, DELIMS, &context);
96 if (tp) {
97 strcpy_s(hgtag, size, tp);
98 result = 1;
99 }
100 }
101 }
102 }
103 fclose(fp);
104 }
105 }
106 _unlink(filename);
107 }
108 return result;
109}
110
111int main(int argc, char*argv[])
112{
113 char command[CMD_SIZE] = "cl.exe -c -D_WIN32 -DUSE_DL_EXPORT -D_WINDOWS -DWIN32 -D_WINDLL ";
114 char tmppath[CMD_SIZE] = "";
115 int do_unlink, result;
116 char *tmpdir = NULL;
117 if (argc <= 2 || argc > 3) {
118 fprintf(stderr, "make_buildinfo $(ConfigurationName) [tmpdir]\n");
119 return EXIT_FAILURE;
120 }
121 if (strcmp(argv[1], "Release") == 0) {
122 strcat_s(command, CMD_SIZE, "-MD ");
123 }
124 else if (strcmp(argv[1], "Debug") == 0) {
125 strcat_s(command, CMD_SIZE, "-D_DEBUG -MDd ");
126 }
127 else if (strcmp(argv[1], "ReleaseItanium") == 0) {
128 strcat_s(command, CMD_SIZE, "-MD /USECL:MS_ITANIUM ");
129 }
130 else if (strcmp(argv[1], "ReleaseAMD64") == 0) {
131 strcat_s(command, CMD_SIZE, "-MD ");
132 strcat_s(command, CMD_SIZE, "-MD /USECL:MS_OPTERON ");
133 }
134 else {
135 fprintf(stderr, "unsupported configuration %s\n", argv[1]);
136 return EXIT_FAILURE;
137 }
138 if (argc > 2) {
139 tmpdir = argv[2];
140 strcat_s(tmppath, _countof(tmppath), tmpdir);
141 /* Hack fix for bad command line: If the command is issued like this:
142 * $(SolutionDir)make_buildinfo.exe" Debug "$(IntDir)"
143 * we will get a trailing quote because IntDir ends with a backslash that then
144 * escapes the final ". To simplify the life for developers, catch that problem
145 * here by cutting it off.
146 * The proper command line, btw is:
147 * $(SolutionDir)make_buildinfo.exe" Debug "$(IntDir)\"
148 * Hooray for command line parsing on windows.
149 */
150 if (strlen(tmppath) > 0 && tmppath[strlen(tmppath)-1] == '"')
151 tmppath[strlen(tmppath)-1] = '\0';
152 strcat_s(tmppath, _countof(tmppath), "\\");
153 }
154
155 if ((do_unlink = make_buildinfo2(tmppath))) {
156 strcat_s(command, CMD_SIZE, "\"");
157 strcat_s(command, CMD_SIZE, tmppath);
158 strcat_s(command, CMD_SIZE, "getbuildinfo2.c\" -DSUBWCREV ");
159 }
160 else {
161 char hgtag[CMD_SIZE];
162 char hgbranch[CMD_SIZE];
163 char hgrev[CMD_SIZE];
164
165 if (get_mercurial_info(hgbranch, hgtag, hgrev, CMD_SIZE)) {
166 strcat_s(command, CMD_SIZE, "-DHGBRANCH=\\\"");
167 strcat_s(command, CMD_SIZE, hgbranch);
168 strcat_s(command, CMD_SIZE, "\\\"");
169
170 strcat_s(command, CMD_SIZE, " -DHGTAG=\\\"");
171 strcat_s(command, CMD_SIZE, hgtag);
172 strcat_s(command, CMD_SIZE, "\\\"");
173
174 strcat_s(command, CMD_SIZE, " -DHGVERSION=\\\"");
175 strcat_s(command, CMD_SIZE, hgrev);
176 strcat_s(command, CMD_SIZE, "\\\" ");
177 }
178 strcat_s(command, CMD_SIZE, "..\\..\\Modules\\getbuildinfo.c");
179 }
180 strcat_s(command, CMD_SIZE, " -Fo\"");
181 strcat_s(command, CMD_SIZE, tmppath);
182 strcat_s(command, CMD_SIZE, "getbuildinfo.o\" -I..\\..\\Include -I..\\..\\PC");
183 puts(command); fflush(stdout);
184 result = system(command);
185 if (do_unlink) {
186 command[0] = '\0';
187 strcat_s(command, CMD_SIZE, "\"");
188 strcat_s(command, CMD_SIZE, tmppath);
189 strcat_s(command, CMD_SIZE, "getbuildinfo2.c\"");
190 _unlink(command);
191 }
192 if (result < 0)
193 return EXIT_FAILURE;
194 return 0;
195}