gparmake.pp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  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> <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 files: ansistring);
  23. var
  24. rulestr: string;
  25. begin
  26. rulestr:=rulenr2str(rulenr);
  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) $(DATE) > $@');
  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. doappend: boolean;
  39. Function ProcessArgs: longint;
  40. var
  41. i,
  42. paramnr,
  43. chunktargetsize,
  44. chunksize,
  45. chunknr,
  46. error: longint;
  47. testname,
  48. nexttestname,
  49. testlist,
  50. outputname: ansistring;
  51. procedure FlushChunk;
  52. begin
  53. WriteChunkRule(chunknr,testlist);
  54. inc(chunknr);
  55. testlist:='';
  56. chunksize:=0;
  57. end;
  58. begin
  59. if paramcount < 3 then
  60. Usage;
  61. doappend:=false;
  62. paramnr:=1;
  63. if paramstr(paramnr)='-a' then
  64. begin
  65. doappend:=true;
  66. inc(paramnr);
  67. end;
  68. outputname:=paramstr(paramnr);
  69. inc(paramnr);
  70. val(paramstr(paramnr),startchunk,error);
  71. if error<>0 then
  72. Usage;
  73. inc(paramnr);
  74. val(paramstr(paramnr),chunktargetsize,error);
  75. if error<>0 then
  76. Usage;
  77. inc(paramnr);
  78. { only redirect output after all possible cases where we may have to write
  79. the usage screen }
  80. assign(output,outputname);
  81. if doappend then
  82. append(output)
  83. else
  84. rewrite(output);
  85. chunknr:=startchunk;
  86. chunksize:=0;
  87. testlist:='';
  88. for i := paramnr to paramcount do
  89. begin
  90. testname:=paramstr(i);
  91. testlist:=testlist+' '+testname;
  92. inc(chunksize);
  93. if chunksize>=chunktargetsize then
  94. begin
  95. if (i=paramcount) then
  96. FlushChunk
  97. else
  98. begin
  99. { keep tests with the same name except for the last character in the same chunk,
  100. because they may have to be executed in order (skip ".pp" suffix and last char) }
  101. nexttestname:=paramstr(i+1);
  102. if lowercase(copy(testname,1,length(testname)-4))<>lowercase(copy(nexttestname,1,length(nexttestname)-4)) then
  103. FlushChunk;
  104. end;
  105. end;
  106. end;
  107. if chunksize<>0 then
  108. FlushChunk;
  109. ProcessArgs:=chunknr-1;
  110. end;
  111. procedure WriteWrapperRules(totalchunks: longint);
  112. const
  113. lognames: array[1..3] of string[11] = ('log','faillist','longlog');
  114. var
  115. logi,
  116. i: longint;
  117. begin
  118. for logi:=1 to 3 do
  119. begin
  120. write('$(TEST_OUTPUTDIR)/',lognames[logi],' :');
  121. for i:=startchunk to totalchunks do
  122. write(' $(TEST_OUTPUTDIR)/',lognames[logi],'.chunk',rulenr2str(i));
  123. writeln;
  124. { if you have multiple rules for one (non-pattern) target, all
  125. prerequisites will be merged, but only one of the rules can have a
  126. recipe }
  127. if not doappend then
  128. begin
  129. writeln(#9'$(Q)$(CONCAT) $(sort $^) $@');
  130. writeln;
  131. end;
  132. writeln;
  133. end;
  134. if not doappend then
  135. begin
  136. writeln('allexectests : $(LOGFILES)');
  137. writeln;
  138. end;
  139. end;
  140. var
  141. totalchunks: longint;
  142. begin
  143. totalchunks:=ProcessArgs;
  144. WriteWrapperRules(totalchunks);
  145. close(output);
  146. end.