Syncqt: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
 
(6 intermediate revisions by the same user not shown)
Line 23: Line 23:
==Types of Qt header files==
==Types of Qt header files==
As you may notice in Qt we separate header files into two basic types – public and private.
As you may notice in Qt we separate header files into two basic types – public and private.
As a Qt contributor, you should already know that private headers have a '_p' suffix and
As a Qt contributor, you should already know that private headers have a <code>_p</code> suffix and
the API exposed by these headers doesn't guarantee cross-version source compatibility or ABI compatibility.
the API exposed by these headers doesn't guarantee cross-version source compatibility or ABI compatibility.
Also, some exceptions don't follow this generic '_p' convention, but
Also, some exceptions don't follow this generic <code>_p</code> convention, but
you will never see these header files in the module include directories.
you will never see these header files in the module include directories.
All private header files land inside version specific private includes directory,
All private header files land inside version specific private includes directory,
like ''include/QtCore/&lt;version&gt;/QtCore/private/''.
like <code>include/QtCore/<version>/QtCore/private/</code>.


From the syncqt perspective, these header file types have different processing and, as a result, syncqt produces different artifacts.
From the syncqt perspective, these header file types have different processing and, as a result, syncqt produces different artifacts.


There are also special header types such as QPA and RHI headers, that
There are also special header types such as QPA and RHI headers, that
are processed by syncqt like the [[#Private header files|private header files]], but deployed to the ''include/Qt&lt;Module&gt;/&lt;version&gt;/Qt&lt;Module&gt;/qpa/'' and ''include/Qt&lt;Module&gt;/&lt;version&gt;/Qt&lt;Module&gt;/rhi/'' directories, respectively.
are processed by syncqt like the [[#Private header files|private header files]], but deployed to the <code>include/Qt<Module>/<version>/Qt<Module>/qpa/</code> and <code>include/Qt<Module>/<version>/Qt<Module>/rhi/</code> directories, respectively.


==Private header files==
==Private header files==
Line 91: Line 91:


===Deployment path===
===Deployment path===
''include/Qt&lt;Module&gt;''
<code>include/Qt<Module></code>


==Pragmas==
==Pragmas==
Line 98: Line 98:
<syntaxhighlight lang="C++">
<syntaxhighlight lang="C++">
#ifdef 0
#ifdef 0
#  pragma &lt;pragma name&gt;
#  pragma <pragma name>
#endif
#endif
</syntaxhighlight>
</syntaxhighlight>
Line 105: Line 105:
====Syntax====
====Syntax====
<syntaxhighlight lang="C++">
<syntaxhighlight lang="C++">
#pragma qt_deprecates(&lt;deprecated header file&gt;[,&lt;major.minor&gt;])
#pragma qt_deprecates(<deprecated header file>[,<major.minor>])
</syntaxhighlight>
</syntaxhighlight>
====Description====
====Description====
Pragma indicates that the header file where this pragma is used replaces the one mentioned in pragma. The replaced header file will be generated containing a warning with the deprecation notice.
Pragma indicates that the header file where this pragma is used replaces the one mentioned in pragma. The replaced header file will be generated containing a warning with the deprecation notice.
Line 117: Line 118:
</syntaxhighlight>
</syntaxhighlight>


syncqt will generate the qtest_global.h header file with #include <QtTest/qttestglobal.h> and the warning that says that the file is deprecated and QtTest/qttestglobal.h should be used instead.
syncqt will generate the qtest_global.h header file with <code>#include <QtTest/qttestglobal.h></code> and the warning that says that the file is deprecated and <code>QtTest/qttestglobal.h</code> should be used instead.


Adding the version argument to the pragma will also limit the deprecated header file lifetime. Once Qt reaches the version that is set as the second argument, the deprecated header file will not be generated by syncqt, but syncqt will show the warning when compiling the Qt itself.
Adding the version argument to the pragma will also limit the deprecated header file lifetime. Once Qt reaches the version that is set as the second argument, the deprecated header file will not be generated by syncqt, but syncqt will show the warning when compiling the Qt itself.
Line 143: Line 144:
</syntaxhighlight>
</syntaxhighlight>
====Description====
====Description====
When syncqt faces this pragma in code it temporarily suspends checking the header file for error and collecting artifacts to generate additional header files. The processing can be resumed by the [[#Pragma qt_sync_resume_processing|qt_sync_resume_processing]] pragma. If qt_sync_suspend_processing is not followed by qt_sync_resume_processing the behavior of qt_sync_suspend_processing is the same as the behavior of [[Pragma qt_sync_stop_processing|qt_sync_stop_processing]].
When syncqt faces this pragma in code it temporarily suspends checking the header file for error and collecting artifacts to generate additional header files. The processing can be resumed by the [[#Pragma qt_sync_resume_processing|qt_sync_resume_processing]] pragma. If <code>qt_sync_suspend_processing</code> is not followed by <code>qt_sync_resume_processing</code> the behavior of <code>qt_sync_suspend_processing</code> is the same as the behavior of [[Pragma qt_sync_stop_processing|qt_sync_stop_processing]].


===Pragma qt_class===
===Pragma qt_class===
====Syntax====
====Syntax====
<syntaxhighlight lang="C++">
<syntaxhighlight lang="C++">
#pragma qt_class(&lt;symbol&gt;)
#pragma qt_class(<symbol>)
</syntaxhighlight>
</syntaxhighlight>
====Description====
====Description====
Line 170: Line 171:


==CMake integration==
==CMake integration==
syncqt is part of the Qt build system and it runs implicitly for all Qt modules that are created using the ''qt_internal_add_module'' command and other ''qt_internal_'' command that imply the ''qt_internal_add_module'' call.
syncqt is part of the Qt build system and it runs implicitly for all Qt modules that are created using the <code>qt_internal_add_module</code> command and other <code>qt_internal_</code> command that imply the <code>qt_internal_add_module</code> call.


There are not too many arguments of the ''qt_internal_add_module'' command that controls the syncqt behavior.
There are not too many arguments of the <code>qt_internal_add_module</code> command that controls the syncqt behavior.


===NO_SYNC_QT===
===NO_SYNC_QT===

Latest revision as of 14:06, 18 August 2023

syncqt is Qt's internal build tool that helps generating build and deployment artifacts such as:

  • CaMeL case header files named by public C++ symbols located in public module header files, e.g.
    #include <QtCore/QCoreApplication>
    
    because
    QCoreApplication
    
    is a public symbol / class
  • Header file that contains the module version information, and named as
    <module>Version
    
    , e.g.
    QtCoreVersion
    
  • A Linux linker (LD) version script, if applicable
  • Aliases or copies of header files categorised into a few different header types:
    public/private/qpa/rhi
    

syncqt work modes

Usually, you don't need to run syncqt directly, but use either module-specific or one of the special targets, that are created by the Qt build system. Two syncqt target types reflect two modes that syncqt is running in:

  • Header mode
  • All mode

The 'header' mode is the regular one that processes only those header files that are specified as syncqt argument. Within a build system, syncqt can be run in the 'header' mode <module>_sync_headers targets, e.g. Core_syncqt_headers.

The 'all' mode is the special one that you don't need to use while developing Qt. It processes all public header files that are found on the file system, recursively. syncqt can be run in 'all' mode using <module>_sync_all_public_headers. This mode is mostly useful when generating documentation, where the processing of private-like header files is not important.

Both modes have meta build system targets that can be used to run syncqt for all modules in specific modes:

  • sync_headers
  • sync_all_public_headers

Types of Qt header files

As you may notice in Qt we separate header files into two basic types – public and private.

As a Qt contributor, you should already know that private headers have a

_p

suffix and

the API exposed by these headers doesn't guarantee cross-version source compatibility or ABI compatibility.

Also, some exceptions don't follow this generic

_p

convention, but

you will never see these header files in the module include directories. All private header files land inside version specific private includes directory,

like

include/QtCore/<version>/QtCore/private/

.

From the syncqt perspective, these header file types have different processing and, as a result, syncqt produces different artifacts.

There are also special header types such as QPA and RHI headers, that

are processed by syncqt like the private header files, but deployed to the

include/Qt<Module>/<version>/Qt<Module>/qpa/

and

include/Qt<Module>/<version>/Qt<Module>/rhi/

directories, respectively.

Private header files

Checks

For private header files, the only sanity check that syncqt does is the "We meant it." check. Private header files should have a disclaimer that is named "We meant it." – if this disclaimer is missing in a freshly added private header file syncqt will warn you as follows:

WARNING: <file name> does not have the "We mean it." warning

Artifacts

For private headers, syncqt only produces the build-time header file aliases in the build directory. These aliases allow using conventional paths in include directives but are never installed or delivered as part of a Qt distribution.

Also, syncqt collects the symbols defined in private headers and generates the ld linker version scripts for Qt modules on Linux platforms.

Deployment path

include/Qt<Module>/<version>/Qt<Module>/private/

Public header files

Checks

User-facing public headers require a more accurate sanity check from syncqt. syncqt runs the following checks on these files:

Private header inclusion check
It's prohibited to include private header files in the public one. syncqt makes the preliminary check of include statements and throws the critical error if this has a place to be:
ERROR: <file name>:<line number> includes private header <private header name>
Wrapping QT_<BEGIN|END>NAMESPACE check
All Qt API need to be wrapped with
QT_<BEGIN|END>NAMESPACE
macros. This allows building and using Qt with an extra namespace. syncqt detects either missing macros or their inconsistent use and throws one of the errors if this has a place to be:
WARNING: <file name> does not include QT_BEGIN_NAMESPACE
Use of the full include qualifiers
For public header files we follow the common rule that full relative include path should be used when including header files that belong to the Qt modules. Developers should prefer using
#include <QtCore/QObject>
but not
#include <QObject>
in public header files. syncqt detects include directives that don't follow this convention and throws the error:
WARNING: <file name>:<line number> includes QObject when it should include QtCore/QObject

Artifacts

syncqt uses public headers to produce the following artifacts:

  • CaMeL case header file aliases
CaMeL case header files are aliases named after public Qt classes. syncqt uses public symbols, like classes, structures, typedefs, and aliases from header files and produces CaMeL case header files based on this input.
  • Deprecated header files
In situations when some public header files are not relevant anymore and should be removed, they should be marked as deprecated first so users have time to adapt their code and use the header file replacement. See #Pragma deprecates
  • Version header file
Header file that contains macros definitions with the module version information. This information is used by Qt versioning macros, but it's also possible to use them in user code directly.
  • "Master" header file
Header file with the
Qt<Module>
name. The file contains the includes of all public header files provided by the module. syncqt also checks if the public header contains
QT_REQUIRE_CONFIG
macros call and guards the header file including directive with corresponding
QT_CONFIG
check.

Also, syncqt produces the build time header file aliases in the build directory that allow using conventional paths in include directives. These aliases are never installed nor delivered as part of Qt distribution.

Deployment path

include/Qt<Module>

Pragmas

It's possible to control the syncqt behavior and output using the special C++ pragmas. To avoid any compilation error you should use these syncqt-specific pragmas as follows:

#ifdef 0
#  pragma <pragma name>
#endif

Pragma qt_deprecates

Syntax

#pragma qt_deprecates(<deprecated header file>[,<major.minor>])

Description

Pragma indicates that the header file where this pragma is used replaces the one mentioned in pragma. The replaced header file will be generated containing a warning with the deprecation notice. For example in qttestglobal.h there is(or was) the following code:

#if 0
#  pragma qt_deprecates(qtest_global.h)
#endif

syncqt will generate the qtest_global.h header file with

#include <QtTest/qttestglobal.h>

and the warning that says that the file is deprecated and

QtTest/qttestglobal.h

should be used instead.

Adding the version argument to the pragma will also limit the deprecated header file lifetime. Once Qt reaches the version that is set as the second argument, the deprecated header file will not be generated by syncqt, but syncqt will show the warning when compiling the Qt itself.

Pragma qt_sync_skip_header_check

Syntax

#pragma qt_sync_skip_header_check

Description

This pragma tells syncqt that it should ignore any errors that are found in a header file. Please use this pragma only if you are confident that the header matches the Qt's requirements.

Pragma qt_sync_stop_processing

Syntax

#pragma qt_sync_stop_processing

Description

This pragma tells syncqt that it should stop any header processing from the point where the pragma is found. syncqt stops both checking the header file for errors and collecting artifacts to generate additional header files.

Pragma qt_sync_suspend_processing

Syntax

#pragma qt_sync_suspend_processing

Description

When syncqt faces this pragma in code it temporarily suspends checking the header file for error and collecting artifacts to generate additional header files. The processing can be resumed by the qt_sync_resume_processing pragma. If

qt_sync_suspend_processing

is not followed by

qt_sync_resume_processing

the behavior of

qt_sync_suspend_processing

is the same as the behavior of qt_sync_stop_processing.

Pragma qt_class

Syntax

#pragma qt_class(<symbol>)

Description

The pragma requests generating of the header file alias with the symbol name. For example, use the following code in qassert.h:

#pragma qt_class(QtAssert)

syncqt generates the QtAssert header file with the inclusion of qassert.h.

Note: syncqt doesn't detect the file name collisions at the moment when this topic is written, so conflicting files will be overwritten in undefined order.

Pragma qt_no_master_include

Syntax

#pragma qt_no_master_include

Description

The pragma indicates to syncqt that the header file shouldn't be included in the module's master header file.

CMake integration

syncqt is part of the Qt build system and it runs implicitly for all Qt modules that are created using the

qt_internal_add_module

command and other

qt_internal_

command that imply the

qt_internal_add_module

call. There are not too many arguments of the

qt_internal_add_module

command that controls the syncqt behavior.

NO_SYNC_QT

Skips syncqt processing of the module header files.

<PRIVATE|QPA|RHI>_HEADER_FILTERS

Indicates accepts the CMake regular expression as an argument and indicates how header files of the corresponding type should be filtered from others.

HEADER_SYNC_SOURCE_DIRECTORY

The source directory for the header sync procedure. Header files outside this directory will be ignored by syncqt.