www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - What is this undefined reference with -betterC about?

reply jfondren <julian.fondren gmail.com> writes:
Here's a complete script that you can run right now, using
a dub module that I just updated:

```d

/+ dub.sdl:
     dependency "hostname" version="~>0.1.1"
     buildOptions "betterC"
+/

extern(C) void main() {
     import hostname : hostnamez;
     import core.stdc.stdio : printf;

     printf("hostname: %s", hostnamez);
}
```

... which fails:

```
/usr/bin/ld: 
/tmp/.dub/build/hostnameex2-~master/application-debug-linux.posix-x86_64-dmd_v2.097.0-96F370DD71342805A23ECDFD2C6
CE6C/hostnameex2.o: in function `main':
/home/jfondren/mars/learn/./hostnameex2.d:11: undefined reference 
to `_D8hostname9hostnamezPa'
```

I've rm -rf'd /tmp/.dub and ~/.dub/packages , I've gotten things 
to a point
where I could modify dub's cached hostname/source.d and confirm 
that e.g.
pragma(msg, hostnamez.mangleof) has exactly the same output in 
that file
as in the script above. This all works fine if instead of a dub 
dependency
I add the path to hostname.d in dflags.

And this script works fine, without betterC:

```d

/+ dub.sdl:
     dependency "hostname" version="~>0.1.1"
+/

void main() {
     import std.stdio : writeln;
     import hostname : hostname, hostnamez;
     import std.string : fromStringz;

     writeln("hostname: ", hostname);
     writeln("hostname: ", hostnamez.fromStringz);
}
```

Why isn't this linking?
Jun 16 2021
parent reply jfondren <julian.fondren gmail.com> writes:
On Wednesday, 16 June 2021 at 14:21:40 UTC, jfondren wrote:
 Why isn't this linking?
OK, with verbose commands I see that libhostname.a is built without -betterC So that's why this fails to link. What do I change to 1. a script like this that uses hostname 2. the hostname module so that both can be built with -betterC when and only when the script is using -betterC?
Jun 16 2021
parent reply Dennis <dkorpel gmail.com> writes:
On Wednesday, 16 June 2021 at 14:38:10 UTC, jfondren wrote:
 What do I change to
 1. a script like this that uses hostname
 2. the hostname module

 so that both can be built with -betterC when and only when
 the script is using -betterC?
That's currently the situation: you can only build when both are betterC or else you get a linker error. It has to be a linker error, dmd cannot know at the time of compiling project A how project B is going to be compiled and vice versa. It noticed your code looks like this: ```D version(D_BetterC) { char* hostnamez; } else { immutable char* hostnamez; } ``` The different types result in different mangles, causing the linking errors. Why not simply give them the same type?
Jun 16 2021
next sibling parent Dennis <dkorpel gmail.com> writes:
On Wednesday, 16 June 2021 at 16:27:13 UTC, Dennis wrote:
 It has to be a linker error, dmd cannot know at the time of 
 compiling project A how project B is going to be compiled and 
 vice versa.
Well I suppose you could use a specific dub configuration, maybe giving 'hostname' a targetType "sourceLibrary" or something, but I would just make the abi consistent.
Jun 16 2021
prev sibling parent jfondren <julian.fondren gmail.com> writes:
On Wednesday, 16 June 2021 at 16:27:13 UTC, Dennis wrote:
 On Wednesday, 16 June 2021 at 14:38:10 UTC, jfondren wrote:
 What do I change to
 1. a script like this that uses hostname
 2. the hostname module

 so that both can be built with -betterC when and only when
 the script is using -betterC?
That's currently the situation: you can only build when both are betterC or else you get a linker error. It has to be a linker error, dmd cannot know at the time of compiling project A how project B is going to be compiled and vice versa.
It's dub that's calling dmd though. Cargo handles this situation with features: https://doc.rust-lang.org/cargo/reference/features.html Where this case would look something like ``` [dependencies] hostname = { version = "0.1.1", features = ["betterC"] } ``` in the script's dub config that uses hostname. I feel like I've seen similar configurations in dub configs, but I see nothing about this in the documentation.
 It noticed your code looks like this:
 ```D
 version(D_BetterC) {
     char* hostnamez;
 } else {
     immutable char* hostnamez;
 }
 ```

 The different types result in different mangles, causing the 
 linking errors. Why not simply give them the same type?
the pragma(crt_constructor) function can't initialize immutables: https://forum.dlang.org/post/wvjfygxfvmoaortmndcv forum.dlang.org
Jun 16 2021