Cross-compiling enet from Linux to Windows, linking errors - c++

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

Related

CMake with clang shows undefined symbol, and with cl links correctly

TLDR
Im building a static library and linking it to an executable. Im generating makefiles with cmake. When I generate the makefile for cl (The compiler from visual studio) I have no problems, but when I generate the makefile for clang I get an undefined symbol.
Versions:
cmake version 3.18.1
clang version 11.0.0
Target: x86_64-pc-windows-msvc
Thread model: posix
cl version 19.26.28806 for x64
Minimal Example
I have the following structure for the proyect:
Proyect Root
│ CMakeLists.txt
│ foo.cpp
│ foo.hpp
│ main.cpp
│
└───bin
And this are the contents of the files:
foo.hpp
namespace foo {
void do_stuff(void);
}
foo.cpp
#include <foo.hpp>
namespace foo {
void do_stuff(void) {}
}
main.cpp
#include <foo.hpp>
int main(void) {
foo::do_stuff();
return 0;
}
And CMakeLists.txt
cmake_minimum_required(VERSION 3.0.0)
project(CompileAndLinkLib)
include_directories(".")
file(GLOB FOO_SRC "foo.cpp")
add_library(foo STATIC ${FOO_SRC})
add_executable(main "main.cpp")
target_link_libraries(main foo)
Correct linking
First I call vcvarsall.bat. I generate a nmake file with the following command:
cmake .. -G "NMake Makefiles"
And compile with:
nmake
The project compiles and links correctly
The undefined symbol
I generate the make file with the following command:
cmake .. -G "Unix Makefiles" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
And when I compile with make I get the following output:
Scanning dependencies of target foo
[ 25%] Building CXX object CMakeFiles/foo.dir/foo.cpp.obj
[ 50%] Linking CXX static library foo.lib
[ 50%] Built target foo
Scanning dependencies of target main
[ 75%] Building CXX object CMakeFiles/main.dir/main.cpp.obj
[100%] Linking CXX executable main.exe
lld-link: error: undefined symbol: void __cdecl foo::do_stuff(void)
>>> referenced by C:\Users\pabsa\temp\main.cpp:4
>>> CMakeFiles/main.dir/main.cpp.obj:(main)
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [main.exe] Error 1
make[1]: *** [CMakeFiles/main.dir/all] Error 2
make: *** [all] Error 2
Im not sure if im doing something wrong, like if im missing something, or if this is an error with the makefile generated by cmake.
I just had the same problem, but with Clang 13. It could be solved with specifying clang as compiler in the CMakeLists, instead of letting CMake determine it automatically.
set(CMAKE_CXX_COMPILER "clang++")
(And yes, I read your original question correct, using this:
-DCMAKE_CXX_COMPILER=clang++
as an additional argument for cmake did not work for me as well, even if it looks like it should behave the same as setting it in CMakeLists.txt)
I tested again with:
clang version 12.0.0
Target: x86_64-pc-windows-msvc
Thread model: posix
And it worked corretly. Seems like it was a problem with clang 11
You're overcomplicating things imo. What about just "cmake .. -T ClangCL && cmake --build ."? Builds fine for me:
C:\Users\vital\test\_build>cmake .. -T ClangCL
-- Building for: Visual Studio 17 2022
-- Selecting Windows SDK version 10.0.20348.0 to target Windows 10.0.22000.
-- The C compiler identification is Clang 14.0.5 with MSVC-like command-line
-- The CXX compiler identification is Clang 14.0.5 with MSVC-like command-line
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/Llvm/x64/bin/clang-cl.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/Llvm/x64/bin/clang-cl.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/vital/test/_build
C:\Users\vital\test\_build>cmake --build .
MSBuild version 17.3.1+2badb37d1 for .NET Framework
Checking Build System
Building Custom Rule C:/Users/vital/test/CMakeLists.txt
foo.vcxproj -> C:\Users\vital\test\_build\Debug\foo.lib
Building Custom Rule C:/Users/vital/test/CMakeLists.txt
main.vcxproj -> C:\Users\vital\test\_build\Debug\main.exe
Building Custom Rule C:/Users/vital/test/CMakeLists.txt
C:\Users\vital\test\_build>

