xtd icon indicating copy to clipboard operation
xtd copied to clipboard

[QUESTION] Documentation - How to build my own xtd project without using CMake, ie. g++ CLI or Qmake.

Open grantrostig opened this issue 6 months ago • 1 comments

Enhancement

Add to the documentation detailed information how build my own xtd project without using CMake, ie. g++ CLI or Qmake. As a minimum, the names of the libraries at must be linked in by the g++ linker.

Description

I am trying to use Qmake or just a plain g++ invocation line at the tty terminal and am having 16900 link errors.

Which of the many xtd *.a library files are required? All of them? Is there one library I can use instead of listing them to g++? On most c++ / C libraries I use there just one big shared library to link in, *.so, or maybe *.a.

I know CMake might do linking automatically (opaquely), but I think there should be a reasonably concise/simple way to build XTD application programs without being forced to use CMake.

Also, what wxWidgets/wxGTK library file (or more than one) must also be linked for the XTD libary to link/work, or are they already linked in by building/instal the XTD repo?

grantrostig avatar Jun 13 '25 20:06 grantrostig

Hello @grantrostig ,

I will explain in this issue how to generate an xtd application without CMake.

On the other hand, I will not make an explanatory page in the xtd documentation, which is why this issue will be renamed to QUESTION and not to ENHANCEMENT.

Why I won't make an explanatory page

xtd uses CMake as the official build system, and this is not an arbitrary choice: it is a central tool to ensure the portability, maintainability and ease of use of the library, especially for such a large project.

Here are the main reasons why I do not offer support or manual configuration without CMake:

Automatic portability

CMake manages the differences between platforms (Windows, Linux, macOS, BSD...) and automatically generates the right projects (Makefiles, Ninja, Visual Studio, Xcode, etc.).

Complex dependency management

xtd depends on many libraries (e.g. wxWidgets, GTK, etc.) depending on the platform.

CMake detects and configures all this automatically. Without CMake, you must manually: • Find the right ways to include (-I) • Find and order libraries (-l) • Manage differences between debug/release • Adapt for each OS

Simplicity of use for end users

The idea of xtd is to allow everyone, even with little system knowledge, to compile a multiplatform graphics app in a few commands.

CMake is key in this promise.

Interoperability with modern IDEs

CMake is natively recognized by Visual Studio, CLion, QtCreator, VS Code (with the right plugins)... which makes it possible not to manage a project manually in each IDE.

Reproducible, traceable, reliable builds

A manual control line can easily "walk by chance" at your home and break elsewhere.

CMake centralizes the logic, versions the config, and keeps the projects synchronized.

xtd is designed around CMake

  • xtd provides CMake functions such as add_sources() or target_type(), which greatly simplifies the creation of projects.
  • Xtd has also added functionality to CMake to generate C++ code for the management and integration of your project resources.
  • Not to mention the CMake functions also added for the generation of settings and information on the assembly of the application.

Reproducing this without CMake is like rewriting all the logic of the project system... and it's not easy.

For more information :

Why I won't maintain support without CMake

  • Manual flags are fragile and often break with a system, distrib, or lib version update.
  • This would force me to maintain and document several parallel build systems, which is neither realistic nor desirable.
  • User support would be multiplied tenfold, just for problems that do not exist if CMake is used.

Method to generate an xtd application without CMake

Now that you know why I won't do documentation, I can still help you do it.

I thought of a simple way to find all xtd dependencies for any platform.

So I will give you an easy method to get there but as I said above I will not support it.

xtd architecture

xtd is composed of four main libraries (xtd public APIs):

  • xtd.core
  • xtd.drawing
  • xtd.forms
  • xtd.tunit

The abstraction to the different platforms is done through three other libraries (non-public APIs):

  • xtd.core.native for xtd.core
  • xtd.drawing.native for xtd.drawing
  • xtd.forms.natives for xtd.forms

In order for xtd.core to access the different platforms xtd implements a library specific to the platform:

  • Xtd.core.native.linux for the different linux distributions
  • xtd.core.native.macos for macOS
  • xtd.core.native.win32 for Windows
  • ...

For xtd drawing to access the graphics, images, ... of the different platforms xtd implements a library specific to each backend (toolkit):

  • xtd.drawing.native.gtk4 for linux GNOME
  • xtd.drawing.native.Qt6 for linux KDE
  • xtd.drawing.native.cocoa for macOS Cocoa
  • xtd.drawing.native.Win32 for Windows
  • ...

