A tool that tries to build every Dub package against a wide range of DMD versions.

builder.d 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. module backporter.builder;
  2. import backporter.git;
  3. import backporter.core;
  4. import std.stdio : File;
  5. import std.experimental.logger;
  6. import std.file;
  7. import std.path;
  8. bool checkout(PackageRevision pkg, string dir)
  9. {
  10. if (!dir.exists || !chainPath(dir, ".git").exists)
  11. {
  12. auto parent = dirName(dir);
  13. mkdirRecurse(parent);
  14. cd(parent);
  15. if (clone(pkg.gitUrl, pkg.packageName).status != 0) return false;
  16. }
  17. cd(dir);
  18. return reset("--hard", pkg.commitId).status == 0;
  19. }
  20. Build build(Config config, PackageRevision revision)
  21. {
  22. Build result;
  23. result.revisionId = revision.revisionId;
  24. result.packageName = revision.packageName;
  25. result.compilerRelease = config.compilerRelease;
  26. static import datefmt;
  27. import std.datetime.systime : Clock;
  28. result.time = datefmt.format(Clock.currTime, datefmt.ISO8601FORMAT);
  29. auto dir = config.dataDir.buildPath(revision.packageName);
  30. if (!checkout(revision, dir)) return result;
  31. result.canCheckOut = true;
  32. cd(dir);
  33. // `dub build` includes app.d / main.d.
  34. // `dub test` runs unittests.
  35. // Without both, you can't be certain a package works.
  36. // `dub test` isn't quite enough, and this doesn't get subpackages...but this is okay for
  37. // starting out, at least.
  38. auto buildResult = run(
  39. config.buildTimeout,
  40. config.dubLoc,
  41. "build",
  42. "--compiler=" ~ config.dmdLoc
  43. );
  44. if (buildResult.status == 0)
  45. {
  46. result.canBuild = true;
  47. }
  48. auto testResult = run(
  49. config.buildTimeout,
  50. config.dubLoc,
  51. "test",
  52. "--compiler=" ~ config.dmdLoc
  53. );
  54. if (testResult.status == 0)
  55. {
  56. result.canTest = true;
  57. }
  58. import std.string : representation;
  59. import std.algorithm.searching : canFind;
  60. result.hasDeprecations = buildResult.stderr.canFind("Deprecated".representation);
  61. return result;
  62. }
  63. void buildAll(Config config, PackageRevision[] pkgs)
  64. {
  65. foreach (pkg; pkgs)
  66. {
  67. auto res = build(config, pkg);
  68. config.record(res);
  69. /*
  70. config.outfile.writefln("%s,%s,%s,%s,%s,%s,%s",
  71. config.compilerRelease,
  72. res.revision.pkg.name,
  73. res.revision.id,
  74. res.canCheckOut,
  75. res.canBuild,
  76. res.canTest,
  77. res.hasDeprecations);
  78. config.outfile.flush;
  79. */
  80. }
  81. }
  82. void exerciseRelease(Config config, string compilerRelease)
  83. {
  84. import backporter.dmd;
  85. config.compilerRelease = compilerRelease;
  86. downloadCompiler(config);
  87. auto remaining = config.countRemainingPackages(compilerRelease);
  88. while (true)
  89. {
  90. auto pkg = config.nextPackage(config.compilerRelease);
  91. if (pkg == PackageRevision.init)
  92. {
  93. break;
  94. }
  95. infof("dmd %s package %s.%s (%s remaining)",
  96. config.compilerRelease,
  97. pkg.packageName,
  98. pkg.revisionId,
  99. remaining);
  100. remaining--;
  101. config.record(build(config, pkg));
  102. }
  103. }