0

i usually can resolve linker's issue like 'undefined reference' using nm and figuring out that i forgot to add a source file in a makefile but here i can t understand what is happening :

$ make
gcc -I.. -I../../data_structures
-I../../iterator -I../../stack -I../../array_stack 
-Wall -Wextra -Werror  array_collection.o -o array_collection
-L.. -larray_collection
-L../../data_structures -ldyn_array
-L../../iterator -literator
-L../../stack -lstack
-L../../array_stack -larray_stack 
../../array_stack/libarray_stack.a(array_stack_init_stack.o): In function `array_stack_init_stack':
array_stack_init_stack.c:(.text+0x79): undefined reference to `stack_init'
$ nm ../../stack/libstack.a| grep stack_init
auto_stack_init.o:
0000000000000000 T auto_stack_init
0000000000000000 T stack_init

Can you help me please ? It is maybe important to say that the gcc command is aliased to clang on the vm i am using.

Here is the stack_init's code :

void    stack_init(t_stack *stack, void *realisation)
{
    stack->realisation = realisation;
    stack->_release = stack->release;
}
David
  • 29
  • 5
  • Obvious question is: Did you actually define a function called `stack_init`? We have no idea how your code looks like, so it's really hard to help you here – UnholySheep Apr 24 '20 at 11:56
  • Where do you define `stack_init` ? – Ôrel Apr 24 '20 at 11:57
  • What part of code do you need here ? don t want to spam. – David Apr 24 '20 at 11:58
  • @David we need the part where `stack_init` is defined – Jabberwocky Apr 24 '20 at 12:00
  • 2
    @David your problem is simple, the function *stack_init* is never defined, or you missed to link with the file defining it, but you call it. Because you link with *stack* lib (`-lstack`) that means you declare it but never define it – bruno Apr 24 '20 at 12:00
  • `export LC_ALL=C` before calling `make` and it should print in english. What is going on with all the `-L... -l...` like `-L../../stack -lstack`? Is there a `libstack.so` library compiled in `../../stack`? `Here is the stack_init's code` - so how is this code included in the compilation? Oooch, the order of static libraries matters. What would happen if you would change the order to `-L../../array_stack -larray_stack -L../../array -larray` so that `array` in linked on the end? Are those libraries static libraries? – KamilCuk Apr 24 '20 at 12:02
  • 1
    Thank you @KamilCuk will change it – David Apr 24 '20 at 12:03
  • @bruno, the stack_init code is in the libstack.a library i link in the 7th line of the gcc command, i nmed the lib just below to check it is in and what i understand is that it is in. – David Apr 24 '20 at 12:05
  • Do `nm libstack.a | grep init_stack` and give us the result. Are you sure you have only one version of that lib ? do you have also a dynamic version of it ? – bruno Apr 24 '20 at 12:09
  • @bruno It was in the frame yet and still is – David Apr 24 '20 at 12:11

1 Answers1

1
  1. Just use the static library path when compiling with it. So instead of gcc -L../../stack -lstack just use gcc ../../stack/libstack.a.

  2. The order of static libraries matter. If a static library depends on another static library, it has to come before it in the command line arguments. The linker scans the following libraries when it searches symbols, so if you have libarray_stack.a that depends on stack.a, it has to be after it. If they both depend on each other, specify them twice (which is a neat way to handle the problem anyway). Or alternatively with gcc compiler use -Wl,--whole-archive. There are varieus resources on the net that explain why/how it happens, for example this thread.

  3. Take the over 40 years old (but still amazing) make tool back to the shelve and move to cmake or other build systems that handle such problems (and many more) for you.

So try to compile with:

gcc -I.. -I../../data_structures
-I../../iterator -I../../stack -I../../array_stack 
-Wall -Wextra -Werror  array_collection.o -o array_collection
-L.. -larray_collection
-L../../data_structures -ldyn_array
-L../../iterator -literator
-L../../stack -lstack
-L../../array_stack -larray_stack 
-L.. -larray_collection
-L../../data_structures -ldyn_array
-L../../iterator -literator
-L../../stack -lstack
-L../../array_stack -larray_stack 
KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • Ok trying this solution make appears one (other) 'undefined reference' complaint so i ll try your first solution but have to change my makefile so it does this first. Thanks. (I am not allowed to use other tool than ``make``) – David Apr 24 '20 at 12:19
  • Sure. Also try `-Wl,--whole-archive ../libarray_collection.a ../../data_structurs/libdyn_array.a -Wl,--no-whole-archive – KamilCuk Apr 24 '20 at 12:24
  • 1
    Finally your second point made the trick but god i need an automatic system to put libraries in the 'good' order now :( ... will have to craft one – David Apr 24 '20 at 12:45
  • `will have to craft one` or use one. `cmake` is a tool that configures the build tool (it does not build the project itself). So you can use `cmake` to just generate makefiles, so you write configuration in `cmake` and generate makefile that in turn will be used. – KamilCuk Apr 24 '20 at 12:47
  • Oh ok thought cmake was to be substituted to make, if it finally use make i certainly can use it. Thank you for your valuable knowledge and time. – David Apr 24 '20 at 13:00