For xtd forms to access the different controls of the different platforms xtd implements a library specific to each backendt (toolkit):

  • xtd.forms.native.gtk4 for linux GNOME
  • xtd.forms.native.Qt6 for linux KDE
  • xtd.forms.native.cocoa for macOS Cocoa
  • xtd.forms.native.Win32 for Windows
  • ...

Note on the current native backend

To enable fast, stable, and cross-platform development, the xtd.drawing and xtd.forms libraries currently use wxWidgets as their single native backend, via xtd.drawing.native.wxwidgets and xtd.forms.native.wxwidgets. This decision allows xtd’s public API to evolve rapidly, without being slowed down by the overhead of maintaining multiple native backends simultaneously (Win32, Cocoa, Gtk4, etc.).

For more information about the xtd architecture look at the pages:

Now that you have a complete view of the architecture, we can get to the heart of the matter.

Minimum application xtd.forms

app.cpp
#include <xtd/xtd>

auto main()->int {
  xtd::forms::application::run(xtd::forms::form {});
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.20)

project(app)
find_package(xtd REQUIRED)
add_sources(app.cpp)
target_type(GUI_APPLICATION)

Reherches of the dependencies of the application

Obviously it is not easy to see what the dependencies of the xtd application are.

We will retrieve the information from the different xtd libraries and its backend on the current platform.

I did the manipulation on the three main platforms to check if it works:

  • Linux (I chose the Fedora distribution but it will work for the other distributions)
  • macOS
  • Windows

First you have to modify the CMakeLists.txt a little like this:

cmake_minimum_required(VERSION 3.20)

project(app)

find_package(xtd REQUIRED)

#_______________________________________________________________________________
#                                     Gets libraries and frameworks informations
find_package(wxWidgets REQUIRED)
if (UNIX AND NOT APPLE)
  find_package(PkgConfig)
  pkg_check_modules(GTK gtk+-3.0)
endif ()

message(STATUS "")
message(STATUS "________________________________________________________________")
message(STATUS "                                             include directories")
message(STATUS "\${xtd_INCLUDE_DIRS} = ${xtd_INCLUDE_DIRS}")
message(STATUS "\${wxWidgets_INCLUDE_DIRS} = ${wxWidgets_INCLUDE_DIRS}")
if (UNIX AND NOT APPLE)
  message(STATUS "\${GTK_INCLUDE_DIRS} = ${GTK_INCLUDE_DIRS}")
endif ()

message(STATUS "________________________________________________________________")
message(STATUS "                                                       libraries")
message(STATUS "\${xtd_LIBRARIES} = ${xtd_LIBRARIES}")
message(STATUS "\${wxWidgets_LIBRARIES} = ${wxWidgets_LIBRARIES}")
if (UNIX AND NOT APPLE)
  message(STATUS "\${GTK_LIBRARIES} = ${GTK_LIBRARIES}")
endif ()

message(STATUS "________________________________________________________________")
message(STATUS "")

#_______________________________________________________________________________

add_sources(app.cpp)
target_type(GUI_APPLICATION)

Remarks I use wxWidgets because at the moment it is the only supported backend. I also take GTK because wxWidgets allows me to speed up the dev but is not enough so I also need GTK under linux. For macOS and Windows I use Cocoa and Win32 respectively to complete wxWidgets, but I don't need to specify them because these booksellers are directly accessible.

When we are going to run the command cmake .. from the build folder of our app, we will get on linux fedora (the other distributions will not necessarily have the same resulat):

