-1

I have a problem with my static libraries. I got one for the use of multimedia elements and another for C general use (linked list...). I want them to be separated to not bloat my program.

Try as I might to use functions from the second library in the first I keep getting the pesky undefined references. I can't find the answer on Google or in the gcc documentation so I came here to find the answer I seek.

How do I link together two .a files? Can gcc even do this ?

linking the .c file of an element of lib1

gcc -g3 -Wall -Wextra -Werror -I src/inc -I src/lib/*/src/inc -L src/lib -locl -o obj/menu/button.o -c src/menu/button.c

creating lib1

ar rcso ../libocml.a  obj/sound/sound.o obj/sys/view.o obj/sys/window.o obj/sys/thread.o obj/sys/clock.o obj/menu/text.o obj/menu/button.o

Compiling of the binary

gcc -g3 -Wall -Wextra -I src/inc -I src/lib/*/src/inc -I src/lib/*/src/lib/*/src/inc -L src/lib -o bin/runner.exe  obj/main.o -locml -lcsfml-graphics -lcsfml-window -lcsfml-audio -lcsfml-system

Unedited error

gcc -g3 -Wall -Wextra -I src/inc -I src/lib/*/src/inc -I src/lib/*/src/lib/*/src/inc -L src/lib -o bin/runner.exe  obj/main.o -locml -lcsfml-graphics -lcsfml-window -lcsfml-audio -lcsfml-system  
/usr/bin/ld : src/lib/libocml.a(sound.o) : dans la fonction « setMusic » :
/home/ornsolot/Bureau/runner/src/lib/ocml/src/sound/sound.c:69 : référence indéfinie vers « setStr »
/usr/bin/ld : src/lib/libocml.a(sound.o) : dans la fonction « unsetMusic » :
/home/ornsolot/Bureau/runner/src/lib/ocml/src/sound/sound.c:82 : référence indéfinie vers « unsetStr »
collect2: error: ld returned 1 exit status
make: *** [Makefile:86 : runner] Erreur 1

the issue is that setMusic and unsetMusic in music.c in lib ocml need setStr and unsetStr in str.c in lib ocl.

Source Tree Source tree

How to reproduce

you need the csfml library for compile it, sudo apt-get install libcsfml-dev create all file at the same place where you fill use the following command.

ocml.h

#include <SFML/Graphics.h>
#include <SFML/Audio.h>
#include <stdio.h>
#define MALLOCSTR(length) (malloc(sizeof(char) * length))
typedef struct osString_s {
    char  *data;
    size_t length;
} String_t;
String_t *setStr(char *data);
void unsetStr(String_t *string);
typedef struct ocmlMusic_s {
    sfMusic  *core;
    String_t *name;
} Music_t;
Music_t *setMusic(char *path, sfBool loop);
void unsetMusic(Music_t *music);

str.c

#include "ocml.h"
static size_t strLen(char *string)
{
    size_t len = 0;
    
    if (string)
        while (string[len] != '\0')
            len++;
    return (len);
}
String_t *setStr(char *data)
{
    size_t len = strLen(data);
    String_t *str = len > 0 ? malloc(sizeof(String_t)) : NULL;

    if (str) {
        str->data = MALLOCSTR(len);
        for (size_t i = 0; i < len ; i++)
            str->data[i] = data[i];
        str->length = len;
    }
    return (str);
}
void unsetStr(String_t *string)
{
    if (string) {
        if (string->data)
            free(string->data);
        free(string);
    }
}
gcc -g3 -Wall -Wextra -Werror -I . -o str.o -c str.c
ar rcso libocml.a  str.o

music.c

#include "ocml.h"

Music_t *setMusic(char *path, sfBool loop)
{
    Music_t *music = (path) ? malloc(sizeof(Music_t)) : NULL;

    if (music) {
        music->core = sfMusic_createFromFile(path);
        sfMusic_setLoop(music->core, loop);
        music->name = setStr(path);
    }
    return (music);
}
void unsetMusic(Music_t *music)
{
    if (music) {
        sfMusic_destroy(music->core);
        unsetStr(music->name);
        free(music);
    }
}
gcc -g3 -Wall -Wextra -Werror -I . -L . -locl -o music.o -c music.c
ar rcso libocml.a  music.o libocl.a

main.c

#include "ocml.h"
int main()
{
    Music_t*loop = setMusic("path/to/file.ogg", sfTrue);
    unsetMusic(loop);
}

gcc -g3 -Wall -Wextra -I . -L . -o a.out main.o -locml -lcsfml-graphics -lcsfml-window -lcsfml-audio -lcsfml-system

Thanks in advance for your guidance.

5
  • 1
    Please show the exact, complete and unedited error message you are getting. Commented Dec 18, 2023 at 11:22
  • You don't link .a files together. They are an archive which you can manipulate with ar. It looks option a or b can be used to add files.
    – user9706
    Commented Dec 18, 2023 at 11:22
  • It looks like you're putting the libocml.a in a different folder than you include with a -L though it isn't clear.
    – matt
    Commented Dec 18, 2023 at 11:25
  • 1
    You might add which source file and library is supposed to provide the 2 mentioned functions that are not found.
    – Gerhardh
    Commented Dec 18, 2023 at 11:50
  • 1
    Edit the question to provide a minimal reproducible example. Commented Dec 18, 2023 at 12:30

2 Answers 2

2

Compiling lib1

ar rcso …

ar is not a compilation command. It is a library manipulation command. The command form you used puts object files into the library. This is simply putting multiple files into one container file. It is not compilation or linking.

Compiling of the binary

gcc … obj/main.o -locml -lcsfml-graphics -lcsfml-window -lcsfml-audio -lcsfml-system

That form of the gcc command does not compile. It links, by executing the linker program (typically called ld).

The linker processes files in the order they are listed on the command line. When it processes each object module, it makes a note of symbols needed by that object module. When it processes each library file, it takes from that library only the routines that define symbols that are currently known to be needed.

Because of that, any library that provides symbols needed by another library (or by an isolated object module) must be listed on the command line after the library that needs it. You have not told us which of those file names are which library or define which symbols, so we cannot check the order is correct.

However, since ocml is the first library listed in your command line (albeit after the main object module), it appears none of your libraries define setMusic or unsetMusic. If one of your libraries is expected to define those, you may have some other problem such as one library being written in C and another being written in C++ so that one uses the decorated linker symbol names of C++ and the other does not. There is insufficient information in the question for a complete diagnosis.

2
  • Compilation are made via makefile, each lib has it's own makefile, each makefile link sources files in on library, lib1 compile lib2 before linking it's file. setMusic/unsetMusic in lib1 need setStr/unsetStr in lib2. Commented Dec 18, 2023 at 13:01
  • I use compiling in stead of linking my bad i will edit the main post. Commented Dec 18, 2023 at 13:07
0
ar rcso libocml.a  music.o libocl.a

This command creates an archive with two members, music.o and libocl.a. The second member is completely useless for linking. Only members that are object files are useful. When searching libocml.a, the linker will only see music.o. It will not search libocl.a and will not see any objects that are members of that archive.

If you want an archive that has all the contents of libocl.a plus music.o, you can do it:

cp libocl.a libocml.a
ar rs libocml.a music.o

I fail to see the point though. If libocl.a is your library, just skip it and build libocml.a directly out of objects. If it is a third party library, don't modify it. Build your own libraries with your own code.

2
  • The point is to compile multiple binary but with the functions they need without the bloat. Anyway thanks for your answer. Commented Dec 19, 2023 at 8:58
  • If you link against a static library, only objects that are actually used are included in the final executable. There is no bloat regardless of how many unused objects are archived in the library. Commented Dec 19, 2023 at 9:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.