I started working on a C++ project using Google Test framework for unit testing and header-only CImg library for internal operations. I want to use CMake build system to compile it.
$ tree
.
├── build
├── cmake
│ └── includes.cmake
├── CMakeLists.txt
├── include
│ └── soccl
│ └── soccl.hpp
└── src
├── soccl
│ ├── CMakeLists.txt
│ └── soccl.cpp
└── tests
├── CMakeLists.txt
├── main.cpp
└── soccl.cpp
7 directories, 8 files
Source:
# .gitignore
*.o
*.so
build
# CMakeLists.txt
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(SoftwareOccluder VERSION 0.1 LANGUAGES CXX)
set(CMAKE_BUILD_TYPE Release)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -Os -Wall -pedantic")
set(CMAKE_EXE_LINKER_FLAGS "-s ${CIMG_FLAGS}")
set(EXTERNAL_INSTALL_LOCATION ${CMAKE_BINARY_DIR}/external)
include_directories(include)
include(cmake/includes.cmake)
ADD_SUBDIRECTORY(src/soccl)
ADD_SUBDIRECTORY(src/tests)
# cmake/includes.cmake
include(ExternalProject)
ExternalProject_Add(
cimg
GIT_REPOSITORY https://github.com/dtschump/CImg.git
SOURCE_DIR "cimg"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/cimg)
SET(CIMG_FLAGS "-lm -lpthread")
/* include/soccl/soccl.hpp */
#ifndef SOCCL_HPP
#define SOCCL_HPP
#define cimg_display 0
#include <CImg.h>
namespace soccl {
struct RGB {
int r, g, b;
};
class Soccl {
public:
Soccl();
RGB get_pixel(int x, int y);
void set_pixel(int x, int y, RGB rgb);
private:
cimg_library::CImg<unsigned char> img_;
};
} // namespace soccl
#endif
# src/soccl/CMakeLists.txt
file(GLOB SOURCES "*.cpp")
add_library(soccl SHARED ${SOURCES})
install(TARGETS soccl DESTINATION /usr/lib)
/* src/soccl/soccl.cpp */
#include "soccl/soccl.hpp"
namespace soccl {
Soccl::Soccl() : img_(320, 240, 1, 3) {
img_.fill(0);
}
RGB Soccl::get_pixel(int x, int y) {
RGB rgb;
rgb.r = static_cast<int>(img_(x, y, 0, 0));
rgb.g = static_cast<int>(img_(x, y, 0, 1));
rgb.b = static_cast<int>(img_(x, y, 0, 2));
return rgb;
}
void Soccl::set_pixel(int x, int y, RGB rgb) {
img_(x, y, 0, 0) = rgb.r;
img_(x, y, 0, 1) = rgb.g;
img_(x, y, 0, 2) = rgb.b;
}
} // namespace soccl
# src/tests/CMakeLists.txt
include(ExternalProject)
ExternalProject_Add(
googletest
GIT_REPOSITORY https://github.com/google/googletest
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTERNAL_INSTALL_LOCATION}
)
include_directories(${EXTERNAL_INSTALL_LOCATION}/include)
link_directories(${EXTERNAL_INSTALL_LOCATION}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
file(GLOB TESTS "*.cpp")
add_executable(tests ${TESTS})
target_link_libraries(tests soccl gtest gmock gtest_main pthread)
/* src/tests/main.cpp */
#include "gmock/gmock.h"
int main(int argc, char** argv) {
testing::InitGoogleMock(&argc, argv);
return RUN_ALL_TESTS();
}
/* src/tests/soccl.cpp */
#include "soccl/soccl.hpp"
#include "gmock/gmock.h"
class SocclTest: public testing::Test {
public:
soccl::Soccl soccl;
};
TEST_F(SocclTest, TestPixelGetter) {
soccl::RGB rgb = soccl.get_pixel(10, 20);
ASSERT_EQ(rgb.r, 0);
ASSERT_EQ(rgb.g, 0);
ASSERT_EQ(rgb.b, 0);
}
TEST_F(SocclTest, TestPixelSetter) {
soccl::RGB rgb{12, 21, 44};
soccl.set_pixel(43, 23, rgb);
ASSERT_EQ(rgb.r, 12);
ASSERT_EQ(rgb.g, 21);
ASSERT_EQ(rgb.b, 44);
}
Compilation:
$ cd build
$ cmake ..
$ make
Running tests (compiled as a binary file in build dir):
$ ./tests
[==========] Running 2 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 2 tests from SocclTest
[ RUN ] SocclTest.TestPixelGetter
[ OK ] SocclTest.TestPixelGetter (0 ms)
[ RUN ] SocclTest.TestPixelSetter
[ OK ] SocclTest.TestPixelSetter (0 ms)
[----------] 2 tests from SocclTest (0 ms total)
[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (0 ms total)
[ PASSED ] 2 tests.