-- 
-- ________________________________________________________________
--                                              include directories
-- ${xtd_INCLUDE_DIRS} = /usr/local/cmake/../include
-- ${wxWidgets_INCLUDE_DIRS} = /usr/lib64/wx/include/gtk3-unicode-3.2;/usr/include/wx-3.2
-- ${GTK_INCLUDE_DIRS} = /usr/include/gtk-3.0;/usr/include/pango-1.0;/usr/include;/usr/include/cloudproviders;/usr/include/cairo;/usr/include/gdk-pixbuf-2.0;/usr/include/webp;/usr/include/at-spi2-atk/2.0;/usr/include/at-spi-2.0;/usr/include/atk-1.0;/usr/lib64/pkgconfig/../../include/dbus-1.0;/usr/lib64/pkgconfig/../../lib64/dbus-1.0/include;/usr/include/fribidi;/usr/include/libxml2;/usr/include/pixman-1;/usr/include/harfbuzz;/usr/include/freetype2;/usr/include/libpng16;/usr/include/gio-unix-2.0;/usr/include/glib-2.0;/usr/lib64/glib-2.0/include;/usr/include/libmount;/usr/include/blkid;/usr/include/sysprof-6
-- ________________________________________________________________
--                                                        libraries
-- ${xtd_LIBRARIES} = xtd;xtd.core;xtd.drawing;xtd.forms;xtd.tunit;xtd
-- ${wxWidgets_LIBRARIES} = -pthread;;;-lwx_gtk3u_xrc-3.2;-lwx_gtk3u_html-3.2;-lwx_gtk3u_qa-3.2;-lwx_gtk3u_core-3.2;-lwx_baseu_xml-3.2;-lwx_baseu_net-3.2;-lwx_baseu-3.2
-- ${GTK_LIBRARIES} = gtk-3;gdk-3;z;pangocairo-1.0;pango-1.0;harfbuzz;atk-1.0;cairo-gobject;cairo;gdk_pixbuf-2.0;gio-2.0;gobject-2.0;glib-2.0
-- ________________________________________________________________
-- 
-- Configuring done (0.2s)
-- Generating done (0.0s)
-- Build files have been written to: /home/parallels/Projects/manually_build_xtd_forms_application/build

Thanks to this information I will be able to build my own tool to generate my application. We have:

  • The path of include files
  • The different xtd and backend libraries (toolkit) wxWidegets
  • As we are under Linux we also have the different GTK libraries

But the libraries used by xod.core are still missing. To retrieve them I will simply look for the information in the CMakeList.txt of the native library of the platform in this case xtd.core.native.linux: I'm looking for the lines including add_references(, there are several but the one that really interests me is this one:

add_references(dl rt asound uuid pthread)

We find the different libraries that xtd.core.native.linux needs:

  • dl
  • rt
  • asound
  • uuid
  • pthread

Generation of a simple bash script

For example, I will create a simple bash script that will execute g++ to compile our simple application without CMake. I added:

  • The different bookstores that were found above
  • Include files directories
  • libraries directories
  • Some necessary flags

I did a little formatting to make it readable.

build_linux.sh
#!/usr/bin/env bash

echo "manually build xtd forms application, copyright © 2025 Gammasoft"
echo ""

#_______________________________________________________________________________
#                                        manually compiling and linking commands
echo "building..."
g++ \
  app.cpp \
  -o app \
  -std=c++20 \
  \
  -I/usr/local/include \
  \
  -L/usr/local/lib \
  \
  -lxtd.tunit \
  -lxtd.forms \
  -lxtd.forms.native.wxwidgets \
  -lxtd.drawing \
  -lxtd.drawing.native.wxwidgets \
  -lxtd.core \
  -lxtd.core.native.linux \
  \
  -lwx_gtk3u_core-3.2 \
  -lwx_baseu-3.2 \
  \
  -lgtk-3 \
  -lgdk-3 \
  -lz \
  -lpangocairo-1.0 \
  -lpango-1.0 \
  -lharfbuzz \
  -latk-1.0 \
  -lcairo-gobject \
  -lcairo \
  -lgdk_pixbuf-2.0 \
  -lgio-2.0 \
  -lgobject-2.0 \
  -lglib-2.0 \
  \
  -ldl \
  -lrt \
  -lasound \
  -luuid \
  -lpthread

echo ""
echo "end"
Execute

All that's left is to execute from the terminal:

./build_linux.sh
./app

Remarks

  • This only works for a common configuration at a time T.
  • Any change in xtd, lib update, implementation of the different native backends, ... will disrupt the script / makefile /Qmake that you have created. It will therefore be necessary to arm ourselves with patience to rebuild what will have been broken by the xtd changes.
  • And as I said above, I will not support this, I repeat it is part of CMake's choice.
  • I therefore advise you not to go this way.

Et voilà.

I hope these explanations will help you and allow you to make the right choices.

Regards, Gammasoft71

gammasoft71 avatar Jun 13 '25 23:06 gammasoft71