Skip to main content

Building: Hello world

Introduction

We will try to create the simplest working application in the terminal with the CMake and in the QtCreator IDE with the qmake.

The HelloWorld example also expects the following folders structure, let's create them.

cd 
mkdir HelloWorld/HelloWorld
cd HelloWorld

Prepare SQLite 3 database

Simplest will be to demonstrate the HelloWorld example with the SQLite 3 database.

To create and insert two rows into the SQLite 3 database, execute the following command in the terminal.

sqlite3 HelloWorld.sqlite3 "
create table posts(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name VARCHAR NOT NULL);
insert into posts values(1, 'First Post');
insert into posts values(2, 'Second Post');
select * from posts;"

Install dependencies

First, install the vcpkg package manager as is described here.

The range-v3 and tabulate libraries are required dependencies because TinyORM uses them in header files, you have to install them before you can use TinyORM. The tabulate library is only needed in the tom migrations it's used by the migrate:status command.

There are two ways how to install the range-v3 and tabulate libraries using vcpkg.

Using vcpkg.json (manifest mode)

Create a vcpkg.json file with the following content. CMake example below uses this method.

cd HelloWorld
vim vcpkg.json
{
"$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json",
"name": "tinyorm-hello-world",
"version-semver": "0.1.0",
"description": "HelloWorld example with TinyORM library.",
"maintainers": "Silver Zachara <silver.zachara@gmail.com>",
"supports": "!(uwp | arm | android | emscripten)",
"dependencies": [
"range-v3",
"tabulate"
]
}
note

Only CMake via the toolchain file supports this method.

Using vcpkg install (manually)

This method can be used with both CMake and qmake.

cd ../../vcpkg

vcpkg search range-v3
vcpkg search tabulate
vcpkg install range-v3 tabulate
vcpkg list

Source code

Let's start in the HelloWorld project folder.

cd /HelloWorld/HelloWorld

Create main.cpp source file.

vim main.cpp
tip

To paste a source code correctly in vim, press Shift + p.

And paste the following code.

#include <QDebug>

#ifdef _WIN32
# include <qt_windows.h>
#endif

#include <orm/db.hpp>

using Orm::DB;

int main(int /*unused*/, char */*unused*/[])
{
#ifdef _WIN32
SetConsoleOutputCP(CP_UTF8);
// SetConsoleOutputCP(1250);
#endif

// Ownership of a shared_ptr()
auto manager = DB::create({
{"driver", "QSQLITE"},
{"database", qEnvironmentVariable("DB_DATABASE", "HelloWorld.sqlite3")},
{"check_database_exists", true},
});

auto posts = DB::select("select * from posts");

while(posts.next())
qDebug() << posts.value("id").toULongLong() << posts.value("name").toString();
}

Hello world with CMake

Create a folder for the CMake build.

cd ..
mkdir HelloWorld-builds-cmake/build-debug

cd HelloWorld

CMake project

Create CMakeLists.txt file with the following content.

cmake_minimum_required(VERSION VERSION 3.22...3.25 FATAL_ERROR)

project(HelloWorld LANGUAGES CXX)

# build tree
list(APPEND CMAKE_PREFIX_PATH "/TinyORM/TinyORM-builds-cmake/build-debug")

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

add_executable(HelloWorld
main.cpp
)

find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED)
find_package(TinyOrm 0.16.0 CONFIG REQUIRED)

target_link_libraries(HelloWorld
PRIVATE
Qt${QT_VERSION_MAJOR}::Core
TinyOrm::TinyOrm
)

FetchContent

If you didn't have cloned and built the TinyORM library, or you want to fastly try TinyORM without wasting time with cloning and building the TinyORM library, then you can use CMake's FetchContent module that will do all of this for you.

Instead of providing a path using the CMAKE_PREFIX_PATH (or using the User Package Registry):

# build tree
list(APPEND CMAKE_PREFIX_PATH "/TinyORM/TinyORM-builds-cmake/build-debug")

You can use the FetchContent module like in the following example.

cmake_minimum_required(VERSION VERSION 3.22...3.25 FATAL_ERROR)

project(HelloWorld LANGUAGES CXX)

# FetchContent method
include(FetchContent)
FetchContent_Declare(TinyORM
GIT_REPOSITORY https://github.com/silverqx/TinyORM.git
GIT_TAG origin/main
OVERRIDE_FIND_PACKAGE
)
# Here you can configure TinyORM CMake options
set(MYSQL_PING OFF)
set(TOM_EXAMPLE ON)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

add_executable(HelloWorld
main.cpp
)

find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED)
find_package(TinyOrm 0.16.0 CONFIG REQUIRED)

target_link_libraries(HelloWorld
PRIVATE
Qt${QT_VERSION_MAJOR}::Core
TinyOrm::TinyOrm
)

How FetchContent module works

The FetchContent_Declare command is like calling the git clone inside the build folder and then adding a cloned folder in a similar way as the add_subdirectory(<cloned_folder>) command does.

The FetchContent_MakeAvailable(<package>) internally calls the find_package(<package>) command or if you pass the OVERRIDE_FIND_PACKAGE argument, then you don't have to call the the FetchContent_MakeAvailable, but you must call the find_package(<package> x.y.z CONFIG REQUIRED) command manually.

info

An advantage of the OVERRIDE_FIND_PACKAGE argument is that you can call the find_package command much later, and you can insert additional configurations between.

Build Hello world

Now you are ready to configure HelloWorld CMake application.

