]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - win/configure.cpp
* Changed forking code, now the parent will attempt to retrieve the exit code of...
[user/henk/code/inspircd.git] / win / configure.cpp
1 /*       +------------------------------------+\r
2  *       | Inspire Internet Relay Chat Daemon |\r
3  *       +------------------------------------+\r
4  *\r
5  *  InspIRCd: (C) 2002-2007 InspIRCd Development Team\r
6  * See: http://www.inspircd.org/wiki/index.php/Credits\r
7  *\r
8  * This program is free but copyrighted software; see\r
9  *            the file COPYING for details.\r
10  *\r
11  * ---------------------------------------------------\r
12  */\r
13 \r
14 #define _CRT_SECURE_NO_DEPRECATE\r
15 \r
16 #include <windows.h>\r
17 #include <stdio.h>\r
18 #include <string>\r
19 #include <time.h>\r
20 #include "colours.h"\r
21 \r
22 using namespace std;\r
23 void Run();\r
24 void Banner();\r
25 void WriteCompileModules();\r
26 void WriteCompileCommands();\r
27 \r
28 /* detects if we are running windows xp or higher (5.1) */\r
29 bool iswinxp()\r
30 {\r
31         OSVERSIONINFO vi;\r
32         vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);\r
33         GetVersionEx(&vi);\r
34         if(vi.dwMajorVersion >= 5)\r
35                 return true;\r
36         \r
37         return false;\r
38 }\r
39 \r
40 int get_int_option(const char * text, int def)\r
41 {\r
42         static char buffer[500];\r
43         int ret;\r
44         printf_c("%s\n[\033[1;32m%u\033[0m] -> ", text, def);\r
45         fgets(buffer, 500, stdin);\r
46         if(sscanf(buffer, "%u", &ret) != 1)\r
47                 ret = def;\r
48 \r
49         printf("\n");\r
50         return ret;\r
51 }\r
52 \r
53 bool get_bool_option(const char * text, bool def)\r
54 {\r
55         static char buffer[500];\r
56         char ret[100];\r
57         printf_c("%s [\033[1;32m%c\033[0m] -> ", text, def ? 'y' : 'n');\r
58         fgets(buffer, 500, stdin);\r
59         if(sscanf(buffer, "%s", ret) != 1)\r
60                 strcpy(ret, def ? "y" : "n");\r
61 \r
62         printf("\n");\r
63         return !strncmp(ret, "y", 1);\r
64 }\r
65 \r
66 void get_string_option(const char * text, char * def, char * buf)\r
67 {\r
68         static char buffer[500];\r
69         printf_c("%s\n[\033[1;32m%s\033[0m] -> ", text, def);\r
70         fgets(buffer, 500, stdin);\r
71         if(sscanf(buffer, "%s", buf) != 1)\r
72                 strcpy(buf, def);\r
73 \r
74         printf("\n");\r
75 }\r
76 \r
77 // escapes a string for use in a c++ file\r
78 bool escape_string(char * str, size_t size)\r
79 {\r
80         size_t len = strlen(str);\r
81         char * d_str = (char*)malloc(len * 2);\r
82     \r
83         size_t i = 0;\r
84         size_t j = 0;\r
85 \r
86         for(; i < len; ++i)\r
87         {\r
88                 if(str[i] == '\\')\r
89                 {\r
90                         d_str[j++] = '\\';\r
91                         d_str[j++] = '\\';\r
92                 }\r
93                 else\r
94                 {\r
95                         d_str[j++] = str[i];\r
96                 }\r
97         }\r
98 \r
99         d_str[j++] = 0;\r
100 \r
101     if(j > size)\r
102         {\r
103                 free(d_str);\r
104                 return false;\r
105         }\r
106 \r
107         strcpy(str, d_str);\r
108         free(d_str);\r
109         return true;\r
110 }\r
111 \r
112 /* gets the svn revision */\r
113 int get_svn_revision(char * buffer, size_t len)\r
114 {\r
115         /* again.. I am lazy :p cbf to pipe output of svn info to us, so i'll just read the file */\r
116         /*\r
117         8\r
118 \r
119         dir\r
120         7033\r
121         */\r
122         char buf[1000];\r
123         FILE * f = fopen("..\\.svn\\entries", "r");\r
124         if(!f) goto bad_rev;\r
125     \r
126         if(!fgets(buf, 1000, f)) goto bad_rev;\r
127         if(!fgets(buf, 1000, f)) goto bad_rev;\r
128         if(!fgets(buf, 1000, f)) goto bad_rev;\r
129         if(!fgets(buf, 1000, f)) goto bad_rev;\r
130         int rev = atoi(buf);\r
131         if(rev == 0) goto bad_rev;\r
132         sprintf(buffer, "%u", rev);\r
133         fclose(f);\r
134         return rev;\r
135         \r
136 bad_rev:\r
137         strcpy(buffer, "non-svn");\r
138         if(f) fclose(f);\r
139         return 0;\r
140 }\r
141 \r
142 int __stdcall WinMain(IN HINSTANCE hInstance, IN HINSTANCE hPrevInstance, IN LPSTR lpCmdLine, IN int nShowCmd )\r
143 {\r
144         AllocConsole();\r
145 \r
146         // pipe standard handles to this console\r
147         freopen("CONIN$", "r", stdin);\r
148         freopen("CONOUT$", "w", stdout);\r
149         freopen("CONOUT$", "w", stderr);\r
150 \r
151         Banner();\r
152         Run();\r
153         WriteCompileCommands();\r
154         WriteCompileModules();\r
155         FreeConsole();\r
156         return 0;\r
157 }\r
158 \r
159 void Banner()\r
160 {\r
161         printf_c("\nWelcome to the \033[1mInspIRCd\033[0m Configuration program! (\033[1minteractive mode\033[0m)\n"\r
162                          "\033[1mPackage maintainers: Type ./configure --help for non-interactive help\033[0m\n\n");\r
163         printf_c("*** If you are unsure of any of these values, leave it blank for    ***\n"\r
164                          "*** standard settings that will work, and your server will run      ***\n"\r
165                          "*** using them. Please consult your IRC network admin if in doubt.  ***\n\n"\r
166                          "Press \033[1m<RETURN>\033[0m to accept the default for any option, or enter\n"\r
167                          "a new value. Please note: You will \033[1mHAVE\033[0m to read the docs\n"\r
168                          "dir, otherwise you won't have a config file!\n\n");\r
169 \r
170 }\r
171 \r
172 void Run()\r
173 {\r
174         int max_fd = 1024;\r
175         bool use_iocp = false;\r
176         bool support_ip6links = false;\r
177         char mod_path[MAX_PATH];\r
178         char config_file[MAX_PATH];\r
179         char library_dir[MAX_PATH];\r
180         char base_path[MAX_PATH];\r
181         char bin_dir[MAX_PATH];\r
182         char revision_text[MAX_PATH];\r
183 \r
184         int max_clients = 1024;\r
185         int nicklen = 31;\r
186         int chanlen = 64;\r
187         int modechanges = 20;\r
188         int identlen = 12;\r
189         int quitlen = 255;\r
190         int topiclen = 500;\r
191         int kicklen = 255;\r
192         int rllen = 128;\r
193         int awaylen = 200;\r
194         int revision = get_svn_revision(revision_text, MAX_PATH);\r
195         char version[514];\r
196 \r
197         // grab version\r
198         FILE * fI = fopen("..\\src\\version.sh", "r");\r
199         if(fI)\r
200         {\r
201                 fgets(version, 514, fI);\r
202                 fgets(version, 514, fI);\r
203                 char * p2 = version;\r
204                 while(*p2 != '\"')\r
205                         ++p2;\r
206                 ++p2;\r
207                 strcpy(version, p2);\r
208                 p2 = version;\r
209                 while(*p2 != '\"')\r
210                         ++p2;\r
211                 *p2 = 0;\r
212                 fclose(fI);\r
213         }\r
214         else\r
215                 strcpy(version, "InspIRCD-Unknown");\r
216         printf_c("Your operating system is: \033[1;32mwindows \033[0m\n");\r
217         printf_c("InspIRCd revision ID: \033[1;32m%s \033[0m\n\n", revision ? revision_text : "(Non-SVN build)");\r
218 \r
219         max_fd = get_int_option("What is the maximum file descriptor count you would like to allow?", 1024);\r
220 \r
221         // detect windows\r
222         if(iswinxp())\r
223         {\r
224                 printf_c("You are running Windows 2000 or above, and IOCP support is most likely available.\n"\r
225                              "This removes the socket number limitation of select and is much more efficent.\n"\r
226                                  "If you are unsure, answer yes.\n\n");\r
227 \r
228                 use_iocp = get_bool_option("Do you want to use the IOCP implementation?", true);\r
229         }\r
230 \r
231         support_ip6links = get_bool_option("\nYou have chosen to build an \033[1;32mIPV4-only\033[0m server.\nWould you like to enable support for linking to IPV6-enabled InspIRCd servers?\nIf you are using a recent operating system and are unsure, answer yes.\nIf you answer 'no' here, your InspIRCd server will be unable\nto parse IPV6 addresses (e.g. for CIDR bans)", \r
232                 true);\r
233         \r
234         printf_c("\033[1mAll paths are relative to the binary directory.\033[0m\n");\r
235         get_string_option("In what directory do you wish to install the InspIRCd base?", "..", base_path);\r
236         get_string_option("In what directory are the configuration files?", "../conf", config_file);\r
237         get_string_option("In what directory are the modules to be compiled to?", "../modules", mod_path);\r
238         get_string_option("In what directory is the IRCd binary to be placed?", ".", bin_dir);\r
239         get_string_option("In what directory are the IRCd libraries to be placed?", "../lib", library_dir);\r
240 \r
241         printf_c("The following questions will ask you for various figures relating\n"\r
242                 "To your IRCd install. Please note that these should usually be left\n"\r
243                 "as defaults unless you have a real reason to change them. If they\n"\r
244                 "changed, then the values must be identical on all servers on your\n"\r
245                 "network, or malfunctions and/or crashes may occur, with the exception\n"\r
246                 "of the 'maximum number of clients' setting which may be different on\n"\r
247                 "different servers on the network.\n\n");\r
248 \r
249     \r
250         max_clients = get_int_option("Please enter the maximum number of clients at any one time?", 1024);\r
251         nicklen = get_int_option("Please enter the maximum length of nicknames?", 31);\r
252         chanlen = get_int_option("Please enter the maximum length of channel names?", 64);\r
253         modechanges = get_int_option("Please enter the maximum number of mode changes in one line?", 20);\r
254         identlen = get_int_option("Please enter the maximum length of an ident (username)?", 12);\r
255         quitlen = get_int_option("Please enter the maximum length of a quit message?", 255);\r
256         topiclen = get_int_option("Please enter the maximum length of a channel topic?", 307);\r
257         kicklen = get_int_option("Please enter the maximum length of a kick message?", 255);\r
258         rllen = get_int_option("Please enter the maximum length of a GECOS (real name)?", 128);\r
259         awaylen = get_int_option("Please enter the maximum length of an away message?", 200);\r
260 \r
261         printf_c("\n\033[1;32mPre-build configuration is complete!\n\n");       sc(TNORMAL);\r
262 \r
263         // dump all the options back out\r
264         printf_c("\033[0mBase install path:\033[1;32m        %s\n", base_path);\r
265         printf_c("\033[0mConfig path:\033[1;32m              %s\n", config_file);\r
266         printf_c("\033[0mModule path:\033[1;32m              %s\n", mod_path);\r
267         printf_c("\033[0mLibrary path:\033[1;32m             %s\n", library_dir);\r
268         printf_c("\033[0mSocket Engine:\033[1;32m            %s\n", use_iocp ? "iocp" : "select");\r
269         printf_c("\033[0mMax file descriptors:\033[1;32m     %u\n", max_fd);\r
270         printf_c("\033[0mMax connections:\033[1;32m          %u\n", max_clients);\r
271         printf_c("\033[0mMax nickname length:\033[1;32m      %u\n", nicklen);\r
272         printf_c("\033[0mMax channel length:\033[1;32m       %u\n", chanlen);\r
273         printf_c("\033[0mMax mode length:\033[1;32m          %u\n", modechanges);\r
274         printf_c("\033[0mMax ident length:\033[1;32m         %u\n", identlen);\r
275         printf_c("\033[0mMax quit length:\033[1;32m          %u\n", quitlen);\r
276         printf_c("\033[0mMax topic length:\033[1;32m         %u\n", topiclen);\r
277         printf_c("\033[0mMax kick length:\033[1;32m          %u\n", kicklen);\r
278         printf_c("\033[0mMax name length:\033[1;32m          %u\n", rllen);\r
279         printf_c("\033[0mMax away length:\033[1;32m          %u\n", awaylen);\r
280         printf("\n"); sc(TNORMAL);\r
281         if(get_bool_option("Are these settings correct?", true) == false)\r
282         {\r
283                 Run();\r
284                 return;\r
285         }\r
286         printf("\n");\r
287 \r
288         // escape the pathes\r
289         escape_string(config_file, MAX_PATH);\r
290         escape_string(mod_path, MAX_PATH);\r
291         escape_string(library_dir, MAX_PATH);\r
292 \r
293         printf("\nWriting inspircd_config.h...");\r
294         FILE * f = fopen("inspircd_config.h", "w");\r
295         fprintf(f, "/* Auto generated by configure, do not modify! */\n");\r
296         fprintf(f, "#ifndef __CONFIGURATION_AUTO__\n");\r
297         fprintf(f, "#define __CONFIGURATION_AUTO__\n\n");\r
298         if(use_iocp)\r
299                 fprintf(f, "#define CONFIG_USE_IOCP 1\n\n");\r
300 \r
301         fprintf(f, "#define CONFIG_FILE \"%s/inspircd.conf\"\n", config_file);\r
302         fprintf(f, "#define MOD_PATH \"%s\"\n", mod_path);\r
303         fprintf(f, "#define MAX_DESCRIPTORS %u\n", max_fd);\r
304         fprintf(f, "#define MAXCLIENTS %u\n", max_clients);\r
305         fprintf(f, "#define MAXCLIENTS_S \"%u\"\n", max_clients);\r
306         fprintf(f, "#define SOMAXCONN_S \"128\"\n");\r
307         fprintf(f, "#define NICKMAX %u\n", nicklen+1);\r
308         fprintf(f, "#define CHANMAX %u\n", chanlen+1);\r
309         fprintf(f, "#define MAXMODES %u\n", modechanges);\r
310         fprintf(f, "#define IDENTMAX %u\n", identlen);\r
311         fprintf(f, "#define MAXQUIT %u\n", quitlen);\r
312         fprintf(f, "#define MAXTOPIC %u\n", topiclen);\r
313         fprintf(f, "#define MAXKICK %u\n", kicklen);\r
314         fprintf(f, "#define MAXGECOS %u\n", rllen);\r
315         fprintf(f, "#define MAXAWAY %u\n", awaylen);\r
316         fprintf(f, "#define LIBRARYDIR \"%s\"\n", library_dir);\r
317         fprintf(f, "#define VERSION \"%s\"\n", version);\r
318         fprintf(f, "#define REVISION \"%s\"\n", revision_text);\r
319         if(support_ip6links)\r
320                 fprintf(f, "#define SUPPORT_IP6LINKS 1\n");\r
321 \r
322         OSVERSIONINFO vi;\r
323         vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);\r
324         GetVersionEx(&vi);\r
325         fprintf(f, "#define SYSTEM \"Windows %u.%u.%u %s\"\n", vi.dwMajorVersion, vi.dwMinorVersion, vi.dwBuildNumber, vi.szCSDVersion);\r
326         fprintf(f, "#define MAXBUF 514\n");\r
327 \r
328         fprintf(f, "\n#include \"inspircd_win32wrapper.h\"\n\n");\r
329         fprintf(f, "#endif\n\n");\r
330         fclose(f);\r
331 \r
332         sc(TGREEN); printf(" done\n"); sc(TNORMAL);\r
333         printf("Writing inspircd_se_config.h...");\r
334 \r
335         f = fopen("inspircd_se_config.h", "w");\r
336         fprintf(f, "/* Auto generated by configure, do not modify or commit to svn! */\n");\r
337         fprintf(f, "#ifndef __CONFIGURATION_SOCKETENGINE__\n");\r
338         fprintf(f, "#define __CONFIGURATION_SOCKETENGINE__\n\n");\r
339         fprintf(f, "#include \"socketengine_%s.h\"\n\n", use_iocp ? "iocp" : "select");\r
340         fprintf(f, "#endif\n\n");\r
341         fclose(f);\r
342 \r
343         sc(TGREEN); printf(" done\n"); sc(TNORMAL);\r
344         printf("Writing command and module compilation scripts...");\r
345         WriteCompileCommands();\r
346         WriteCompileModules();\r
347         sc(TGREEN); printf(" done\n"); sc(TNORMAL);\r
348 \r
349         printf("\nconfigure is done.. exiting!\n");\r
350 }\r
351 \r
352 void WriteCompileCommands()\r
353 {\r
354         char commands[300][100];\r
355         int command_count = 0;\r
356         printf("\n  Finding Command Sources...\n");\r
357         WIN32_FIND_DATA fd;\r
358         HANDLE fh = FindFirstFile("..\\src\\cmd_*.cpp", &fd);\r
359         if(fh == INVALID_HANDLE_VALUE)\r
360                 printf_c("\033[1;32m  No command sources could be found! This \033[1m*could*\033[1;32m be a bad thing.. :P\033[0m");\r
361         else\r
362         {\r
363                 sc(TGREEN);\r
364                 do \r
365                 {\r
366                         strcpy(commands[command_count], fd.cFileName);\r
367                         commands[command_count][strlen(fd.cFileName) - 4] = 0;\r
368                         printf("    %s\n", commands[command_count]);\r
369                         ++command_count;\r
370                 } while(FindNextFile(fh, &fd));\r
371                 sc(TNORMAL);\r
372         }\r
373     \r
374         // Write our spiffy new makefile :D\r
375         // I am such a lazy fucker :P\r
376         FILE * f = fopen("..\\src\\commands.mak", "w");\r
377 \r
378         time_t t = time(NULL);\r
379         fprintf(f, "# Generated at %s\n", ctime(&t));\r
380         fprintf(f, "all: makedir ");\r
381 \r
382         // dump modules.. first time :)\r
383         for(int i = 0; i < command_count; ++i)\r
384                 fprintf(f, "%s.so ", commands[i]);\r
385 \r
386         fprintf(f, "\n.cpp.obj:\n");\r
387 #ifdef _DEBUG\r
388         fprintf(f, "  cl /nologo /LD /Od /I \".\" /I \"../include\" /I \"../include/modes\" /I \"../include/commands\" /I \"../win\" /D \"WIN32\" /D \"_DEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"DLL_BUILD\" /Gm /EHsc /GS /RTC1 /MTd /Fo\"Debug/\" /Fd\"Debug/vc70.pdb\" /W2 /Wp64 /Zi /TP $*.cpp ..\\win\\inspircd_memory_functions.cpp /link ..\\bin\\debug\\bin\\inspircd.lib /OUT:\"..\\bin\\debug\\lib\\$*.so\" /PDB:\"..\\bin\\debug\\lib\\$*.pdb\" /IMPLIB:\"..\\bin\\debug\\lib\\$*.lib\"\n\n");\r
389         CreateDirectory("..\\src\\debug", NULL);\r
390         CreateDirectory("..\\bin\\debug\\bin", NULL);\r
391         CreateDirectory("..\\bin\\debug\\lib", NULL);\r
392         CreateDirectory("..\\bin\\debug\\modules", NULL);\r
393 #else\r
394         fprintf(f, "  cl /nologo /LD /Od /I \".\" /I \"../include\" /I \"../include/modes\" /I \"../include/commands\" /I \"../win\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"DLL_BUILD\" /EHsc /GS /MT /Fo\"Release/\" /Fd\"Release/vc70.pdb\" /W2 /Wp64 /Zi /TP $*.cpp ..\\win\\inspircd_memory_functions.cpp /link ..\\bin\\release\\bin\\inspircd.lib /OUT:\"..\\bin\\release\\lib\\$*.so\" /PDB:\"..\\bin\\release\\lib\\$*.pdb\" /IMPLIB:\"..\\bin\\release\\lib\\$*.lib\"\n\n");\r
395         CreateDirectory("..\\src\\release", NULL);\r
396         CreateDirectory("..\\bin\\release\\bin", NULL);\r
397         CreateDirectory("..\\bin\\release\\lib", NULL);\r
398         CreateDirectory("..\\bin\\release\\modules", NULL);\r
399 #endif\r
400 \r
401         fprintf(f, "makedir:\n  if not exist debug mkdir debug\n\n");\r
402         \r
403         // dump modules.. again the second and last time :)\r
404         for(int i = 0; i < command_count; ++i)\r
405                 fprintf(f, "%s.so : %s.obj\n", commands[i], commands[i]);\r
406 \r
407         fprintf(f, "\n");\r
408         fclose(f);\r
409 }\r
410 \r
411 void WriteCompileModules()\r
412 {\r
413         char modules[300][100];\r
414         int module_count = 0;\r
415 \r
416         printf("Finding Modules...\n");\r
417         WIN32_FIND_DATA fd;\r
418         HANDLE fh = FindFirstFile("..\\src\\modules\\m_*.cpp", &fd);\r
419         if(fh == INVALID_HANDLE_VALUE)\r
420                 printf_c("\033[1;32m  No module sources could be found! This \033[1m*could*\033[1;32m be a bad thing.. :P\033[0m");\r
421         else\r
422         {\r
423                 sc(TGREEN);\r
424                 do \r
425                 {\r
426                         strcpy(modules[module_count], fd.cFileName);\r
427                         modules[module_count][strlen(fd.cFileName) - 4] = 0;\r
428                         printf("  %s\n", modules[module_count]);\r
429                         ++module_count;\r
430                 } while(FindNextFile(fh, &fd));\r
431                 sc(TNORMAL);\r
432         }\r
433 \r
434         // Write our spiffy new makefile :D\r
435         // I am such a lazy fucker :P\r
436         FILE * f = fopen("..\\src\\modules\\modules.mak", "w");\r
437 \r
438         time_t t = time(NULL);\r
439         fprintf(f, "# Generated at %s\n", ctime(&t));\r
440         fprintf(f, "all: makedir ");\r
441 \r
442         // dump modules.. first time :)\r
443         for(int i = 0; i < module_count; ++i)\r
444                 fprintf(f, "%s.so ", modules[i]);\r
445 \r
446         fprintf(f, "\n.cpp.obj:\n");\r
447 #ifdef _DEBUG\r
448         fprintf(f, "  cl /nologo /LD /Od /I \".\" /I \"../../include\" /I \"../../include/modes\" /I \"../../include/modules\" /I \"../../win\" /D \"WIN32\" /D \"_DEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"DLL_BUILD\" /Gm /EHsc /GS /RTC1 /MTd /Fo\"Debug/\" /Fd\"Debug/vc70.pdb\" /W2 /Wp64 /Zi /TP $*.cpp ..\\..\\win\\inspircd_memory_functions.cpp /link ..\\..\\bin\\debug\\bin\\inspircd.lib ws2_32.lib /OUT:\"..\\..\\bin\\debug\\modules\\$*.so\" /PDB:\"..\\..\\bin\\debug\\modules\\$*.pdb\" /IMPLIB:\"..\\..\\bin\\debug\\modules\\$*.lib\"\n\n");\r
449         CreateDirectory("..\\src\\modules\\debug", NULL);\r
450 #else\r
451         fprintf(f, "  cl /nologo /LD /Od /I \".\" /I \"../../include\" /I \"../../include/modes\" /I \"../../include/modules\" /I \"../../win\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"DLL_BUILD\" /EHsc /GS /MT /Fo\"Release/\" /Fd\"Release/vc70.pdb\" /W2 /Wp64 /Zi /TP $*.cpp ..\\..\\win\\inspircd_memory_functions.cpp /link ..\\..\\bin\\release\\bin\\inspircd.lib ws2_32.lib /OUT:\"..\\..\\bin\\release\\modules\\$*.so\" /PDB:\"..\\..\\bin\\release\\modules\\$*.pdb\" /IMPLIB:\"..\\..\\bin\\release\\modules\\$*.lib\"\n\n");\r
452         CreateDirectory("..\\src\\modules\\release", NULL);\r
453 #endif\r
454         \r
455         fprintf(f, "makedir:\n  if not exist debug mkdir debug\n\n");\r
456 \r
457         // dump modules.. again the second and last time :)\r
458         for(int i = 0; i < module_count; ++i)\r
459                 fprintf(f, "%s.so : %s.obj\n", modules[i], modules[i]);\r
460 \r
461         fprintf(f, "\n");\r
462         fclose(f);\r
463 }\r