QT Framework Overview

Qt is a powerful cross-platform application framework used for developing GUI (Graphical User Interface) applications Qt provides various tools, libraries, and APIs for building applications that can run on multiple platforms, including Windows, macOS, Linux, Android, and iOS.

Qt has its "write once, run anywhere" philosophy, which allows developers to write code once and deploy it on different platforms without significant modifications. Qt has this cross-compatible feature set.

Qt's architecture is based on the concept of signals and slots, which enables easy communication between different components of an application both between the C++ backend parts and with the frontend Code components.

Many times we get confused about the different QT tools and terms because maybe they all start with Qt. I have made the following table can help you have some more information in this regard

.ui format 

Ui file is the old format for designing desktop GUI App

It is the older QT Gui file format 

.qml format

QML is the new format to design cross platform applications . materialistic design 

QML is kind if of a programming language 

QtQuick 

Qt Quick is a software framework holding buttons , text fields etc 

QML is the language to work with Qt Quick 

Qt Designer

This is a graphical tool to make ui file 

Ui file is older Qt Widget desktop application type  

Qt Design Studio 

Can work with both .qml and .ui format file 

Previously it was known as Qt Quick Designer 

QtCreator 

It is an IDE where you can write both C++ code and it has Design options

to work on QML and ui file 


It is used for creating a project out of QT SDK versions 


You need to Link a SDK to Creator IDE 

But there are dependencies for example using QtCreator 11

you cannot create a project targeting Qt SDK version 5.14 .


You need to use QtCreator 4.14 for that 


QT SDK 

This is the main SDK . it has different versions 

For example QT 5.14 SDK 

QT Maintenance Tool

You can use this to add/remove/update all the above components 

To use it you need an online registration 


QT Widget vs QML 

widget is powerful for native classic desktop applications and QML is for overall all platforms . Qt Creator IDE itself is created using Qt Widgets .

Qt Widget file format is ui format and can be designed using Qt Designer .











QT Creator Examples

There are a lot of QML examples in QT Creator.Search by QML and you will find many



In QTCreator you can enable QT Design option in the following way. Afterwards you can design QML in QT Creator IDE itself .



With QML, you can create rich, dynamic UIs using a declarative syntax that's more intuitive
Moreover, QML seamlessly integrates with Qt's C++ backend, enabling you to leverage the full power of the Qt framework while benefiting from the flexibility and agility of QML for UI design.

Additionally, QML offers excellent support for different user interfaces that can easily scale across different screen sizes and orientations on a wide range of devices, from smartphones and tablets to desktops and embedded systems Displays.

So if you're starting a new Qt project or considering migrating an existing one, embracing QML would be the Ideal choice


Embedded CI/CD with STM32 (Part-1) : MakeFile Based build System



It's usual for us Embedded System Engineers to rely solely upon an IDE provided by the Silicon Vendor to Write the code, compile, Flash, and Debug the target Microcontroller. For Example, While developing Application firmware for STM32 Microcontrollers, The Choice of STM Cube IDE is the defacto. Using the IDE we can do all the required operations but Have you ever thought of moving from IDE to a Command line-based compilation process?  In this short blog Post, we will find how we can move into such a mechanism and experience how this would bring new autonomy to our embedded development pipeline. 


Moving From IDE to CMD Line can bring a number of benefits to our overall project development process. Such as

  • Build commands can be wrapped into a bash script 
  • Faster Build Cycle by using all processor threads 
  • Ability to include Unit test step in the build process 
  • Prepares the Base Framework for arranging a CI / CD pipeline
  • Invoke Build Process on a new Git Commit push.
  • No need to depend on the IDE buttons anymore. 
  • Avoiding Manual Labours 

While using STM32 Cube IDE for the first phase of project Initialization, you have probably noticed that STM32CubeIDE can also Generate a Makefile for your project. Well, Once you have configured initial MCU settings such as GPIO, Clock, and different peripherals & have generated the Make File, from that point onwards you can move on to using the the command line only to build/compile your firmware. First I am going to show you how to set up an STM32 MCU project from the beginning to compile it in a bare-metal command line console depending on the Makefile 


Download https://www.st.com/en/development-tools/stm32cubemx.html  

Start CubeMX by Running the following command 

hassin@P51:/usr/local/STMicroelectronics/STM32Cube/STM32CubeMX$ ./STM32CubeMX

Create a new project and Start Configuring using the IDE 

First, we configure the Clocks 

Then We Configure the Peripherals such as USART 

Put Pin Labels using the Graphical Tool 

Configure Clock signal Routes 

Now Comes the Most important Settings Page. Here in the Code generation page, Select Makefile 


Then we need to click on Generate Code 


After Generation, the FileSystem of the project will have the following tree
Then we test the building of the project using the Make tool

hassin@P51:~/projects2/stm32-cmake-bare$ make -j8


If you have followed everything correctly then you should get output like the following 


This shows that the default make-based build system is working. Now if you want you can flash the elf using any stm32 firmware flashing utility and check the code in hardware. But Remember our target is to automate all this process.

In this next Post, we will see how we can wrap this project under a CMake type Build System and move to the next level.

CMake Hands On Tutorial

 

CMake Hands-On Tutorial



What is CMake


CMake is a cross-platform build system generator. Cmake is not a build system itself. It Generates another system's build files. After Generation, it can invoke native build environments such as Make to build the final executable / Libraries.

To use CMake, you create a CMakeLists.txt file in the root directory of your project and specify the source files, dependencies, and build options. CMake then generates a build system for your project based on the information provided in the CMakeLists.txt file. Let's have a short quick hands-on on its usage from scratch and later apply it to an advanced usage scenario with multiple source files. We would do that from the command line i.e without using any IDE so that we can learn the internals and Its working method more clearly


