Building the compiler in 2 seconds with `dmd -i`

H. S. Teoh hsteoh at qfbox.info
Fri May 19 16:52:19 UTC 2023


On Fri, May 19, 2023 at 09:13:02AM -0700, Ali Çehreli via Digitalmars-d wrote:
> On 5/19/23 07:28, Adam D Ruppe wrote:
> 
> > dmd -i is heaven. I, without a doubt, place it as the most
> > significant addition to the D ecosystem of the last six years
> > (probably more if I extended the audit)
> >
> > I've deleted so many convoluted builds in favor of it and always
> > seen wins.
> 
> -i is great and I've started with -i in my last project that uses
> Makefiles.  For now, I went back to manual dependencies by listing all
> the modules explicitly. Otherwise, 'make' did not know modifications
> to the -i files. I think I will incorporate the -deps switch later.
[...]

I propose a new compiler switch that does the following:
- For every file included by -i, check whether it has changed since the
  last compile.
- If none of the input files, including those pulled in by -i, have
  changed since the last compile, skip all semantic and codegen steps
  and exit with a success status.

Then you could just unconditionally run {dmd,ldc2} -i every time, and it
will just be a (mostly) no-op if none of the source files have changed.

//

The big question is, of course, how will the compiler know whether a
file has changed?  There are several ways of doing this.

- The age-old Make way of checking timestamps. OK if you're on the
  filesystem, but unreliable and prone to false positives and false
  negatives. False positives are not horrible -- the worst is you just
  recompile something that didn't change, no problem, you get the same
  binary. But false negatives are very bad: the compiler gives you the
  impression that it has recompiled the binary but actually did nothing.
  But in the general case this shouldn't happen (not frequently anyway),
  so a workaround could just be to recompile without the new switch when
  you suspect false negatives are happening.

- Do a quick checksum of each imported file and compare against some
  stored checksums. This could be stored in the executable in an
  optional section that gets ignored by the linker, for example. The
  compiler loads this section and compares the checksum of each source
  file against it. If the checksum is the same, the source file hasn't
  changed. If the checksum is different, or if there's no checksum
  loaded (this is the first compilation of that file), compile as usual.
  The advantage of this approach is that if your checksum algorithm is
  reliable, false positives and false negatives should (almost) never
  happen. The disadvantage is that this will be slow.

//

The above scheme, of course, falls down if you do tricky things like
having string mixins that construct import statements:

	string makeCode(string x, string y) {
		return x ~ " " ~ y ~ ";";
	}
	void main() {
		mixin(makeCode("import", "mymodule");
	}

The compiler wouldn't know that mymodule.d is being pulled in without
running semantic. So the savings will be less, possibly much less, and
you might as well just recompile everything every time instead.


T

-- 
Mediocrity has been pushed to extremes.


More information about the Digitalmars-d mailing list