www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Surprise using DMD as replacement C compiler

reply Carl Sturtivant <sturtivant gmail.com> writes:
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.
Feb 29
next sibling parent reply Hipreme <msnmancini hotmail.com> writes:
On Thursday, 29 February 2024 at 15:34:43 UTC, Carl Sturtivant 
wrote:
 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!

 [...]
The linking flags need to be preppended with `-L` on each: `-L-lm -L-lrt -L-lphobos2`. It doesn't look like you've done that from the logs
Feb 29
parent Carl Sturtivant <sturtivant gmail.com> writes:
On Thursday, 29 February 2024 at 18:49:00 UTC, Hipreme wrote:
 The linking flags need to be preppended with `-L` on each: 
 `-L-lm -L-lrt -L-lphobos2`. It doesn't look like you've done 
 that from the logs
You didn't understand the post! Look at my command line. I didn't use any linking flags. I didn't mention any of those libraries.
Feb 29
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/29/2024 7:34 AM, Carl Sturtivant wrote:
 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'm lovin' it!
Feb 29
parent Carl Sturtivant <sturtivant gmail.com> writes:
On Thursday, 29 February 2024 at 19:16:51 UTC, Walter Bright 
wrote:
 On 2/29/2024 7:34 AM, Carl Sturtivant wrote:
 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'm lovin' it!
Me too! Very pleased: now the brittle C from the early '80s through the'90s is mutable via D. I did this on Linux. I used [cproto](https://invisible-island.net/cproto/cproto.html) and [ctags](https://github.com/universal-ctags/ctags) in a quick and dirty script to replace K&R defs in dozens of source files in one fell swoop. That went surprisingly smoothly.
Feb 29
prev sibling parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
Looks like we don't have a dmd specific CC variable.

https://github.com/dlang/dmd/blob/03f149760f53926d1c411d646f87894569fb1948/compiler/src/dmd/link.d#L480

```sh
DMD_CC=$CC
CC=dmd
```

That would've made it easier for you.

https://issues.dlang.org/show_bug.cgi?id=24423
Feb 29
parent reply Carl Sturtivant <sturtivant gmail.com> writes:
On Thursday, 29 February 2024 at 20:40:34 UTC, Richard (Rikki) 
Andrew Cattermole wrote:
 Looks like we don't have a dmd specific CC variable.

 https://github.com/dlang/dmd/blob/03f149760f53926d1c411d646f87894569fb1948/compiler/src/dmd/link.d#L480

 ```sh
 DMD_CC=$CC
 CC=dmd
 ```
I wanted CC=dmd in the build because it's now a C compiler, and that's what I am using it for. And it's handy when replacing a compiler for an existing C project. I just didn't expect dmd to confuse itself with its paired C compiler. Only a tiny change needed to fix this, as it happens on exactly one occasion, when CC=dmd and then dmd should ignore CC. That way there's no effect on the rest of the world. The issue of whether to have a DMD_CC can then be regarded as a separate matter. I submitted a precise bug report. https://issues.dlang.org/show_bug.cgi?id=24424
Feb 29
parent reply Lance Bachmeier <no spam.net> writes:
On Thursday, 29 February 2024 at 20:58:22 UTC, Carl Sturtivant 
wrote:
 On Thursday, 29 February 2024 at 20:40:34 UTC, Richard (Rikki) 
 Andrew Cattermole wrote:
 Looks like we don't have a dmd specific CC variable.

 https://github.com/dlang/dmd/blob/03f149760f53926d1c411d646f87894569fb1948/compiler/src/dmd/link.d#L480

 ```sh
 DMD_CC=$CC
 CC=dmd
 ```
I wanted CC=dmd in the build because it's now a C compiler, and that's what I am using it for. And it's handy when replacing a compiler for an existing C project. I just didn't expect dmd to confuse itself with its paired C compiler. Only a tiny change needed to fix this, as it happens on exactly one occasion, when CC=dmd and then dmd should ignore CC. That way there's no effect on the rest of the world. The issue of whether to have a DMD_CC can then be regarded as a separate matter. I submitted a precise bug report. https://issues.dlang.org/show_bug.cgi?id=24424
I think Rikki is suggesting replacing ``` const(char)* cc = getenv("CC"); ``` with ``` const(char)* cc = getenv("DMD_CC"); if (!cc) { const(char)* cc = getenv("CC"); } ``` or something like that. Then you'd set `DMD_CC` to whatever `cc` should be used inside DMD.
Feb 29
next sibling parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 01/03/2024 10:27 AM, Lance Bachmeier wrote:
 I think Rikki is suggesting replacing
 
 |const(char)* cc = getenv("CC"); |
 
 with
 
 |const(char)* cc = getenv("DMD_CC"); if (!cc) { const(char)* cc = 
 getenv("CC"); } |
 
 or something like that. Then you'd set |DMD_CC| to whatever |cc| should 
 be used inside DMD.
There are two separate issues here, my ticket is to prevent invasive changes in a build script. What Carl's ticket is for, is to prevent an accidental infinite recursion. Both are needed :)
Feb 29
parent reply Lance Bachmeier <no spam.net> writes:
On Thursday, 29 February 2024 at 21:34:03 UTC, Richard (Rikki) 
Andrew Cattermole wrote:

 There are two separate issues here, my ticket is to prevent 
 invasive changes in a build script. What Carl's ticket is for, 
 is to prevent an accidental infinite recursion.

 Both are needed :)