Basic usage


Let’s say we have the following sources 

Here is a simple example of a CMakeLists.txt file that builds a hello world program:


cmake_minimum_required(VERSION 3.10)

project(HelloWorld)


add_executable(hello main.c hello.c hello.h)


This CMakeLists.txt file specifies that a single executable, hello, should be built from the main.c source file. Save this file in the same directory 


To build the project with CMake, you can use the following steps:


Create a build directory and navigate to it:

mkdir build
cd build


Run CMake to generate the build system:

cmake ..


This will generate the necessary makefiles or workspaces for your project.

This will create the makefile which you can use to build the project 


Now Build the project:

make


This will build the hello executable.


CMake also provides several advanced features, such as support for static and dynamic libraries, integration with testing frameworks, and the ability to generate project files for IDEs such as Visual Studio and Xcode.


Advanced Usage


Now let’s move on to a more complex project setup. We must learn this because CMake is mainly used for working with a very large codebase. This example although not very big but still larger than the basic example to demonstrate CMake's working method and it's benefits on Larger Codebase cases.


Let’s Say we have the following sources 


The sources look like the following 


Create an empty CMakeLists.txt file and a build directory 


The CMakeLists.txt file looks like the following 

cmake_minimum_required(VERSION 3.10)
project(MyProject)

# Set some variables
set(EXECUTABLE_NAME myproject)
set(SOURCE_FILES src/main.c src/util.c src/lib/lib1.c src/lib/lib2.c)

# Enable C and C++ languages
enable_language(C CXX)

# Find and include header files
file(GLOB_RECURSE HEADER_FILES "include/*.h")
include_directories(${HEADER_FILES})

# Add an executable to be built from the source files
add_executable(${EXECUTABLE_NAME} ${SOURCE_FILES})

# Set compile definitions and include directories for the target
target_compile_definitions(${EXECUTABLE_NAME} PRIVATE MY_DEFINITION=1)
target_include_directories(${EXECUTABLE_NAME} PRIVATE include)

# Set compile and link options for the target
target_compile_options(${EXECUTABLE_NAME} PRIVATE -O2 -Wall -Wextra)
target_link_options(${EXECUTABLE_NAME} PRIVATE -lm -lpthread)

# Add a custom command to generate documentation
find_package(Doxygen)
if(DOXYGEN_FOUND)
  add_custom_command(
    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/docs
    COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile
    DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile
    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
    COMMENT "Generating API documentation with Doxygen"
  )
  add_custom_target(docs DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/docs)
endif()


Then run the cmake command like below and makefile will get generated


Then Run the make command to build the executable from the generated CMakeLists.txt 

 Then run the executable 


Explanation (Step by Step)


Here is a brief explanation of each line in the CMakeLists.txt file that I provided in the example

cmake_minimum_required(VERSION 3.10)


This line specifies the minimum version of CMake required to build the project. It ensures that the version of CMake being used is compatible with the commands and syntax used in the CMakeLists.txt file.

project(MyProject)


This line specifies the name of the project.

set(EXECUTABLE_NAME myproject)
set(SOURCE_FILES src/main.c src/util.c src/lib/lib1.c src/lib/lib2.c)


These lines define two variables: EXECUTABLE_NAME and SOURCE_FILES. The EXECUTABLE_NAME variable specifies the name of the executable to be built, and the SOURCE_FILES variable specifies a list of source files that should be compiled to create the executable.

enable_language(C CXX)


This line enables support for the C and C++ languages.


file(GLOB_RECURSE HEADER_FILES "include/*.h")
include_directories(${HEADER_FILES})

These lines use the file(GLOB_RECURSE) command to recursively search for header files in the include directory and store them in the HEADER_FILES variable. The include_directories command is then used to include these header files in the build.


add_executable(${EXECUTABLE_NAME} ${SOURCE_FILES})

This line adds an executable target to be built from the source files specified in the SOURCE_FILES variable. The executable will be named according to the value of the EXECUTABLE_NAME variable.


target_compile_definitions(${EXECUTABLE_NAME} PRIVATE MY_DEFINITION=1)
target_include_directories(${EXECUTABLE_NAME} PRIVATE include)

These lines use the target_compile_definitions and target_include_directories commands to set compile definitions and include directories for the target, respectively. The PRIVATE keyword specifies that the definitions and include directories are only for the target and are not propagated to other targets that depend on it


target_compile_options(${EXECUTABLE_NAME} PRIVATE -O2 -Wall -Wextra)
target_link_options(${EXECUTABLE_NAME} PRIVATE -lm -lpthread)

These lines use the target_compile_options and target_link_options commands to set compile and link options for the target, respectively. The PRIVATE keyword specifies that the options are only for the target and are not propagated to other targets that depend on it.


include_directories vs target_include_directories


include_directories is used to specify directories to be included in the build process for the entire project. It adds the specified directories to the included search path for all targets in the project.


On the other hand, target_include_directories are used to specify directories to be included in the build process for a specific target. It adds the specified directories to the included search path for a particular target, rather than for the entire project.


Here's an example of how you might use these two commands:

include_directories(common)

add_library(libA libA.cpp)

add_executable(appA appA.cpp)
target_include_directories(appA PRIVATE appA)

In this example, the include_directories command specifies that the common directory should be included in the include search path for all targets in the project. The target_include_directories command specifies that the appA directory should be included in the include search path for the appA target only.


So, to summarize: include_directories is used to specify directories to be included in the include search path for the entire project, while target_include_directories is used to specify directories to be included in the include search path for a specific target.



Categories

Pages

Firmware Engineer

My photo
Works on Firmware, Embedded Linux, Smart Metering, RTOS, IoT backend

Contact Form

Name

Email *

Message *

Copyrighted by Hassin. Powered by Blogger.