gparmake.pp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. { See procedure "Usage". This code is in the public domain. }
  2. Program GParMake;
  3. procedure Usage;
  4. begin
  5. writeln('GParMake: create make rules for parallel execution of testsuite');
  6. writeln('Usage: gparmake [-a] <outputfile> <dirname> <startchunk> <tests_per_chunk> <test1> [<test2> ...]');
  7. writeln('Output: makefile fragment with rules to run the tests in sequences of <tests_per_chunk>');
  8. writeln;
  9. halt(1);
  10. end;
  11. { make all numbers of the same string length so they can be sorted
  12. lexographically }
  13. function rulenr2str(rulenr: longint): string;
  14. var
  15. i: longint;
  16. begin
  17. str(rulenr:9,rulenr2str);
  18. for i:=1 to length(rulenr2str)-1 do
  19. if rulenr2str[i]=' ' then
  20. rulenr2str[i]:='0';
  21. end;
  22. procedure WriteChunkRule(rulenr: longint; const dirname, files: ansistring);
  23. var
  24. rulestr: string;
  25. begin
  26. rulestr:=rulenr2str(rulenr)+dirname;
  27. writeln('$(TEST_OUTPUTDIR)/testchunk_',rulestr,'-stamp.$(TEST_FULL_TARGET): testprep-stamp.$(TEST_FULL_TARGET)');
  28. writeln(#9'$(Q)$(DOTEST) $(DOTESTOPT) -Lchunk',rulestr,' -e ',files);
  29. writeln(#9'$(ECHOREDIR) $(TEST_DATETIME) > $@');
  30. writeln;
  31. writeln('$(addsuffix .chunk',rulestr,', $(LOGFILES)) : $(TEST_OUTPUTDIR)/testchunk_',rulestr,'-stamp.$(TEST_FULL_TARGET)');
  32. writeln;
  33. writeln('.INTERMEDIATE: $(addsuffix .chunk',rulestr,', $(LOGFILES)) $(TEST_OUTPUTDIR)/testchunk_',rulestr,'-stamp.$(TEST_FULL_TARGET)');
  34. writeln;
  35. end;
  36. var
  37. startchunk: longint;
  38. dirname : ansistring;
  39. doappend: boolean;
  40. Function ProcessArgs: longint;
  41. var
  42. i,
  43. paramnr,
  44. chunktargetsize,
  45. chunksize,
  46. chunknr,
  47. error: longint;
  48. testname,
  49. nexttestname,
  50. testlist,
  51. outputname: ansistring;
  52. procedure FlushChunk;
  53. begin
  54. WriteChunkRule(chunknr,dirname,testlist);
  55. inc(chunknr);
  56. testlist:='';
  57. chunksize:=0;
  58. end;
  59. begin
  60. if paramcount < 3 then
  61. Usage;
  62. doappend:=false;
  63. paramnr:=1;
  64. if paramstr(paramnr)='-a' then
  65. begin
  66. doappend:=true;
  67. inc(paramnr);
  68. end;
  69. outputname:=paramstr(paramnr);
  70. inc(paramnr);
  71. dirname:=paramstr(paramnr);
  72. inc(paramnr);
  73. val(paramstr(paramnr),startchunk,error);
  74. if error<>0 then
  75. Usage;
  76. inc(paramnr);
  77. val(paramstr(paramnr),chunktargetsize,error);
  78. if error<>0 then
  79. Usage;
  80. inc(paramnr);
  81. { only redirect output after all possible cases where we may have to write
  82. the usage screen }
  83. assign(output,outputname);
  84. if doappend then
  85. append(output)
  86. else
  87. rewrite(output);
  88. chunknr:=startchunk;
  89. chunksize:=0;
  90. testlist:='';
  91. for i := paramnr to paramcount do
  92. begin
  93. testname:=paramstr(i);
  94. testlist:=testlist+' '+testname;
  95. inc(chunksize);
  96. if chunksize>=chunktargetsize then
  97. begin
  98. if (i=paramcount) then
  99. FlushChunk
  100. else
  101. begin
  102. { keep tests with the same name except for the last character in the same chunk,
  103. because they may have to be executed in order (skip ".pp" suffix and last char) }
  104. nexttestname:=paramstr(i+1);
  105. if lowercase(copy(testname,1,length(testname)-4))<>lowercase(copy(nexttestname,1,length(nexttestname)-4)) then
  106. FlushChunk;
  107. end;
  108. end;
  109. end;
  110. if chunksize<>0 then
  111. FlushChunk;
  112. ProcessArgs:=chunknr-1;
  113. end;
  114. procedure WriteWrapperRules(totalchunks: longint);
  115. const
  116. lognames: array[1..3] of string[11] = ('log','faillist','longlog');
  117. var
  118. logi,
  119. i: longint;
  120. begin
  121. for logi:=1 to 3 do
  122. begin
  123. write('$(TEST_OUTPUTDIR)/',lognames[logi],' :');
  124. for i:=startchunk to totalchunks do
  125. write(' $(TEST_OUTPUTDIR)/',lognames[logi],'.chunk',rulenr2str(i)+dirname);
  126. writeln;
  127. { if you have multiple rules for one (non-pattern) target, all
  128. prerequisites will be merged, but only one of the rules can have a
  129. recipe }
  130. if not doappend then
  131. begin
  132. writeln(#9'$(Q)$(CONCAT) $(sort $^) $@');
  133. writeln;
  134. end;
  135. writeln;
  136. end;
  137. if not doappend then
  138. begin
  139. writeln('gparmake_allexectests : $(LOGFILES)');
  140. writeln;
  141. end;
  142. end;
  143. var
  144. totalchunks: longint;
  145. begin
  146. totalchunks:=ProcessArgs;
  147. WriteWrapperRules(totalchunks);
  148. close(output);
  149. end.