www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Libc functions undefined when linking

reply Ben Jones <fake fake.fake> writes:
I have a somewhat unusual use case and I'm having trouble getting 
everything to link properly.

I'm writing an assignment for a course I'm teaching and I've 
written the skeleton code in D, and students are going to 
implement one function in C, which my skeleton code will call.  
The tricky part is that the lab machines that the students will 
be using don't have a D compiler installed (they're Fedora 
machines, and I didn't see a dmd package in their repos, or I 
would have asked the admins to install it).

I plan to distribute compiled .o files for all the d modules, 
along with a static libphobos.  The students can compile their C 
file, and then link everything together.  I haven't tested it on 
the linux machines yet, but developing it on my mac, I'm getting 
undefined symbols for libc and pthread functions from libphobos:

```
"_thread_suspend", referenced from:
       __D4core6thread8osthread7suspendFNbNiCQBjQBhQBd6ThreadZb in 
libphobos2.a(osthread_8db_302.o)
      (maybe you meant: _thread_suspendAll)
   "_tmpfile", referenced from:
       __D3std5stdio4File7tmpfileFNfZSQBcQBbQy in 
libphobos2.a(stdio_d42_180.o)
   "_toupper", referenced from:
       __D2rt6config16rt_envvarsOptionFNbNiAyaMDFNbNiQkZQnZQq in 
libphobos2.a(config_94b_6c3.o)
   "_waitpid", referenced from:
       
__D4core8internal2gc2os8wait_pidFNbNiibZEQBmQBkQBeQBe11ChildStatus in
libphobos2.a(os_610_351.o)
```

So I think I need to specify that I want to explicitly include 
libc when I link it.  `-lc` didn't seem to work.  Anyone how the 
right way to do so?

Here are the steps I'm doing.  I'll compile all the D stuff 
myself, and distribute the .o files with my assignment, and 
they'll just be doing the C compilation and linking steps.

```
dmd -c -I=source -of=build/simpledisplay.o 
source/arsd/simpledisplay.d
dmd -c -I=source -of=build/color.o source/arsd/color.d
dmd -c -I=source -of=app.o source/app.d
clang -c -o source/assignment1.o source/assignment1.c
ld build/*.o -L. -lphobos2 -o build/executable
```
Jan 04 2022
next sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 1/4/22 10:13 AM, Ben Jones wrote:

 So I think I need to specify that I want to explicitly include libc when
 I link it.  `-lc` didn't seem to work.
