├── .gitignore ├── README.md ├── include ├── Uuid.h └── meson.build ├── meson.build ├── src ├── Uuid.cpp ├── main.cpp └── meson.build └── test ├── doctest.h ├── meson.build └── uuid_test.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Example of C++ project skeleton with Meson Build and Catch. 2 | 3 | This project consists of: 4 | - a library (let's name it `luuid`) 5 | - an executable `uuidgen` using that `luuid` 6 | - unit test executable for `luuid` and using Catch framework 7 | 8 | This project was created as learning example for article: [Choosing C++ stack](https://carlosvin.github.io/posts/choosing-modern-cpp-stack) 9 | 10 | Catch vs Doctest (2 branches) 11 | ============================= 12 | 13 | Both test frameworks are quite similar, you can check differencies here: https://github.com/onqtam/doctest/blob/master/doc/markdown/faq.md#how-is-doctest-different-from-catch 14 | 15 | I've created project using both frameworks you can find them in corresponding branches: [doctest branch](https://github.com/carlosvin/uuid-cpp/tree/doctest) 16 | and [catch branch](https://github.com/carlosvin/uuid-cpp/tree/catch). 17 | 18 | For now I will merge doctest branch to master, both are quite similar, but doctest is supposed to be lighter and faster. 19 | 20 | 21 | How to build the example 22 | ======================== 23 | 24 | ```bash 25 | meson build . 26 | cd build 27 | ninja 28 | ninja test # to run unit tests 29 | ``` 30 | 31 | How to test 32 | =========== 33 | 34 | ```bash 35 | ninja test 36 | ``` 37 | 38 | How to install 39 | ============== 40 | 41 | In default system directory 42 | --------------------------- 43 | ```bash 44 | ninja install 45 | ``` 46 | 47 | You can run it just with command `uuidgen`. 48 | 49 | 50 | In specific directory, e.g: ./install 51 | ------------------------------------- 52 | 53 | ```bash 54 | DESTDIR=./install ninja install 55 | ``` 56 | Running `uuidgen` is a little bit more difficult in this case because the installation directory might not belong to library path (`LD_LIBRARY_PATH`). 57 | 58 | ```bash 59 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./install/usr/local/lib 60 | ./install/usr/local/bin/uuidgen #path to installed binary 61 | ``` 62 | -------------------------------------------------------------------------------- /include/Uuid.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Uuid.h 3 | * Author: carlos 4 | */ 5 | 6 | #ifndef UUID_H_ 7 | #define UUID_H_ 8 | 9 | #include 10 | 11 | namespace ids { 12 | 13 | class Uuid { 14 | private: 15 | static constexpr char SEP = '-'; 16 | static constexpr short FIRST_SEP_POSITION = 8; 17 | 18 | static int64_t get_rnd(); 19 | 20 | public: 21 | const int64_t most, least; 22 | 23 | Uuid(int64_t most, int64_t least); 24 | /** 25 | * automatic generation of this uuid 26 | * */ 27 | Uuid(); 28 | 29 | Uuid(const Uuid & id); 30 | 31 | bool operator==(const Uuid & id); 32 | bool operator!=(const Uuid & id); 33 | 34 | ~Uuid() = default; 35 | 36 | const std::string to_str(); 37 | 38 | }; 39 | 40 | } /* namespace ids */ 41 | 42 | #endif /* UUID_H_ */ 43 | -------------------------------------------------------------------------------- /include/meson.build: -------------------------------------------------------------------------------- 1 | 2 | # Select header files to be installed 3 | install_headers('Uuid.h') 4 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project( 2 | 'cpp-meson-example', # project name 3 | 'cpp', # C++ project, e.g: for C project 4 | version : '1.0.0', 5 | license : 'MIT', 6 | default_options : ['cpp_std=c++11']) # compile for C++ 7 | 8 | # it will be referred from subdir projects 9 | inc = include_directories('include') 10 | 11 | # meson will try to find a meson.build file inside following directories 12 | subdir('include') 13 | subdir('src') 14 | subdir('test') 15 | -------------------------------------------------------------------------------- /src/Uuid.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Uuid.cpp 3 | * 4 | * Created on: 29/3/2015 5 | * Author: carlos 6 | */ 7 | 8 | #include "Uuid.h" 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace ids { 15 | 16 | using namespace std; 17 | 18 | auto SEED = chrono::system_clock::now().time_since_epoch().count(); 19 | auto RND = bind (uniform_int_distribution{}, mt19937{SEED} ); 20 | constexpr short LEN = 16; 21 | auto convert_to_hex = [] (stringstream & stream, int64_t l) { stream << setfill('0') << setw(LEN) << hex << l; }; 22 | 23 | Uuid::Uuid(): most(get_rnd()), least(get_rnd()){} 24 | 25 | Uuid::Uuid(int64_t m, int64_t l): most(m), least(l) {} 26 | 27 | Uuid::Uuid(const Uuid & id): most(id.most), least(id.least) 28 | { 29 | } 30 | 31 | bool Uuid::operator==(const Uuid & id){ 32 | return most == id.most && least == id.least; 33 | } 34 | 35 | bool Uuid::operator!=(const Uuid & id){ 36 | return !(*this == id); 37 | } 38 | 39 | int64_t Uuid::get_rnd() 40 | { 41 | return RND(); 42 | } 43 | 44 | const string Uuid::to_str() 45 | { 46 | // 8-4-4-4-12 47 | stringstream stream; 48 | convert_to_hex(stream, most); 49 | convert_to_hex(stream, least); 50 | string result( stream.str() ); 51 | for (int i=0; i<4; i++) 52 | { 53 | result.insert(FIRST_SEP_POSITION + (i * 4) + i, 1, SEP); 54 | } 55 | return result; 56 | } 57 | 58 | } /* namespace ids */ 59 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "Uuid.h" 3 | #include 4 | 5 | int main() 6 | { 7 | ids::Uuid uuid; 8 | std::cout << uuid.to_str() << std::endl; 9 | return 0; 10 | } -------------------------------------------------------------------------------- /src/meson.build: -------------------------------------------------------------------------------- 1 | libuuid = shared_library( 2 | 'uuid', # library name 3 | 'Uuid.cpp', # source files to be compiled 4 | include_directories : inc, # previously declared include directories in root :code:`meson.build` 5 | install : true) # :code:`libuuid` will be part of project installation 6 | 7 | uuidgen = executable( 8 | 'uuidgen', # executable name 9 | 'main.cpp', # source files to be compiled 10 | include_directories : inc, # previously declared include directories in root :code:`meson.build` 11 | link_with : libuuid, # linking executable with shared previously declared shared library :code:`libuuid` 12 | install : true) # :code:`uuidgen` executable be part of project installation -------------------------------------------------------------------------------- /test/meson.build: -------------------------------------------------------------------------------- 1 | 2 | testexe = executable( 3 | 'testexe', # test executable name 4 | 'uuid_test.cpp', # tests source files to be compiled 5 | include_directories : inc, # declared include directories in root :code:`meson.build` 6 | link_with : libuuid) # link test executable with previously declared shared library :code:`libuuid` 7 | 8 | # test execution 9 | test('Uuid test', testexe) 10 | 11 | # we can specify other test execution passing arguments or environment variables 12 | test('Uuid test with args and env', testexe, args : ['arg1', 'arg2'], env : ['FOO=bar']) 13 | -------------------------------------------------------------------------------- /test/uuid_test.cpp: -------------------------------------------------------------------------------- 1 | #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN 2 | 3 | #include "doctest.h" 4 | #include "Uuid.h" 5 | #include 6 | 7 | constexpr int MAX_ITERS = 100; 8 | 9 | TEST_CASE("Uuid") 10 | { 11 | for (int i = 0; i < MAX_ITERS; i++) 12 | { 13 | ids::Uuid uuid; 14 | std::string uuid_str{uuid.to_str()}; 15 | 16 | INFO(uuid_str); 17 | 18 | // If assertion fails test execution is stopped 19 | REQUIRE(uuid_str.size() == 36); 20 | 21 | // If assertion fails test execution continues 22 | CHECK(uuid.most > 0); 23 | CHECK(uuid.least > 0); 24 | } 25 | } 26 | 27 | // BDD style 28 | 29 | SCENARIO("UUID creation") 30 | { 31 | 32 | GIVEN("A random UUID ") 33 | { 34 | 35 | ids::Uuid uuid; 36 | std::string uuid_str{uuid.to_str()}; 37 | 38 | REQUIRE(uuid_str.size() == 36); 39 | 40 | WHEN("get the most and least") 41 | { 42 | THEN("should be more than 0") 43 | { 44 | CHECK(uuid.most > 0); 45 | CHECK(uuid.least > 0); 46 | } 47 | } 48 | } 49 | } 50 | --------------------------------------------------------------------------------