i4_make.cc 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914
  1. /********************************************************************** <BR>
  2. This file is part of Crack dot Com's free source code release of
  3. Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
  4. information about compiling & licensing issues visit this URL</a>
  5. <PRE> If that doesn't help, contact Jonathan Clark at
  6. golgotha_source@usa.net (Subject should have "GOLG" in it)
  7. ***********************************************************************/
  8. #include <stdio.h>
  9. #include "i4_make.hh"
  10. #include <ctype.h>
  11. #include "string.cc"
  12. #include "error.cc"
  13. #include "deps.cc"
  14. #include <sys/types.h>
  15. #include <sys/stat.h>
  16. #ifdef __linux
  17. #include <sys/wait.h>
  18. #include <unistd.h>
  19. #define MKDIR(x) mkdir(x, 0xffff)
  20. #endif
  21. #ifdef _WINDOWS
  22. #include <direct.h>
  23. #include <process.h>
  24. #include <winsock.h>
  25. #define MKDIR(x) _mkdir(x)
  26. #endif
  27. #include "array_tree.hh"
  28. char *link_file="c:\\tmp\\link.lk";
  29. mk_options_struct mk_options;
  30. enum {MAX_LEN=1000};
  31. char abs_path[MAX_LEN];
  32. int current_build_type=0;
  33. list failed_targets;
  34. list files_to_clean;
  35. list files_to_backup;
  36. #ifdef _WINDOWS
  37. int my_system (const char *command, int force=0)
  38. {
  39. char *argv[4];
  40. if (current_build_type==BUILD_DEBUG ||
  41. current_build_type==BUILD_OPT ||
  42. current_build_type==BUILD_PROF ||
  43. force)
  44. {
  45. if (command == 0)
  46. return 1;
  47. argv[0] = "command";
  48. argv[1] = "/c";
  49. argv[2] = (char *) command;
  50. argv[3] = 0;
  51. OSVERSIONINFO os;
  52. os.dwOSVersionInfoSize=sizeof(os);
  53. GetVersionEx(&os);
  54. if (os.dwPlatformId==VER_PLATFORM_WIN32_NT)
  55. return system(command);
  56. else
  57. return _spawnv(_P_WAIT, "c:\\windows\\command.com", argv);
  58. }
  59. return 0;
  60. }
  61. #else
  62. int my_system (const char *command, int force=0)
  63. {
  64. if (current_build_type==BUILD_DEBUG ||
  65. current_build_type==BUILD_OPT ||
  66. current_build_type==BUILD_PROF ||
  67. force)
  68. {
  69. // warning- this breaks if you have a child process running already
  70. int pid, status;
  71. if (command == 0)
  72. return 1;
  73. pid = fork();
  74. if (pid == -1)
  75. return -1;
  76. if (pid == 0)
  77. {
  78. char *argv[4];
  79. argv[0] = "sh";
  80. argv[1] = "-c";
  81. argv[2] = (char*) command;
  82. argv[3] = 0;
  83. execv("/bin/sh", argv);
  84. exit(127);
  85. }
  86. do
  87. {
  88. wait(&status);
  89. return status;
  90. } while(1);
  91. }
  92. return 0;
  93. }
  94. #endif
  95. void extract(char *fn)
  96. {
  97. FILE *in=fopen(fn,"rb");
  98. while (1)
  99. {
  100. unsigned char l,s1,s2,s3,s4;
  101. if (fread(&l,1,1,in)!=1)
  102. {
  103. fclose(in);
  104. exit(0);
  105. }
  106. char fn[256],buf[4096];
  107. fread(fn, 1,l,in);
  108. FILE *out=fopen(fn,"wb");
  109. if (!out)
  110. {
  111. for (int i=0; i<l; i++)
  112. if (fn[i]=='\\' || fn[i]=='/')
  113. {
  114. int old=fn[i];
  115. fn[i]=0;
  116. MKDIR(fn);
  117. fn[i]=old;
  118. }
  119. out=fopen(fn,"wb");
  120. }
  121. if (out)
  122. {
  123. fread(&s1,1,1,in); fread(&s2,1,1,in); fread(&s3,1,1,in); fread(&s4,1,1,in);
  124. int size=(s1<<24)|(s2<<16)|(s3<<8)|(s4);
  125. while (size)
  126. {
  127. int rsize=size>sizeof(buf) ? sizeof(buf) :size;
  128. fread(buf, 1,rsize,in);
  129. fwrite(buf, 1, rsize, out);
  130. size-=rsize;
  131. }
  132. fclose(out);
  133. }
  134. else printf("extract: could not open %s for writing\n", fn);
  135. }
  136. }
  137. void mk_options_struct::get(int argc, char **argv)
  138. {
  139. int i;
  140. quiet=1;
  141. for (i=1; i<argc; i++)
  142. {
  143. if (strcmp(argv[i],"/k")==0 || strcmp(argv[i],"-k")==0)
  144. continue_on_error=1;
  145. else if (strcmp(argv[i],"/f")==0 || strcmp(argv[i],"-f")==0)
  146. {
  147. i++;
  148. project_file=argv[i];
  149. }
  150. else if (strcmp(argv[i],"debug")==0)
  151. build_flags|=BUILD_DEBUG;
  152. else if (strcmp(argv[i],"profile")==0)
  153. build_flags|=BUILD_PROF;
  154. else if (strcmp(argv[i],"clean")==0)
  155. build_flags|=BUILD_CLEAN;
  156. else if (strcmp(argv[i],"backup")==0)
  157. {
  158. build_flags|=BUILD_BACKUP;
  159. }
  160. else if (strcmp(argv[i],"opt")==0 || strcmp(argv[i],"optimized")==0)
  161. build_flags|=BUILD_OPT;
  162. else if (strcmp(argv[i],"-d")==0)
  163. mk_debug_on=1;
  164. else if (strcmp(argv[i],"-show_deps")==0)
  165. show_deps=1;
  166. else if (strcmp(argv[i],"-v")==0)
  167. {
  168. verbose=1;
  169. quiet=0;
  170. }
  171. else if (strcmp(argv[i],"-v1")==0)
  172. {
  173. verbose=0;
  174. quiet=0;
  175. }
  176. else if (strcmp(argv[i],"-extract")==0)
  177. extract(argv[i+1]);
  178. else if (strcmp(argv[i],"-q")==0)
  179. quiet=1;
  180. else if (strcmp(argv[i],"-nl")==0 || strcmp(argv[i],"-no_libs")==0)
  181. no_libs=1;
  182. else if (strcmp(argv[i],"-sim_win32")==0)
  183. os=OS_WIN32;
  184. else if (strcmp(argv[i],"-static")==0)
  185. unix_libs_are_shared=0;
  186. else if (strcmp(argv[i],"-shared")==0)
  187. unix_libs_are_shared=1;
  188. else if (strcmp(argv[i],"-no_tmp")==0)
  189. no_tmp=1;
  190. else if (strcmp(argv[i],"-no_syms")==0)
  191. no_syms=1;
  192. else if (strcmp(argv[i],"-show_incs")==0)
  193. show_includes=1;
  194. else if (strcmp(argv[i],"-tmp")==0)
  195. {
  196. i++;
  197. tmp_dir=argv[i];
  198. }
  199. else if ((strcmp(argv[i],"-no_compile")==0) || (strcmp(argv[i],"-nc")==0))
  200. no_compile=1;
  201. else if (strcmp(argv[i],"--help")==0 ||
  202. strcmp(argv[i],"-help")==0 ||
  203. strcmp(argv[i],"?")==0 ||
  204. strcmp(argv[i],"-?")==0)
  205. {
  206. printf("%s ussage :\n"
  207. "%s [-f filename] [-k,q,nl,v,v1,no_libs] [debug] [opt] [clean] [backup] [targets..]\n"
  208. " -f overides default project.i4 for building\n"
  209. " -k continues on error\n"
  210. " debug build debug version of everything\n"
  211. " opt builds optimized version of everything\n"
  212. " backup backs up all the files referenced by project.i4 including\n"
  213. " headers, ram files, and .cc files (saves to backup.i4)\n"
  214. " if targets are not listed all targets list in project file are built\n"
  215. " -q quiet, shows only the file being processed, and not the actual command\n"
  216. " -v verbose show all commands executed\n"
  217. " -v1 shows verbose paths (normally simplified when show compiling\n"
  218. " -d show debug info relating to i4_make\n"
  219. " -nl causes the compilation not to use library files (where possible)\n"
  220. " -show_deps shows depdancies that are out of date\n"
  221. " -no_compile/-nc runs through the make process without compiling/linking\n"
  222. " -static don't make libraries shared (unix only)\n"
  223. " -no_syms don't include any symbol information in the object files or exes\n"
  224. " -extract filename extracts a backup into files (use i4_make backup)\n",
  225. argv[0]);
  226. exit(0);
  227. }
  228. else
  229. targets_to_build+=argv[i];
  230. }
  231. if (build_flags==0)
  232. build_flags=BUILD_DEBUG | BUILD_OPT;
  233. if (os==OS_WIN32) slash_char='\\';
  234. else slash_char='/';
  235. }
  236. enum { BUF_SIZE=1024*1000 };
  237. char *buf=0;
  238. int boff=0;
  239. char *buf_alloc(char *p, int len)
  240. {
  241. if (!buf || boff+len>BUF_SIZE)
  242. {
  243. buf=(char *)malloc(BUF_SIZE);
  244. boff=0;
  245. }
  246. memcpy(buf+boff,p,len);
  247. boff+=len;
  248. return buf+boff-len;
  249. }
  250. char *get_abs_path(char *filename, int force=0);
  251. void add_to_backup(char *fname)
  252. {
  253. char *full_name=get_abs_path(fname,1); // force a full name
  254. if (files_to_backup.find(full_name)==-1)
  255. files_to_backup.add(full_name);
  256. }
  257. void pcwd()
  258. {
  259. char buf[100];
  260. getcwd(buf, 100);
  261. printf("cwd = %s\n",buf);
  262. }
  263. char start_path[256];
  264. void set_abs_path(char *filename)
  265. {
  266. char tmp[MAX_LEN];
  267. strcpy(tmp, filename);
  268. char *last_slash=0, *p=tmp, *q;
  269. for (; *p; p++)
  270. if (*p=='/' || *p=='\\')
  271. last_slash=p;
  272. if (last_slash)
  273. {
  274. last_slash[1]=0;
  275. strcpy(abs_path, get_abs_path(tmp));
  276. if (mk_options.no_tmp)
  277. {
  278. chdir(start_path);
  279. chdir(abs_path);
  280. }
  281. }
  282. }
  283. char *get_abs_path(char *filename, int force)
  284. {
  285. if (mk_options.no_tmp && !force)
  286. return filename;
  287. else
  288. {
  289. char tmp[MAX_LEN];
  290. strcpy(tmp, abs_path);
  291. char *s, *d;
  292. if ((filename[0]=='/' || filename[0]=='\\') || (filename[1]==':'))
  293. return filename;
  294. for (s=filename, d=tmp + strlen(tmp); *s; )
  295. {
  296. if (s[0]=='.' && s[1]=='.' && (s[2]=='/' || s[2]=='\\'))
  297. {
  298. d-=2;
  299. while (*d!='/' && *d!='\\')
  300. {
  301. d--;
  302. if (d<tmp) mk_error("bad file path %s\n",filename);
  303. }
  304. d++;
  305. s+=3;
  306. }
  307. else
  308. {
  309. while (*s && *s!='/' && *s!='\\')
  310. {
  311. *d=*s;
  312. s++;
  313. d++;
  314. }
  315. if (*s)
  316. {
  317. *d=*s;
  318. d++;
  319. s++;
  320. }
  321. }
  322. }
  323. *d=0;
  324. for (d=tmp; *d; d++)
  325. if (mk_options.os==OS_LINUX && *d=='\\')
  326. *d='/';
  327. else if (mk_options.os==OS_WIN32 && *d=='/')
  328. *d='\\';
  329. return buf_alloc(tmp, strlen(tmp)+1);
  330. }
  331. }
  332. enum { EXT_O,
  333. EXT_LIB,
  334. EXT_DLL,
  335. EXT_PLUGIN,
  336. EXT_EXE,
  337. EXT_DEP,
  338. EXT_PCH,
  339. EXT_PDB,
  340. EXT_RAM_FILE,
  341. EXT_RC_RES
  342. };
  343. void show_command(char *cmd, int force=0)
  344. {
  345. if (current_build_type==BUILD_DEBUG ||
  346. current_build_type==BUILD_OPT ||
  347. current_build_type==BUILD_PROF ||
  348. force)
  349. {
  350. if (mk_options.verbose)
  351. printf("%s",cmd);
  352. else
  353. {
  354. for (;*cmd;)
  355. {
  356. if ((*cmd=='/' || *cmd=='\\') || (cmd[0]=='_' && cmd[1]=='_'))
  357. {
  358. char *start=cmd, *c, *d;
  359. for (c=cmd; *c && *c!=' '; c++)
  360. if (*c=='/' || *c=='\\')
  361. start=c+1;
  362. else if (c[0]=='_' && c[1]=='_')
  363. start=c+2;
  364. for (d=start; d!=c; d++)
  365. printf("%c",*d);
  366. cmd=c;
  367. }
  368. else
  369. {
  370. printf("%c", *cmd);
  371. cmd++;
  372. }
  373. }
  374. }
  375. printf("\n");
  376. }
  377. }
  378. char *make_out_name(char *filename, int ext_type=-1, int use_full_path=1, char *outdir=0)
  379. {
  380. char tmp[MAX_LEN], *s, *d;
  381. if (ext_type==-1)
  382. {
  383. int l=strlen(filename);
  384. if (l>4)
  385. {
  386. if (filename[l-3]=='.' && filename[l-2]=='r' && filename[l-1]=='c')
  387. ext_type=EXT_RC_RES;
  388. else if (filename[l-3]=='.' && filename[l-2]=='c' && filename[l-1]=='c')
  389. ext_type=EXT_O;
  390. else
  391. {
  392. printf("make_out_name : don't know what extension to use for %s",filename);
  393. exit(0);
  394. }
  395. } else
  396. {
  397. printf("make_out_name : filename to short : %s",filename);
  398. exit(0);
  399. }
  400. }
  401. if (mk_options.no_tmp)
  402. {
  403. d=tmp;
  404. char *start=filename;
  405. for (s=filename; *s && *s!='.'; s++);
  406. if (*s)
  407. {
  408. memcpy(d,filename, s-filename);
  409. d+=s-filename;
  410. }
  411. else
  412. {
  413. strcpy(d,filename);
  414. d+=strlen(d);
  415. }
  416. *d=0;
  417. }
  418. else
  419. {
  420. if (outdir)
  421. {
  422. strcpy(tmp,outdir);
  423. use_full_path=0;
  424. }
  425. else
  426. {
  427. if (mk_options.tmp_dir)
  428. sprintf(tmp,"%s%c", mk_options.tmp_dir, mk_options.slash_char);
  429. else
  430. {
  431. char *t=getenv("I4_TMP");
  432. if (t)
  433. sprintf(tmp,"%s%c", t, mk_options.slash_char);
  434. else
  435. {
  436. if (mk_options.os==OS_LINUX)
  437. strcpy(tmp,"/tmp/");
  438. else
  439. strcpy(tmp,"c:\\tmp\\");
  440. }
  441. }
  442. }
  443. d=tmp+strlen(tmp);
  444. if (!use_full_path)
  445. {
  446. char *start=filename;
  447. for (s=filename; *s; s++)
  448. if (*s=='\\' || *s=='/' || *s==':')
  449. start=s+1;
  450. strcpy(d,start);
  451. d+=strlen(d);
  452. }
  453. else
  454. {
  455. for (s=filename; *s; s++)
  456. {
  457. if (*s=='\\' || *s=='/' || *s==':')
  458. {
  459. d[0]=d[1]='_';
  460. d++;
  461. }
  462. else if (*s=='.')
  463. {
  464. d[0]='-';
  465. } else *d=*s;
  466. d++;
  467. }
  468. }
  469. }
  470. if (current_build_type==BUILD_DEBUG)
  471. strcpy(d,"_debug");
  472. else if (current_build_type==BUILD_OPT)
  473. strcpy(d,"_opt");
  474. else if (current_build_type==BUILD_PROF)
  475. strcpy(d,"_prof");
  476. else if (current_build_type==BUILD_CLEAN)
  477. strcpy(d,"_*");
  478. d+=strlen(d);
  479. if (mk_options.os==OS_LINUX)
  480. {
  481. switch (ext_type)
  482. {
  483. case EXT_O : strcpy(d,".o"); break;
  484. case EXT_LIB :
  485. {
  486. if (mk_options.unix_libs_are_shared)
  487. strcpy(d,".so");
  488. else
  489. strcpy(d,".a");
  490. } break;
  491. case EXT_DEP : strcpy(d,".dep"); break;
  492. case EXT_PLUGIN:
  493. case EXT_DLL : strcpy(d,".dll"); break;
  494. case EXT_RAM_FILE : strcpy(d,".cc"); break;
  495. }
  496. }
  497. else
  498. {
  499. switch (ext_type)
  500. {
  501. case EXT_O : strcpy(d,".obj"); break;
  502. case EXT_LIB : strcpy(d,".lib"); break;
  503. case EXT_EXE : strcpy(d,".exe"); break;
  504. case EXT_DEP : strcpy(d,".dep"); break;
  505. case EXT_PDB : strcpy(d,".pdb"); break;
  506. case EXT_PCH : strcpy(d,".pch"); break;
  507. case EXT_PLUGIN:
  508. case EXT_DLL : strcpy(d,".dll"); break;
  509. case EXT_RAM_FILE : strcpy(d,".cc"); break;
  510. case EXT_RC_RES : strcpy(d,".res"); break;
  511. }
  512. }
  513. char *ret=buf_alloc(tmp, strlen(tmp)+1);
  514. if (current_build_type==BUILD_CLEAN)
  515. {
  516. char *full_name=get_abs_path(ret,1); // force a full name
  517. if (files_to_clean.find(full_name)==-1)
  518. files_to_clean.add(full_name);
  519. }
  520. return ret;
  521. }
  522. unsigned long check_sum32(void *buf, int buf_len)
  523. {
  524. unsigned char c1=0,c2=0,c3=0,c4=0;
  525. while (buf_len)
  526. {
  527. c1+=*((unsigned char *)buf);
  528. c2+=c1;
  529. buf=(void *)(((unsigned char *)buf)+1);
  530. c3+=c2;
  531. c4+=c3;
  532. buf_len--;
  533. }
  534. return (c1|(c2<<8)|(c3<<16)|(c4<<24));
  535. }
  536. class mk_file_mod_node
  537. {
  538. public:
  539. int left, right;
  540. unsigned long checksum;
  541. unsigned long mod_time;
  542. int operator>(const mk_file_mod_node &b) const { return (checksum > b.checksum); }
  543. int operator<(const mk_file_mod_node &b) const { return (checksum < b.checksum); }
  544. mk_file_mod_node(unsigned long checksum) : checksum(checksum) {}
  545. mk_file_mod_node() {}
  546. };
  547. i4_array_tree<mk_file_mod_node, 5000> mod_tree;
  548. void set_mod_time(char *filename, int time_to_set)
  549. {
  550. mk_file_mod_node n(check_sum32(filename,strlen(filename)));
  551. int i=mod_tree.find(n);
  552. if (i!=-1)
  553. {
  554. mod_tree.get(i).mod_time=time_to_set;
  555. return ;
  556. }
  557. n.mod_time=time_to_set;
  558. mod_tree.add(n);
  559. }
  560. int get_mod_time(char *filename, int force_stat=0)
  561. {
  562. mk_file_mod_node n(check_sum32(filename,strlen(filename)));
  563. int i=mod_tree.find(n);
  564. if (i!=-1 && !force_stat)
  565. return mod_tree.get(i).mod_time;
  566. unsigned long t;
  567. #ifdef _WINDOWS
  568. struct _stat s;
  569. if (_stat(filename, &s)==0)
  570. t=s.st_mtime;
  571. else
  572. return 0;
  573. #elif __linux
  574. struct stat s;
  575. if (stat(filename, &s)==0)
  576. t=s.st_mtime;
  577. else
  578. return 0;
  579. #else
  580. #error define os here
  581. #endif
  582. if (i!=-1)
  583. mod_tree.get(i).mod_time=t;
  584. n.mod_time=t;
  585. mod_tree.add(n);
  586. return t;
  587. }
  588. enum { ALREADY_UP_TO_DATE,
  589. CHANGED,
  590. BUILD_ERROR,
  591. NO_MORE_TARGETS
  592. };
  593. void clean_file(char *outname)
  594. {
  595. char cmd[200];
  596. if (outname[strlen(outname)-1]!='*')
  597. {
  598. #ifdef _WINDOWS
  599. sprintf(cmd,"del %s", outname);
  600. #else
  601. sprintf(cmd,"rm %s", outname);
  602. #endif
  603. show_command(cmd,1);
  604. my_system(cmd, 1);
  605. }
  606. }
  607. int build_file(char *filename,
  608. mk_target_struct &target,
  609. mk_target_struct &top_target)
  610. {
  611. char *p=filename, *last_dot=0, cmd[MAX_LEN], inc[MAX_LEN], def[MAX_LEN];
  612. inc[0]=0;
  613. def[0]=0;
  614. int i;
  615. for (p=filename; *p; p++)
  616. if (*p=='.' && p[1]!='.')
  617. last_dot=p;
  618. if (last_dot)
  619. {
  620. if (strcmp(last_dot,".cc")==0)
  621. {
  622. char *source_name=get_abs_path(filename);
  623. char *outname=make_out_name(source_name,EXT_O);
  624. if (failed_targets.find(outname)!=-1)
  625. return BUILD_ERROR;
  626. switch (current_build_type)
  627. {
  628. case BUILD_BACKUP:
  629. {
  630. add_to_backup(source_name);
  631. list *dep=get_deps(source_name, &target.inc);
  632. if (dep)
  633. {
  634. for (i=0; i<dep->size(); i++)
  635. add_to_backup((*dep)[i]);
  636. }
  637. } break;
  638. case BUILD_OPT :
  639. case BUILD_DEBUG :
  640. case BUILD_PROF :
  641. int rebuild=0;
  642. int m1=get_mod_time(outname);
  643. if (m1)
  644. {
  645. list *dep=get_deps(source_name, &target.inc);
  646. if (mk_options.show_includes && dep)
  647. {
  648. printf( "%s\n",filename);
  649. for (i=0; i<dep->size(); i++)
  650. printf( " %s\n",(*dep)[i]);
  651. }
  652. if (dep)
  653. {
  654. for (i=0; !rebuild && i<dep->size(); i++)
  655. {
  656. int src_mod_time=get_mod_time( (*dep)[i]);
  657. if (src_mod_time>m1)
  658. {
  659. if (mk_options.show_deps)
  660. printf( "%s newer than %s\n", (*dep)[i], outname);
  661. rebuild=1;
  662. }
  663. }
  664. }
  665. } else rebuild=1;
  666. if (rebuild)
  667. {
  668. if (mk_options.os==OS_LINUX)
  669. {
  670. for (i=0; i<target.inc.size(); i++)
  671. sprintf(inc+strlen(inc), "-I%s ",target.inc[i]);
  672. for (i=0; i<target.defines.size(); i++)
  673. sprintf(def+strlen(def), "-D%s ", target.defines[i]);
  674. for (i=0; i<mk_global_defines.size(); i++)
  675. sprintf(def+strlen(def), "-D%s ", mk_global_defines[i]);
  676. char *sym_string = mk_options.no_syms ? "" : "-g ";
  677. sprintf(cmd, "g++ %s%s%s%s-c %s -o %s",
  678. sym_string,
  679. current_build_type==BUILD_DEBUG ? "-DDEBUG " :
  680. current_build_type==BUILD_OPT ? "-O2 " :
  681. "-O2 -pg ", // profile version
  682. def, inc, source_name, outname);
  683. }
  684. else
  685. {
  686. for (i=0; i<target.inc.size(); i++)
  687. sprintf(inc+strlen(inc), "/I %s ",target.inc[i]);
  688. for (i=0; i<target.defines.size(); i++)
  689. sprintf(def+strlen(def), "/D%s ",target.defines[i]);
  690. for (i=0; i<mk_global_defines.size(); i++)
  691. sprintf(def+strlen(def), "/D%s ",mk_global_defines[i]);
  692. char *dll_def=(strcmp(target.target_type,"dll")==0 ||
  693. strcmp(target.target_type,"plugin")==0) ? "/DBUILDING_DLL " : "";
  694. sprintf(cmd, "cl /GX /EHa /D_WINDOWS %s%s%s%s/c /Tp %s /Fo%s /Fd%s",
  695. dll_def,
  696. current_build_type==BUILD_DEBUG ? "/MD /Zi /Od /DDEBUG /nologo " :
  697. current_build_type==BUILD_OPT ? "/MD /Zi /Ox /nologo " :
  698. "/MD /Zi /Ox /nologo /Gh " // profile version
  699. ,
  700. def, inc, source_name, outname,
  701. // make_out_name(get_abs_path(target.target), EXT_PCH),
  702. make_out_name(get_abs_path(target.target), EXT_PDB));
  703. }
  704. if (mk_options.quiet && current_build_type!=BUILD_CLEAN)
  705. printf("Compiling %s (%s)\n", filename,
  706. current_build_type==BUILD_DEBUG ? "debug" :
  707. current_build_type==BUILD_OPT ? "opt" :
  708. "profile");
  709. else
  710. show_command(cmd);
  711. if (mk_options.no_compile)
  712. {
  713. set_mod_time(outname, 0x7fffffff);
  714. return CHANGED;
  715. }
  716. else
  717. {
  718. if (my_system(cmd)==0)
  719. {
  720. get_mod_time(outname,1); // get time of output file
  721. return CHANGED;
  722. }
  723. else
  724. {
  725. failed_targets.add(outname);
  726. return BUILD_ERROR;
  727. }
  728. }
  729. } else return ALREADY_UP_TO_DATE;
  730. break;
  731. }
  732. return ALREADY_UP_TO_DATE;
  733. }
  734. else if (strcmp(last_dot,".rc")==0)
  735. {
  736. add_to_backup(filename);
  737. char *source_name=get_abs_path(filename);
  738. char *outname=make_out_name(source_name,EXT_RC_RES);
  739. if (failed_targets.find(outname)!=-1)
  740. return BUILD_ERROR;
  741. if (get_mod_time(source_name)<get_mod_time(outname))
  742. return ALREADY_UP_TO_DATE;
  743. sprintf(cmd, "rc /fo%s ",outname);
  744. for (i=0; i<target.inc.size(); i++)
  745. sprintf(cmd+strlen(cmd), "/i %s ",target.inc[i]);
  746. sprintf(cmd+strlen(cmd),"%s", source_name);
  747. if (mk_options.quiet && current_build_type!=BUILD_CLEAN)
  748. printf("Compiling %s (%s)", source_name,
  749. current_build_type == BUILD_DEBUG ? "debug" :
  750. current_build_type == BUILD_OPT ? "opt" :
  751. "profile");
  752. else
  753. show_command(cmd);
  754. if (mk_options.no_compile)
  755. {
  756. set_mod_time(outname, 0x7fffffff);
  757. return CHANGED;
  758. }
  759. else
  760. {
  761. if (my_system(cmd)==0)
  762. {
  763. get_mod_time(outname, 1);
  764. return CHANGED;
  765. }
  766. else
  767. {
  768. failed_targets.add(outname);
  769. return BUILD_ERROR;
  770. }
  771. }
  772. }
  773. else
  774. mk_error("don't know how to build files with extension '%s' : %s",last_dot, filename);
  775. }
  776. else
  777. mk_error("don't know how to build files without extensions '%s'", filename);
  778. return BUILD_ERROR;
  779. }
  780. int build_lib(int object_files_have_changed,
  781. mk_target_struct &target,
  782. mk_target_struct &top_target,
  783. int dll=0)
  784. {
  785. char tmp[50000];
  786. int i;
  787. if (target.src.size()==0)
  788. return ALREADY_UP_TO_DATE;
  789. char *lname=make_out_name(get_abs_path(target.target),
  790. dll ? EXT_DLL : EXT_LIB, 1, target.outdir);
  791. if (failed_targets.find(lname)!=-1)
  792. return BUILD_ERROR;
  793. if (dll)
  794. {
  795. if (top_target.dlls.find(lname)==-1)
  796. top_target.dlls.add(lname);
  797. }
  798. else if (!dll && top_target.libs.find(lname)==-1)
  799. top_target.libs.add(lname);
  800. int ltime=get_mod_time(lname);
  801. if (!ltime)
  802. object_files_have_changed=1;
  803. if (mk_options.os==OS_LINUX)
  804. {
  805. char *sym_string = mk_options.no_syms ? "" : "-g ";
  806. char shared_string[100];
  807. if (mk_options.unix_libs_are_shared)
  808. sprintf(shared_string, "-shared -Wl,-soname,%s ", lname);
  809. else
  810. shared_string[0]=0;
  811. if (dll || mk_options.unix_libs_are_shared)
  812. sprintf(tmp, "g++ %s%s -g -o %s ",
  813. sym_string,
  814. shared_string,
  815. lname);
  816. else
  817. sprintf(tmp, "ar rucs %s ", lname);
  818. char *d=tmp+strlen(tmp);
  819. for (i=0; i<target.src.size(); i++)
  820. {
  821. char *oname=make_out_name(get_abs_path(target.src[i]));
  822. sprintf(d, "%s ", oname);
  823. if (!object_files_have_changed && get_mod_time(oname)>ltime)
  824. {
  825. if (mk_options.show_deps)
  826. printf( "%s newer than %s\n",oname, lname);
  827. object_files_have_changed=1;
  828. }
  829. d+=strlen(d);
  830. }
  831. }
  832. else
  833. {
  834. if (dll)
  835. sprintf(tmp,
  836. "link /MACHINE:IX86 /DEBUG /debugtype:coff /debugtype:both /DLL "
  837. "/nologo /PDB:%s /OUT:%s @%s%s",
  838. make_out_name(get_abs_path(lname), EXT_PDB, 0),
  839. lname, link_file,
  840. mk_options.quiet ? "> c:\\tmp\\null" : "");
  841. else
  842. sprintf(tmp, "lib /nologo /OUT:%s @%s%s", lname, link_file,
  843. mk_options.quiet ? "> c:\\tmp\\null" : "");
  844. FILE *fp=fopen(link_file, "wb");
  845. for (i=0; i<target.src.size(); i++)
  846. {
  847. char *oname=make_out_name(get_abs_path(target.src[i]));
  848. fprintf(fp, "%s\n", oname);
  849. if (!object_files_have_changed && get_mod_time(oname)>ltime)
  850. {
  851. if (mk_options.show_deps)
  852. printf( "%s newer than %s\n",oname, lname);
  853. object_files_have_changed=1;
  854. }
  855. }
  856. if (dll)
  857. {
  858. for (i=0; i<target.libs.size(); i++)
  859. {
  860. char *oname=target.libs[i];
  861. fprintf(fp, "%s\n", oname);
  862. if (!object_files_have_changed && get_mod_time(oname)>ltime)
  863. {
  864. if (mk_options.show_deps)
  865. printf( "%s newer than %s\n",oname, lname);
  866. object_files_have_changed=1;
  867. }
  868. }
  869. if (target.def_file)
  870. sprintf(tmp+strlen(tmp), " /def:\"%s\"", target.def_file);
  871. }
  872. fclose(fp);
  873. }
  874. if (object_files_have_changed)
  875. {
  876. if (mk_options.quiet && (current_build_type!=BUILD_CLEAN && current_build_type!=BUILD_BACKUP))
  877. printf("Creating library %s\n", target.target);
  878. else
  879. show_command(tmp);
  880. if (mk_options.no_compile)
  881. {
  882. set_mod_time(lname, 0x7fffffff);
  883. return CHANGED;
  884. }
  885. else
  886. {
  887. if (my_system(tmp)==0)
  888. {
  889. get_mod_time(lname, 1); // get time of output file
  890. // don't need to relink executable if using shared libraries
  891. if (mk_options.is_unix() && mk_options.unix_libs_are_shared)
  892. return ALREADY_UP_TO_DATE;
  893. return CHANGED;
  894. }
  895. else
  896. {
  897. failed_targets.add(lname); // don't try to build this again
  898. return BUILD_ERROR;
  899. }
  900. }
  901. }
  902. else
  903. return ALREADY_UP_TO_DATE;
  904. }
  905. int build_exe(int deps_have_changed, mk_target_struct &target)
  906. {
  907. char tmp[50000];
  908. int i;
  909. char *ename=make_out_name(get_abs_path(target.target), EXT_EXE, 0, target.outdir);
  910. int etime=get_mod_time(ename);
  911. if (!etime)
  912. deps_have_changed=1;
  913. FILE *fp;
  914. if (mk_options.os==OS_LINUX)
  915. {
  916. char *sym_str=mk_options.no_syms ? "" : "-g ";
  917. sprintf(tmp, "g++ -rdynamic %s%s-o %s ",
  918. sym_str,
  919. current_build_type==BUILD_DEBUG ? "" :
  920. current_build_type==BUILD_OPT ? "-O2 " :
  921. "-O2 -pg ",
  922. ename);
  923. }
  924. else
  925. {
  926. sprintf(tmp, "link /SUBSYSTEM:%s /MACHINE:IX86 /DEBUG "
  927. "/NOLOGO /PDB:%s /NODEFAULTLIB /OUT:%s @%s", // /INCREMENTAL:NO
  928. target.app_type==WIN32_CONSOLE_APP ? "CONSOLE" : "WINDOWS",
  929. make_out_name(get_abs_path(target.target), EXT_PDB, 0),
  930. ename, link_file);
  931. fp=fopen(link_file,"wb");
  932. if (!fp) mk_error("could not open %s for writing\n",link_file);
  933. }
  934. char *d=tmp+strlen(tmp);
  935. for (i=0; i<target.src.size(); i++)
  936. {
  937. char *oname=make_out_name(get_abs_path(target.src[i]));
  938. if (!deps_have_changed && get_mod_time(oname)>etime)
  939. {
  940. if (mk_options.show_deps)
  941. printf( "%s newer than %s\n",oname, ename);
  942. deps_have_changed=1;
  943. }
  944. if (mk_options.os==OS_LINUX)
  945. sprintf(d, "%s ", oname);
  946. else
  947. fprintf(fp, "%s\n", oname);
  948. d+=strlen(d);
  949. }
  950. for (i=target.libs.size()-1; i>=0; i--)
  951. {
  952. if (mk_options.os==OS_LINUX)
  953. sprintf(d, "%s ", target.libs[i]);
  954. else
  955. fprintf(fp, "%s\n", target.libs[i]);
  956. if (!deps_have_changed && get_mod_time(target.libs[i])>etime)
  957. {
  958. if (mk_options.show_deps)
  959. printf( "%s newer than %s\n", target.libs[i], ename);
  960. deps_have_changed=1;
  961. }
  962. d+=strlen(d);
  963. }
  964. if (mk_options.os==OS_WIN32)
  965. fclose(fp);
  966. if (deps_have_changed)
  967. {
  968. if (current_build_type!=BUILD_CLEAN && current_build_type!=BUILD_BACKUP)
  969. {
  970. if (mk_options.quiet)
  971. printf("Linking %s\n", target.target);
  972. else
  973. printf("%s\n", tmp);
  974. }
  975. if (mk_options.no_compile)
  976. {
  977. set_mod_time(ename, 0x7fffffff);
  978. return CHANGED;
  979. }
  980. else
  981. {
  982. if (my_system(tmp)==0)
  983. {
  984. get_mod_time(ename, 1); // get time of output file
  985. return CHANGED;
  986. }
  987. else
  988. return BUILD_ERROR;
  989. }
  990. }
  991. else return ALREADY_UP_TO_DATE;
  992. }
  993. int build_target(mk_target_struct &target,
  994. mk_target_struct &top_target)
  995. // list &exe_src,
  996. // list &exe_inc,
  997. // list &exe_def,
  998. // list &lib_files,
  999. // list &dll_libs)
  1000. {
  1001. int i;
  1002. int change=0;
  1003. if (mk_options.targets_built.find(target.target)==-1)
  1004. {
  1005. mk_options.targets_built.add(target.target);
  1006. if (strcmp(target.target_type,"list")==0)
  1007. {
  1008. for (i=0; i<target.src.size(); i++)
  1009. {
  1010. char *fname=get_abs_path(target.src[i]);
  1011. if (top_target.src.find(fname)==-1)
  1012. top_target.src.add(fname);
  1013. }
  1014. }
  1015. // if (strcmp(target.target_type,"executable")==0 || strcmp(target.target_type,"plugin")==0)
  1016. // {
  1017. // for (i=0; i<target.src.size(); i++)
  1018. // {
  1019. // char *fn=target.src[i];
  1020. // if (fn[strlen(fn)-1]=='.')
  1021. // printf("adding to src_file with no extension\n");
  1022. // target.src+=exe_src[i];
  1023. // }
  1024. // }
  1025. int ret=ALREADY_UP_TO_DATE;
  1026. for (i=0; i<target.src.size(); i++)
  1027. {
  1028. mk_debug("checking depends for %s\n", target.src[i]);
  1029. int result=build_file(target.src[i], target, top_target);
  1030. if (result==BUILD_ERROR && !mk_options.continue_on_error)
  1031. return BUILD_ERROR;
  1032. if (result==CHANGED)
  1033. change=1;
  1034. }
  1035. if (strcmp(target.target_type,"lib")==0)
  1036. {
  1037. if (mk_options.no_libs) // they don't want to use libs, add files to top target
  1038. {
  1039. for (i=0; i<target.src.size(); i++)
  1040. {
  1041. char *fname=get_abs_path(target.src[i]);
  1042. if (top_target.libs.find(fname)==-1)
  1043. top_target.libs.add(fname);
  1044. }
  1045. }
  1046. else
  1047. {
  1048. switch (build_lib(change, target, top_target, 0))
  1049. {
  1050. case BUILD_ERROR : return BUILD_ERROR; break;
  1051. case CHANGED : change=1; break;
  1052. }
  1053. }
  1054. }
  1055. if (strcmp(target.target_type,"executable")==0)
  1056. {
  1057. switch (build_exe(change, top_target))
  1058. {
  1059. case BUILD_ERROR : return BUILD_ERROR; break;
  1060. case CHANGED : change=1; break;
  1061. }
  1062. }
  1063. if (strcmp(target.target_type,"dll")==0)
  1064. {
  1065. switch (build_lib(change, target, top_target, 1))
  1066. {
  1067. case BUILD_ERROR : return BUILD_ERROR; break;
  1068. case CHANGED : change=1; break;
  1069. }
  1070. }
  1071. if (strcmp(target.target_type,"plugin")==0)
  1072. {
  1073. switch (build_lib(change, target, top_target, 1))
  1074. {
  1075. case BUILD_ERROR : return BUILD_ERROR; break;
  1076. case CHANGED : change=1; break;
  1077. }
  1078. }
  1079. }
  1080. if (change)
  1081. return change;
  1082. else
  1083. return ALREADY_UP_TO_DATE;
  1084. }
  1085. char skip_white(char *&p)
  1086. {
  1087. while (*p && (*p==' ' || *p=='\n' || *p=='\t' || *p=='\r' || *p=='#' || *p==28))
  1088. {
  1089. if (*p=='#')
  1090. {
  1091. while (*p && *p!='\n')
  1092. p++;
  1093. }
  1094. else if (*p==' ' || *p=='\r' || *p=='\t' || *p==28)
  1095. p++;
  1096. else if (*p=='\n')
  1097. {
  1098. p++;
  1099. line_on++;
  1100. }
  1101. else
  1102. {
  1103. char c=*p;
  1104. p++;
  1105. return c;
  1106. }
  1107. }
  1108. return 0;
  1109. }
  1110. int token_char(char p)
  1111. {
  1112. return isalnum(p) || p=='_' || p=='.' || p=='\\' || p=='/' || p==':';
  1113. }
  1114. char tmp[2000];
  1115. char *get_token(char *&p)
  1116. {
  1117. skip_white(p);
  1118. if (*p)
  1119. {
  1120. if (p[0]==']' || p[0]=='[' || p[0]=='=')
  1121. {
  1122. tmp[0]=p[0]; tmp[1]=0; p++;
  1123. return buf_alloc(tmp,2);
  1124. }
  1125. else if (p[0]=='"')
  1126. {
  1127. int len=0;
  1128. char *c=tmp;
  1129. p++;
  1130. while (*p && *p!='"')
  1131. {
  1132. *(c++)=*(p++);
  1133. len++;
  1134. }
  1135. *c=0;
  1136. p++;
  1137. return buf_alloc(tmp, len+1);
  1138. } else if (token_char(*p))
  1139. {
  1140. int len=0;
  1141. char *c=tmp;
  1142. while (*p && token_char(*p))
  1143. {
  1144. *(c++)=*(p++);
  1145. len++;
  1146. }
  1147. *c=0;
  1148. return buf_alloc(tmp, len+1);
  1149. }
  1150. else
  1151. {
  1152. mk_error("unexpected char '%c'", p[0]);
  1153. return 0;
  1154. }
  1155. }
  1156. else return 0;
  1157. }
  1158. void next_line(char *&p)
  1159. {
  1160. int l=line_on;
  1161. while (l==line_on)
  1162. {
  1163. skip_white(p);
  1164. if (l==line_on)
  1165. get_token(p);
  1166. }
  1167. }
  1168. int build_ram_file(char *name, char *out_name, mk_target_struct &top_target)
  1169. {
  1170. char *data_name=get_abs_path(name);
  1171. char *cc_name=make_out_name(data_name, EXT_RAM_FILE, 1);
  1172. if (top_target.src.find(cc_name)==-1)
  1173. top_target.src.add(cc_name);
  1174. int m1=get_mod_time(cc_name);
  1175. if (!m1 || m1<get_mod_time(data_name))
  1176. {
  1177. show_command(form("Generating ram file .cc %s", cc_name));
  1178. FILE *fp=fopen(data_name, "rb");
  1179. if (!fp)
  1180. {
  1181. printf( "%s : Unable to open file to genertate ram file\n", data_name);
  1182. return 0;
  1183. }
  1184. fseek(fp, 0, SEEK_END);
  1185. int fsize=ftell(fp);
  1186. fseek(fp, 0, SEEK_SET);
  1187. unsigned char *buf=(unsigned char *)malloc(fsize);
  1188. fread(buf, fsize, 1, fp);
  1189. fclose(fp);
  1190. unsigned long id=check_sum32(cc_name, strlen(cc_name)) +
  1191. check_sum32(out_name, strlen(out_name));
  1192. fp=fopen(cc_name, "wb");
  1193. fprintf(fp, "#include \"file/ram_file_man.hh\"\n\nunsigned char i4_%x_ptr[%d]={\n",
  1194. id, fsize);
  1195. for (int i=0; i<fsize-1; i++)
  1196. {
  1197. if ((i%15)==0)
  1198. fprintf(fp, "\n");
  1199. fprintf(fp, "%d, ", buf[i]);
  1200. }
  1201. if (fsize)
  1202. fprintf(fp, "%d", buf[fsize-1]);
  1203. fprintf(fp,"};\n\ni4_openable_ram_file_info i4_%x(\"%s\", i4_%x_ptr, %d);",
  1204. id, out_name, id, fsize);
  1205. fclose(fp);
  1206. get_mod_time(cc_name, 1);
  1207. return CHANGED;
  1208. }
  1209. else return ALREADY_UP_TO_DATE;
  1210. }
  1211. char *load_file(char *fn, int set_current_file)
  1212. {
  1213. char *abs_filename=get_abs_path(fn);
  1214. FILE *fp=fopen(abs_filename, "rb");
  1215. if (!fp) return 0;
  1216. fseek(fp, 0, SEEK_END);
  1217. int fsize=ftell(fp);
  1218. fseek(fp, 0, SEEK_SET);
  1219. char *buf=(char *)malloc(fsize+1);
  1220. fread(buf, fsize, 1, fp);
  1221. buf[fsize]=0;
  1222. fclose(fp);
  1223. if (set_current_file)
  1224. {
  1225. file_on=abs_filename;
  1226. line_on=0;
  1227. file_contents=buf;
  1228. }
  1229. return buf;
  1230. }
  1231. int get_target(mk_target_struct &target,
  1232. mk_target_struct &top_target,
  1233. char *&p,
  1234. char *target_name_to_match=0)
  1235. {
  1236. int ret=ALREADY_UP_TO_DATE;
  1237. while (1)
  1238. {
  1239. char *left_brace=get_token(p);
  1240. if (left_brace)
  1241. {
  1242. if (strcmp(left_brace, "["))
  1243. mk_error("expecting '['");
  1244. target.reset();
  1245. target.target_type=get_token(p);
  1246. target.target=get_token(p);
  1247. if (strcmp(get_token(p), "]"))
  1248. mk_error("expecting ']'");
  1249. // should we use this target or skip it
  1250. if (target_name_to_match && strcmp(target.target, target_name_to_match))
  1251. {
  1252. mk_debug("skipping section %s\n", target.target);
  1253. skip_white(p);
  1254. while (*p && *p!='[')
  1255. {
  1256. get_token(p);
  1257. skip_white(p);
  1258. }
  1259. }
  1260. else
  1261. {
  1262. mk_debug("processing section %s\n", target.target);
  1263. skip_white(p);
  1264. while (*p && *p!='[')
  1265. {
  1266. char *t=get_token(p);
  1267. if (strcmp(t, "win32")==0)
  1268. {
  1269. if (mk_options.os!=OS_WIN32)
  1270. {
  1271. mk_debug("%s : skipping line, wrong os\n", t);
  1272. next_line(p);
  1273. }
  1274. }
  1275. else if (strcmp(t, "linux")==0)
  1276. {
  1277. if (mk_options.os!=OS_LINUX)
  1278. {
  1279. mk_debug("%s : skipping line, wrong os\n", t);
  1280. next_line(p);
  1281. }
  1282. }
  1283. else if (strcmp(t, "opt")==0)
  1284. {
  1285. if (current_build_type!=BUILD_OPT)
  1286. {
  1287. mk_debug("%s : skipping line, wrong build type\n", t);
  1288. next_line(p);
  1289. }
  1290. }
  1291. else if (strcmp(t, "debug")==0)
  1292. {
  1293. if (current_build_type!=BUILD_DEBUG)
  1294. {
  1295. mk_debug("%s : skipping line, wrong build type\n", t);
  1296. next_line(p);
  1297. }
  1298. }
  1299. else if (strcmp(t, "profile")==0)
  1300. {
  1301. if (current_build_type!=BUILD_PROF)
  1302. {
  1303. mk_debug("%s : skipping line, wrong build type\n", t);
  1304. next_line(p);
  1305. }
  1306. }
  1307. else if (strcmp(t, "hostname")==0)
  1308. {
  1309. t=get_token(p);
  1310. char name[200];
  1311. gethostname(name,200);
  1312. if (strcmp(t, name)!=0)
  1313. next_line(p);
  1314. }
  1315. else if (strcmp(t, "nothostname")==0)
  1316. {
  1317. t=get_token(p);
  1318. char name[200];
  1319. gethostname(name,200);
  1320. if (strcmp(t, name)==0)
  1321. next_line(p);
  1322. }
  1323. else if (strcmp(t, "link_as_windowed_app")==0)
  1324. top_target.app_type=WIN32_WINDOWED_APP;
  1325. else if (strcmp(t, "target_dir")==0)
  1326. {
  1327. char *dir=get_token(p);
  1328. MKDIR(dir);
  1329. target.outdir=form("%s/",dir);
  1330. }
  1331. else if (strcmp(t, "add_to_plugin")==0)
  1332. {
  1333. char *fn=get_token(p);
  1334. char *file=get_abs_path(fn);
  1335. char *d=file+strlen(file);
  1336. while (d>file && *d!='.') d--;
  1337. if (strcmp(top_target.target_type,"plugin")==0)
  1338. {
  1339. if (strcmp(d,".def")==0)
  1340. top_target.def_file=file;
  1341. else if (strcmp(d,".a")==0 ||
  1342. (strstr(file, ".so")!=0) ||
  1343. strcmp(d,".lib")==0 ||
  1344. strcmp(d,".res")==0)
  1345. {
  1346. if (strcmp(d,".res")==0)
  1347. add_to_backup(file);
  1348. if (top_target.libs.find(file)==-1)
  1349. top_target.libs.add(file);
  1350. }
  1351. else if (top_target.src.find(file)==-1)
  1352. top_target.src.add(file);
  1353. }
  1354. }
  1355. else if (strcmp(t, "add_to_executable")==0)
  1356. {
  1357. char *fn=get_token(p);
  1358. char *file=get_abs_path(fn);
  1359. char *d=file+strlen(file);
  1360. while (d>file && *d!='.') d--;
  1361. if (strcmp(top_target.target_type,"executable")==0 ||
  1362. strcmp(top_target.target_type,"plugin")==0)
  1363. {
  1364. if (strcmp(d,".def")==0)
  1365. top_target.def_file=file;
  1366. else if (strcmp(d,".a")==0 ||
  1367. (strstr(file, ".so")!=0) ||
  1368. strcmp(d,".lib")==0 ||
  1369. strcmp(d,".res")==0)
  1370. {
  1371. if (strcmp(d,".res")==0)
  1372. add_to_backup(file);
  1373. if (top_target.libs.find(file)==-1)
  1374. top_target.libs.add(file);
  1375. }
  1376. else if (top_target.src.find(file)==-1)
  1377. top_target.src.add(file);
  1378. }
  1379. }
  1380. else if (strcmp(t,"backup")==0)
  1381. {
  1382. char *fname=get_token(p);
  1383. add_to_backup(fname);
  1384. }
  1385. else if (strcmp(t,"add_include_directory")==0)
  1386. {
  1387. char *i=get_abs_path(get_token(p), 1);
  1388. if (target.inc.find(i)==-1)
  1389. target.inc.add(i);
  1390. if (top_target.inc.find(i)==-1)
  1391. top_target.inc.add(i);
  1392. mk_debug("add_include_directory (dir=%s)\n", i);
  1393. }
  1394. else if (strcmp(t,"add_define")==0)
  1395. {
  1396. char *i=get_token(p);
  1397. if (target.defines.find(i)==-1)
  1398. target.defines.add(i);
  1399. mk_debug("add_define (define=%s)\n", i);
  1400. }
  1401. else if (strcmp(t,"add_global_define")==0)
  1402. {
  1403. char *i=get_token(p);
  1404. if (mk_global_defines.find(i)==-1)
  1405. mk_global_defines.add(i);
  1406. mk_debug("add_global_define (define=%s)\n", i);
  1407. }
  1408. else if (strcmp(t, "ram_file")==0)
  1409. {
  1410. char *in_name=get_token(p);
  1411. int l=line_on;
  1412. skip_white(p);
  1413. if (current_build_type==BUILD_BACKUP)
  1414. {
  1415. add_to_backup(in_name);
  1416. if (line_on==l)
  1417. get_token(p);
  1418. }
  1419. else
  1420. {
  1421. if (line_on==l)
  1422. build_ram_file(in_name, get_token(p), top_target);
  1423. else
  1424. build_ram_file(in_name, in_name, top_target);
  1425. }
  1426. }
  1427. else if (strcmp(t, "use")==0)
  1428. {
  1429. t=get_token(p);
  1430. char *use_file=0;
  1431. if (strcmp(t,"file")==0)
  1432. {
  1433. if (strcmp(get_token(p),"="))
  1434. mk_error("expected = after file");
  1435. use_file=get_token(p);
  1436. t=get_token(p);
  1437. add_to_backup(use_file);
  1438. }
  1439. mk_debug("use (file=%s) (target=%s)\n", use_file, t);
  1440. mk_target_struct tar;
  1441. int cur_line=line_on; // save current line & file info
  1442. char *cur_file=file_on;
  1443. char *cur_contents=file_contents;
  1444. char old_abs[MAX_LEN];
  1445. char *f;
  1446. if (use_file)
  1447. {
  1448. f=load_file(use_file, 1);
  1449. if (!f)
  1450. mk_error("could not load project file '%s'", use_file);
  1451. strcpy(old_abs, abs_path);
  1452. set_abs_path(use_file);
  1453. }
  1454. else f=file_contents;
  1455. if (get_target(tar, top_target, f,t)==NO_MORE_TARGETS)
  1456. mk_error("could not find target '%s'", t);
  1457. // add include paths to local target
  1458. for (int i=0; i<tar.inc.size(); i++)
  1459. if (target.inc.find(tar.inc[i])==-1)
  1460. target.inc.add(tar.inc[i]);
  1461. ret=build_target(tar, top_target);
  1462. if (use_file)
  1463. {
  1464. file_contents=cur_contents;
  1465. file_on=cur_file;
  1466. set_abs_path(old_abs);
  1467. }
  1468. line_on=cur_line;
  1469. }
  1470. else
  1471. {
  1472. mk_debug("add to target %s\n",t);
  1473. target.src.add(t);
  1474. }
  1475. skip_white(p);
  1476. }
  1477. return ret;
  1478. }
  1479. }
  1480. else return NO_MORE_TARGETS;
  1481. }
  1482. }
  1483. void backup()
  1484. {
  1485. if (files_to_backup.size())
  1486. {
  1487. FILE *out=fopen("backup.i4", "wb");
  1488. if (out)
  1489. {
  1490. int t_files=0;
  1491. for (int i=0; i<files_to_backup.size(); i++)
  1492. {
  1493. FILE *in=fopen(files_to_backup[i], "rb");
  1494. if (in)
  1495. {
  1496. char *fn=files_to_backup[i];
  1497. if (fn[1]==':') fn+=2;
  1498. if (fn[0]=='\\' || fn[0]=='/') fn++;
  1499. unsigned char l=strlen(fn)+1, s1,s2,s3,s4;
  1500. fwrite(&l, 1, 1, out);
  1501. fwrite(fn, l, 1, out);
  1502. fseek(in, 0, SEEK_END);
  1503. int size=ftell(in);
  1504. fseek(in, 0, SEEK_SET);
  1505. s1=(size&0xff000000)>>24;
  1506. s2=(size&0xff0000)>>16;
  1507. s3=(size&0xff00)>>8;
  1508. s4=(size&0xff)>>0;
  1509. fwrite(&s1, 1,1, out);
  1510. fwrite(&s2, 1,1, out);
  1511. fwrite(&s3, 1,1, out);
  1512. fwrite(&s4, 1,1, out);
  1513. char buf[4096];
  1514. int rsize=0;
  1515. do
  1516. {
  1517. rsize=fread(buf, 1, 4096, in);
  1518. fwrite(buf, rsize, 1, out);
  1519. } while (rsize);
  1520. t_files++;
  1521. fclose(in);
  1522. }
  1523. else printf("backup: couldn't open %s\n", files_to_backup[i]);
  1524. }
  1525. fclose(out);
  1526. printf("backed up %d files to backup.i4\n", t_files);
  1527. }
  1528. else printf("backup: couldn't backup.i4 for writing\n");
  1529. }
  1530. }
  1531. int i4_make_main(int argc, char **argv)
  1532. {
  1533. setbuf(stdout, 0);
  1534. #ifdef _WINDOWS
  1535. mk_options.os=OS_WIN32;
  1536. _getcwd(abs_path, sizeof(abs_path));
  1537. #elif __linux
  1538. mk_options.os=OS_LINUX;
  1539. getcwd(abs_path, sizeof(abs_path));
  1540. #else
  1541. #error add new os here
  1542. #endif
  1543. strcat(abs_path, "/");
  1544. mk_options.get(argc, argv);
  1545. char *file_start=load_file(mk_options.project_file, 1), *b;
  1546. if (!file_start)
  1547. mk_error("Project file not found : '%s'", mk_options.project_file);
  1548. mk_target_struct target;
  1549. getcwd(start_path, 256);
  1550. for (current_build_type=1; current_build_type<=BUILD_LAST; current_build_type*=2)
  1551. {
  1552. if (mk_options.build_flags & current_build_type)
  1553. {
  1554. if (current_build_type==BUILD_BACKUP)
  1555. add_to_backup(mk_options.project_file);
  1556. if (!mk_options.targets_to_build.size())
  1557. {
  1558. b=file_start;
  1559. int ret;
  1560. while (ret=get_target(target, target, b)!=NO_MORE_TARGETS)
  1561. {
  1562. if (build_target(target, target)==BUILD_ERROR)
  1563. if (!mk_options.continue_on_error)
  1564. {
  1565. perror("Stopping : ");
  1566. exit(-1);
  1567. }
  1568. target.reset();
  1569. mk_options.targets_built.clear();
  1570. }
  1571. }
  1572. for (int i=0; i<mk_options.targets_to_build.size(); i++)
  1573. {
  1574. b=file_start;
  1575. if (get_target(target, target, b, mk_options.targets_to_build[i])==NO_MORE_TARGETS)
  1576. mk_error("can't find target '%s' to build\n", mk_options.targets_to_build[i]);
  1577. else if (build_target(target, target)==BUILD_ERROR)
  1578. if (!mk_options.continue_on_error)
  1579. return -1;
  1580. target.reset();
  1581. mk_options.targets_built.clear();
  1582. }
  1583. if (current_build_type==BUILD_CLEAN)
  1584. {
  1585. for (int i=0; i<files_to_clean.size(); i++)
  1586. clean_file(files_to_clean[i]);
  1587. files_to_clean.clear();
  1588. }
  1589. }
  1590. }
  1591. if (mk_options.build_flags & BUILD_BACKUP)
  1592. backup();
  1593. return 0;
  1594. }
  1595. int main(int argc, char **argv)
  1596. {
  1597. return i4_make_main(argc, argv);
  1598. }