Did you add -lc and -lpthread on the linker line?
 ld build/*.o -L. -lphobos2 -o build/executable
Ali
Jan 04 2022
parent Ben Jones <fake fake.fake> writes:
On Tuesday, 4 January 2022 at 18:26:41 UTC, Ali Çehreli wrote:
 On 1/4/22 10:13 AM, Ben Jones wrote:

 So I think I need to specify that I want to explicitly
include libc when
 I link it.  `-lc` didn't seem to work.
Did you add -lc and -lpthread on the linker line?
 ld build/*.o -L. -lphobos2 -o build/executable
Ali
Maybe it's a mac thing and that will work when I get to linux, but I did try that and ld couldn't find the lib: ``` ld: library not found for -lc ``` Same result for -lpthread, and for -pthread (no l)
Jan 04 2022
prev sibling next sibling parent reply Adam D Ruppe <destructionator gmail.com> writes:
On Tuesday, 4 January 2022 at 18:13:56 UTC, Ben Jones wrote:
 clang -c -o source/assignment1.o source/assignment1.c
you might have better luck just telling clang to link it too like since there's a bunch of default search paths and libs etc the compiler pass to the linker. otherwise if you do need to use the linker directly worth remembering the order of args matter too. you need to put the more derived dependencies first followed by more general ones at the end
Jan 04 2022
parent reply Ben Jones <fake fake.fake> writes:
On Tuesday, 4 January 2022 at 18:37:25 UTC, Adam D Ruppe wrote:
 On Tuesday, 4 January 2022 at 18:13:56 UTC, Ben Jones wrote:
 clang -c -o source/assignment1.o source/assignment1.c
you might have better luck just telling clang to link it too like since there's a bunch of default search paths and libs etc the compiler pass to the linker. otherwise if you do need to use the linker directly worth remembering the order of args matter too. you need to put the more derived dependencies first followed by more general ones at the end
Using clang seems to work better. It sounds like Apple basically hides system libraries since Big Sur, and I guess their clang knows the magic flags to pass to find them. Thanks!
Jan 04 2022
parent reply Ben Jones <fake fake.fake> writes:
On Tuesday, 4 January 2022 at 18:45:37 UTC, Ben Jones wrote:
 On Tuesday, 4 January 2022 at 18:37:25 UTC, Adam D Ruppe wrote:
 On Tuesday, 4 January 2022 at 18:13:56 UTC, Ben Jones wrote:
 clang -c -o source/assignment1.o source/assignment1.c
you might have better luck just telling clang to link it too like since there's a bunch of default search paths and libs etc the compiler pass to the linker. otherwise if you do need to use the linker directly worth remembering the order of args matter too. you need to put the more derived dependencies first followed by more general ones at the end
Using clang seems to work better. It sounds like Apple basically hides system libraries since Big Sur, and I guess their clang knows the magic flags to pass to find them. Thanks!
All good, except now simpledisplay is segfaulting on XDisplayConnection.get again (you helped me before by specifying a DISPLAY environment variable, but that's not working now, with either :0 or the longer value set by xquartz when opening an xterm). I'm not sure how it can segfault since there are null checks in that method... maybe I should just head to the linux lab and stop fighting Apple.
Jan 04 2022
parent reply Adam D Ruppe <destructionator gmail.com> writes:
On Tuesday, 4 January 2022 at 19:10:25 UTC, Ben Jones wrote:
 All good, except now simpledisplay is segfaulting on 
 XDisplayConnection.get again
run it in the debugger; do a -g build and run it in gdb or lldb and do check the exact line it is on. could be that the Xlib things didn't dynamically load. I thought I tested that but could have missed a spot and Apple has a bad habit of movign things so who knows.
Jan 04 2022
parent reply Ben Jones <fake fake.fake> writes:
On Tuesday, 4 January 2022 at 19:14:04 UTC, Adam D Ruppe wrote:
 On Tuesday, 4 January 2022 at 19:10:25 UTC, Ben Jones wrote:
 All good, except now simpledisplay is segfaulting on 
 XDisplayConnection.get again
run it in the debugger; do a -g build and run it in gdb or lldb and do check the exact line it is on. could be that the Xlib things didn't dynamically load. I thought I tested that but could have missed a spot and Apple has a bad habit of movign things so who knows.
Crashes on `display = XOpenDisplay(displayName);` : ``` EXC_BAD_ACCESS (code=1, address=0x0) gameboy`_D4arsd13simpledisplay18XDisplayConnection3getFZPSQBwQBu7Display at simpledisplay.d:12572 gameboy`_D4arsd13simpledisplay5Image4impl11createImageMFiibbZv(this 0x0000000101200000, enableAlpha=false, forcexshm=false, height=144, width=160) at simpledisplay.d:12678 gameboy`_D4arsd13simpledisplay5Image6__ctorMFiibbZCQBpQBnQBb(this 0x0000000101200000, enableAlpha=false, forcexshm=false, height=144, width=160) at simpledisplay.d:7065 ``` Which makes lots of sense because: "On a POSIX-conformant system, if the display_name is NULL, it defaults to the value of the DISPLAY environment variable." (https://www.x.org/releases/X11R7.5/doc/man/man3/XOpenDisplay.3.html) (/sarcasm) Explicitly calling setDisplayName before I try to use the display didn't make a difference, so maybe it's assignment to display that's causing the segfault? Not sure why that would cause a segfault either
Jan 04 2022
parent reply Ben Jones <fake fake.fake> writes:
On Tuesday, 4 January 2022 at 20:28:00 UTC, Ben Jones wrote:
 On Tuesday, 4 January 2022 at 19:14:04 UTC, Adam D Ruppe wrote:
 [...]
Crashes on `display = XOpenDisplay(displayName);` : ``` EXC_BAD_ACCESS (code=1, address=0x0) gameboy`_D4arsd13simpledisplay18XDisplayConnection3getFZPSQBwQBu7Display at simpledisplay.d:12572 gameboy`_D4arsd13simpledisplay5Image4impl11createImageMFiibbZv(this 0x0000000101200000, enableAlpha=false, forcexshm=false, height=144, width=160) at simpledisplay.d:12678 gameboy`_D4arsd13simpledisplay5Image6__ctorMFiibbZCQBpQBnQBb(this 0x0000000101200000, enableAlpha=false, forcexshm=false, height=144, width=160) at simpledisplay.d:7065 [...]
Hmm, I get the same segfault on linux, I'm linking with these flags and I the only warnings I get are about unwinding offsets: `clang build/*.o -L. -lphobos2 -lX11 -ldl -lpthread -o build/gameboy`
Jan 04 2022
parent reply Adam D Ruppe <destructionator gmail.com> writes:
On Tuesday, 4 January 2022 at 21:22:26 UTC, Ben Jones wrote:

That's null, meaning the library wasn't loaded. simpledisplay actually doesn't need -lX11 since it always dynamic loads the libraries. Normally it throws when this fails though instead of keeping null but that check is also initialized in a static constructor.... With your different build process though, do you still have a D main? If druntime is not fully initialized these libs won't load nor will it set the success flag. So that'd leave null. You can also quite possibly try to load it yourself: xlib.loadDynamicLibrary(); xext.loadDynamicLibrary(); in your main and see if it works. Then the variable to check is `if(!librariesSuccessfullyLoaded)` and see if it set it up.
Jan 04 2022
parent Ben Jones <fake fake.fake> writes:
On Tuesday, 4 January 2022 at 21:34:46 UTC, Adam D Ruppe wrote:
 On Tuesday, 4 January 2022 at 21:22:26 UTC, Ben Jones wrote:

That's null, meaning the library wasn't loaded. simpledisplay actually doesn't need -lX11 since it always dynamic loads the libraries. Normally it throws when this fails though instead of keeping null but that check is also initialized in a static constructor.... With your different build process though, do you still have a D main? If druntime is not fully initialized these libs won't load nor will it set the success flag. So that'd leave null. You can also quite possibly try to load it yourself: xlib.loadDynamicLibrary(); xext.loadDynamicLibrary(); in your main and see if it works. Then the variable to check is `if(!librariesSuccessfullyLoaded)` and see if it set it up.
Ah, that was the issue. I had a linker error when I had a normal d main, so I made main `extern(C)`. Looks like that wasn't actually necessary (I think maybe I had actually just put the .o with main in the wrong place so the symbol was missing). Reverting it to extern(D) fixed it on mac and linux. Thanks so much for the help!
Jan 04 2022
prev sibling next sibling parent bachmeier <no spam.net> writes:
On Tuesday, 4 January 2022 at 18:13:56 UTC, Ben Jones wrote:
 be using don't have a D compiler installed (they're Fedora 
 machines, and I didn't see a dmd package in their repos, or I 
 would have asked the admins to install it).
Just for the record, while the official Fedora repos don't have dmd, they have both ldc and gdc.
Jan 04 2022
prev sibling parent reply Tejas <notrealemail gmail.com> writes:
On Tuesday, 4 January 2022 at 18:13:56 UTC, Ben Jones wrote:

 The tricky part is that the lab machines that the students will 
 be using don't have a D compiler installed (they're Fedora 
 machines, and I didn't see a dmd package in their repos, or I 
 would have asked the admins to install it).
I'm using Fedora 34 `sudo dnf install ldc` works and gives ldc version 1.25.0(based on dmd 2.095.1)(but you invoke via `ldc2` or `ldmd2`) name of rpm: Source : ldc-1.25.1-2.fc34.src.rpm `sudo dnf install gcc-gdc` also works(but it's not the recent one with the D frontend)(you don't even need to write `gdc <input_file>.d`, `gcc <infut_file>.d` also works.) name of rpm: Source : gcc-11.2.1-1.fc34.src.rpm
Jan 04 2022
parent reply Ben Jones <fake fake.fake> writes:
On Wednesday, 5 January 2022 at 03:38:54 UTC, Tejas wrote:
 On Tuesday, 4 January 2022 at 18:13:56 UTC, Ben Jones wrote:

 The tricky part is that the lab machines that the students 
 will be using don't have a D compiler installed (they're 
 Fedora machines, and I didn't see a dmd package in their 
 repos, or I would have asked the admins to install it).
I'm using Fedora 34 `sudo dnf install ldc` works and gives ldc version 1.25.0(based on dmd 2.095.1)(but you invoke via `ldc2` or `ldmd2`) name of rpm: Source : ldc-1.25.1-2.fc34.src.rpm `sudo dnf install gcc-gdc` also works(but it's not the recent one with the D frontend)(you don't even need to write `gdc <input_file>.d`, `gcc <infut_file>.d` also works.) name of rpm: Source : gcc-11.2.1-1.fc34.src.rpm
good to know. What about dub?
Jan 05 2022
parent Tejas <notrealemail gmail.com> writes:
On Wednesday, 5 January 2022 at 16:14:02 UTC, Ben Jones wrote:
 On Wednesday, 5 January 2022 at 03:38:54 UTC, Tejas wrote:
 On Tuesday, 4 January 2022 at 18:13:56 UTC, Ben Jones wrote:

 The tricky part is that the lab machines that the students 
 will be using don't have a D compiler installed (they're 
 Fedora machines, and I didn't see a dmd package in their 
 repos, or I would have asked the admins to install it).
I'm using Fedora 34 `sudo dnf install ldc` works and gives ldc version 1.25.0(based on dmd 2.095.1)(but you invoke via `ldc2` or `ldmd2`) name of rpm: Source : ldc-1.25.1-2.fc34.src.rpm `sudo dnf install gcc-gdc` also works(but it's not the recent one with the D frontend)(you don't even need to write `gdc <input_file>.d`, `gcc <infut_file>.d` also works.) name of rpm: Source : gcc-11.2.1-1.fc34.src.rpm
good to know. What about dub?
I can't say for sure, since I installed dmd from the website before installing the other two, but `dub` should be bundled with the other two as well Regardless, know that I didn't install dub seperately, it got installed with either the dmd rpm, or the LDC or GDC one
Jan 05 2022