Unit testing with QTestLib - c++

I'm trying to unit-testing my Qt application with QTestLib. I saw that the new Visual Studio 2012 has a built-in C++ test framework and googling for it I saw this page that talks about different methods to test a native project. I would have two different projects, one for the normal program and one for the tests. Actually my application is not a DLL but it's a simple C++ exe. Is the best way to test it with another project to link against .obj files or against libs? I wouldn't export anything from the source code as mine is not a DLL

This is a typical QtTest project with three code units: unit1, unit2 and unit3
project/
├── project.pro
├── src
│ ├── main.cpp
│ ├── src.pro
│ ├── unit1.cpp
│ ├── unit1.h
│ ├── unit2.cpp
│ ├── unit2.h
│ ├── unit3.cpp
│ └── unit3.h
└── tests
├── stubs
│ ├── stubs.pro
│ ├── unit1_stub.cpp
│ ├── unit2_stub.cpp
│ └── unit3_stub.cpp
├── test1
│ ├── test1.cpp
│ ├── test1.h
│ └── test1.pro
├── test2
│ ├── test2.cpp
│ ├── test2.h
│ └── test2.pro
├── test3
│ ├── test3.cpp
│ ├── test3.h
│ └── test3.pro
└── tests.pro
This project results in 4 binaries: 1 application itself and three test binaries for testing each of the units. For example, test1 should include src/unit1.cpp, src/unit1.h and also stubbed unit2 and unit3: src/unit2.h, tests/stubs/unit2_stub.cpp, src/unit2.h, tests/stubs/unit3_stub.cpp. With this kind of setup src/unit1.cpp and tests/stubs/unit1_tests.cpp will be compiled twice and this number will grow, if number of units will be larger. This is not a problem for small projects, but for huge projects this may lead to significant increase of build time.
Then splitting unitX.cpp and unitX.h into separate libraries with static linking to main application and each of the tests will eliminate need for building multiple times.

Related

C recursive makefile targets for different build types

I am new to Makefiles and have been trying to get following working with little success. In my project each subdir has:
Release/ dir with a makefile that builds object files into ./Release/Src/ and outputs a dir.so to ../Bin/ (1 for each dir)
Debug/ dir with a makefile that build object files into ./Debug/Src/ and outputs a dir.so to ../Bin/ (1 for each dir)
Src/ dir with source code from which Release or Debug is built
Currently the below Makefile seems to always builds Release/ and not Debug/. I would like a way (or some equivalent) to run something like:
make release - which would recursively run make in the release folders OR
make debug - which would recursively run make in the debug folders
I would like to retain the recursive nature of the makefiles if possible here (I appreciate there is some dispute as to whether this is best practice).
Project structure:
├── Makefile
├── Bin
│ ├── *.so
├── dir1
│ ├── Src
│ │ ├── prog1.cpp
│ │ ├── prog2.cpp
│ ├── Debug
│ │ ├── makefile
│ │ ├── Src
│ │ | ├── *.o
| | | ├── *.d
│ ├── Release
│ │ ├── makefile
│ │ ├── Src
│ │ | ├── *.o
| | | ├── *.d
├── dir2
│ ├── Src
│ │ ├── prog1.cpp
│ │ ├── prog2.cpp
│ ├── Debug
│ │ ├── makefile
│ │ ├── Src
│ │ | ├── *.o
| | | ├── *.d
│ ├── Release
│ │ ├── makefile
│ │ ├── Src
│ │ | ├── *.o
| | | ├── *.d
Top level Makefile:
SUBDIRS := dir1 dir2 dir3 #...
DEBUG_DIRS := $(addsuffix /Debug,$(SUBDIRS))
RELEASE_DIRS := $(addsuffix /Release,$(SUBDIRS))
$(info $(RELEASE_DIRS))
.PHONY: debug release $(DEBUG_DIRS) $(RELEASE_DIRS) $(SUBDIRS)
debug: $(DEBUG_DIRS)
$(DEBUG_DIRS):
$(MAKE) -C $#
release: $(RELEASE_DIRS)
$(RELEASE_DIRS):
$(MAKE) -C $#
If you're compiling with different options, then what you need to do...
Produce different .so files such as Dir-debug.so and Dir-release.so.
Based on .o files found in different directories such as obj-debug/foo.o and obj-release/foo.o
Then you can create generic, nearly identical rules for building both obj-debug/%.o and obj-release/%.o
And after that, nearly identical rules for creating the shared libs.
Using GNU make patsubst() method (substitute) means you can fairly readily do something like this:
ALL_MY_SRC = $(shell find ${SRCDIR} -name "*.cpp" | sort)
DEBUG_OBJ = $patsubst(%.cpp, ${DEBUG_OBJDIR}/%.o, ${ALL_MY_SRC})
RELEASE_OBJ = $patsubst(%.cpp, ${RELEASE_OBJDIR}/%.o, ${ALL_MY_SRC})
Those might not be perfect. You might have to play with them a bit. But that should give you one variable with all the source and 1 each for the two sets of object lists. Then you can make a rule like:
${DEBUG_OBJDIR}/%.o: ${SRCDIR}/%.cpp
g++ ...
Again, play with it.