CMake + MSys2 undefined references to everything (including c++ runtime)

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.

Fail to run the example of 3D Surface Mesh Generation with CGAL

I am trying to run this example of 3D Surface Mesh Generation with CGAL. The code is:
#include <CGAL/Surface_mesh_default_triangulation_3.h>
#include <CGAL/Complex_2_in_triangulation_3.h>
#include <CGAL/make_surface_mesh.h>
#include <CGAL/Implicit_surface_3.h>
// default triangulation for Surface_mesher
typedef CGAL::Surface_mesh_default_triangulation_3 Tr;
// c2t3
typedef CGAL::Complex_2_in_triangulation_3<Tr> C2t3;
typedef Tr::Geom_traits GT;
typedef GT::Sphere_3 Sphere_3;
typedef GT::Point_3 Point_3;
typedef GT::FT FT;
typedef FT (*Function)(Point_3);
typedef CGAL::Implicit_surface_3<GT, Function> Surface_3;
FT sphere_function (Point_3 p) {
const FT x2=p.x()*p.x(), y2=p.y()*p.y(), z2=p.z()*p.z();
return x2+y2+z2-1;
}
int main() {
Tr tr; // 3D-Delaunay triangulation
C2t3 c2t3 (tr); // 2D-complex in 3D-Delaunay triangulation
// defining the surface
Surface_3 surface(sphere_function, // pointer to function
Sphere_3(CGAL::ORIGIN, 2.)); // bounding sphere
// Note that "2." above is the *squared* radius of the bounding sphere!
// defining meshing criteria
CGAL::Surface_mesh_default_criteria_3<Tr> criteria(30., // angular bound
0.1, // radius bound
0.1); // distance bound
// meshing surface
CGAL::make_surface_mesh(c2t3, surface, criteria, CGAL::Non_manifold_tag());
std::cout << "Final number of points: " << tr.number_of_vertices() << "\n";
}
The CMakeLists file contains:
# Created by the script cgal_create_CMakeLists
# This is the CMake script for compiling a set of CGAL applications.
cmake_minimum_required(VERSION 3.7)
project(_cgal)
# CGAL and its components
find_package( CGAL QUIET COMPONENTS Core )
if ( NOT CGAL_FOUND )
message(STATUS "This project requires the CGAL library, and will not be compiled.")
return()
endif()
# include helper file
include( ${CGAL_USE_FILE} )
# Boost and its components
find_package( Boost REQUIRED )
if ( NOT Boost_FOUND )
message(STATUS "This project requires the Boost library, and will not be compiled.")
return()
endif()
# Creating entries for target: out
# ############################
set(CMAKE_CXX_STANDARD 11)
set(SOURCE_FILES main.cpp)
add_executable(_cgal ${SOURCE_FILES})
add_to_cached_list( CGAL_EXECUTABLE_TARGETS _cgal )
# Link the executable to CGAL and third-party libraries
target_link_libraries(_cgal ${CGAL_LIBRARIES} ${CGAL_3RD_PARTY_LIBRARIES} )
Output of cmake:
-- The C compiler identification is GNU 7.1.0
-- The CXX compiler identification is GNU 7.1.0
-- Checking whether C compiler has -isysroot
-- Checking whether C compiler has -isysroot - yes
-- Checking whether C compiler supports OSX deployment target flag
-- Checking whether C compiler supports OSX deployment target flag - yes
-- Check for working C compiler: /usr/local/bin/gcc-7
-- Check for working C compiler: /usr/local/bin/gcc-7 -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Checking whether CXX compiler has -isysroot
-- Checking whether CXX compiler has -isysroot - yes
-- Checking whether CXX compiler supports OSX deployment target flag
-- Checking whether CXX compiler supports OSX deployment target flag - yes
-- Check for working CXX compiler: /usr/local/bin/g++-7
-- Check for working CXX compiler: /usr/local/bin/g++-7 -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Build type: Release
-- USING CXXFLAGS = ' -DNDEBUG'
-- USING EXEFLAGS = ' '
-- Targetting Unix Makefiles
-- Using /usr/local/bin/g++-7 compiler.
-- DARWIN_VERSION=16
-- Mac Leopard detected
-- Requested component: Core
-- Requested component: MPFR
-- Requested component: GMP
-- Boost version: 1.64.0
-- Configuring done
-- Generating done
However, I am getting the following error:
Scanning dependencies of target _cgal
[ 50%] Building CXX object CMakeFiles/_cgal.dir/main.cpp.o
[100%] Linking CXX executable _cgal
Undefined symbols for architecture x86_64:
"CGAL::get_mode(std::basic_ios<char, std::char_traits<char> >&)", referenced from:
std::basic_ostream<char, std::char_traits<char> >& CGAL::insert<CGAL::Epick>(std::basic_ostream<char, std::char_traits<char> >&, CGAL::Point_3<CGAL::Epick> const&, CGAL::Cartesian_tag const&) in main.cpp.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
make[3]: *** [_cgal] Error 1
make[2]: *** [CMakeFiles/_cgal.dir/all] Error 2
make[1]: *** [CMakeFiles/_cgal.dir/rule] Error 2
make: *** [_cgal] Error 2
I would highly appreciate if you could explain me how to fix it.
UPD: This seems to be related, but do not get what packages I should add in my cmake.
UPD2: I found that it may be related to the issue of:
There are two implementations of the standard C++ library available on
OS X: libstdc++ and libc++. They are not binary compatible and libMLi3
requires libstdc++.
On 10.8 and earlier libstdc++ is chosen by default, on 10.9 libc++ is
chosen by default. To ensure compatibility with libMLi3, we need to
choose libstdc++ manually.
To do this, add -stdlib=libstdc++ to the linking command.
I modified the following line in the CMake file, but it did not help:
# Link the executable to CGAL and third-party libraries
target_link_libraries(_cgal ${CGAL_LIBRARIES} ${CGAL_3RD_PARTY_LIBRARIES} -static-libstdc++)
UPD3: I tried the solution suggested here, however it does not help
project( _cgal )
cmake_minimum_required(VERSION 2.8.10)
find_package(CGAL QUIET COMPONENTS Core )
if ( CGAL_FOUND )
include( ${CGAL_USE_FILE} )
include( CGAL_CreateSingleSourceCGALProgram )
create_single_source_cgal_program( "main.cpp" )
else()
message(STATUS "This program requires the CGAL library, and will not be compiled.")
endif()
The answer is: fix compiler! CGAL was installed with brew that uses clang compiler. But to compile the project I had been using g++. I should code in C++ more often :)

