Search code examples
cmakefileldpintos

ld: multiple definitions of const variable


I am going through the PintOS project using the JHU version of PintOS. But when I make under src/userprog(which is ~/Documents/PintOS/userprog/ on my local machine), it throws this error to me:

cd build && make all 
make[1]: Entering directory '/home/pairman/Documents/PintOS/userprog/build'
gcc -Wl,--build-id=none -nostdlib -static -Wl,-T,../../lib/user/user.lds tests/userprog/multi-recurse.o tests/lib.o lib/user/entry.o libc.a -o tests/userprog/multi-recurse
/usr/bin/ld: tests/lib.o:/home/pairman/Documents/PintOS/userprog/build/../../tests/lib.c:8: multiple definition of `test_name'; tests/userprog/multi-recurse.o:/home/pairman/Documents/PintOS/userprog/build/../../tests/userprog/multi-recurse.c:10: first defined here
collect2: error: ld returned 1 exit status
make[1]: *** [../../Makefile.userprog:39: tests/userprog/multi-recurse] 
Error 1 
make[1]: Leaving directory '/home/pairman/Documents/PintOS/userprog/build'
make: *** [../Makefile.kernel:10: all] Error 2

Part of the related code:

tests/lib.c:

#include "tests/lib.h"
#include <random.h>
...
#include <syscall.h>

const char *test_name;

...

tests/lib.c:

#ifndef TESTS_LIB_H
#define TESTS_LIB_H

#include <debug.h>
...
#include <syscall.h>

extern const char *test_name;

...

#endif /* test/lib.h */

tests/userprog/multi-recurse.c:

#include <debug.h>
...
#include <syscall.h>
#include "tests/lib.h"

const char *test_name = "multi-recurse";

...

My system is Fedora 39 and I'm using the toolchain installed via dnf, not self-compiled. The above code comes from the original repository. I don't know what broke the code on my machine. On my machine, make under threads can pass but userprog has this issue, while compiling the same code on my campus lab environment has no issue.

I tried to fix declaration in tests/lib.c with #ifndef and #define around it, but this will cause a no type error in tests/userprog/multi-recurse.c, so what I'm doing is probably wrong.

Is there any way to fix this make error?


Solution

  • In tests/lib.c, change const char *test_name; to extern const char *test_name;.

    const char *test_name; is a tentative definition, which, in spite of its name, is not a definition itself but may result in the generation of a definition.

    Some tools, including versions of GCC and associated tools before GCC version 10, treated multiple definitions resulting from tentative definitions as “common” definitions and coalesced them to a single definition (along with one regular definition if it existed). Your tools are treating definitions from tentative definitions as regular definitions.

    You can request the old behavior by adding -fcommon to the GCC command(s).