Linking static libraries in CMake Project - Undefined Reference

I'm trying to refactor some classes from a large main file into separate header and cpp files and am getting undefined reference errors at link time.
I've got a project that looks like this:
├── CMakeLists.txt
├── data
│   └── ICING BE SI Data.csv
├── gcc
│   ├── CMakeCache.txt
│   ├── CMakeFiles
│   ├── cmake_install.cmake
│   ├── lib
│   ├── Makefile
│   ├── src
│   └── tmp
├── include
│   ├── Interpolator.hpp
│   ├── InverseCDFProcess.hpp
│   └── XYParser.hpp
├── lib
│   ├── CMakeLists.txt
│   ├── Interpolator.cpp
│   ├── InverseCDFProcess.cpp
│   └── XYParser.cpp
└── test
└── test_icing.cpp
The project has a few classes, Interpolator and InverseCDFProcess, which I recently moved from the main executable file, test_icing.cpp to their own .cpp and .hpp files, located within the lib and include directories, respectively.
Since the classes do depend on each other (InverseCDFProcess needs Interpolator, which in turn needs a function in XYParser.cpp), I decided to build them as static libraries that then get linked into the main executable at compile time.
They're built like so:
add_library(xyparser STATIC XYParser.cpp)
add_library(interpolator STATIC Interpolator.cpp)
add_library(inversecdf STATIC InverseCDFProcess.cpp)
I then link these libraries into my executable in the normal way:
include_directories(include)
link_directories(lib)
link_directories(include) # Do I need this?
add_executable(test_icing test/test_icing.cpp)
# ... some code adding an external library which works fine
target_link_libraries(test_icing inversecdf interpolator xyparser ${external_library_name})
This produces this link command:
/usr/bin/c++ CMakeFiles/test_icing.dir/test/test_icing.cpp.o -o test_icing -L/mnt/c/Users/foo/projects/chase-icing/lib -L/mnt/c/Users/foo/projects/chase-icing/include -L/mnt/c/Users/foo/projects/chas
e-icing/gcc/src/imtc-build/lib -Wl,-rpath,/mnt/c/Users/foo/projects/chase-icing/lib:/mnt/c/Users/foo/projects/chase-icing/include:/mnt/c/Users/foo/projects/chase-icing/gcc/src/imtc-build/lib lib/libinversecdf
.a lib/libinterpolator.a lib/libxyparser.a -limt
At this point the compilation stop with the error:
/mnt/c/Users/foo/projects/chase-icing/test/test_icing.cpp:(.text+0xcca): undefined reference to `Interpolator<double>::Interpolator(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > co
nst&)'
/mnt/c/Users/foo/projects/chase-icing/test/test_icing.cpp:(.text+0xd4c): undefined reference to `Interpolator<double>::set_bounds(std::pair<double, double> const&)'
/mnt/c/Users/foo/projects/chase-icing/test/test_icing.cpp:(.text+0xd99): undefined reference to `InverseCDFProcess<double>::InverseCDFProcess(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<
char> > const&)'
/mnt/c/Users/foo/projects/chase-icing/test/test_icing.cpp:(.text+0xdd9): undefined reference to `InverseCDFProcess<double>::generate()'
It doesn't matter if the libraries are built STATIC or SHARED. The undefined reference error still happens.
My question is this: am I missing some extern or similar in my class definitions or implementations? Why is this relatively straightforward refactoring resulting in undefined references? Is my link directory incorrect? Should it refer to build directories?
Any help is appreciated.
Gonna go ahead and answer this for future people:
The solution is embedded in the error messages:
/mnt/c/Users/foo/projects/chase-icing/test/test_icing.cpp:(.text+0xdd9): undefined reference to `InverseCDFProcess<double>::generate()'
This error shows that the classes are templated. The problem is that I placed the implementations of these templates in .cpp files, as seen here:
├── include
│ ├── Interpolator.hpp
│ ├── InverseCDFProcess.hpp
│ └── XYParser.hpp
├── lib
│ ├── CMakeLists.txt
│ ├── Interpolator.cpp
│ ├── InverseCDFProcess.cpp
│ └── XYParser.cpp
Templates need to contain the full implementation in the header files. So, the good news is that I don't need those libraries in the first place. Just #include "Interpolator.hpp etc and it should work as expected!
The reason templates need the implementation is seen here: Why can templates only be implemented in the header file?

Multidirectory makefile with pybind

I'm trying to create a pybind project with multiple subdirectories. I managed to get the example.cpp file working with the following command (link below):
c++ -O3 -Wall -shared -std=c++11 -undefined dynamic_lookup `python3 -m pybind11 --includes` example.cpp -o example`python3-config --extension-suffix`
https://pybind11.readthedocs.io/en/stable/compiling.html#building-manually
It works right now by importing "example" and calling example.method. What I am trying to do moving forward is create a Makefile independent of cmake where I have the following directory structure and import classes when needed.
Top Level Folder
├── Makefile
├── Folder 1
│ ├── Makefile?
│ ├── example1.cpp
│ ├── example2.cpp
│ ├── example3.cpp
│ ├── ...
├── Folder 2
│ ├── Makefile?
│ ├── example1.cpp
│ ├── example2.cpp
│ ├── example3.cpp
│ ├── ...
I want to make the Makefile generic so that I can create a new folder with new cpp files and everything can work cleanly in python. Some classes may use information from other classes in different folders and I'm having some difficulty doing this. Does anyone know how to do this? Thanks!

Compile and link OpenCV to my project in my main CMakeLists.txt

I am new to cmake. I have a project which uses dlib and opencv. They are defined as submodules which are in third_party folder. I want to link them to my main project which is 'node' with cmake but I could not achieved. I am sharing my project tree. I did with find_package(OpenCV) and target_link_libraries(recognition-node ${OPENCV_LIBS}) way but I need to compile from source without installing anything. At last, I just want to write 'cmake . && make'
.
├── CMakeLists.txt
├── node
│ ├── build.sh
│ ├── CMakeLists.txt
│ ├── configure.sh
│ ├── findfacestask.cpp
│ ├── findfacestask.h
│ ├── main.cpp
│ ├── matrixwrapper.h
│ ├── poolcontext.cpp
│ ├── poolcontext.h
│ ├── recognition.dat
│ ├── recognizefacetask.cpp
│ ├── recognizefacetask.h
│ ├── runscript
│ ├── sp.dat
│ ├── task.cpp
│ ├── task.h
│ ├── unhandledexception.cpp
│ ├── unhandledexception.h
│ ├── webcamfeed.cpp
│ ├── webcamfeed.h
│ ├── wrapper.cpp
│ └── wrapper.h
└── third_party
├── dlib
│ ├── appveyor.yml
│ ├── CMakeLists.txt
│ ├── dlib
│ ├── docs
│ ├── examples
│ ├── MANIFEST.in
│ ├── python_examples
│ ├── README.md
│ ├── setup.py
│ └── tools
└── opencv
├── 3rdparty
├── apps
├── cmake
├── CMakeLists.txt
├── CONTRIBUTING.md
├── data
├── doc
├── include
├── LICENSE
├── modules
├── platforms
├── README.md
└── samples
Content of my top CMakeLists.txt
cmake_minimum_required(VERSION 2.8.12)
set (CMAKE_CXX_STANDARD 11)
add_subdirectory(node)
add_subdirectory(third_party/dlib)
add_subdirectory(third_party/opencv)
Content of node/CMakeLists.txt
cmake_minimum_required(VERSION 2.8.12)
project(recognition-node)
set(CMAKE_AUTOMOC ON)
find_package(Qt5Widgets REQUIRED)
add_executable(recognition-node main.cpp
webcamfeed.cpp
poolcontext.cpp
unhandledexception.cpp
task.cpp
findfacestask.cpp
wrapper.cpp
recognizefacetask.cpp)
target_link_libraries(recognition-node Qt5::Widgets)
target_link_libraries(recognition-node dlib::dlib)
target_link_libraries(recognition-node opencv::core)
It gives error in 'make' stage which is :
/home/arnes/workspace/recognition-node/node/poolcontext.h:10:28: fatal error:
opencv2/core.hpp: No such file or directory
Since you insist on keeping the opencv in your project tree
It is easier way but I just want it to do in this way.
Here is the solution that for sure works fine with your project tree that you posted in the question and with opencv-3.4.1. For simplicity I will neglect dlib library and Qt dependency, since you didn't have any problem with it.
Root CMakeLists.txt should have the following content:
cmake_minimum_required(VERSION 2.8.11) # or anything higher, if you wish
project(recognition-node CXX)
add_subdirectory(node)
The CMakeLists.txt under the node directory should have the following content:
add_subdirectory(third_party)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -g") # or any other additional flags
# at this point you can add find_package(Qt5Widgets REQUIRED) and later link your binary against Qt5::widgets as well
add_executable(myExec main.cpp
# and put here all the other source files of your project ...
)
# for linking libs I have put additionally highgui and imgproc to check the solution against OpenCV official sample
target_link_libraries(myExec opencv_core opencv_highgui opencv_imgproc)
target_include_directories(myExec PUBLIC
third_party/opencv/modules/calib3d/include
third_party/opencv/modules/core/include
third_party/opencv/modules/cudaarithm/include
third_party/opencv/modules/cudabgsegm/include
third_party/opencv/modules/cudacodec/include
third_party/opencv/modules/cudafeatures2d/include
third_party/opencv/modules/cudafilters/include
third_party/opencv/modules/cudaimgproc/include
third_party/opencv/modules/cudalegacy/include
third_party/opencv/modules/cudaobjdetect/include
third_party/opencv/modules/cudaoptflow/include
third_party/opencv/modules/cudastereo/include
third_party/opencv/modules/cudawarping/include
third_party/opencv/modules/cudev/include
third_party/opencv/modules/dnn/include
third_party/opencv/modules/features2d/include
third_party/opencv/modules/flann/include
third_party/opencv/modules/highgui/include
third_party/opencv/modules/imgcodecs/include
third_party/opencv/modules/imgproc/include
third_party/opencv/modules/ml/include
third_party/opencv/modules/objdetect/include
third_party/opencv/modules/photo/include
third_party/opencv/modules/shape/include
third_party/opencv/modules/stitching/include
third_party/opencv/modules/superres/include
third_party/opencv/modules/ts/include
third_party/opencv/modules/video/include
third_party/opencv/modules/videoio/include
third_party/opencv/modules/videostab/include
third_party/opencv/modules/viz/include
third_party/opencv/modules/world/include
)
The CMakeLists.txt under third_party should contain only:
add_subdirectory(opencv)
# add_subdirectory(dlib) # if you will use dlib, of course also add dlib
The sample I used to verify the build is contours2.cpp (just copy pasted the content into main.cpp).
However, I still think that it is a terrible idea to use this solution.
OpenCv takes really a lot of time to compile
you have to manually add include dirs (you can use some macro generators, but usually it looks even more ugly)
in your build system you have a lot of targets (over 300) that you don't really need, including install target
So, my recommendation is: if you want, use this solution for scientific purpose, but just compile and install OpenCv system-wise (or locally, if you are not the admin) when you really need to use it.

How to link many files with cmake

How Is simple way to link files in this tree files with cmake?
root
├── 1
│ └── 2
│ └── 3
├── 2
│ └── 3
└── 3
└── 4
└── 5
└── 6
└── 7
How can I better than this example?
file(GLOB SOURCES "*.cpp" "*/*.cpp" "*/*/*.cpp" "*/*/*/*.cpp" "*/*/*/*/*.cpp")
add_executable(a.out ${SOURCES})