undefined reference to `WinMain' with cygwin and cmake

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)

CMake does not properly find CUDA library

I'm trying to build a program that requires CUDA. To the CMake script I supply:
cmake -D CUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda ..
CUDA is found and CMake runs normally:
staudt ~/workspace/clutbb/cluster/build $ cmake -D CUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda ..
-- Found CUDA: /usr/local/cuda (found version "6.5")
-- Found Intel TBB
-- Boost version: 1.56.0
-- Found the following Boost libraries:
-- iostreams
-- program_options
-- 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
-- Could NOT find SDL (missing: SDL_LIBRARY SDL_INCLUDE_DIR)
-- Configuring done
-- Generating done
-- Build files have been written to: /home/i11/staudt/workspace/clutbb/cluster/build
But then the linker step fails:
staudt ~/workspace/clutbb/cluster/build $ make
[ 69%] Built target cluster
Linking CXX executable clu
CMakeFiles/clu.dir/clu.cpp.o: In function `initCUDA(int&, CUctx_st*&, int const&)':
clu.cpp:(.text+0x517): undefined reference to `cuInit'
clu.cpp:(.text+0x52b): undefined reference to `cuDeviceGet'
clu.cpp:(.text+0x53f): undefined reference to `cuCtxCreate_v2'
clu.cpp:(.text+0x559): undefined reference to `cuDeviceGetName'
clu.cpp:(.text+0x55e): undefined reference to `cuCtxSynchronize'
CMakeFiles/clu.dir/clu.cpp.o: In function `exitCUDA(int&, CUctx_st*&)':
clu.cpp:(.text+0x684): undefined reference to `cuCtxDestroy_v2'
CMakeFiles/clu.dir/clu.cpp.o: In function `main':
clu.cpp:(.text.startup+0x1092): undefined reference to `cuCtxDestroy_v2'
clu.cpp:(.text.startup+0x10d1): undefined reference to `cuCtxSynchronize'
clu.cpp:(.text.startup+0x10e1): undefined reference to `cuCtxSynchronize'
collect2: error: ld returned 1 exit status
make[2]: *** [bin/clu] Fehler 1
make[1]: *** [bin/CMakeFiles/clu.dir/all] Fehler 2
make: *** [all] Fehler 2
The required library is at /usr/local/cuda/lib64/stubs/libcuda.so, but how can I point that out to cmake or make?
In the archive you have now posted, there are multiple project hierarchies. The actual error you have posted in the question is occurring during compile and linking of the clu project based on clu.cpp in the clutbb/cluster/bin directory.
In this same directory, there is a CMakeLists.txt file. This file governs this particular level of the project hierarchy.
In this particular CMakeLists.txt file, there is the following section:
cuda_add_executable(clu clu.cpp)
target_link_libraries(clu ${CUDA_LIBRARY} ${TBB_LIBRARY} ${Boost_LIBRARIES} rt)
target_link_libraries(clu cluster)
Try modifying the middle line above to:
target_link_libraries(clu ${CUDA_LIBRARY} ${TBB_LIBRARY} ${Boost_LIBRARIES} rt cuda)
This should fix the missing -lcuda in the linker command line. It may still be necessary to give it the path to libcuda.so on your machine, but it may not be necessary, depending on how your machine environment is set up.
The correct way of doing this on CMake 3.17+ is to use the FindCUDAToolkit module, like so:
find_package(CUDAToolkit REQUIRED)
target_link_libraries(my_target PRIVATE CUDA::cudart CUDA::cuda_driver)
The CUDA::cuda_driver target is equivalent to -lcuda when the linker would find it, and is otherwise an absolute path to the correct library. You should avoid adding system libraries via target_link_libraries to ensure portability.
If you have an older version (CMake 3.0+), you can use the (now-deprecated) FindCUDA module to imitate the 3.17 module, like so:
find_package(CUDA REQUIRED)
# Do what the new package does
find_library(CUDA_DRIVER_LIBRARY
NAMES cuda_driver cuda
HINTS ${CUDA_TOOLKIT_ROOT_DIR}
ENV CUDA_PATH
PATH_SUFFIXES nvidia/current lib64 lib/x64 lib)
if (NOT CUDA_DRIVER_LIBRARY)
# Don't try any stub directories until we have exhausted all other search locations.
find_library(CUDA_DRIVER_LIBRARY
NAMES cuda_driver cuda
HINTS ${CUDA_TOOLKIT_ROOT_DIR}
ENV CUDA_PATH
PATH_SUFFIXES lib64/stubs lib/x64/stubs lib/stubs stubs)
endif ()
mark_as_advanced(CUDA_DRIVER_LIBRARY)
##
target_include_directories(my_target PRIVATE ${CUDA_INCLUDE_DIRS})
target_link_libraries(my_target PRIVATE ${CUDA_LIBRARIES} ${CUDA_DRIVER_LIBRARY})
This is adapted from the official sources, here.
The C++ file with host calls doesnt know it needs to link to libcudart. You have to explicitly set dependencies for the file/binary that file is in, eg.
target_link_libraries(clu ${CUDA_LIBRARIES})
The above response is slightly wrong. It looks like libcuda.so is installed in unexpected location for whatever reason. You can try setting CMAKE_LIBRARY_PATH or/and CUDA_LIB_PATH to that path.
The CUDA_LIB_PATH needs to be set outside cmake I think, eg export CUDA_LIB_PATH=/usr/local/cuda/lib64/stubs/