Why do I get a segmentation fault when running an example program compiled without cmake? (MSYS2, Mingw-w64) - gcc

In short
What are cmake's web of makefiles doing differently from a simple compile and link that is making a difference in the final executable?
I'm trying to use the bullet physics library (bullet3-2.83.7) https://github.com/bulletphysics/bullet3.
I compiled the library okay with few warnings in MSYS2 with Mingw-w64.
Afterwards I can run the example programs without problems, specifically ExampleBrowser and HelloWorld.
I've been trying to incorporate the HelloWorld source into a test project using just a Makefile but I get SIGSEGV errors whenever there is a call to dynamicsWorld in the executable. The SEGFAULT occurs at lines dynamicsWorld->AddRigidBody(body); or if those are commented out dynamicsWorld->stepSimulation
This occurs with the exact example source file compiled with the makefile (source not modified).
gdb tells me this
main (argc=1, argv=0x5f4eb0) at main.cpp:78
78 dynamicsWorld->addRigidBody(body);
(gdb) step
0x0000000000002000 in ?? ()
(gdb) step
Cannot find bounds of current function
(gdb) bt full
#0 0x0000000000002000 in ?? ()
No symbol table info available.
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
I don't know what to do with this info. I assume/hope I'm just missing a compiler or linker flag?
My original Makefile is a big mess based off http://make.mad-scientist.net/papers/advanced-auto-dependency-generation. I assumed it would be enough to just use the existing makefile on the example code by adding the libraries and include directory -lBulletDynamics_Debug -lBulletCollision_Debug -lLinearMath_Debug
I've also tried a simplified Makefile with commands and flags I found grepping the CMake directories from bullet3/examples/HelloWorld.
My PATH environment variable is clean, nothing in LD_LIBRARY_PATH (In MSYS: echo $PATH)
MSYS2 Mingw-w64
gcc 10.1.0
MSYS 20180531msys64 ? pacman updated a lot of things
CMake 3.17.3
GNU Make 4.3
Makefile
CXX_DEFINES = -DUSE_GRAPHICAL_BENCHMARK -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS
CXX_INCLUDES = -I"C:\lib64\include\bullet3"
CXX_FLAGS = -g -fpermissive -D_DEBUG
.PHONY: all
all:
g++.exe $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o main.obj -c main.cpp
ar cr main.a main.obj
g++.exe $(CXX_FLAGS) -Wl,--whole-archive main.a -Wl,--no-whole-archive -o bulletTest.exe -Wl,--major-image-version,0,--minor-image-version,0 libBulletDynamics_Debug.a libBulletCollision_Debug.a libLinearMath_Debug.a -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32
# -L"C:\lib64\lib"
.PHONY: run
run:
gdb -ex run bulletTest.exe -ex "bt full" -ex quit --batch
.PHONY: clean
clean:
rm -f ./bulletTest.exe ./main.obj ./main.a
Building the bullet physics library in MSYS2
In the bullet3-2.83.7 directory (tar.gz from https://github.com/bulletphysics/bullet3/releases)
mkdir build-mingw64
cd build-mingw64
cmake -G "MSYS Makefiles" \
-DBUILD_SHARED_LIBS=0 \
-DBUILD_EXTRAS=1 \
-DINSTALL_LIBS=0 \
-DUSE_GLUT=1 \
-DCMAKE_CXX_FLAGS_DEBUG="-fpermissive -g" \
-DINSTALL_EXTRA_LIBS=0 \
-DCMAKE_BUILD_TYPE=Debug ..
make -j

I ran into the same issue. In my case, it was because Bullet was compiled with USE_DOUBLE_PRECISION, so adding the following to cmakelists for my executable fixed the issue for me:
target_compile_options(<target_name> BEFORE PUBLIC -DBT_USE_DOUBLE_PRECISION)

Related

How to link different object file with LLVM library?

I am following the LLVM tutorial : Kaleidoscope: Code generation to LLVM IR, which will use LLVM libraries like LLVMContext, Module and so on. Different from the tutorial, I am trying to write the lexer, parser and code generator in different source file and link them into one executable file.
Here is my compile command on the Ubuntu 20.04:
clang++ -g -O3 -I /home/therlf/LLVM/include -I ./ -I /home/therlf/LLVM_Temp/llvm/include `llvm-config --cxxflags --ldflags --system-libs --libs all` ast/CallExprAST.o ast/NumberExprAST.o ast/PrototypeAST.o ast/FunctionAST.o ast/BinaryExprAST.o ast/VariableExprAST.o lexer/lexer.o logger/logger.o parser/parser.o main.cpp -o main
But I only get lots of "undefined error".
Here are some of them:
/usr/bin/ld: /tmp/main-2b71c8.o:(.data+0x0): undefined reference to `llvm::DisableABIBreakingChecks
/home/therlf/MyProject/tmp/ast/CallExprAST.cpp:6: undefined reference to `llvm::Module::getFunction(llvm::StringRef) const'
/home/therlf/LLVM/include/llvm/IR/InstrTypes.h:1112: undefined reference to `llvm::Instruction::Instruction(llvm::Type*, unsigned int, llvm::Use*, unsigned int, llvm::Instruction*)'
/usr/bin/ld: /home/therlf/LLVM/include/llvm/IR/InstrTypes.h:977: undefined reference to `llvm::VectorType::get(llvm::Type*, llvm::ElementCount)'
At first I thought it's including path's error. But when I compiled and ran the source file in the tutorial successfully, which is just a whole source file with everything packed into file, I knew the including path is nothing wrong.
I have searched for this question, and some blogs say that you should link them with lld and use the -fuse-ld=lld in the compile command. But I don't have lld, and the clang++ doesn't know the argument -fuse-ld, which will report an error. The blog says that you should have lld as long as you have installed LLVM. In fact here are what I got: LLVM tools
And I know the llvm-link is used to link IR file, not the object file compiled from cpp source file.
Here is my LLVM version:
10.0.0svn
And here is my Makefile:
SOURCES = $(shell find ast kaleidoscope lexer logger parser -name '*.cpp')
HEADERS = $(shell find ast kaleidoscope lexer logger parser -name '*.h')
OBJ = ${SOURCES:.cpp=.o}
CC = clang++
# -stdlib=libc++ -std=c++11
CFLAGS = -g -O3 -I /home/therlf/LLVM/include -I ./ -I /home/therlf/LLVM_Temp/llvm/include
LLVMFLAGS = `llvm-config --cxxflags --ldflags --system-libs --libs all`
.PHONY: main
main: main.cpp ${OBJ}
${CC} ${CFLAGS} ${LLVMFLAGS} ${OBJ} $< -o $#
clean:
rm -r ${OBJ}
%.o: %.cpp ${HEADERS}
${CC} ${CFLAGS} ${LLVMFLAGS} -c $< -o $#
In fact, I follow the project structure from the repository : ghaiklor/llvm-kaleidoscope and the Makefile is nearly identical.
Sincerely thank you for your answers!
I have sloved this problem by exchanging my linker ld with linker lld.
You should install lld first by this command in ubuntu if you can't find it in the LLVM/tools directory like I did.
sudo apt-get update
sudo apt-get -y install lld
And then you can add -fuse-ld=lld to your compile command
or you can
cd /usr/bin
ln -s /path/to/ld.lld /usr/bin/ld
This should work if everything goes well.
But I still can't figure out the reason behand this situation :-(

How does cygwin terminal work? (Makefile issue)

Here's my makefile:
assemblera: main.o parsingA.o parsingC.o symbolTable.o
gcc -o assemblera main.o parsingA.o parsingC.o symbolTable.o
main.o: main.c parsingA.h parsingC.h symbolTable.h
gcc -c main.c
parsingA.o: parsingA.c parsingA.h
gcc -c parsingA.c
parsingC.o: parsingC.c parsingC.h
gcc -c parsingC.c
symbolTable.o: symbolTable.c symbolTable.h
gcc -c symbolTable.c
clean:
rm *.o assemblera
Now for the problem: with Windows command prompt I can easily generate all the .o files and .exe file, and if I run the latter it works as intended. Now, if I use the cygwin terminal, I can give the instructions to generate the object files / the exe, but those do not appear nowhere in the folder and no error is returned. Also, if I use the make command, it returns this error:
gcc -c main.c
make: *** [Makefile:5: main.o] Error 1
(I did put tabs in front of every "gcc" and "rm"). I know next to nothing about makefiles and cygwin.

Why compiling with musl on Alpine fails and on ArchLinux succeeds

This is a curiosity question: why?
Why does it have a different behavior for the exact same code?
I often have the issue that I can compile something in one distribution but not in another. So today I bumped into one of those issue again where when I build in the same way PostgreSQL's pg_dump with ArchLinux it works, but when I do it on Alpine it fails with this error:
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -static -fPIC -D_REENTRANT -D_THREAD_SAFE -D_POSIX_PTHREAD_SEMANTICS -fPIC -shared -Wl,-soname,libpq.so.5 -Wl,--version-script=exports.list -o libpq.so.5.11 fe-auth.o fe-auth-scram.o fe-connect.o fe-exec.o fe-misc.o fe-print.o fe-lobj.o fe-protocol2.o fe-protocol3.o pqexpbuffer.o fe-secure.o libpq-events.o chklocale.o inet_net_ntop.o noblock.o pgstrcasecmp.o pqsignal.o thread.o getpeereid.o pg_strong_random.o encnames.o wchar.o base64.o ip.o md5.o scram-common.o saslprep.o unicode_norm.o sha2.o -L../../../src/port -L../../../src/common -Wl,--as-needed -Wl,-rpath,'/usr/local/pgsql/lib',--enable-new-dtags
/lib/gcc/x86_64-linux-musl/8.2.0/../../../../x86_64-linux-musl/bin/ld: /lib/gcc/x86_64-linux-musl/8.2.0/crtbeginT.o: relocation R_X86_64_32 against hidden symbol `__TMC_END__' can not be used when making a shared object
/lib/gcc/x86_64-linux-musl/8.2.0/../../../../x86_64-linux-musl/bin/ld: /lib/gcc/x86_64-linux-musl/8.2.0/crtend.o: relocation R_X86_64_32 against `.ctors' can not be used when making a shared object; recompile with -fPIC
/lib/gcc/x86_64-linux-musl/8.2.0/../../../../x86_64-linux-musl/bin/ld: final link failed: nonrepresentable section on output
collect2: error: ld returned 1 exit status
make[1]: Leaving directory '/src/src/interfaces/libpq'
make[1]: *** [../../../src/Makefile.shlib:309: libpq.so.5.11] Error 1
make: *** [../../../src/Makefile.global:580: submake-libpq] Error 2
Here is the Dockerfile for Alpine:
FROM muslcc/x86_64:x86_64-linux-musl
RUN apk update && apk add make
ENV DOWNLOAD_URL https://ftp.postgresql.org/pub/source/v11.2/postgresql-11.2.tar.bz2
WORKDIR /src
RUN wget "$DOWNLOAD_URL" && \
tar xvjf "${DOWNLOAD_URL##*/}" --strip-components=1 && \
rm -fv "${DOWNLOAD_URL##*/}"
# NOTE: I left the -fPIC here for clarity sake but it fails with
# the same error with or without it
RUN ./configure --without-readline --without-zlib CFLAGS="-static -fPIC"
RUN cd src/bin/pg_dump && make pg_dump
Here is the Dockerfile for ArchLinux:
FROM archlinux/base
RUN pacman -Syu --noconfirm --needed base-devel musl
ENV DOWNLOAD_URL https://ftp.postgresql.org/pub/source/v11.2/postgresql-11.2.tar.bz2
WORKDIR /src
RUN curl -o "${DOWNLOAD_URL##*/}" "$DOWNLOAD_URL" && \
tar xvjf "${DOWNLOAD_URL##*/}" --strip-components=1 && \
rm -fv "${DOWNLOAD_URL##*/}"
RUN ./configure --without-readline --without-zlib CC="musl-gcc" CFLAGS="-static"
RUN cd src/bin/pg_dump && make pg_dump
I don't even know where to look at. Could it be a difference of version of musl? Another compiling tool? I don't really want the solution, I want to understand why.
I don't have that much experience with Alpine Linux and I would need to play with it myself, but it seems some pretty basic standard C libraries are built as non-platform-independent-code (PIC), which means you aren't allowed to link a dynamic library with it.
I'd start chasing Alpine Linux developers about this, because there are probably configuration flags for PostgreSQL which would allow you to build what you want.
Now, I've notices one thing. You pass CFLAGS=-static to the compilation, but it's pointless as ./configure already set it up as shared - look carefully at the compiler invocation you quote. If you want static build, you need to find a proper configuration flag and use it with ./configure. I your case --disable-shared should work.
CFLAGS="-static" CXXFLAGS="-static" LDFLAGS="-Wl,-Bstatic" ./configure --without-readline --without-zlib
seem to enable -static without leaving -shared.

Compiling Fortran 77 with an external library using a Makefile

I have main program Engine.f that calls functions/external in LIB.f.
Unlike C++ and Java there is no include in the main program so it will be possible to compile.
How does my Fortran comiler know that there is another library which I use?
I'm using photran from Eclipse.
The MAKE file:
.PHONY: all clean
# Change this line if you are using a different Fortran compiler
FORTRAN_COMPILER = gfortran
all: src/Engine.f
$(FORTRAN_COMPILER) -O2 -g \
-o bin/Engine.exe \
src/Engine.f
clean:
rm -f bin/Engine.exe *.mod
errors that I get when I compile:
undefined reference to (name of function in **LIB.f**)
.PHONY: all clean
all: Engine.exe
# Change this line if you are using a different Fortran compiler
FORTRAN_COMPILER = gfortran
FORTRAN_FLAGS=-O2 -g
%.o: src/%.f
$(FORTRAN_COMPILER) $(FORTRAN_FLAGS) -c $<
Engine.exe: Lib.o Engine.o
$(FORTRAN_COMPILER) $(FORTRAN_FLAGS) \
-o bin/Engine.exe \
Lib.o Engine.o
clean:
rm -f *.o *.mod
In FORTRAN 77, the compiler "just" needs the function to be supplied in a .o file at link time. You can test the Makefile below, it should do what you want.
Modern versions of Fortran use module files to structure libraries, if you ever upgrade to that.

Changing OCaml's gcc after installation

I installed OCaml via OPAM, and by default it uses gcc as the command to compile .c files. For instance, if I run ocamlopt -verbose file.c, I obtain:
+ gcc -Wall -D_FILE_OFFSET_BITS=64 -D_REENTRANT -g
-fno-omit-frame-pointer -c -I'/home/user/.opam/4.02.1+fp/lib/ocaml' 'test.c'
I'd like to change the GCC binary that is used by OCaml, for instance to replace it with gcc-5.1 or /opt/my-gcc/bin/gcc.
Is it possible to do so without reconfiguring and recompiling OCaml? I suppose I could add a gcc alias to a directory in the PATH, but I'd prefer a cleaner solution if there is one.
To check if gcc was not chosen based on a textual configuration file (that I could easily change), I searched for occurrences of gcc in my /home/user/.opam/4.02.1+fp directory, but the only occurrence in a non-binary file that I found was in lib/ocaml/Makefile.config, and changing it does nothing for the already-compiled binary.
ocamlopt uses gcc for three things. First, for compiling .c files that appear on the command line of ocamlopt. Second, for assembling the .s files that it generates internally when compiling an OCaml source file. Third, for linking the object files together at the end.
For the first and third, you can supply a different compiler with the -cc flag.
For the second, you need to rebuild the OCaml compiler.
Update
Here's what I see on OS X when compiling a C and an OCaml module with the -verbose flag:
$ ocamlopt -verbose -cc gcc -o m m.ml c.c 2>&1 | grep -v warning
+ clang -arch x86_64 -c -o 'm.o' \
'/var/folders/w4/1tgxn_s936b148fdgb8l9xv80000gn/T/camlasm461f1b.s' \
+ gcc -c -I'/usr/local/lib/ocaml' 'c.c'
+ clang -arch x86_64 -c -o \
'/var/folders/w4/1tgxn_s936b148fdgb8l9xv80000gn/T/camlstartup695941.o' \
'/var/folders/w4/1tgxn_s936b148fdgb8l9xv80000gn/T/camlstartupb6b001.s'
+ gcc -o 'm' '-L/usr/local/lib/ocaml' \
'/var/folders/w4/1tgxn_s936b148fdgb8l9xv80000gn/T/camlstartup695941.o' \
'/usr/local/lib/ocaml/std_exit.o' 'm.o' \
'/usr/local/lib/ocaml/stdlib.a' 'c.o' \
'/usr/local/lib/ocaml/libasmrun.a'
So, the compiler given by the -cc option is used to do the compilation of the .c file and the final linking. To change the handling of the .s files you need to rebuild the compiler. I'm going to update my answer above.

Resources