I'm trying to build basic GTK+ code(one of its tutorials) with CMake, but I keep getting 'undefined reference to *' where * is any GTK function that is in the code. I tried to look after guides/tutorials on this, but most of them are mostly similar to what I have.
Regular compilation from terminal works without a problem using command:
g++ ./test.cpp -o test `pkg-config --cflags --libs gtk+-3.0`
When I try using CMake my CMakeLists.txt is:
cmake_minimum_required(VERSION 3.0.2)
project(gtktest)
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
include_directories(${GTK3_INCLUDE_DIRS})
link_directories(${GTK3_LIBRARY_DIRS})
add_definitions(${GTK3_CFLAGS_OTHER})
add_executable(gtktest test.cpp)
target_link_libraries(gtktest ${GKT3_LIBRARIES})
Now cmake . seems to work without problems
cmake .
-- The C compiler identification is GNU 7.4.0
-- The CXX compiler identification is GNU 7.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found PkgConfig: /usr/bin/pkg-config (found version "0.29.1")
-- Checking for module 'gtk+-3.0'
-- Found gtk+-3.0, version 3.22.30
-- Configuring done
-- Generating done
-- Build files have been written to: /home/dfdark/Desktop/gtk test
But make command after that is the problem:
make
Scanning dependencies of target gtktest
[ 50%] Building CXX object CMakeFiles/gtktest.dir/test.cpp.o
[100%] Linking CXX executable gtktest
CMakeFiles/gtktest.dir/test.cpp.o: In function `activate(_GtkApplication*, void*)':
test.cpp:(.text+0x27): undefined reference to `gtk_application_window_new'
test.cpp:(.text+0x30): undefined reference to `gtk_window_get_type'
test.cpp:(.text+0x42): undefined reference to `g_type_check_instance_cast'
test.cpp:(.text+0x51): undefined reference to `gtk_window_set_title'
test.cpp:(.text+0x56): undefined reference to `gtk_window_get_type'
test.cpp:(.text+0x68): undefined reference to `g_type_check_instance_cast'
test.cpp:(.text+0x7a): undefined reference to `gtk_window_set_default_size'
test.cpp:(.text+0x86): undefined reference to `gtk_widget_show_all'
CMakeFiles/gtktest.dir/test.cpp.o: In function `main':
test.cpp:(.text+0xcc): undefined reference to `gtk_application_new'
test.cpp:(.text+0xfb): undefined reference to `g_signal_connect_data'
test.cpp:(.text+0x100): undefined reference to `g_application_get_type'
test.cpp:(.text+0x112): undefined reference to `g_type_check_instance_cast'
test.cpp:(.text+0x126): undefined reference to `g_application_run'
test.cpp:(.text+0x135): undefined reference to `g_object_unref'
collect2: error: ld returned 1 exit status
CMakeFiles/gtktest.dir/build.make:94: recipe for target 'gtktest' failed
make[2]: *** [gtktest] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/gtktest.dir/all' failed
make[1]: *** [CMakeFiles/gtktest.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
test.cpp code (From GTK+ tutorials)
#include <gtk/gtk.h>
static void
activate (GtkApplication* app,
gpointer user_data)
{
GtkWidget *window;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
gtk_widget_show_all (window);
}
int
main (int argc,
char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}
Is the problem messed up order of CMake's commands?
Use GTK in your CMakeLists.txt instead of GTK3:
cmake_minimum_required(VERSION 3.0.2)
project(gtktest)
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK REQUIRED gtk+-3.0)
include_directories(${GTK_INCLUDE_DIRS})
link_directories(${GTK_LIBRARY_DIRS})
add_definitions(${GTK_CFLAGS_OTHER})
add_executable(gtktest test.cpp)
target_link_libraries(gtktest ${GTK_LIBRARIES})
GTK or GTK3 is a prefix and you can use any prefix you want for example.
cmake_minimum_required(VERSION 3.0.0)
project(gtktest)
find_package(PkgConfig REQUIRED)
pkg_check_modules(HI REQUIRED gtk+-3.0)
add_executable(gtktest test.cpp)
target_include_directories(gtktest PRIVATE ${HI_INCLUDE_DIRS})
target_link_libraries(gtktest PRIVATE ${HI_LIBRARIES})
However the prefix must be the same through all the CMakeLists.txt file and you are using the prefix GTK3 but later you write GKT3_LIBRARIES
Related
I'm playing around with developing a cross-platform C++ project. Things build fine on Linux, but on Windows (10) + MSys2 I've run into a strange issue. Compile works fine (picks up my include dirs, etc.), but linking fails with all sorts of undefined reference errors to a static imported library I have, and even the C++ runtime.
I've tried setting CMAKE_C[XX]_COMPILER, CMAKE_MAKE_PROGRAM, but the output from the configuration step is always the same:
$ cmake ..
-- The C compiler identification is GNU 10.2.0
-- The CXX compiler identification is GNU 10.2.0
System is unknown to cmake, create:
Platform/MINGW64_NT-10.0-19041 to use this system, please post your config file on discourse.cmake.org so it can be added to cmake
-- Detecting C compiler ABI info
System is unknown to cmake, create:
Platform/MINGW64_NT-10.0-19041 to use this system, please post your config file on discourse.cmake.org so it can be added to cmake
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /mingw64/bin/cc.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
System is unknown to cmake, create:
Platform/MINGW64_NT-10.0-19041 to use this system, please post your config file on discourse.cmake.org so it can be added to cmake
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /mingw64/bin/CC.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: <....>
As mentioned earlier the compile works, but linking the executable fails spectacularly. Here is my minimal working example:
$ cat ../CMakeLists.txt
project(example)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
add_executable(example
main.cpp
)
Here is an sample of the output (the rest is omitted for brevity):
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles/example.dir/main.cpp.obj:main.cpp:(.text+0x51): undefined reference to `std::ios_base::Init::~Init()'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles/example.dir/main.cpp.obj:main.cpp:(.text+0x81): undefined reference to `std::ios_base::Init::Init()'
Adding -v to cmake produces the following commands.
Compile:
/mingw64/bin/CC.exe -std=gnu++17 -o CMakeFiles/example.dir/main.cpp.obj -c /home/.../Development/minex/main.cpp
Link:
/mingw64/bin/CC.exe CMakeFiles/example.dir/main.cpp.obj -o example
CC.exe seems off... and it's used if I set the CXX compiler flag or not...
I also tried generating "MSYS2 Makefiles" but that also fails (doesn't know the generator).
I can reproduce the output by running
$ CC main.cpp -o example
while
$ g++ main.cpp -o example
works fine.
CMake version is 3.18.4.
Edit: This is the entire output of running make VERBOSE=1 (using mingw64-cmake seems to produce the same output, except the 'entering directory' and 'leaving directory' paths are absolute windows paths):
$ cat log
/usr/bin/cmake.exe -S/home/<...>/Development/minex -B/home/<...>/Development/minex/build --check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake.exe -E cmake_progress_start /home/<...>/Development/minex/build/CMakeFiles /home/<...>/Development/minex/build//CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/home/<...>/Development/minex/build'
make -f CMakeFiles/example.dir/build.make CMakeFiles/example.dir/depend
make[2]: Entering directory '/home/<...>/Development/minex/build'
cd /home/<...>/Development/minex/build && /usr/bin/cmake.exe -E cmake_depends "Unix Makefiles" /home/<...>/Development/minex /home/<...>/Development/minex /home/<...>/Development/minex/build /home/<...>/Development/minex/build /home/<...>/Development/minex/build/CMakeFiles/example.dir/DependInfo.cmake --color=
Dependee "/home/<...>/Development/minex/build/CMakeFiles/example.dir/DependInfo.cmake" is newer than depender "/home/<...>/Development/minex/build/CMakeFiles/example.dir/depend.internal".
Dependee "/home/<...>/Development/minex/build/CMakeFiles/CMakeDirectoryInformation.cmake" is newer than depender "/home/<...>/Development/minex/build/CMakeFiles/example.dir/depend.internal".
Scanning dependencies of target example
make[2]: Leaving directory '/home/<...>/Development/minex/build'
make -f CMakeFiles/example.dir/build.make CMakeFiles/example.dir/build
make[2]: Entering directory '/home/<...>/Development/minex/build'
[ 50%] Building CXX object CMakeFiles/example.dir/main.obj
/mingw64/bin/CC.exe -std=gnu++17 -o CMakeFiles/example.dir/main.obj -c /home/<...>/Development/minex/main.cpp
[100%] Linking CXX executable example
/usr/bin/cmake.exe -E cmake_link_script CMakeFiles/example.dir/link.txt --verbose=1
/mingw64/bin/CC.exe CMakeFiles/example.dir/main.obj -o example
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles/example.dir/main.obj:main.cpp:(.text+0x23): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles/example.dir/main.obj:main.cpp:(.text+0x32): undefined reference to `std::ostream::operator<<(std::ostream& (*)(std::ostream&))'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles/example.dir/main.obj:main.cpp:(.text+0x51): undefined reference to `std::ios_base::Init::~Init()'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles/example.dir/main.obj:main.cpp:(.text+0x81): undefined reference to `std::ios_base::Init::Init()'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles/example.dir/main.obj:main.cpp:(.rdata$.refptr._ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_[.refptr._ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_]+0x0): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles/example.dir/main.obj:main.cpp:(.rdata$.refptr._ZSt4cout[.refptr._ZSt4cout]+0x0): undefined reference to `std::cout'
collect2.exe: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/example.dir/build.make:103: example] Error 1
make[2]: Leaving directory '/home/<...>/Development/minex/build'
make[1]: *** [CMakeFiles/Makefile2:95: CMakeFiles/example.dir/all] Error 2
make[1]: Leaving directory '/home/<...>/Development/minex/build'
make: *** [Makefile:103: all] Error 2
Solution:
I was setting CMAKE_CXX_COMPILER wrong :/. I was doing it from memory, and I just did
CMAKE_CXX_COMPILER=... cmake ..
not
cmake .. -DCMAKE_CXX_COMPILER=...
However! It's still weird that CC is used to successfully compile cpp files, but it can't link the object files.
If you are using mingw64 compiler in MSYS2 make sure you are using mingw64 version of cmake too.
Using cmake not aligned with gcc e.g.:
MINGW64
# which gcc
/mingw64/bin/gcc
MINGW64
# which cmake
/usr/bin/cmake
Will led to following error when running cmake:
...
-- The CXX compiler identification is GNU 10.2.0
System is unknown to cmake, create:
Platform/MINGW64_NT-10.0-19041 to use this system, please post your config file on discourse.cmake.org so it can be added to cmake
...
and linker error in build step.
So make sure you install mingw64 version of cmake:
MINGW64
pacman -S mingw-w64-x86_64-cmake
You need to close terminal and open it again after cmake is installed. Then make sure you have aligned versions of gcc and cmake installed:
MINGW64
# which gcc
/mingw64/bin/gcc
MINGW64
# which cmake
/mingw64/bin/cmake
Now cmake should work properly.
You have these errors because you are trying to compile/link c++ program with a c compiler. For example the two undefined references you are mentioning are part of libstdc++. It is used by default when using g++ but not with CC. If you want to use CC you have to add it manually -lstdc++.
The easiest way is to compile and link c++ programs by using g++.
For some reason the /mingw64/bin/CC.exe is considered as the CXX compiler and the working detection is skipped. to avoid the skipp of the working detection you can add set(CMAKE_CXX_COMPILER_WORKS 1). to modify the compiler it self you can set CMAKE_CXX_COMPILER as explained in CMAKE_CXX_COMPILER or set CXX as explained in CXX . be careful to clean the cache.
Introduction
I'm trying to cross compile to Windows from Linux using MinGW-W64.
I had it working before I added enet to my project, however I'm now receiving issues with linking to enet
CMake finds enet correctly. ENET_LIBRARY and ENET_INCLUDE_DIR are set to the right locations.
ENet contains the symbols, as verified using /usr/x86_64-w64-mingw32/bin/objdump /usr/local/mingw64/lib/libenet.a -t
Build fails with "undefined reference to `enet_address_set_host'"
I'm able to compile the same code base natively using Visual Studio and VCPkg
Edit: Checking the contents of libenet.a verifies that it's a problem with cross-compiling enet, not my program in particular
None of my other dependencies use GNU autoconf, so I expect there's a problem there.
The Error
-- The C compiler identification is GNU 8.2.0
-- The CXX compiler identification is GNU 8.2.0
-- Check for working C compiler: /usr/bin/x86_64-w64-mingw32-gcc
-- Check for working C compiler: /usr/bin/x86_64-w64-mingw32-gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/x86_64-w64-mingw32-g++
-- Check for working CXX compiler: /usr/bin/x86_64-w64-mingw32-g++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found SFML 2.5 in /usr/local/mingw64/include
-- Found SFGUI in /usr/local/mingw64/include
-- Found Thor in /usr/local/mingw64/include
-- Found Lua in /usr/local/mingw64/include/lua5.1/
-- Found Lua: /usr/local/mingw64/lib/liblua5.1.a
-- Found ENet: /usr/local/mingw64/lib/libenet.a
-- Found ENet in /usr/local/mingw64/include
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - found
-- Found Threads: TRUE
/usr/local/mingw64/lib/liblua5.1.a/usr/local/mingw64/lib/libenet.awsock32ws2_32winmm
-- Adding executable: client (with server)
-- Configuring done
-- Generating done
-- Build files have been written to: /home/ruben/dev/rvwp
Scanning dependencies of target rvwp
[SNIP]
[ 98%] Building CXX object CMakeFiles/rvwp.dir/source/tests/t_chunk.cpp.obj
[100%] Linking CXX executable bin/rvwp.exe
/usr/lib/gcc/x86_64-w64-mingw32/8.2.0/../../../../x86_64-w64-mingw32/bin/ld: CMakeFiles/rvwp.dir/objects.a(address.cpp.obj):address.cpp:(.text+0xc6): undefined reference to `enet_address_set_host'
/usr/lib/gcc/x86_64-w64-mingw32/8.2.0/../../../../x86_64-w64-mingw32/bin/ld: CMakeFiles/rvwp.dir/objects.a(net.cpp.obj):net.cpp:(.text+0x105): undefined reference to `enet_initialize'
/usr/lib/gcc/x86_64-w64-mingw32/8.2.0/../../../../x86_64-w64-mingw32/bin/ld: CMakeFiles/rvwp.dir/objects.a(net.cpp.obj):net.cpp:(.text+0x204): undefined reference to `enet_packet_create'
/usr/lib/gcc/x86_64-w64-mingw32/8.2.0/../../../../x86_64-w64-mingw32/bin/ld: CMakeFiles/rvwp.dir/objects.a(net.cpp.obj):net.cpp:(.text+0x217): undefined reference to `enet_peer_send'
/usr/lib/gcc/x86_64-w64-mingw32/8.2.0/../../../../x86_64-w64-mingw32/bin/ld: CMakeFiles/rvwp.dir/objects.a(net.cpp.obj):net.cpp:(.text+0x29f): undefined reference to `enet_packet_create'
/usr/lib/gcc/x86_64-w64-mingw32/8.2.0/../../../../x86_64-w64-mingw32/bin/ld: CMakeFiles/rvwp.dir/objects.a(net.cpp.obj):net.cpp:(.text+0x2b3): undefined reference to `enet_peer_send'
/usr/lib/gcc/x86_64-w64-mingw32/8.2.0/../../../../x86_64-w64-mingw32/bin/ld: CMakeFiles/rvwp.dir/objects.a(net.cpp.obj):net.cpp:(.text+0x5af): undefined reference to `enet_host_destroy'
/usr/lib/gcc/x86_64-w64-mingw32/8.2.0/../../../../x86_64-w64-mingw32/bin/ld: CMakeFiles/rvwp.dir/objects.a(net.cpp.obj):net.cpp:(.text+0x65b): undefined reference to `enet_host_create'
/usr/lib/gcc/x86_64-w64-mingw32/8.2.0/../../../../x86_64-w64-mingw32/bin/ld: CMakeFiles/rvwp.dir/objects.a(net.cpp.obj):net.cpp:(.text+0x91f): undefined reference to `enet_host_create'
/usr/lib/gcc/x86_64-w64-mingw32/8.2.0/../../../../x86_64-w64-mingw32/bin/ld: CMakeFiles/rvwp.dir/objects.a(net.cpp.obj):net.cpp:(.text+0x950): undefined reference to `enet_host_connect'
/usr/lib/gcc/x86_64-w64-mingw32/8.2.0/../../../../x86_64-w64-mingw32/bin/ld: CMakeFiles/rvwp.dir/objects.a(net.cpp.obj):net.cpp:(.text+0x96c): undefined reference to `enet_host_service'
/usr/lib/gcc/x86_64-w64-mingw32/8.2.0/../../../../x86_64-w64-mingw32/bin/ld: CMakeFiles/rvwp.dir/objects.a(net.cpp.obj):net.cpp:(.text+0x1023): undefined reference to `enet_host_service'
/usr/lib/gcc/x86_64-w64-mingw32/8.2.0/../../../../x86_64-w64-mingw32/bin/ld: CMakeFiles/rvwp.dir/objects.a(net.cpp.obj):net.cpp:(.text+0x1437): undefined reference to `enet_packet_destroy'
/usr/lib/gcc/x86_64-w64-mingw32/8.2.0/../../../../x86_64-w64-mingw32/bin/ld: CMakeFiles/rvwp.dir/objects.a(net.cpp.obj):net.cpp:(.text+0x121): undefined reference to `enet_deinitialize'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/rvwp.dir/build.make:991: bin/rvwp.exe] Error 1
make[1]: *** [CMakeFiles/Makefile2:73: CMakeFiles/rvwp.dir/all] Error 2
make: *** [Makefile:130: all] Error 2
Cross-compiling Enet
To cross compile enet, I use the following script
#!/bin/bash
TOOLSET="x86_64-w64-mingw32"
wget http://enet.bespin.org/download/enet-1.3.13.tar.gz
tar -xzf enet-1.3.13.tar.gz
cd enet-1.3.13
./configure \
--build=${TOOLSET} \
--host=x86_64-windows \
--target=${TOOLSET} \
--prefix=/usr/local/mingw64 \
--enable-shared
make -j3
sudo make install
My Program
I'm using cmake to generate the makefiles, and a toolchain to allow cross-compilation. The program compiles with SFML, thor, std::thread, and Lua fine. None of these libraries use GNU autoconf
My CMakeLists.txt looks like this:
find_package(ENet REQUIRED)
include_directories(${ENET_INCLUDE_DIR})
set(BASE_LIBRARIES ${CMAKE_THREAD_LIBS_INIT} ${LUA_LIBRARY} ${CMAKE_DL_LIBS} ${ENET_LIBRARY})
set(BASE_LIBRARIES ${BASE_LIBRARIES} wsock32 ws2_32 winmm)
message(${BASE_LIBRARIES})
set(EXECUTABLE_NAME "rvwp")
add_executable(${EXECUTABLE_NAME} WIN32 ${CLIENT_SRC})
set_target_properties(${EXECUTABLE_NAME} PROPERTIES BUILD_WITH_INSTALL_RPATH true)
install(TARGETS ${EXECUTABLE_NAME} DESTINATION bin)
target_link_libraries(${EXECUTABLE_NAME} ${BASE_LIBRARIES} ${SFML_LIBRARIES} ${SFGUI_LIBRARY} ${THOR_LIBRARY})
The findENet file looks like this:
FIND_PATH(ENET_INCLUDE_DIR enet/enet.h
PATHS
$ENV{ENETDIR}
/usr/local
/usr
PATH_SUFFIXES include)
FIND_LIBRARY(ENET_LIBRARY
NAMES enet
PATHS
$ENV{ENETDIR}
/usr/local
/usr
PATH_SUFFIXES lib)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(ENet DEFAULT_MSG ENET_LIBRARY ENET_INCLUDE_DIR)
IF (ENet_FOUND)
MESSAGE(STATUS "Found ENet in ${ENET_INCLUDE_DIR}")
IF(WIN32)
SET(WINDOWS_ENET_DEPENDENCIES "ws2_32;winmm")
SET(ENET_LIBRARIES ${ENET_LIBRARY} ${WINDOWS_ENET_DEPENDENCIES})
ELSE(WIN32)
SET(ENET_LIBRARIES ${ENET_LIBRARY})
ENDIF(WIN32)
ENDIF (ENet_FOUND)
MARK_AS_ADVANCED(ENET_LIBRARY ENET_LIBRARIES ENET_INCLUDE_DIR)
The tool chain looks like this:
# Sample toolchain file for building for Windows from an Ubuntu Linux system.
#
# Typical usage:
# *) install cross compiler: `sudo apt-get install mingw-w64 g++-mingw-w64`
# *) cd build
# *) cmake -DCMAKE_TOOLCHAIN_FILE=~/Toolchain-Ubuntu-mingw64.cmake ..
set(CMAKE_SYSTEM_NAME Windows)
set(TOOLCHAIN_PREFIX x86_64-w64-mingw32)
# cross compilers to use for C and C++
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++)
set(CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres)
SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++" )
# target environment on the build host system
# set 1st to dir with the cross compiler's C/C++ headers/libs
set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX} /usr/local/mingw64 ./extlibs)
set(LUA_INCLUDE_DIR /usr/local/mingw64/include/lua5.1/)
set(LUA_LIBRARY /usr/local/mingw64/lib/liblua5.1.a)
set(OPENAL_LIBRARY /usr/local/mingw64/lib/libopenal32.a)
# modify default behavior of FIND_XXX() commands to
# search for headers/libs in the target environment and
# search for programs in the build host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
The linklibs.rsp file is used to pass linking commands to the linker, here is its value:
/usr/local/mingw64/lib/liblua5.1.a /usr/local/mingw64/lib/libenet.a -lwsock32 -lws2_32 -lwinmm /usr/local/mingw64/lib/libsfml-system.a /usr/local/mingw64/lib/libsfml-window.a /usr/local/mingw64/lib/libsfml-graphics.a /usr/local/mingw64/lib/libsfml-network.a /usr/local/mingw64/lib/libsfml-audio.a /usr/local/mingw64/bin/sfgui.dll /usr/local/mingw64/bin/libthor.dll -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32
(EDIT) AR Formats
Extracting the not-working libenet.a and using file results in this:
callbacks.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), with debug_info, not stripped
Extracting the working libsfml-graphics.a results in this:
d000508.o: Intel amd64 COFF object file, no line number info, not stripped, 5 sections, symbol offset=0x144, 8 symbols
So it appears that the problem is in compiling enet
How to build the following library: Boost.Beast (which will not be available in boost until Boost 1.66.0)?
Reading the build instructions they seem to be focused on Windows only:
cd ..
mkdir bin64
cd bin64
cmake -G"Visual Studio 14 2015 Win64" .. # for 64-bit Windows builds (VS2015)
cmake -G"Visual Studio 15 2017 Win64" .. # for 64-bit Windows builds (VS2017)
I've installed Boost which is a dependency of Beast (include/boost/beast/config.hpp includes <boost/config.hpp>) using:
sudo apt install libboost-dev
I've tried using cmake . and make to build the library which resulted in the below:
user:~/libraries/beast$ cmake .
-- The C compiler identification is GNU 6.3.0
-- The CXX compiler identification is GNU 6.3.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - not found
-- Check if compiler accepts -pthread
-- Check if compiler accepts -pthread - yes
-- Found Threads: TRUE
-- Found OpenSSL: /usr/lib/x86_64-linux-gnu/libssl.so;/usr/lib/x86_64-linux-gnu/libcrypto.so (found version "1.0.2g")
-- Configuring done
-- Generating done
-- Build files have been written to: /home/user/libraries/beast
user:~/libraries/beast$ make
[ 0%] Building CXX object example/advanced/server/CMakeFiles/advanced-server.dir/advanced_server.cpp.o
In file included from /home/user/libraries/beast/include/boost/beast/websocket/stream.hpp:3512:0,
from /home/user/libraries/beast/include/boost/beast/websocket.hpp:18,
from /home/user/libraries/beast/example/advanced/server/advanced_server.cpp:18:
/home/user/libraries/beast/include/boost/beast/websocket/impl/read.ipp: In member function ‘std::size_t boost::beast::websocket::stream<NextLayer>::read_some(const MutableBufferSequence&, boost::beast::error_code&)’:
/home/user/libraries/beast/include/boost/beast/websocket/impl/read.ipp:1077:49: warning: enumeral and non-enumeral type in conditional expression [-Wextra]
cr.code == close_code::none ?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
close_code::normal : cr.code,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[ 0%] Linking CXX executable advanced-server
CMakeFiles/advanced-server.dir/advanced_server.cpp.o: In function `std::thread::thread<main::{lambda()#1}>(main::{lambda()#1}&&)':
advanced_server.cpp:(.text+0x11a9): undefined reference to `pthread_create'
CMakeFiles/advanced-server.dir/advanced_server.cpp.o: In function `__static_initialization_and_destruction_0(int, int)':
advanced_server.cpp:(.text+0x158c): undefined reference to `boost::system::generic_category()'
advanced_server.cpp:(.text+0x1598): undefined reference to `boost::system::generic_category()'
advanced_server.cpp:(.text+0x15a4): undefined reference to `boost::system::system_category()'
CMakeFiles/advanced-server.dir/advanced_server.cpp.o: In function `boost::system::error_code::error_code()':
advanced_server.cpp:(.text._ZN5boost6system10error_codeC2Ev[_ZN5boost6system10error_codeC5Ev]+0x17): undefined reference to `boost::system::system_category()'
CMakeFiles/advanced-server.dir/advanced_server.cpp.o: In function `boost::system::errc::make_error_condition(boost::system::errc::errc_t)':
advanced_server.cpp:(.text._ZN5boost6system4errc20make_error_conditionENS1_6errc_tE[_ZN5boost6system4errc20make_error_conditionENS1_6errc_tE]+0x1c): undefined reference to `boost::system::generic_category()'
CMakeFiles/advanced-server.dir/advanced_server.cpp.o: In function `boost::asio::error::get_system_category()':
advanced_server.cpp:(.text._ZN5boost4asio5error19get_system_categoryEv[_ZN5boost4asio5error19get_system_categoryEv]+0x5): undefined reference to `boost::system::system_category()'
CMakeFiles/advanced-server.dir/advanced_server.cpp.o: In function `boost::beast::file_posix::close(boost::system::error_code&)':
advanced_server.cpp:(.text._ZN5boost5beast10file_posix5closeERNS_6system10error_codeE[_ZN5boost5beast10file_posix5closeERNS_6system10error_codeE]+0x32): undefined reference to `boost::system::generic_category()'
CMakeFiles/advanced-server.dir/advanced_server.cpp.o: In function `boost::beast::file_posix::open(char const*, boost::beast::file_mode, boost::system::error_code&)':
advanced_server.cpp:(.text._ZN5boost5beast10file_posix4openEPKcNS0_9file_modeERNS_6system10error_codeE[_ZN5boost5beast10file_posix4openEPKcNS0_9file_modeERNS_6system10error_codeE]+0x39): undefined reference to `boost::system::generic_category()'
advanced_server.cpp:(.text._ZN5boost5beast10file_posix4openEPKcNS0_9file_modeERNS_6system10error_codeE[_ZN5boost5beast10file_posix4openEPKcNS0_9file_modeERNS_6system10error_codeE]+0x173): undefined reference to `boost::system::generic_category()'
advanced_server.cpp:(.text._ZN5boost5beast10file_posix4openEPKcNS0_9file_modeERNS_6system10error_codeE[_ZN5boost5beast10file_posix4openEPKcNS0_9file_modeERNS_6system10error_codeE]+0x1d8): undefined reference to `boost::system::generic_category()'
CMakeFiles/advanced-server.dir/advanced_server.cpp.o: In function `boost::beast::file_posix::size(boost::system::error_code&) const':
advanced_server.cpp:(.text._ZNK5boost5beast10file_posix4sizeERNS_6system10error_codeE[_ZNK5boost5beast10file_posix4sizeERNS_6system10error_codeE]+0x38): undefined reference to `boost::system::generic_category()'
CMakeFiles/advanced-server.dir/advanced_server.cpp.o:advanced_server.cpp:(.text._ZNK5boost5beast10file_posix4sizeERNS_6system10error_codeE[_ZNK5boost5beast10file_posix4sizeERNS_6system10error_codeE]+0x7e): more undefined references to `boost::system::generic_category()' follow
collect2: error: ld returned 1 exit status
example/advanced/server/CMakeFiles/advanced-server.dir/build.make:94: recipe for target 'example/advanced/server/advanced-server' failed
make[2]: *** [example/advanced/server/advanced-server] Error 1
CMakeFiles/Makefile2:133: recipe for target 'example/advanced/server/CMakeFiles/advanced-server.dir/all' failed
make[1]: *** [example/advanced/server/CMakeFiles/advanced-server.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
The CMakeLists.txt only works for Windows, but the bjam build scripts work on all platforms. The docs could do a better job explaining this. However, note that Beast is header-only so you only need to use bjam or cmake if you are trying to build the examples or tests.
I am trying to build a executable with cygwin in windows 7 and I get the following error in the linking stage.
/usr/lib/gcc/x86_64-pc-cygwin/4.9.3/../../../../lib/libcygwin.a(libcmain.o): In function `main':
/usr/src/debug/cygwin-2.3.0-1/winsup/cygwin/lib/libcmain.c:39: undefined reference to `WinMain'
/usr/src/debug/cygwin-2.3.0-1/winsup/cygwin/lib/libcmain.c:39:(.text.startup+0x7f): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `WinMain'
collect2: error: ld returned 1 exit status
I dont understand why it tries to find WinMain. I have a cpp file with int main(int, char**) function defined which is part of the build. I do not understand why it is trying to use libcmain.c, which is part of cygwin during executable creation. I am using cmake and it has following:
add_executable(binary_name ${SOURCE_FILES})
This application need to be a console type application and does not have a GUI.
EDIT:
My main function is as follows.
#include "gtest/gtest.h"
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
Three points I would recommend to check:
Check the command line(s) that are called by activating verbose output. See Using CMake with GNU Make: How can I see the exact commands?
Are you sure that you really have only one main() function in your code?
Is the source file containing main() function directly added to the add_executable() call?
Because I just have given your code a try with the latest CMake package available in Cygwin and it seems to work just fine (with and without #include <windows.h> in main.cpp).
In the hope that it might help finding your problem, here is what I've done:
$ export PATH=/usr/local/bin:/usr/bin:/bin:/usr/bin
$ cmake --version
cmake version 3.3.2
CMake suite maintained and supported by Kitware (kitware.com/cmake).
$ c++ -v --version
c++ (GCC) 4.9.3
gcc-Version 4.9.3 (GCC)
GNU C (GCC) Version 4.9.3 (x86_64-pc-cygwin)
GNU assembler version 2.25 (x86_64-pc-cygwin) using BFD version (GNU Binutils) 2.25
GNU assembler (GNU Binutils) 2.25
GNU ld (GNU Binutils) 2.25
$ cmake ..
-- The CXX compiler identification is GNU 4.9.3
-- Check for working CXX compiler: /usr/bin/c++.exe
-- Check for working CXX compiler: /usr/bin/c++.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found GTest: /cygdrive/c/gtest-1.7.0/lib/.libs/libgtest.a
-- Configuring done
-- Generating done
-- Build files have been written to: ...
Scanning dependencies of target binary_name
[ 50%] Building CXX object CMakeFiles/binary_name.dir/main.cpp.o
[100%] Linking CXX executable binary_name.exe
[100%] Built target binary_name
$ ./binary_name.exe
[==========] Running 0 tests from 0 test cases.
[==========] 0 tests from 0 test cases ran. (3 ms total)
[ PASSED ] 0 tests.
I've used the following CMakeLists.txt:
cmake_minimum_required(VERSION 3.0)
project(binary_name CXX)
enable_testing()
set(GTEST_ROOT /cygdrive/c/gtest-1.7.0)
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${GTEST_ROOT}/lib/.libs")
find_package(GTest REQUIRED)
add_executable(binary_name main.cpp)
target_include_directories(binary_name PRIVATE ${GTEST_INCLUDE_DIRS})
target_link_libraries(binary_name PRIVATE ${GTEST_LIBRARIES})
Resulting in the following link line CMakeFiles/binary_name.dir/link.txt:
/usr/bin/c++.exe
-Wl,--enable-auto-import CMakeFiles/binary_name.dir/main.cpp.o
-o binary_name.exe
-Wl,--out-implib,libbinary_name.dll.a
-Wl,--major-image-version,0,--minor-image-version,0
/cygdrive/c/gtest-1.7.0/lib/.libs/libgtest.a
More References
Most references to similar problems where in combination with SDL or far more general:
undefined reference to 'WinMain' with SDL compiling in a native enviroment
Undefined reference to WinMain in Cygwin
g++ linker problem with libcygwin.a -> linker error libcygwin
WINMAIN and main() in C++ (Extended)
I try to set up an SDL project using CMake, but it seems like the executable isn't linked properly.
This is the CMakeLists.txt I use
cmake_minimum_required(VERSION 3.0)
project(MuspellsheimR)
# includes cmake/FindSDL2.cmake
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/modules)
# find SDL2
find_package(SDL2 REQUIRED)
include_directories(${SDL2_INCLUDE_DIR})
set(SOURCE_FILES src/main.cpp)
add_executable(MuspellsheimR ${SOURCE_FILES})
target_link_libraries(MuspellsheimR ${SDL_LIBRARY})
src/main.cpp looks like this:
#include <iostream>
#include <SDL.h>
int main(int, char**){
if (SDL_Init(SDL_INIT_VIDEO) != 0){
std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl;
return 1;
}
SDL_Quit();
return 0;
}
Here is the log output.
[omtcyf0#localhost MuspellsheimR_Build]$ cmake -G "Unix Makefiles" ../MuspellsheimR
-- The C compiler identification is GNU 5.1.1
-- The CXX compiler identification is GNU 5.1.1
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Looking for include file pthread.h
-- Looking for include file pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - not found
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Found SDL2: /usr/local/lib/libSDL2main.a;/usr/local/lib/libSDL2.so;-lpthread
-- Configuring done
-- Generating done
-- Build files have been written to: /home/omtcyf0/Desktop/MuspellsheimR_Build
[omtcyf0#localhost MuspellsheimR_Build]$
[omtcyf0#localhost MuspellsheimR_Build]$ ls
CMakeCache.txt CMakeFiles cmake_install.cmake Makefile
[omtcyf0#localhost MuspellsheimR_Build]$ make
Scanning dependencies of target MuspellsheimR
[100%] Building CXX object CMakeFiles/MuspellsheimR.dir/src/main.cpp.o
Linking CXX executable MuspellsheimR
CMakeFiles/MuspellsheimR.dir/src/main.cpp.o: In function `main':
main.cpp:(.text+0x25): undefined reference to `SDL_Init'
main.cpp:(.text+0x3e): undefined reference to `SDL_SetVideoMode'
main.cpp:(.text+0x51): undefined reference to `SDL_RWFromFile'
main.cpp:(.text+0x5e): undefined reference to `SDL_LoadBMP_RW'
main.cpp:(.text+0x7c): undefined reference to `SDL_UpperBlit'
main.cpp:(.text+0x88): undefined reference to `SDL_Flip'
main.cpp:(.text+0x92): undefined reference to `SDL_Delay'
main.cpp:(.text+0x9e): undefined reference to `SDL_FreeSurface'
main.cpp:(.text+0xa3): undefined reference to `SDL_Quit'
collect2: error: ld returned 1 exit status
CMakeFiles/MuspellsheimR.dir/build.make:85: recipe for target 'MuspellsheimR' failed
make[2]: *** [MuspellsheimR] Error 1
CMakeFiles/Makefile2:60: recipe for target 'CMakeFiles/MuspellsheimR.dir/all' failed
make[1]: *** [CMakeFiles/MuspellsheimR.dir/all] Error 2
Makefile:116: recipe for target 'all' failed
make: *** [all] Error 2
What am I doing wrong?
SDL_LIBRARY is the wrong variable. You need to use SDL2_LIBRARY.