cd ../HelloWorld-builds-cmake/build-debug
cmake.exe `
-S "/HelloWorld/HelloWorld" `
-B "/HelloWorld/HelloWorld-builds-cmake/build-debug" `
-G 'Ninja' `
-D CMAKE_BUILD_TYPE:STRING='Debug' `
-D CMAKE_TOOLCHAIN_FILE:FILEPATH="/vcpkg/scripts/buildsystems/vcpkg.cmake" `
-D CMAKE_INSTALL_PREFIX:PATH="/tmp/HelloWorld"

And build.

cmake --build . --target all

Execute Hello world

Do not forget to add TinyOrm0d.dll on the path on Windows and on the LD_LIBRARY_PATH on Linux, so HelloWorld application can find it during execution, as is described here.

$env:Path = "\TinyORM\TinyORM-builds-cmake\build-debug;" + $env:Path

Create a symbolic link to the HelloWorld.sqlite3 database inside the build folder. If you do not have enabled symbolic links without Administrator rights on your Windows, you can just simply copy the HelloWorld.sqlite3 database or Allow symbolic links unprivileged.

New-Item -ItemType SymbolicLink -Target ../../HelloWorld.sqlite3 -Name HelloWorld.sqlite3
# Or simply copy
Copy-Item ../../HelloWorld.sqlite3 .

Execute HelloWorld example.

.\HelloWorld.exe

The output will look like this.

Executed prepared query (6ms, -1 results, 0 affected, tinyorm_default) : select * from posts
1 "First Post"
2 "Second Post"

Hello world with qmake

Create a folder for the qmake build.

cd /HelloWorld

mkdir HelloWorld-builds-qmake

The source code is the same as for the HelloWorld CMake example.

qmake project

Create HelloWorld.pro qmake file with the following content.

cd HelloWorld
vim HelloWorld.pro
tip

To paste a source code correctly in vim, press Shift + p.

QT *= core sql
QT -= gui

TEMPLATE = app

SOURCES += $$PWD/main.cpp

# Configure TinyORM library
include($$TINY_MAIN_DIR/TinyORM/qmake/TinyOrm.pri)

# vcpkg - range-v3
win32-msvc: \
INCLUDEPATH += $$quote($$TINY_VCPKG_INSTALLED/x64-windows/include/)
mingw: \
QMAKE_CXXFLAGS += -isystem $$shell_quote($$TINY_VCPKG_INSTALLED/x64-mingw-dynamic/include/)
unix:!macx: \
QMAKE_CXXFLAGS += -isystem $$shell_quote($$TINY_VCPKG_INSTALLED/x64-linux/include/)
caution

The exact folders structure is crucial in this example because the paths to the TinyORM source and build folders are relative.

tip

On Linux -isystem marks the directory as a system directory, it prevents warnings.

On Windows you can use QMAKE_CXXFLAGS_WARN_ON = -external:anglebrackets -external:W0, it applies a warning level 0 to the angel bracket includes; #include <file>.

Configure using .qmake.conf

Create .qmake.conf in the HelloWorld project root folder with the following content.

TINY_MAIN_DIR = $$clean_path($$PWD/../../TinyORM)
# Name of this qmake variable is crucial
TINYORM_BUILD_TREE = $$quote($$TINY_MAIN_DIR/TinyOrm-builds-qmake/build-TinyOrm-Desktop_Qt_6_3_1_MSVC2019_64bit-Debug)
# vcpkg - range-v3
TINY_VCPKG_INSTALLED = $$clean_path($$PWD/../../../vcpkg/installed)
info

Configuring with the .qmake.conf file has one big advantage that is that you do not have to modify the project files.

Build Hello world

tip

I recommend creating a new Session in the QtCreator IDE as is described here.

Now you can open the HelloWorld.pro project in the QtCreator IDE.

This will open the Configure Project tab, select some kit and update build folder paths to meet our folders structure or like you want.

HelloWorld - QtCreator - Configure Project

You are ready to configure build options, hit Ctrl+5 to open Project Settings tab and select Build in the left sidebar to open the Build Settings, it should look similar to the following picture.

HelloWorld - QtCreator - Build Settings

Disable QML debugging and profiling and Qt Quick Compiler, they are not used.

In the left sidebar open Dependencies and check TinyOrm and Synchronize configuration, this setting ensures that the current project will be rebuilt correctly when the TinyORM library source code changes.

Everything is ready to build, you can press Ctrl+b to build the project.

Execute Hello world

The QtCreator takes care about all the necessary configuration, sets up the build environment correctly and also prepends dependency libraries on the path on Windows and on the LD_LIBRARY_PATH on Linux.

Only one thing you might want to change is to run the HelloWorld example in the new terminal window. To do so, hit Ctrl+5 to open the Project Settings tab and select Run in the left sidebar to open the Run Settings, then in the Run section select the Run in terminal checkbox.

Create a symbolic link to the HelloWorld.sqlite3 database inside the build folder. If you do not have enabled symbolic links without Administrator rights on your Windows, you can just simply copy the HelloWorld.sqlite3 database or Allow symbolic links unprivileged.

cd ../HelloWorld-builds-qmake/build-HelloWorld-Desktop_Qt_5_15_2_MSVC2019_64bit-Debug

New-Item -ItemType SymbolicLink -Target ../../HelloWorld.sqlite3 -Name HelloWorld.sqlite3
# Or simply copy
Copy-Item ../../HelloWorld.sqlite3 .

To execute the HelloWorld example press Ctrl + r.

The output will look like this.

Executed prepared query (6ms, -1 results, 0 affected, tinyorm_default) : select * from posts
1 "First Post"
2 "Second Post"