I am using FANN (http://leenissen.dk/fann/wp/download/). Both headers are available in the archive that you can download there (I hope I don't create too much trouble for you).
/*
* File: main.cpp
* Author: johannsebastian
*
* Created on November 26, 2013, 8:50 PM
*/
#include "../FANN-2.2.0-Source/src/include/doublefann.h"
#include "../FANN-2.2.0-Source/src/include/fann_cpp.h"
#include <cstdlib>
#include <iostream>
using namespace std;
using namespace FANN;
/*
*
*/
//Remember: fann_type is double!
int main(int argc, char** argv) {
neural_net * N = new neural_net;
const unsigned int myLayerArray[4] = {1,2,2,1};
const unsigned int numLayers = 4;
N->create_standard(3,1,2,1);
cout<<"Easy!";
return 0;
}
g++ says
"/usr/bin/make" -f nbproject/Makefile-Debug.mk QMAKE= SUBPROJECTS= .build-conf
make[1]: Entering directory `/home/johannsebastian/Desktop/heatmap3d/BACHnet/BACHnet'
"/usr/bin/make" -f nbproject/Makefile-Debug.mk dist/Debug/GNU-Linux-x86/bachnet
make[2]: Entering directory `/home/johannsebastian/Desktop/heatmap3d/BACHnet/BACHnet'
mkdir -p build/Debug/GNU-Linux-x86
rm -f "build/Debug/GNU-Linux-x86/main.o.d"
g++ -c -g -MMD -MP -MF "build/Debug/GNU-Linux-x86/main.o.d" -o build/Debug/GNU-Linux-x86/main.o main.cpp
mkdir -p dist/Debug/GNU-Linux-x86
g++ -o dist/Debug/GNU-Linux-x86/bachnet build/Debug/GNU-Linux-x86/main.o
build/Debug/GNU-Linux-x86/main.o: In function `FANN::neural_net::destroy()':
/home/johannsebastian/Desktop/heatmap3d/BACHnet/BACHnet/../FANN-2.2.0-Source/src/include/fann_cpp.h:915: undefined reference to `fann_get_user_data'
/home/johannsebastian/Desktop/heatmap3d/BACHnet/BACHnet/../FANN-2.2.0-Source/src/include/fann_cpp.h:919: undefined reference to `fann_destroy'
build/Debug/GNU-Linux-x86/main.o: In function `FANN::neural_net::create_standard_array(unsigned int, unsigned int const*)':
/home/johannsebastian/Desktop/heatmap3d/BACHnet/BACHnet/../FANN-2.2.0-Source/src/include/fann_cpp.h:979: undefined reference to `fann_create_standard_array'
collect2: error: ld returned 1 exit status
make[2]: *** [dist/Debug/GNU-Linux-x86/bachnet] Error 1
make[2]: Leaving directory `/home/johannsebastian/Desktop/heatmap3d/BACHnet/BACHnet'
make[1]: *** [.build-conf] Error 2
make[1]: Leaving directory `/home/johannsebastian/Desktop/heatmap3d/BACHnet/BACHnet'
make: *** [.build-impl] Error 2
BUILD FAILED (exit value 2, total time: 773ms)
Can you help me fix this? I think I might have some basic compiler config wrong or something.
The compiler has compiled your code. The includes are really work. (But you don't have to specify full path there, just the name of the header, if the library is installed correctly).
This is the linker (ld) who can't find the method.
The linker problems about whether you have library with the method definition and give it to the linker (in its options) when you call it.
You use make file, so you have to specify options (something like -lFANN) and path to the library there (like -L/path/path/path. The path you also can specified in $LD_LIBRARY_PATH system variable, then you don't need -L option). Also you have to install (compile) the library itself before to use it. You have installation guide here.
The guide works for me:
Download the FANN-2.2.0-Source.
Install it with cmake:
[08:42:24]~/Downloads$ cd FANN-2.2.0-Source/
[08:42:27]~/Downloads/FANN-2.2.0-Source$ ls
CMakeLists.txt README.txt bin datasets src
COPYING.txt VS2010 cmake examples
[08:42:27]~/Downloads/FANN-2.2.0-Source$ cmake .
-- The C compiler identification is GNU 4.7.3
-- The CXX compiler identification is GNU 4.7.3
-- 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: /opt/local/bin/gcc
-- Check for working C compiler: /opt/local/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - 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: /<...>g++
-- Check for working CXX compiler: /<...>g++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- FANN is used as APPLICATION_NAME
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/ikulakov/Downloads/FANN-2.2.0-Source
[08:43:57]~/Downloads/FANN-2.2.0-Source$ make
Scanning dependencies of target doublefann
[ 25%] Building C object src/CMakeFiles/doublefann.dir/doublefann.c.o
Linking C shared library libdoublefann.dylib
[ 25%] Built target doublefann
Scanning dependencies of target fann
[ 50%] Building C object src/CMakeFiles/fann.dir/floatfann.c.o
Linking C shared library libfann.dylib
[ 50%] Built target fann
Scanning dependencies of target fixedfann
[ 75%] Building C object src/CMakeFiles/fixedfann.dir/fixedfann.c.o
Linking C shared library libfixedfann.dylib
[ 75%] Built target fixedfann
Scanning dependencies of target floatfann
[100%] Building C object src/CMakeFiles/floatfann.dir/floatfann.c.o
Linking C shared library libfloatfann.dylib
[100%] Built target floatfann
[08:44:02]~/Downloads/FANN-2.2.0-Source$ sudo make install
In your case, not the Compiler, but the Linker fails to find the function.
The compiler is what you satisfy with including the files containing the declarations of the functions you use, and specifying the directory for the included files.
The linker wants to see the actual library containing the compiled definition of the code.
You probably have to specify -lfann on the linker command line (for the exact name to use after -l, refer to what the library is actually called - if it is called libfann.so, use above parameter).
In case the library is installed in the default directories, thish should be enough; otherwise you might also need the -L parameter pointing to the path containing the library (and the library would have to be compiled first, of course).
Related
I am starting to work my way through CGAL and have a question about the Algebraic foundations package.
How do you use the square function defined here?
I tried the following
// tmp.cpp
#include <CGAL/number_utils.h>
int main() {
double dist = 0.002;
auto sq_dist = CGAL::square(dist);
return 0;
}
The compiler throws the following error message
$ make tmp
Consolidate compiler generated dependencies of target tmp
[ 14%] Building CXX object CMakeFiles/tmp.dir/tmp.cpp.o
In file included from /home/USER/info/cgal/tmp/tmp.cpp:1:
/home/USER/info/cgal/Algebraic_foundations/include/CGAL/number_utils.h: In instantiation of ‘typename CGAL::Algebraic_structure_traits<Type_>::Square::result_type CGAL::square(const AS&) [with AS = double; typename CGAL::Algebraic_structure_traits<Type_>::Square::result_type = CGAL::Null_tag; typename CGAL::Algebraic_structure_traits<Type_>::Square = CGAL::Null_functor]’:
/home/USER/info/cgal/tmp/tmp.cpp:5:30: required from here
/home/USER/info/cgal/Algebraic_foundations/include/CGAL/number_utils.h:71:18: error: no match for call to ‘(CGAL::Algebraic_structure_traits<double>::Square {aka CGAL::Null_functor}) (const double&)’
71 | return square( x );
| ~~~~~~^~~~~
make[3]: *** [CMakeFiles/tmp.dir/build.make:146: CMakeFiles/tmp.dir/tmp.cpp.o] Error 1
make[2]: *** [CMakeFiles/Makefile2:83: CMakeFiles/tmp.dir/all] Error 2
make[1]: *** [CMakeFiles/Makefile2:90: CMakeFiles/tmp.dir/rule] Error 2
make: *** [Makefile:124: tmp] Error 2
It is mentioned in this github issue.
Update: Following the comment by #MarcGlisse I changed the header include to
// tmp.cpp
#include <CGAL/number_utils.h>
#include <CGAL/basic.h>
int main() {
double dist = 0.002;
auto sq_dist = CGAL::square(dist);
return 0;
}
Compilation runs through smoothly but linking throws new errors
$ make tmp
[ 14%] Building CXX object CMakeFiles/tmp.dir/tmp.cpp.o
[ 28%] Linking CXX executable tmp
/usr/bin/ld: CMakeFiles/tmp.dir/tmp.cpp.o: in function `main':
/home/USER/info/cgal/STL_Extension/include/CGAL/exceptions.h:88: multiple definition of `main'; /usr/bin/ld: DWARF error: section .debug_str is larger than its filesize! (0x32f0bc2 vs 0x2447b28)
/usr/bin/ld: DWARF error: section .debug_str is larger than its filesize! (0x32f0bc2 vs 0x2447b28)
/usr/bin/ld: DWARF error: section .debug_str is larger than its filesize! (0x32f0bc2 vs 0x2447b28)
...
The referenced line STL_Extension/include/CGAL/exceptions.h:88 can be found here.
Update: I found the issue (see my answer) but it doesnt make sense to me. Why am I not able to have multiple main functions in different files in the same folder?
I built the following way
cd ${CGAL_DIR}/tmp
cgal_create_CMakeLists -s tmp
cmake -DCMAKE_BUILD_TYPE=Debug .
make tmp
The following example (cgal_ex.cpp) works for me:
#include <iostream>
#include <CGAL/Simple_cartesian.h>
typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_2 Point_2;
int main()
{
Point_2 p(0,0), q(3,4);
std::cout << "p = " << p << std::endl;
std::cout << "q = " << q.x() << " " << q.y() << std::endl;
std::cout << "sqdist(p,q) = "
<< CGAL::squared_distance(p,q) << std::endl;
return 0;
}
g++ cgal_ex.cpp; a.out
p = 0 0
q = 3 4
sqdist(p,q) = 25
Reference: [https://doc.cgal.org/latest/Manual/tutorial_hello_world.html][1]
Adding example of a Makefile for two files having main in the same directory:
MODULES=cgal_ex cgal_ex1
%: %.cpp
g++ -O2 -o $# $<
strip $#
%: %.c
gcc -o $# $<
strip $#
clean:
-rm -rf $(MODULES)
all: $(MODULES)
Usage example:
make all -f Makefile.cgal
g++ -O2 -o cgal_ex cgal_ex.cpp
strip cgal_ex
g++ -O2 -o cgal_ex1 cgal_ex1.cpp
strip cgal_ex1
Usage example with cgal_create_CMakeLists.
Source: https://github.com/CGAL/releases/blob/main/scripts/cgal_create_CMakeLists
Usage example:
Create new directory, which has 3 files only:
cgal_create_CMakeLists cgal_ex.cpp cgal_ex1.cpp
Run the following commands:
cmake $PWD
make
Results:
-- The C compiler identification is GNU 9.3.0
-- The CXX compiler identification is GNU 9.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
-- Using header-only CGAL
-- Targetting Unix Makefiles
-- Using /usr/bin/c++ compiler.
-- Found GMP: /usr/lib/x86_64-linux-gnu/libgmp.so
-- Found MPFR: /usr/lib/x86_64-linux-gnu/libmpfr.so
-- Found Boost: /usr/lib/x86_64-linux-gnu/cmake/Boost-1.71.0/BoostConfig.cmake (found suitable version "1.71.0", minimum required is "1.48")
-- Boost include dirs: /usr/include
-- Boost libraries:
-- Using gcc version 4 or later. Adding -frounding-math
-- Found Boost: /usr/lib/x86_64-linux-gnu/cmake/Boost-1.71.0/BoostConfig.cmake (found version "1.71.0")
CMake Warning at /usr/lib/x86_64-linux-gnu/cmake/CGAL/CGAL_enable_end_of_configuration_hook.cmake:99 (message):
=======================================================================
Call Stack (most recent call first):
CMakeLists.txt:9999 (CGAL_run_at_the_end_of_configuration)
-- Configuring done
-- Generating done
-- Build files have been written to: /home/<username>/cgal
Scanning dependencies of target cgal_ex1
[ 25%] Building CXX object CMakeFiles/cgal_ex1.dir/cgal_ex1.cpp.o
[ 50%] Linking CXX executable cgal_ex1
[ 50%] Built target cgal_ex1
Scanning dependencies of target cgal_ex
[ 75%] Building CXX object CMakeFiles/cgal_ex.dir/cgal_ex.cpp.o
[100%] Linking CXX executable cgal_ex
[100%] Built target cgal_ex
[1]: https://doc.cgal.org/latest/Manual/tutorial_hello_world.html
[2]: https://github.com/CGAL/releases/blob/main/scripts/cgal_create_CMakeLists
The issue arises because of the -s tmp argument.
The solution is to call it in either of the following formats
cgal_create_CMakeLists tmp
cgal_create_CMakeLists
The documentation gives an explanation
$ cgal_create_CMakeLists -h
Usage: cgal_create_CMakeLists [-s source] ...
...
-s source If this parameter is given the script will create one single executable for 'source' with all source files; otherwise it creates one executable for each main'ed source.
...
There is no reasonable way to create one executable for files containing multiple main functions.
EDIT 1: verbose make output now included in error, see below as well
I'm currently trying to compile a C++ project with CMake from a different laptop than the one I had been working on before. When I run make after the CMake configuration is done (withouth errors) I get the following error:
$ make
/usr/bin/cmake -S/home/luc/coding/hiwi/peltier-control-panel -B/home/luc/coding/hiwi/peltier-control-panel/build --check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake -E cmake_progress_start /home/luc/coding/hiwi/peltier-control-panel/build/CMakeFiles /home/luc/coding/hiwi/peltier-control-panel/build//CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/home/luc/coding/hiwi/peltier-control-panel/build'
make -f CMakeFiles/sio_client.dir/build.make CMakeFiles/sio_client.dir/depend
make[2]: Entering directory '/home/luc/coding/hiwi/peltier-control-panel/build'
cd /home/luc/coding/hiwi/peltier-control-panel/build && /usr/bin/cmake -E
cmake_depends "Unix Makefiles" /home/luc/coding/hiwi/peltier-control-panel
/home/luc/coding/hiwi/peltier-control-panel /home/luc/coding/hiwi/peltier-control-
panel/build /home/luc/coding/hiwi/peltier-control-panel/build /home/luc/coding/hiwi/peltier-control-
panel/build/CMakeFiles/sio_client.dir/DependInfo.cmake --color=
make[2]: Leaving directory '/home/luc/coding/hiwi/peltier-control-panel/build'
make -f CMakeFiles/sio_client.dir/build.make CMakeFiles/sio_client.dir/build
make[2]: Entering directory '/home/luc/coding/hiwi/peltier-control-panel/build'
[ 6%] Building CXX object CMakeFiles/sio_client.dir/lib/socket.io-client-cpp/src/sio_client.cpp.o
/usr/bin/c++ -DSIMULATION -I/home/luc/coding/hiwi/peltier-control-panel/include
-I/home/luc/coding/hiwi/peltier-control-panel/src
-I/home/luc/coding/hiwi/peltier-control-panel/lib
-I/home/luc/coding/hiwi/peltier-control-panel/lib/websocketpp
-I/home/luc/coding/hiwi/peltier-control-panel/lib/rapidjson/include
-I/home/luc/coding/hiwi/peltier-control-panel/lib/WiringPi/wiringPi
-Wall -Wextra -o3 -std=gnu++11 -MD -MT
CMakeFiles/sio_client.dir/lib/socket.io-client-cpp/src/sio_client.cpp.o
-MF CMakeFiles/sio_client.dir/lib/socket.io-client-cpp/src/sio_client.cpp.o.d
-o CMakeFiles/sio_client.dir/lib/socket.io-client-cpp/src/sio_client.cpp.o
-c /home/luc/coding/hiwi/peltier-control-panel/lib/socket.io-client-cpp/src/sio_client.cpp
cc1plus: error: too many filenames given; type ‘cc1plus --help’ for usage
cc1plus: fatal error: CMakeFiles/sio_client.dir/lib/socket.io-client-cpp/src/sio_client.cpp.d: No such file or directory
compilation terminated.
make[2]: *** [CMakeFiles/sio_client.dir/build.make:79: CMakeFiles/sio_client.dir/lib/socket.io-client-cpp/src/sio_client.cpp.o] Error 1
make[2]: Leaving directory '/home/luc/coding/hiwi/peltier-control-panel/build'
make[1]: *** [CMakeFiles/Makefile2:175: CMakeFiles/sio_client.dir/all] Error 2
make[1]: Leaving directory '/home/luc/coding/hiwi/peltier-control-panel/build'
make: *** [Makefile:94: all] Error 2
On the old laptop the code compiles without a problem (Ubuntu 16), so it must be independent of the code. On this laptop I have Arch installed, which means I have much newer versions of all of the installed compilers and programs. Boost libraries are requried in my project but it seems to fail even before it gets to the point where it starts compiling and linking that so I don't think it's really relevant. I'm including it only for the sake of completeness.
Ubuntu 16:
CMake: 3.15.4
Make: 4.1
g++/gcc: 5.4.0
libboost 1.68.0
Arch:
CMake: 3.21.2
Make: 4.2
g++/gcc: 11.1.0
libboost 1.76.0
I'm not sure this is the reason however, since the only issue I found on the internet that is similar to this has to do with the mingw installation path on Windows, which is certainly not the issue I seem to be facing.
CMake output:
cmake .. -DSIMULATION=TRUE
-- The C compiler identification is GNU 11.1.0
-- The CXX compiler identification is GNU 11.1.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - 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: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
Using simulated temperature data...
-- Found Boost: /usr/lib64/cmake/Boost-1.76.0/BoostConfig.cmake (found version "1.76.0") found components: system
-- Linking against boost shared libraries
-- location of boost libraries
-- Boost::system
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Failed
-- Check if compiler accepts -pthread
-- Check if compiler accepts -pthread - yes
-- Found Threads: TRUE
-- Linking SIMULATION
-- Configuring done
-- Generating done
-- Build files have been written to: /home/luc/coding/hiwi/peltier-control-panel/build
An interesting fact I have observed is that on the Arch laptop the checks for working C/CXX compilers are skipped whereas they aren't for the Ubuntu laptop. However, I am able to compile programs with gcc/g++ so they must in principle be working.
I've never encountered this problem before, and it's not something that a quick search seems to be able to resolve. I'm hoping someone may have had some experience with this at some point and could point me in the right direction. Any help at all would be greatly appreciated, however.
EDIT
#Stephen Newell thank you very much for your comment, I wasn't aware of this trick! (I'm still somewhat new to using make/cmake.)
Okay so I think I've narrowed it down to this: when running the same CMakeLists.txt on both systems they produce varying compilation commands:
Ubuntu 16:
/usr/bin/c++ -DSIMULATION
-I/home/luc/coding/hiwi/peltier-heater/include
-I/home/luc/coding/hiwi/peltier-heater/src
-I/home/luc/coding/hiwi/peltier-heater/lib -I/home/luc/coding/hiwi/peltier-heater/lib/websocketpp
-I/home/luc/coding/hiwi/peltier-heater/lib/rapidjson/include
-Wall -Wextra -o3 -std=gnu++11
-o CMakeFiles/PIDController.dir/src/PIDController.cpp.o
-c /home/luc/coding/hiwi/peltier-heater/src/PIDController.cpp
Arch:
/usr/bin/c++ -DSIMULATION
-I/home/luc/coding/hiwi/peltier-heater/include
-I/home/luc/coding/hiwi/peltier-heater/src
-I/home/luc/coding/hiwi/peltier-heater/lib
-I/home/luc/coding/hiwi/peltier-heater/lib/websocketpp
-I/home/luc/coding/hiwi/peltier-heater/lib/rapidjson/include
-Wall -Wextra -o3 -std=gnu++11
-MT CMakeFiles/PIDController.dir/src/PIDController.cpp.o
-MF CMakeFiles/PIDController.dir/src/PIDController.cpp.o.d
-o CMakeFiles/PIDController.dir/src/PIDController.cpp.o
-c /home/luc/coding/hiwi/peltier-heater/src/PIDController.cpp
Notice the -MF and -MT flags. If I pass the Ubuntu command in the build folder on my Arch system it compiles without error (though obviously it only does that specific step)
Is there any reason in particular why these flags are being generated on one system but not on the other? Can (and should) I turn them off? Or should I maybe change some configuration in my CMakeLists.txt to correct for this?
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>
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.
So I tried to install clang + cmake to compile a simple C++ program and I'm getting the following error:
-- The C compiler identification is GNU 4.8.3
-- The CXX compiler identification is Clang 3.5.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
-- Check for working CXX compiler: /usr/local/bin/clang++
-- Check for working CXX compiler: /usr/local/bin/clang++ -- broken
CMake Error at /usr/share/cmake/Modules/CMakeTestCXXCompiler.cmake:54 (message):
The C++ compiler "/usr/local/bin/clang++" is not able to compile a simple
test program.
It fails with the following output:
Change Dir: /home/jtcwang/tmp/CMake/CMake/CMakeFiles/CMakeTmp
Run Build Command:/usr/bin/gmake "cmTryCompileExec697180971/fast"
/usr/bin/gmake -f CMakeFiles/cmTryCompileExec697180971.dir/build.make
CMakeFiles/cmTryCompileExec697180971.dir/build
gmake[1]: Entering directory
`/home/jtcwang/tmp/CMake/CMake/CMakeFiles/CMakeTmp'
/usr/bin/cmake -E cmake_progress_report
/home/jtcwang/tmp/CMake/CMake/CMakeFiles/CMakeTmp/CMakeFiles 1
Building CXX object
CMakeFiles/cmTryCompileExec697180971.dir/testCXXCompiler.cxx.o
/usr/local/bin/clang++ -o
CMakeFiles/cmTryCompileExec697180971.dir/testCXXCompiler.cxx.o -c
/home/jtcwang/tmp/CMake/CMake/CMakeFiles/CMakeTmp/testCXXCompiler.cxx
Linking CXX executable cmTryCompileExec697180971
/usr/bin/cmake -E cmake_link_script
CMakeFiles/cmTryCompileExec697180971.dir/link.txt --verbose=1
/usr/local/bin/clang++
CMakeFiles/cmTryCompileExec697180971.dir/testCXXCompiler.cxx.o -o
cmTryCompileExec697180971 -rdynamic
/usr/bin/ld: cannot find -lstdc++
clang: error: linker command failed with exit code 1 (use -v to see
invocation)
gmake[1]: Leaving directory
`/home/jtcwang/tmp/CMake/CMake/CMakeFiles/CMakeTmp'
gmake[1]: *** [cmTryCompileExec697180971] Error 1
gmake: *** [cmTryCompileExec697180971/fast] Error 2
It's not even compiling my program because it fails to compile a test program.
Looks like the important line is here:
/usr/bin/ld: cannot find -lstdc++
However, I have checked that libstdc++ is installed and up to date, so at this point I'm quite lost.
Other things I've tried:
Using prebuilt binaries instead of sudo yum install clang
remove and reinstall
Tried clang++ hello.cpp (hello world program). It says <iostreams> is not found. Is clang missing a standard library? EDIT: changing to <iostream> gives me the same linker error above.
I'm not familiar with the clang, cmake and C++ scene in general, so I'd appreciate any pointers. Thanks!
You need the development libraries and headers for C++ library, try
yum install libstdc++-devel
Your /home/gnu/bin/c++ seem to require additional flag to link things properly and CMake doesn't know about that.
To use /usr/bin/c++ as your compiler run cmake with -DCMAKE_CXX_COMPILER=/usr/bin/c++.
Also, CMAKE_PREFIX_PATH variable sets destination dir where your project' files should be installed. It has nothing to do with CMake installation prefix and CMake itself already know this.