I'm trying to use the GLFW library, but am having difficulty with compiling a simple program. I went to the GLFW website and download the latest release, then using "How to build & install GLFW 3 and use it in a Linux project" I built and installed it.
Here's my code:
#include <GLFW/glfw3.h>
#include <iostream>
using std::cout;
using std::endl;
void GLFW_error(int error, const char* description)
{
fputs(description, stderr);
}
void run()
{
cout << "pooch" << endl;
}
int main()
{
glfwSetErrorCallback(GLFW_error);
if (!glfwInit()) exit(EXIT_FAILURE);
run();
glfwTerminate();
return 0;
}
Using the command line:
bulletbill22#ROBOTRON ~/Desktop $ g++ -std=c++11 -lglfw source.cpp
yields
source.cpp:function main: error: undefined reference to 'glfwSetErrorCallback'
glfwSetErrorCallback is taken from their tutorial for "Setting an error callback".
Inclusion of -glfw3 results in /usr/bin/ld: error: cannot find -lglfw3
Even though everything seemed to be installed correctly, I suspect the problem may lie somewhere with the installation of the GLFW library because I'm not used to CMake and don't entirely understand how it works. I'm frustrated because the answer must be simple, but I'm not sure which keywords are really relevant when googling the problem; mostly the results are people who were incorrectly compiling with CMake, which I'm not compiling with in this case.
It seems that the directories for the glfw3.h header and libglfw3.so (and/or libglfw3.a) library are not in the default path.
You can check with by adding the -v option to the g++ options. Locate the directory where the glfw3.h header is found - call this $GLFW_INCDIR - it typically ends with .../GLFW. Locate the directory where the library is found - call this $GLFW_LIBDIR. Try:
g++ -std=c++11 -I$GLFW_INCDIR source.cpp -o pooch -L$GLFW_LIBDIR -lglfw3
If all the library dependencies are satisfied, this hopefully results in a program called pooch.
One other thing: GLFW3 is a C library, and the callback function arguments are expected to be C functions. So your callback should have 'C' linkage, i.e.,
extern "C" void GLFW_error(int error, const char* description) ...
Also, if you're having trouble with cmake, you may have ccmake installed. Try ccmake . in the top-level directory of the GLFW3 package for 'interactive' configuration.
Related
I just came to Linux c++ programming from Windows. Trying to make a shared library libso.so, which uses std::thread. The shared library will be loaded by other people and call the export function. The test code:
// so.cpp, the .so library
#include <iostream>
#include <thread>
using namespace std;
extern "C"
void run() {
cout << "run() begin" << endl;
std::thread t([] {
});
t.join();
cout << "run() end" << endl;
}
// test.cpp, the test loader
#include <dlfcn.h>
int main() {
typedef void (*run_t)();
auto dll = dlopen("libso.so", RTLD_LAZY);
run_t run = (run_t) dlsym(dll, "run");
run();
}
// The CMakeLists.txt file
cmake_minimum_required(VERSION 3.0)
PROJECT (test)
Include_Directories(${PROJECT_SOURCE_DIR})
Link_Directories(${PROJECT_BINARY_DIR})
add_library(so SHARED so.cpp )
target_link_libraries(so pthread)
add_executable( test test.cpp )
target_link_libraries(test pthread dl)
It crashes in the run() function, the output is:
run() begin
“./test” terminated by signal SIGSEGV (Address boundary error)
The std::thread seems work fine in executable, but not in shared library. What do I miss?
The environment: g++ 9.3.0, cmake 3.16.3
Edited:
Try ldd.
ldd ./test shows no pthread, but ldd ./libso.so has libpthread.so.0.
The difference of linking param with SET(CMAKE_VERBOSE_MAKEFILE TRUE)
// linking executable 'test'
/usr/bin/c++ -rdynamic CMakeFiles/test.dir/test.cpp.o -o test -L/e/c/1/kali -Wl,-rpath,/e/c/1/kali -ldl -lpthread
// linking library 'libso.so'
/usr/bin/c++ -fPIC -shared -Wl,-soname,libso.so -o libso.so CMakeFiles/so.dir/so.cpp.o -L/e/c/2/kali -Wl,-rpath,/e/c/1/kali -lpthread
The only difference is -fPIC, I googled and add set_property(TARGET test PROPERTY POSITION_INDEPENDENT_CODE ON) to the executable, but nothing changed.
Workaround 1
Since the .so has libpthread.so.0, I tried to add the code in .so to the executable:
int main() {
std::thread t([]{}); // to make executable linking to `pthread`
t.join();
// ... load dll and call run function
}
And it works, now the ldd ./test shows libpthread.so.0 and no crash. Which means: if a shared library uses std::thread and an executable wants to load it, the executable itself must also use std::thread.
Workaround 2:
The std::thread works fine in executable, but crashes in shared library. Found some related discuss, the walkaround is using boost::thread instead of std::thread and linking to boost_thread library, no crash .
I guess the problem is more related to dynamic linking
than threads.
The call dlopen("libso.so", RTLD_LAZY) will try to
find the library in a standard location.
Except if you set the LD_LIBRARY_PATH environment
variable to something that includes . (the current
directory) this library won't be found.
For a simple test you can either:
use export LD_LIBRARY_PATH=. in the terminal before
launching your program,
use dlopen("./libso.so", RTLD_LAZY) in your source code.
After using dlopen() or dlsym() if you obtain a null
pointer, then dlerror() can help displaying the reason
of the failure.
Note that on Windows the current directory and the executable
path are standard search paths for dynamic libraries; on UNIX
this is not the case, which could be surprising when changing
the target platform.
edit
cmake uses the -Wl,-rpath option to hardcode a library search
path in the executable, so all of what I explained above becomes
useless for this problem.
Assuming the dynamic library is found, the only way I can reproduce
the crash is to forget pthread in target_link_libraries for
test.
second edit
I finally managed to reproduce the crash with Ubuntu (in WSL).
Apparently your linker decides to ignore the libraries that are
not directly used by the executable.
This behavior suggests that the linker option --as-needed is
switched on by default.
To contradict this default behaviour, you need to pass the linker
option --no-as-needed before -lpthread.
This way, you don't have to insert a dummy thread in your
executable.
Using set(CMAKE_CXX_FLAGS -Wl,--no-as-needed) in the CMakeLists.txt
file you provide did the trick for me.
Compile command/what's in the .bat:
g++ -o program.exe SME.cpp -w -Wl -subsystem,windows -lmingw32 -lSDL2main -lSDL2
pause >nul
SME.cpp:
#include "SDL2\SDL.h"
int main()
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Quit();
return 0;
}
I have build.bat, SME.cpp and SDL2.dll in a folder
MinGW is in the default C:\MinGW directory
I installed MinGW using the installer
I added C:\MinGW\include
I put the SDL2 header files in C:\MinGW\include\SDL2\
I put the SDL2 library files (SDL2main.lib and SDL2.lib) in C:\MinGW\lib.
I added C:\MinGW\bin to the Path variable
I've solved all of the previous problems by looking on the internet for answers to them
The compiler keeps complaining that there is an undefined reference to SDL_Init and SDL_Quit and that ld.exe (I have no idea what that is) has returned exit status 1 due to an undefined reference to #WinMain16.
I've searched everywhere and there is a short supply of answers to this problem and all of the answers I've come across haven't worked. I've tried 3 different ways of doing this: with a .bat, with a Makefile and with Eclipse. It always comes down to these three errors. I have no idea what is going wrong, I checked and SDL_init.h and SDL_quit.h both exist. I don't know what #WinMain16 is either.
I wanted to start learning to program with SDL. So I download x86 for windows,
put all the lib and the include in MinGW. But when I compile it doesn't know the SDL functions exist.
# define SDL_MAIN_HANDLED // somehow it want it to not define its own main
#include <iostream>
#include <sdl2/SDL.h>
using namespace std;
int main( int argc, char* argv[] ) {
SDL_SetMainReady(); // just for check
return 0;
}
I read that the linking need to be in specific order (mingw32, SDL2main and then libSDL2), But I think Eclipse run a wrong compiling command.
The eclipse command:
g++ -O0 -g3 -Wall -c -fmessage-length=0 -o "src\\fire.o" "..\\src\\fire.cpp"
g++ -o fire.exe "src\\fire.o" -lmingw32 -lSDL2main -llibSDL2
src\fire.o: In function `main':
C:\Or\C++\Projects\fire\Debug/../src/fire.cpp:16: undefined reference to `SDL_SetMainReady'
collect2.exe: error: ld returned 1 exit status
Do you think I miss something?
I think you need to change -llibSDL2 to -lSDL2.
Ok I solve it. I'm not sure if the problem was lack of support on 32 bit or the fact that minGW and SDL were from different compilers that probably didn't match..
But what I did is to delete minGW from my pc and download WinBuild. WinBuild its a download manager that offer a lot of libs and tools, include minGW64 bit and SDL.
The advantage is that they were all compile from the same compiler with the same configurations.
after that i change the path to minGW in to the new 64 bit path inside WinBuild folder, add g++ from Winbuild the to the path as well and restart.
Then, adding and linking work without any problem!
I still need to put # define SDL_MAIN_HANDLED on the start to make it work, but its work!
I am trying to develop an openGL application with GLEW and GLFW on Windows using minGW. In the current directory, project/, I have the directories src/, bin/, and glfw-3.0.4.bin.WIN64/. I have the files test.cpp, glew.h, glew.c, and wglew.h in the src/ directory.
The directory ./glfw-3.0.4.bin.WIN64/include/ contains the GLFW/glfw3.h header file.
The directory ./glfw-3.0.4.bin.WIN64/lib-mingw/ contains glfw3.dll, glfw3dll.a, and libglfw3.a.
My main file, test.cpp contains,
#include "glew.h"
#include "GLFW/glfw3.h"
#include <stdio.h>
int main(int argc, char** argv) {
printf("Hello, World!\n");
glewInit();
glfwInit();
}
I am compiling the program from the project/ directory by running (split into two lines for readability)
gcc -DGLEW_STATIC -DGLFW_DLL -o ./bin/test ./src/*.cpp ./src/glew.c
-I ./glfw-3.0.4.bin.WIN64/include/ -L ./glfw-3.0.4.bin.WIN64/lib-mingw/ -lglfw3 -lopengl32
and I am getting the following error:
undefined reference to `_imp_glfwInit'
I think the problem has to do with me linking the GLFW library incorrectly. From what I understand, including the compiler option -lglfw3 will tell gcc to link ./glfw-3.0.4.bin.WIN64/lib-mingw/glfw3.dll, which contains the definition for glfwInit().
I've looked at solutions to other problems similar to mine and they suggest things such as copying the dll file to the source/binary directories and changing the order of the -l options, but none have seemed to solve the problem for me.
Your problem is that gcc follows strict library naming conventions. It attempts to find glfw3.dll.a, but finds none (because it is named glfw3dll.a - simple rename will fix your problem).
Next step it looks for libglfw3.a, and succeeds - but it is a static library, while reference declared as dynamic in header files (tricky windows DECLSPECs... this problem don't exist on e.g. linux). So, it cannot find _imp__glfwInit, because in static library it is called just glfwInit, so you getting an error.
Removing libglfw3.a is also one of options - in that case gcc will look further and eventually find glfw3.dll and use it.
I've been learning SDL for a little time, and now I've decided to try out SDL2, mainly to try its hardware acceleration. But the problem is, I can't compile it at all, while the same code compiled correctly with SDL1.2.
The sample code is:
#include "SDL/SDL.h"
int main( int argc, char *args[] )
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Quit();
return 0;
}
With the original linker settings: -lmingw32 -lSDLmain -lSDL
everything compiles.
But as soon as I change #include "SDL/SDL.h" to #include "SDL2/SDL.h"
and change linker settings to
-lmingw32 -lSDL2main -lSDL2
I get the errors:
obj\Debug\main.o||In function `SDL_main':|
main.cpp|5|undefined reference to `SDL_Init'|
main.cpp|8|undefined reference to `SDL_Quit'|
libmingw32.a(main.o):main.c:(.text.startup+0xa7)||undefined reference to `WinMain#16'|
I've got SDL1.2 installed in C:/SDL-1.2.15 and SDL2 installed in C:/SDL2
In search directories, I added both SDL1.2 and SDL2 Include and Lib folders.
I'm not sure if this will work, but if you are using the "x86_64-w64-mingw32" folder, try using the other one (the one with i686) this helped me. I was having the EXACT same problem as you, and using literally, to the line, the same test code as you. I hope this helps.