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?
In
tests/lib.c
, changeconst char *test_name;
toextern 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).