What you're proposing would prevent infinite recursion, wouldn't it? Maybe I'm missing something. The source of the problem is grabbing the `CC` environment variable inside link.d.
Feb 29
parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 01/03/2024 10:41 AM, Lance Bachmeier wrote:
 On Thursday, 29 February 2024 at 21:34:03 UTC, Richard (Rikki) Andrew 
 Cattermole wrote:
 
 There are two separate issues here, my ticket is to prevent invasive 
 changes in a build script. What Carl's ticket is for, is to prevent an 
 accidental infinite recursion.

 Both are needed :)
What you're proposing would prevent infinite recursion, wouldn't it? Maybe I'm missing something. The source of the problem is grabbing the `CC` environment variable inside link.d.
No. DMD_CC=dmd That'll still be recursive.
Feb 29
next sibling parent Carl Sturtivant <sturtivant gmail.com> writes:
On Thursday, 29 February 2024 at 21:52:50 UTC, Richard (Rikki) 
Andrew Cattermole wrote:
 What you're proposing would prevent infinite recursion, 
 wouldn't it? Maybe I'm missing something. The source of the 
 problem is grabbing the `CC` environment variable inside 
 link.d.
No. DMD_CC=dmd That'll still be recursive.
Yes, so here's a combined proposal for the underlying logic (pseudo-code): ``` cc = getenv("DMD_CC") if( cc=="" || cc=="dmd" ){ // DMD_CC effectively undefined cc = getenv("CC") if( cc=="" || cc=="dmd" ) { // CC effectively undefined as well cc = platform_default_compiler } } assert( cc!="dmd" ) ```
Feb 29
prev sibling parent reply Lance Bachmeier <no spam.net> writes:
On Thursday, 29 February 2024 at 21:52:50 UTC, Richard (Rikki) 
Andrew Cattermole wrote:
 On 01/03/2024 10:41 AM, Lance Bachmeier wrote:
 On Thursday, 29 February 2024 at 21:34:03 UTC, Richard (Rikki) 
 Andrew Cattermole wrote:
 
 There are two separate issues here, my ticket is to prevent 
 invasive changes in a build script. What Carl's ticket is 
 for, is to prevent an accidental infinite recursion.

 Both are needed :)
What you're proposing would prevent infinite recursion, wouldn't it? Maybe I'm missing something. The source of the problem is grabbing the `CC` environment variable inside link.d.
No. DMD_CC=dmd That'll still be recursive.
You'd be telling the compiler you want an infinite recursion if you do that, so it would be the intended behavior. Your original proposal was ```sh DMD_CC=$CC CC=dmd ``` which wouldn't do that.
Feb 29
parent "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 01/03/2024 12:30 PM, Lance Bachmeier wrote:
 On Thursday, 29 February 2024 at 21:52:50 UTC, Richard (Rikki) Andrew 
 Cattermole wrote:
 On 01/03/2024 10:41 AM, Lance Bachmeier wrote:
 On Thursday, 29 February 2024 at 21:34:03 UTC, Richard (Rikki) Andrew 
 Cattermole wrote:

 There are two separate issues here, my ticket is to prevent invasive 
 changes in a build script. What Carl's ticket is for, is to prevent 
 an accidental infinite recursion.

 Both are needed :)
What you're proposing would prevent infinite recursion, wouldn't it? Maybe I'm missing something. The source of the problem is grabbing the `CC` environment variable inside link.d.
No. DMD_CC=dmd That'll still be recursive.
You'd be telling the compiler you want an infinite recursion if you do that, so it would be the intended behavior. Your original proposal was
Exactly. This is why its two separate tickets, two separate problems.
Feb 29
prev sibling parent Carl Sturtivant <sturtivant gmail.com> writes:
On Thursday, 29 February 2024 at 21:27:13 UTC, Lance Bachmeier 
wrote:
 I think Rikki is suggesting replacing

 ```
 const(char)* cc = getenv("CC");
 ```

 with

 ```
 const(char)* cc = getenv("DMD_CC");
 if (!cc) {
   const(char)* cc = getenv("CC");
 }
 ```

 or something like that. Then you'd set `DMD_CC` to whatever 
 `cc` should be used inside DMD.
Good logic. I just want anything that's done to satisfy `assert(cc!="dmd");` after it's done.
Feb 29