I have been trying to write a simple program, which simply storage a structure of vector and integer, and read it back later. The code is shown as below:
#include <iostream>
#include <string>
#include <fstream>
#include <queue>
#include <vector>
#include <boost/serialization/vector.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
using namespace std;
struct testS
{
int num1;
vector<int> num2;
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & num1;
ar & num2;
}
};
int main()
{
std::queue<std::string> files;
for(int i = 0;i<50;i++){
testS t1 = testS();
t1.num1=i;
for(int k=0;k<10;k++){
t1.num2.push_back(k);
}
std::string fileName = std::to_string(i)+".test";
std::ofstream tempSaveFile(fileName);
boost::archive::text_oarchive oa(tempSaveFile);
oa<<t1;
files.push(fileName);
}
for (int i=0;i<50;i++){
std::string curRecName =files.front();
std::cout<<"file name: "<<curRecName<<std::endl;
std::ifstream input_file(curRecName);
testS curRec;
boost::archive::text_iarchive ia(input_file);
ia>>curRec;
for(int k=0;k<10;k++){
std::cout<<curRec.num2[k];
}
std::cout<<'\n';
std::remove(&curRecName[0]);
files.pop();
}
}
However, the above cannot even compile since there is some problem with my CMakeLists.txt
cmake_minimum_required(VERSION 3.0.0)
project(RecorderTest)
set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -pthread -lboost_serialization" ) #you can set with add_definitions("-Wall -std=c+11, etc")
set(Boost_INCLUDE_DIR /home/lowlimb/Downloads/boost_1_70_0)
set(Boost_LIBRARY_DIR /home/lowlimb/Downloads/boost_1_70_0/stage/lib)
find_package(Boost 1.70.0 COMPONENTS system filesystem REQUIRED)
include_directories(
include
src
${Boost_INCLUDE_DIR}
)
add_library(
recLib
include/Recorder.hpp
include/Recorder.cpp
)
link_directories(${Boost_LIBRARY_DIR})
enable_testing()
add_executable(rec_o src/main.cpp )
target_link_libraries(rec_o PRIVATE recLib ${Boost_LIBRARIES})
The result I get is
CMake Warning at /usr/share/cmake-3.10/Modules/FindBoost.cmake:801 (message):
New Boost version may have incorrect or missing dependencies and imported
targets
Call Stack (most recent call first):
/usr/share/cmake-3.10/Modules/FindBoost.cmake:907 (_Boost_COMPONENT_DEPENDENCIES)
/usr/share/cmake-3.10/Modules/FindBoost.cmake:1558 (_Boost_MISSING_DEPENDENCIES)
CMakeLists.txt:6 (find_package)
CMake Warning at /usr/share/cmake-3.10/Modules/FindBoost.cmake:801 (message):
New Boost version may have incorrect or missing dependencies and imported
targets
Call Stack (most recent call first):
/usr/share/cmake-3.10/Modules/FindBoost.cmake:907 (_Boost_COMPONENT_DEPENDENCIES)
/usr/share/cmake-3.10/Modules/FindBoost.cmake:1558 (_Boost_MISSING_DEPENDENCIES)
CMakeLists.txt:6 (find_package)
-- Boost version: 1.70.0
-- Found the following Boost libraries:
-- system
-- filesystem
-- Configuring done
-- Generating done
-- Build files have been written to: /home/lowlimb/cdrive/UCLA/lab/Exoskeleton/Controller/Test/TestPtr/Final/build
[ 25%] Building CXX object CMakeFiles/recLib.dir/include/Recorder.cpp.o
[ 50%] Linking CXX static library librecLib.a
[ 50%] Built target recLib
[ 75%] Building CXX object CMakeFiles/rec_o.dir/src/main.cpp.o
[100%] Linking CXX executable rec_o
CMakeFiles/rec_o.dir/src/main.cpp.o: In function `boost::archive::text_oarchive::text_oarchive(std::ostream&, unsigned int)':
main.cpp:(.text._ZN5boost7archive13text_oarchiveC2ERSoj[_ZN5boost7archive13text_oarchiveC5ERSoj]+0x25): undefined reference to `boost::archive::text_oarchive_impl<boost::archive::text_oarchive>::text_oarchive_impl(std::ostream&, unsigned int)'
CMakeFiles/rec_o.dir/src/main.cpp.o: In function `boost::archive::text_iarchive::text_iarchive(std::istream&, unsigned int)':
main.cpp:(.text._ZN5boost7archive13text_iarchiveC2ERSij[_ZN5boost7archive13text_iarchiveC5ERSij]+0x25): undefined reference to `boost::archive::text_iarchive_impl<boost::archive::text_iarchive>::text_iarchive_impl(std::istream&, unsigned int)'
CMakeFiles/rec_o.dir/src/main.cpp.o: In function `boost::archive::text_oarchive_impl<boost::archive::text_oarchive>::~text_oarchive_impl()':
main.cpp:(.text._ZN5boost7archive18text_oarchive_implINS0_13text_oarchiveEED2Ev[_ZN5boost7archive18text_oarchive_implINS0_13text_oarchiveEED5Ev]+0x32): undefined reference to `boost::archive::basic_text_oprimitive<std::ostream>::~basic_text_oprimitive()'
CMakeFiles/rec_o.dir/src/main.cpp.o: In function `boost::archive::text_iarchive_impl<boost::archive::text_iarchive>::~text_iarchive_impl()':
This is just part of the output, yet the rest are in similar pattern. I wonder did I made any mistake in CMakeLists.txt? I can assure the paths are 100% correct, no typo there.
Your find_package statement is missing boost::serialization in the required components:
find_package(Boost 1.70.0 COMPONENTS system filesystem serialization REQUIRED)
Related
I am trying to compile a simple C++ program with CMake, but I am getting a linker error :
[2/2] Linking CXX executable bin/MY_PROGRAM
FAILED: bin/MY_PROGRAM
: && g++ -g CMakeFiles/MY_PROGRAM.dir/src/main.cpp.o -o bin/MY_PROGRAM && :
/usr/bin/ld: CMakeFiles/MY_PROGRAM.dir/src/main.cpp.o: in function `main':
/home/user/Code/root/src/main.cpp:27: undefined reference to `str_toupper(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)'
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.
I have tried looking at some questions with similar issues but couldn't find what I did wrong. There must be a problem with my directory structure and CMake files. I could change the directory structure to make things easier, but I may be missing something important and I'd like to figure out why. Also, I am new to C++ so I might be doing something wrong in the code itself, but my IDE doesn't find any issue.
My directory structure is :
root
|-- CMakeLists.txt
|-- src
|-- main.cpp
|-- utils
|-- CMakeLists.txt
|-- src
|-- strutils.cpp
|-- include
|-- strutils.h
The top-level CMakeLists.txt is :
// general stuff (standard, etc...)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY bin)
set(MY_PROGRAM_SRC src/main.cpp)
add_executable(MY_PROGRAM ${MY_PROGRAM_SRC})
include_directories(utils/include)
link_libraries(MY_LIBRARY)
and utils/CMakeLists.txt :
set(MY_LIBRARY_SRC include/strutils.h src/strutils.cpp)
add_library(MY_LIBRARY STATIC ${MY_LIBRARY_SRC})
// This is to include strutils.h in strutils.cpp
// (but is it needed ? I could just #include <string> in strutils.cpp, I guess)
target_include_directories(MY_LIBRARY PUBLIC include)
Finally, the source files :
// strutils.h
#include <string>
void str_toupper(const std::string &in, std::string &out);
// strutils.cpp
#include <algorithm>
#include <strutils.h>
void str_toupper(const std::string &in, std::string &out) {
std::transform(in.begin(), in.end(), out.begin(), [](char c){return std::toupper(c);});
}
// main.cpp
#include <strutils.h>
#include <cstdlib>
#include <cstdio>
#include <string>
int main(int argc, char *argv[]) {
// ...
std::string arg_in;
for (int i = 0; i < argc; i++) {
str_toupper(std::string(argv[i]), arg_in);
}
}
Does anyone have an idea of what's going on ? Thanks !
The first sentence in the manual link_libraries
Link libraries to all targets added later.
You use this directive after the target MY_PROGRAM is added - the target MY_PROGRAM is added prior link_libraries.
Prefer use target_link_libraries(MY_PROGRAM MY_LIBRARY) - other targets can require different dependencies and it's better not use a global set of dependencies for all targets.
I am trying to have a member array in a class with its length specified by the const static int variable for future needs.
My compiler throws an error with it, and I am not sure this is an error about a uniform initialization or array initialization, or both.
Here is the header file:
#ifndef SOUECE_H
#define SOURCE_H
class Test
{
public:
Test();
static const int array_length{2};
double array[array_length];
};
#endif
This is the source file.
#include "source.h"
Test::Test()
:array_length{0} //Typo of array{0}
{
}
These are the problem messages.
[enter image description here][1]
[1]: https://i.stack.imgur.com/IQ2Mk.png
This is the CMake file.
cmake_minimum_required(VERSION 3.0.0)
project(temp VERSION 0.1.0)
include(CTest)
enable_testing()
add_executable(temp main.cpp)
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)
Finally, these are what the compiler is complaining about when I try to build the project.
[main] Building folder: temp
[build] Starting build
[proc] Executing command: /usr/local/bin/cmake --build /Users/USERNAME/Desktop/temp/build --config Debug --target all -j 14 --
[build] [1/2 50% :: 0.066] Building CXX object CMakeFiles/temp.dir/main.cpp.o
[build] FAILED: CMakeFiles/temp.dir/main.cpp.o
[build] /usr/bin/clang++ -g -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk -MD -MT CMakeFiles/temp.dir/main.cpp.o -MF CMakeFiles/temp.dir/main.cpp.o.d -o CMakeFiles/temp.dir/main.cpp.o -c ../main.cpp
[build] In file included from ../main.cpp:1:
[build] ../source.h:8:22: error: function definition does not declare parameters
[build] static const int array_length{2};
[build] ^
[build] ../source.h:9:18: error: use of undeclared identifier 'array_length'
[build] double array[array_length];
[build] ^
[build] 2 errors generated.
[build] ninja: build stopped: subcommand failed.
[build] Build finished with exit code 1
I am using macOS 12.0 beta, with VS Code 1.60.2, clang 13.0.0, CMake 3.20.2.
Please let me know if you see any wrong or have any suggestions.
This cannot work:
Test::Test()
:array_length{0}
You cannot set a const static data member in your constructor. A static value has the same value accross all object instances. But as it is also const no instance is allowed to change the value.
Since array_length is static const you have to initialize it like this:
source.h
#ifndef SOUECE_H
#define SOURCE_H
class Test
{
public:
Test();
static const int array_length = 2;
//static const int array_length{2}; this will also work just note that we cannot use constructor initializer list to initialize static data members
double array[array_length];
};
#endif
source.cpp
#include "source.h"
Test::Test()//we cannot use constructor initializer list to initialize array_length
{
}
Note that static const int array_length{2}; will also work but the thing is that in the constructor we cannot use constructor initializer list to initialize static data member.
EDIT:
If you decide to use static const int array_length{2}; then make sure that you have C++11(or later) enabled in your CMakeLists.txt. For this you can add
set (CMAKE_CXX_STANDARD 11)
to your CMakeLists.txt.
Alternatively, you could instead add
target_compile_features(targetname PUBLIC cxx_std_11)
in your CMakeLists.txt. In your case replace targetname with temp since that is the targetname that you have. Check this out for more how to active C++11 in CMake .
Good day,
here is my code
#include <iostream>
#include <Magick++.h>
using namespace std;
using namespace Magick;
int main(int argc, char **argv) {
InitializeMagick(*argv);
Image image;
try {
image.read(argv[1]);
}
catch( Exception &error_ ) {
cout << "Caught exception: " << error_.what() << endl;
return 1;
}
int x = image.columns();
cout<<"your picture's width is "<< x << "px"<<endl;
return 0;
}
I use KDevelop(which uses CMake as builder),
when I try to compile the app, it throws me an error
main.cpp:25: undefined reference to `Magick::Image::columns() const'
Here's what my CMakeLists.txt contains.
cmake_minimum_required(VERSION 3.5)
project(hello)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES main.cpp)
add_executable(hello ${SOURCE_FILES})
add_definitions( -DMAGICKCORE_QUANTUM_DEPTH=16 )
add_definitions( -DMAGICKCORE_HDRI_ENABLE=0 )
find_package(ImageMagick COMPONENTS Magick++)
include_directories(${ImageMagick_INCLUDE_DIRS})
target_link_libraries(hello ${ImageMagick_LIBRARIES})
I figured out that there're often issues with undefined references when CMakeLists isn't written correctly, but I made it according to this About Magick++, how to write the CMakeLists?
where am I wrong? I can add any information needed.
UPD 1.
version of magick++,
8:6.8.9.9-7ubuntu5.7
system info:
Description: Linux Mint 18.1 Serena
UPD 2.
I just removed parenthesis and when tryed to compile with
size_t x = image.columns;
size_t y = image.rows;
KDevelop threw me
main.cpp:25:22: error: cannot convert ‘Magick::Image::columns’ from type ‘size_t (Magick::Image::)() const {aka long unsigned int (Magick::Image::)() const}’ to type ‘size_t {aka long unsigned int}’
even when
auto x = image.columns;
auto y = image.rows;
it throws
main.cpp:25:20: error: cannot convert ‘Magick::Image::columns’ from
type ‘size_t (Magick::Image::)() const {aka long unsigned int
(Magick::Image::)() const}’ to type ‘long unsigned int
(Magick::Image::*)() const’
what's happening?
P.S. hooray, this is my first question on stackoverflow! :-)
If you are able to compile your program without CMake using g++ main.cpp `Magick++-config --cxxflags --cppflags --ldflags --libs` (but for some reason cannot use ${ImageMagick_LIBRARIES} in CMake), then you can make use of Magick++-config in your CMakeLists.txt:
cmake_minimum_required(VERSION 3.5)
project(hello LANGUAGES CXX)
add_executable(hello main.cpp)
target_compile_features(hello PRIVATE cxx_std_11)
find_package(ImageMagick REQUIRED COMPONENTS Magick++)
target_compile_definitions(hello PRIVATE
MAGICKCORE_QUANTUM_DEPTH=16
MAGICKCORE_HDRI_ENABLE=0
)
target_include_directories(hello PRIVATE ${ImageMagick_INCLUDE_DIRS})
execute_process(COMMAND Magick++-config --ldflags
OUTPUT_VARIABLE ImageMagick_LINK_FLAGS
OUTPUT_STRIP_TRAILING_WHITESPACE
)
target_link_libraries(hello PRIVATE ${ImageMagick_LINK_FLAGS})
Here, execute_process allows us to get the result of Magick++-config --ldflags into a variable, which we can pass as flags to the linker through target_link_libraries.
Also, note how I've used target_compile_features rather than setting the global CMAKE_CXX_FLAGS variable, target_compile_definitions rather than add_definitions and target_include_directories rather than include_directories. It's better to use local (target-based) commands rather than modifying global state, both in programming and in CMake, since they can have unforeseen repercussions down the line -- in the context of CMake, those global commands would have affected nested sub-projects.
ForgottenUbrella 's version which I adapted didn't quite work for me, copying a line in from another project fixed it. Note, I'm using c++20 not 11.
I had the following error:
..... undefined reference to symbol 'pthread_create##GLIBC_2.2.5'
and the line that fixed it:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++2a -pthread")
I am trying to compile simple gmock example on my ubuntu vmware(16.04 LTS)
and getting below error while doing "make"
I have below files -
"test.h"
class CBasicMath
{
public:
CBasicMath(){}
virtual ~CBasicMath() {}
virtual int Addition(int x, int y);
virtual int Multiply(int x, int y);
virtual int Divide(int x, int y);
};
"test.cpp"
#include "test.h"
int CBasicMath::Addition(int x, int y)
{
return (x + y);
}
int CBasicMath::Multiply(int x, int y)
{
return (x * y);
}
int CBasicMath::Divide(int x, int y)
{
return (x / y);
}
"mocktest.h"
#include "gmock/gmock.h"
#include "test.cpp"
class MockBasicTest : public CBasicMath {
public:
MOCK_METHOD2(Addition, int(int x, int y));
MOCK_METHOD2(Multiply, int(int x, int y));
MOCK_METHOD2(Divide, int(int x, int y));
};
"main.cpp"
#include "mocktest.h"
#include "gtest/gtest.h"
#include "gmock/gmock.h"
TEST(BasicMathTest, testAddition) {
MockBasicTest basictest;
EXPECT_CALL(basictest, Addition(2,3)).Times(0);
// EXPECT_EQ(0, basictest.Addition(2,3));
/*
.Times(5);
EXPECT_EQ(0,basictest.Addition(2,3));
EXPECT_EQ(0,basictest.Addition(2,3));
EXPECT_EQ(0,basictest.Addition(2,3));
EXPECT_EQ(0,basictest.Addition(2,3));
EXPECT_EQ(0,basictest.Addition(2,3));
*/
}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
"CMakeLists.txt"
cmake_minimum_required(VERSION 2.6)
# Locate GTest
find_package(GTest REQUIRED)
include_directories(${GTEST_INCLUDE_DIRS})
# Link runTests with what we want to test and the GTest and pthread library
add_executable(runTests main.cpp)
target_link_libraries(runTests -lgtest -lgmock -lpthread)
These are the steps I followed for compilation -
ajay#ubuntu:~/Desktop/for_gtest/ajay/gtest/ajay/demo/gmock/simple_demo$ cmake CMakeLists.txt
-- Configuring done
-- Generating done
-- Build files have been written to: /home/ajay/Desktop/for_gtest/ajay/gtest/ajay/demo/gmock/simple_demo
ajay#ubuntu:~/Desktop/for_gtest/ajay/gtest/ajay/demo/gmock/simple_demo$
and after that When I did make I am facing the issue
ajay#ubuntu:~/Desktop/for_gtest/ajay/gtest/ajay/demo/gmock/simple_demo$ make
Scanning dependencies of target runTests
make[2]: Warning: File 'main.cpp' has modification time 84978 s in the future
[ 50%] Building CXX object CMakeFiles/runTests.dir/main.cpp.o
[100%] Linking CXX executable runTests
/usr/bin/ld: cannot find -lgmock
collect2: error: ld returned 1 exit status
CMakeFiles/runTests.dir/build.make:94: recipe for target 'runTests' failed
make[2]: *** [runTests] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/runTests.dir/all' failed
make[1]: *** [CMakeFiles/runTests.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
ajay#ubuntu:~/Desktop/for_gtest/ajay/gtest/ajay/demo/gmock/simple_demo$
I don't know why this "/usr/bin/ld: cannot find -lgmock" issue is coming even though I have installed gmock successfully.
I am able to run gtest programs but when I am adding gmock I am getting this issue.
Please help me to resolve.
Let me know for more info.
Lookup the documentation for taget_link_libraries. Check the comments in FindGtest.cmake
You should not specify libraries them with -l instead use the variables from find_package e.g. ${GTEST_LIBRARIES}
You haven't done find_package for GMOCK so there are no variables defined for GMOCK. As this is not a standard CMake module, write your own or take one from the Internet
BUT, the Google test documentation recommends not use the installed libraries from the system, but to build them yourself inside your Project.There are several examples on the internet how to add gtest/gmock as ExternalProject to your cmake project.
I'm running the basic OpenCV example with OpenCV3.0.0 dev:
project(ImageDenoise)
cmake_minimum_required(VERSION 2.8)
aux_source_directory(. SRC_LIST)
find_package(OpenCV REQUIRED)
include_directories( ${OpenCV_INCLUDE_DIRS} )
add_executable(${PROJECT_NAME} ${SRC_LIST})
target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS})
MESSAGE(${OpenCV_LIBS})
MESSAGE(${OpenCV_INCLUDE_DIRS})
Source code:
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;
int main(int argc, char* argv[] )
{
if ( argc != 2 )
{
printf("usage: DisplayImage.out <Image_Path>\n");
return -1;
}
Mat image;
image = imread( argv[1], IMREAD_COLOR );
if ( !image.data )
{
printf("No image data \n");
return -1;
}
namedWindow("Display Image", WINDOW_AUTOSIZE );
imshow("Display Image", image);
waitKey(0);
return 0;
}
When I import this project into QtCreator, I got the following linking errors when building project:
[100%] Building CXX object CMakeFiles/ImageDenoise.dir/main.cpp.o
Linking CXX executable ImageDenoise
CMakeFiles/ImageDenoise.dir/main.cpp.o: In function `main':
main.cpp:(.text+0x7c): undefined reference to `cv::imread(cv::String const&, int)'
main.cpp:(.text+0xf5): undefined reference to `cv::namedWindow(cv::String const&, int)'
main.cpp:(.text+0x144): undefined reference to `cv::imshow(cv::String const&, cv::_InputArray const&)'
However when I run cmake from command line and using make, then it works perfectly. What is the reason behind this?
dzung#Cronus:~/kSVD/build$ make
Scanning dependencies of target ImageDenoise
[100%] Building CXX object CMakeFiles/ImageDenoise.dir/main.cpp.o
Linking CXX executable ImageDenoise
[100%] Built target ImageDenoise
dzung#Cronus:~/kSVD/build$ ls
CMakeCache.txt CMakeFiles cmake_install.cmake ImageDenoise Makefile
dzung#Cronus:~/kSVD/build$ ./ImageDenoise
usage: DisplayImage.out <Image_Path>
I had exactly the same issue. I think this is some sort of a Qt-creator bug.
I solved this by:
Remove everything except *.cpp and CMakeLists.txt in the project
folder.
Before creating anything with Qt-creator do: cmake . && make
Now open existing project in Qt-creator.
Now you can run cmake/compile/run etc just fine.