Surprise using DMD as replacement C compiler

Carl Sturtivant sturtivant at gmail.com
Thu Feb 29 15:34:43 UTC 2024


Hello, I ran into this issue when compiling an old large project 
on Linux with DMD as its C compiler implicitly using 
[ImportC](https://dlang.org/spec/importc.html). I was successful: 
  ImportC really came through!

I used `CC = dmd` in the configuration of the top level Makefile 
and all was well after some technical rearrangements (e.g. 
replacing `-o` by `-of=` when the compiler is invoked and fixing 
up old C constructs that DMD didn't like) excepting one part of 
the build.

That part made a dynamic library, and had to get exactly the 
right command line arguments to the C compiler for linking so 
that symbols would be exported and so forth. To do that, it ran a 
shell script to do the linking containing a branch based upon the 
output of `uname -s`. To do that it set shell variables in the 
environment the script runs in by e.g. in the Makefile the shell 
command `CC="$(CC)"` prefixing the command to run the script. 
Imagine my surprise when I got what follows in the terminal on 
typing `make`.
```
dmd -shared -fPIC -of=libcfunc.so external.o
Error: -o no longer supported, use -of or -od
Error: unrecognized switch '-Xlinker'
Error: unrecognized switch '--export-dynamic'
Error: unrecognized switch '-Xlinker'
Error: unrecognized switch '-Bstatic'
Error: unrecognized switch '-lphobos2'
Error: unrecognized switch '-Xlinker'
Error: unrecognized switch '-Bdynamic'
Error: unrecognized switch '-lpthread'
Error: unrecognized switch '-lm'
Error: unrecognized switch '-lrt'
Error: unrecognized switch '-ldl'
        run `dmd` to print the compiler manual
        run `dmd -man` to open browser on manual
Error: linker exited with status 1
```
The reason for this is that the *shell variable* `CC` is set to 
`CC=dmd` when DMD is invoked in the script. It seems that DMD 
uses its paired C compiler to do the linking and if the shell 
variable CC is defined, will get the compiler from its value, 
meaning itself in this case!

The result is what you see: a command line intended for `gcc` is 
instead executed with `dmd` in its place. Naturally `dmd` knows 
nothing of the various options used by `gcc` to invoke the linker 
at `dmd`'s request and complains accordingly, so at least 
recursion of this forwarding is prevented.

A test if `CC` is `dmd` in the script with `unset CC` preceding 
explicit use of `dmd` in place of `$CC` works around the problem.


More information about the Digitalmars-d mailing list