How to fix the Unbound module Graphics in an ocaml project

Image
From ~/pr/gitl/ocaml-gol In a constant effort to learn new programming languages, I'm currently trying to use ocaml , a free and open-source general-purpose, multi-paradigm programming language maintained at the Inria . It's basically an extension of Caml with object-oriented features. I'm mostly interested by its functionnal and pattern matching features but the module part of the language can be a bit difficult to understand for someone with little to none ML (Meta Language) background.   The error When trying to use the graphics module to create a graphical window and go just a little further than the simplest helloworld program, here is the result : If the project uses dune : (executable (name ocaml_project) (libraries lwt.unix graphics) ) with this code : let () = Printf.printf "Hello, world!\n";; Lwt_io.printf "Hello, world!\n";; Graphics.open_graph " 800x600";; The first times I built this project running the du...

How to use Qt5 ui form in C++ with cmake

Qt is a cross-platform application framework and widget library written in C++. It is shiped with a form designer simply called designer which save the created mockup in XML format with the .ui extension.

While Qt is generally used with Qt its own build called qmake and a project file, if you need external dependency checks and more control on the building process, you may want to use it with cmake.

The Qt designer tool creating a new widget .ui file

 

The .ui form

The .ui file contains the form definition. The simplest way to get one is to create it using the designer tool but this is plain XML so you can copy/paste it with a simple text editor as well. Let's call it form.ui :
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Form</class>
 <widget class="QWidget" name="Form">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>300</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
 </widget>
 <resources/>
 <connections/>
</ui>

The cmake script

Here, we have to list MOC-handled files in sources (.ui and .qrc). MOC is the Qt's Meta-Object Compiler. we also need to search for the Qt5 Widgets components and add its ldflags to our project

cmake_minimum_required(VERSION 3.1.0)

project(prjname
  VERSION 0.0.0
  LANGUAGES CXX)
set(REVISION 2)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Here we will auto-handle .ui .qrc files using MOC
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)

find_package(Qt5 COMPONENTS Widgets REQUIRED)

# Here we list sources, including .ui and .qrc files
set(SRC
  src/main.cpp
  
  src/ui/MainWindow.ui

  media/resources.qrc
)

add_executable(prjname ${SRC}) 
target_link_libraries(udp-browser ${LIBS_LIBRARIES} prjname Qt5::Widgets)

The C++ code

Since MOC will generate a header based on our .ui form, the key here is to understand the name of the header of the MOC-generated file. Generally, you have to prepend the CamelCase ui name with ui/ui_ :

#ifndef __MAIN_WINDOW_HPP__
#define __MAIN_WINDOW_HPP__

#include "ui/ui_MainWindow.h" // MOC generated file

class MainWindow : public QMainWindow
{
 Q_OBJECT

public:
  explicit MainWindow(Preferences*, QWidget *parent = nullptr):
  QMainWindow()
  {
  	ui.setupUi(this);
  }
  virtual ~MainWindow();						

private:
  Ui::MainWindow ui; 

};

#endif // !__MAIN_WINDOW_HPP__

CMake example output

This is a part of the output that occurs after the make call, not the cmake .. one :*

[  5%] Automatic MOC and UIC for target udpb
[  5%] Built target udpb_autogen
[ 10%] Building CXX object CMakeFiles/udpb.dir/udpb_autogen/mocs_compilation.cpp.o

And obviously, the output continue with C++ files compilation until it reaches 100%.

Conclusion

UI forms are a fast way to develop new interface when you want to build desktop applications. The main challenge here is to understand how to name MOC-generated header in the C++ include statement. Once cmake script rules are correctly written, the re-compilation is automatic.

Comments

Popular posts from this blog

How to make a map of variant in C++