hannorein / rebound

💫 An open-source multi-purpose N-body code.
https://rebound.readthedocs.io/
GNU General Public License v3.0
817 stars 216 forks source link

linker error when running make #754

Closed tbui468 closed 4 months ago

tbui468 commented 4 months ago

Environment Which version of REBOUND are you using and on what operating system?

Describe the bug Linker error when running the default Makefile with following messages: /usr/bin/ld: ./librebound.so: undefined reference to pthread_join' /usr/bin/ld: ./librebound.so: undefined reference topthread_create' /usr/bin/ld: ./librebound.so: undefined reference to `pthread_cancel'

The shared librebound.so compiles fine, but linking it causes those errors.

To Reproduce Running make inside of /rebound/examples/simplest or any of the examples causes this error. Running this line from the README.md also causes this problem. git clone https://github.com/hannorein/rebound && cd rebound/examples/shearing_sheet && make && ./rebound

Additional context Linking the pthread library in src/Makefile.defs when the OS is Linux solves this problem for me (see example below). Would love to submit a pull request and contribute to the project if possible!

ifeq ($(OS), Linux) OPT+= -Wall -g LIB+= -lm -lrt -lpthread endif

hannorein commented 4 months ago

Hi Thomas. Thanks for reporting this. I can't reproduce this (I'm using Ubuntu 22.04.2). Googling a bit, it looks like most C compilers will include standard libraries by default in a "hosted environment" but not in a "freestanding" one. May I suggest you try updating WSL? Also, I'd be curious what you can when you run cc -v.

tbui468 commented 4 months ago

Hi hannorein. Thank you for the response. I've updated WSL and still get the same error. I will look into the hosted/freestanding environments and see if that works for me. cc -v for me shows this:

Using built-in specs. COLLECT_GCC=cc COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper OFFLOAD_TARGET_NAMES=nvptx-none:hsa OFFLOAD_TARGET_DEFAULT=1 Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.2' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-9QDOt0/gcc-9-9.4.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2)

hannorein commented 4 months ago

Hm. I'm not sure what the right solution here is. This post suggests to use -pthread instead. All this seems rather compiler specific.

tbui468 commented 4 months ago

Using -pthread rather than -lpthread also works for me. Thank you for the link and information.

tbui468 commented 4 months ago

Compiling examples/openmp works fine with my current setup without having to include the -pthread option. I think this is due to -fopenmp being implemented with pthreads. source . Seems like pthreads are defined and linked when compiled with the -fopenmp option on my system.

I wrote a few example C programs using pthreads and included the -fopenmp option, and indeed it worked fine without needing to pass the -pthread option.

I modified Makefile.defs to include the -pthread option only when not using openmp, and now all examples compile fine on my system. Adding the -pthread option here is a little more surgical than what I suggest before.

ifeq ($(OPENMP), 1)
    PREDEF+= -DOPENMP
ifeq ($(CC), icc)
    OPT+= -openmp
    LIB+= -openmp
else
    OPT+= -fopenmp
    LIB+= -fopenmp
endif
else
ifeq ($(OPENMPCLANG), 1)
    PREDEF+= -DOPENMP
    OPT+= -I$(brew --prefix libomp)/include -Xpreprocessor -fopenmp
    LIB+= -lomp
else
    ifneq ($(OS), Windows_NT) #this branch runs when trying to compile other examples (exception is examples/openmp)
        OPT+= -Wno-unknown-pragmas
        OPT+= -pthread #adding the -pthread option here defines pthread functions when openmp isn't used
    endif
endif
endif
hannorein commented 4 months ago

I think the logic is even more complicated. Pthreads is only needed if either the SERVER or the OPENGL flag is set to 1. Given that I still can't reproduce this issue on my version of Windows/WSL (neither are there issues on the CI), I think we should just leave things the way they are. There might be some unpredictable consequences... for various OS/compiler combinations.

tbui468 commented 4 months ago

That's a good point about unpredictable consequences. I'll just use the -pthread option as a temporary fix on my setup. Thank you for your responses!

hannorein commented 4 months ago

Sound good. Note that you can also just do something like (without editing any files):

OPT=-pthread make

The proper way to handle these things would be a configure script, but I hesitate adding this extra layer of abstraction. I'll close this now but hopefully it will come up if someone else has the same issue. In any case, thanks for reporting it.