1#
2#  W A R N I N G
3#  -------------
4#
5# This file is not part of the Qt API.  It exists purely as an
6# implementation detail.  It may change from version to version
7# without notice, or even be removed.
8#
9# We mean it.
10#
11
12load(qt_build_paths)
13
14!build_pass:git_build {
15    qtPrepareTool(QMAKE_SYNCQT, syncqt, , system)
16    minimal_syncqt {
17        QMAKE_SYNCQT += -minimal $$QMAKE_SYNCQT_OPTIONS
18    } else {
19        qtConfig(private_tests): \   # -developer-build
20            QMAKE_SYNCQT += -check-includes
21    }
22    for(mod, MODULE_INCNAME): \
23        QMAKE_SYNCQT += -module $$mod
24    QMAKE_SYNCQT += \
25        -version $$VERSION -outdir $$system_quote($$MODULE_BASE_OUTDIR) \
26        -builddir $$system_quote($$REAL_MODULE_BASE_OUTDIR) $$MODULE_SYNCQT_DIR
27    !silent: message($$QMAKE_SYNCQT)
28    system($$QMAKE_SYNCQT)|error("Failed to run: $$QMAKE_SYNCQT")
29
30    !minimal_syncqt {
31        include-distclean.commands = \
32            $$QMAKE_DEL_TREE $$shell_quote($$shell_path($$MODULE_BASE_OUTDIR/include/$$MODULE_INCNAME))
33        QMAKE_EXTRA_TARGETS += include-distclean
34        DISTCLEAN_DEPS += include-distclean
35    }
36}
37
38# Pre-generated headers in the source tree (tar-ball) and
39# - shadow build or
40# - non-shadow non-prefix build of a module which is not qtbase
41#   (because the build-time generated headers all end up in qtbase).
42!git_build: \
43        if(!equals(_PRO_FILE_PWD_, $$OUT_PWD) \
44           |if(!prefix_build:!equals(MODULE_BASE_INDIR, $$[QT_HOST_PREFIX]))): \
45    CONFIG += split_incpath
46
47# To avoid stuffing the code with repetetive conditionals,
48# we parametrize the names of the variables we assign to.
49
50# Internal modules have no private part - they *are* private.
51!internal_module: \
52    prv = _PRIVATE
53
54# When doing a framework build with a prefix, the module needs to point
55# into the frameworks' Headers dirs directly, as no shared include/ dir
56# is installed.
57# However, during the build, it needs to point into the shared include/
58# dir, as the framework doesn't even exist yet. For bootstrapped modules
59# which borrow headers from "proper" modules, this situation persists
60# even beyond the module's own build. The implication of this is that
61# qmake might never use a framework's headers in a non-prefix build,
62# as there is no separate set of .pri files for users outside Qt.
63# Borrowing is assumed to happen from modules which, in a framework build,
64# actually are frameworks.
65prefix_build:module_frameworks: \
66    fwd = _FWD
67# When using a split include path during the build, the installed module's
68# include path is also structurally different from that in the build dir.
69prefix_build:split_incpath: \
70    sfwd = _FWD
71
72ibase = \$\$QT_MODULE_INCLUDE_BASE
73MODULE$${fwd}_INCLUDES = $$ibase
74split_incpath {
75    bibase = $$val_escape(MODULE_BASE_OUTDIR)/include
76    MODULE$${sfwd}_INCLUDES += $$bibase
77}
78for(mod, MODULE_INCNAME) {
79    mibase = $$ibase/$$mod
80    MODULE$${fwd}_INCLUDES += $$mibase
81    MODULE$${fwd}$${prv}_INCLUDES += $$mibase/$$VERSION $$mibase/$$VERSION/$$mod
82    split_incpath {
83        mbibase = $$bibase/$$mod
84        MODULE$${sfwd}_INCLUDES += $$mbibase
85        generated_privates: \
86            MODULE$${sfwd}$${prv}_INCLUDES += $$mbibase/$$VERSION $$mbibase/$$VERSION/$$mod
87    }
88    prefix_build:module_frameworks {
89        mfbase = \$\$QT_MODULE_LIB_BASE/$${mod}$${QT_LIBINFIX}.framework/Headers
90        MODULE_INCLUDES += $$mfbase
91        MODULE$${prv}_INCLUDES += $$mfbase/$$VERSION $$mfbase/$$VERSION/$$mod
92    }
93}
94MODULE_INCLUDES += $$MODULE_AUX_INCLUDES
95MODULE_PRIVATE_INCLUDES += $$MODULE_PRIVATE_AUX_INCLUDES
96
97minimal_syncqt: return()
98
99defineTest(syncQtResolve) {
100    out =
101    for (f, SYNCQT.$$1): \
102        out += $$absolute_path($$f, $$2)
103    SYNCQT.$$1 = $$out
104    export(SYNCQT.$$1)
105}
106
107#load up the headers info
108git_build: \
109    INC_PATH = $$MODULE_BASE_OUTDIR
110else: \
111    INC_PATH = $$MODULE_BASE_INDIR
112include($$INC_PATH/include/$$MODULE_INCNAME/headers.pri, "", true)
113syncQtResolve(HEADER_FILES, $$_PRO_FILE_PWD_)
114syncQtResolve(PRIVATE_HEADER_FILES, $$_PRO_FILE_PWD_)
115syncQtResolve(QPA_HEADER_FILES, $$_PRO_FILE_PWD_)
116syncQtResolve(GENERATED_HEADER_FILES, $$INC_PATH/include/$$MODULE_INCNAME)
117!lib_bundle: \  # Headers are embedded into the bundle, so don't install them separately.
118    CONFIG += qt_install_headers
119
120alien_syncqt: return()
121
122MODULE_INC_OUTDIR = $$MODULE_BASE_OUTDIR/include/$$MODULE_INCNAME
123
124isEmpty(MODULE_CFG_FILE): MODULE_CFG_FILE = qt$${MODULE}-config
125exists($$OUT_PWD/$${MODULE_CFG_FILE}.h) {
126    fwd_rel = $$relative_path($$OUT_PWD, $$REAL_MODULE_BASE_OUTDIR)
127    SYNCQT.INJECTIONS += \
128        $$fwd_rel/$${MODULE_CFG_FILE}.h:$${MODULE_CFG_FILE}.h \
129        $$fwd_rel/$${MODULE_CFG_FILE}_p.h:$$MODULE_VERSION/$$MODULE_INCNAME/private/$${MODULE_CFG_FILE}_p.h
130}
131
132for (injection, SYNCQT.INJECTIONS) {
133    injects = $$split(injection, :)
134    dst_hdr = $$absolute_path($$member(injects, 0), $$REAL_MODULE_BASE_OUTDIR)
135    ofwd_hdr = $$member(injects, 1)
136    fwd_hdr = $$replace(ofwd_hdr, ^\\^, )
137    MAIN_FWD = $$MODULE_INC_OUTDIR/$$fwd_hdr
138    MAIN_FWD_CONT = '$${LITERAL_HASH}include "$$relative_path($$dst_hdr, $$dirname(MAIN_FWD))"'
139    write_file($$MAIN_FWD, MAIN_FWD_CONT)|error()
140    equals(fwd_hdr, ofwd_hdr): touch($$MAIN_FWD, $$dst_hdr)
141    !git_build: QMAKE_DISTCLEAN += $$MAIN_FWD
142    !contains(ofwd_hdr, .*/private/.*): \
143        SYNCQT.INJECTED_HEADER_FILES += $$dst_hdr
144    else: \
145        SYNCQT.INJECTED_PRIVATE_HEADER_FILES += $$dst_hdr
146    injects = $$member(injects, 2, -1)
147    for (inject, injects) {
148        CLASS_FWD = $$MODULE_INC_OUTDIR/$$inject
149        CLASS_FWD_CONT = '$${LITERAL_HASH}include "$$fwd_hdr"'
150        write_file($$CLASS_FWD, CLASS_FWD_CONT)|error()
151        touch($$CLASS_FWD, $$MAIN_FWD)
152        !git_build: QMAKE_DISTCLEAN += $$CLASS_FWD
153        SYNCQT.INJECTED_HEADER_FILES += $$CLASS_FWD
154    }
155}
156
157autogen_warning = \
158    "/* This file was generated by qmake with the info from <root>/$$relative_path($$_PRO_FILE_, $$MODULE_BASE_INDIR). */"
159
160# Create a module master depends header
161MODULE_MASTER_DEPS_HEADER = $$MODULE_BASE_OUTDIR/include/$$MODULE_INCNAME/$${MODULE_INCNAME}Depends
162!build_pass {
163    MODULE_MASTER_DEPS_HEADER_CONT = $$autogen_warning
164    MODULE_MASTER_DEPS_HEADER_CONT += "$${LITERAL_HASH}ifdef __cplusplus /* create empty PCH in C mode */"
165    for(dep, MODULE_DEPENDS) {
166        depname = $$eval(QT.$${dep}.master_header)
167        isEmpty(depname): \
168            depname = $$eval(QT.$${dep}.name)
169        MODULE_MASTER_DEPS_HEADER_CONT += "$${LITERAL_HASH}include <$$depname/$$depname>"
170    }
171    MODULE_MASTER_DEPS_HEADER_CONT += "$${LITERAL_HASH}endif"
172    write_file($$MODULE_MASTER_DEPS_HEADER, MODULE_MASTER_DEPS_HEADER_CONT)|error()
173    !git_build: QMAKE_DISTCLEAN += $$MODULE_MASTER_DEPS_HEADER
174}
175SYNCQT.HEADER_FILES += $$MODULE_MASTER_DEPS_HEADER
176
177# Automatically enable precompiled headers for Qt modules with more than 2 sources
178combined_SOURCES = $$SOURCES $$OBJECTIVE_SOURCES
179count(combined_SOURCES, 2, >) {
180    # except for Gcc/Windows: Larger precompiled headers crash cc1plus.exe
181    # (e.g. with i686-4.8.2-release-posix-dwarf-rt_v3-rev3)
182    !if(gcc:equals(QMAKE_HOST.os, Windows)):!equals(TEMPLATE, aux) {
183        !defined(PRECOMPILED_HEADER, "var"): PRECOMPILED_HEADER = $$MODULE_MASTER_DEPS_HEADER
184    }
185} else {
186    CONFIG -= precompile_header
187}
188unset(combined_SOURCES)
189
190headersclean:!internal_module {
191    # Make sure that the header compiles with our strict options
192    hcleanDEFS = -DQT_NO_CAST_TO_ASCII=1 \
193                 -DQT_NO_CAST_FROM_ASCII=1 \
194                 -UQT_RESTRICTED_CAST_FROM_ASCII \
195                 -DQT_STRICT_ITERATORS \
196                 -DQT_NO_URL_CAST_FROM_STRING=1 \
197                 -DQT_NO_CAST_FROM_BYTEARRAY=1 \
198                 -DQT_NO_KEYWORDS=1 \
199                 -DQT_USE_QSTRINGBUILDER \
200                 -DQT_USE_FAST_OPERATOR_PLUS \
201                 -Dsignals=int \
202                 -Dslots=int \
203                 -Demit=public: \
204                 -Dforeach=public: \
205                 -Dforever=public:
206
207    gcc:!rim_qcc {
208        # Turn on some extra warnings not found in -Wall -Wextra.
209        # Common to GCC, Clang and ICC (and other compilers that masquerade as GCC):
210        hcleanFLAGS = -Wall -Wextra -Werror \
211                      -Woverloaded-virtual -Wshadow -Wundef -Wfloat-equal \
212                      -Wnon-virtual-dtor -Wpointer-arith -Wformat-security \
213                      -Wno-long-long -Wno-variadic-macros -pedantic-errors
214
215        intel_icc {
216            # these warnings are disabled because explicit constructors with zero or
217            # multiple arguments are permitted in C++11:
218            # 2304: non-explicit constructor with single argument may cause implicit type conversion
219            # 2305: declaration of 'explicit' constructor without a single argument is redundant
220            hcleanFLAGS += -wd2304,2305
221            greaterThan(QT_ICC_MAJOR_VERSION, 13) {
222                # ICC 14+ has a bug with -Wshadow, emitting it for cases where there's no shadowing
223                # (issue ID 0000698329, task DPD200245740)
224                hcleanFLAGS -= -Wshadow
225            }
226        } else {
227            # options accepted by GCC and Clang
228            hcleanFLAGS += -Wchar-subscripts -Wold-style-cast
229
230            !contains(QT_ARCH, arm):!contains(QT_ARCH, mips): \
231                hcleanFLAGS += -Wcast-align
232
233            clang_ver = $${QT_CLANG_MAJOR_VERSION}.$${QT_CLANG_MINOR_VERSION}
234            versionAtLeast(clang_ver, 3.8): hcleanFLAGS += -Wdouble-promotion
235
236            !clang {
237                # options accepted only by GCC
238
239                gcc_ver = $${QT_GCC_MAJOR_VERSION}.$${QT_GCC_MINOR_VERSION}
240                versionAtLeast(gcc_ver, 4.5): hcleanFLAGS += -Wdouble-promotion
241                versionAtLeast(gcc_ver, 4.9): hcleanFLAGS += -Wfloat-conversion
242                # GCC 9 has a lot of false positives relating to this, so disable completely
243                greaterThan(QT_GCC_MAJOR_VERSION, 8): hcleanFLAGS += -Wno-deprecated-copy
244                # GCC 9 introduced this
245                greaterThan(QT_GCC_MAJOR_VERSION, 8): hcleanFLAGS += -Wno-redundant-move
246                # GCC 9 introduced this
247                greaterThan(QT_GCC_MAJOR_VERSION, 8): hcleanFLAGS += -Wno-format-overflow
248                # GCC 9 introduced this
249                greaterThan(QT_GCC_MAJOR_VERSION, 8): hcleanFLAGS += -Wno-init-list-lifetime
250
251                c++11 {
252                    # only enabled for actual c++11 builds due to
253                    # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52806
254                    hcleanFLAGS += -Wzero-as-null-pointer-constant
255                }
256            }
257        }
258
259        # Use strict mode C++11 or C++98, with no GNU extensions (see -pedantic-errors above).
260        # The module might set CONFIG += c++11, but it might also change QMAKE_CXXFLAGS_CXX11
261        # or the module (or the mkspec) can set the C++11 flag on QMAKE_CXXFLAGS
262        # (or QMAKE_CXXFLAGS_{RELEASE,DEBUG} but that's unlikely).
263        c++11:contains(QMAKE_CXXFLAGS_CXX11, -std=gnu++11) {
264            hcleanFLAGS += -std=c++11
265        } else: contains(QMAKE_CXXFLAGS, -std=gnu++11) {
266            hcleanFLAGS += -std=c++11
267        } else: c++11:contains(QMAKE_CXXFLAGS_CXX11, -std=gnu++0x) {
268            hcleanFLAGS += -std=c++0x
269        } else: contains(QMAKE_CXXFLAGS, -std=gnu++0x) {
270            hcleanFLAGS += -std=c++0x
271        } else: !c++11:!contains(QMAKE_CXXFLAGS, -std=c++0x):!contains(QMAKE_CXXFLAGS, -std=c++11) {
272            hcleanFLAGS += -std=c++98
273        }
274
275        hcleanCOMMAND = $(CXX) -c $(CXXFLAGS) $$hcleanFLAGS $(INCPATH) $$hcleanDEFS -xc++ ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT}
276    } else: msvc:!intel_icl {
277        # 4180: qualifier applied to function type has no meaning; ignored
278        # 4458: declaration of 'identifier' hides class member
279        # -Za enables strict standards behavior, but we can't add it because
280        # <windows.h> and <GL.h> violate the standards.
281        hcleanFLAGS = -WX -W3 -wd4180 -wd4458
282
283        # MSVC 2015 (compiler version 19.0):
284        # 4577: 'noexcept' used with no exception handling mode specified; termination on exception is not guaranteed. Specify /EHsc
285        greaterThan(QMAKE_MSC_VER, 18): hcleanFLAGS += -wd4577
286
287        hcleanCOMMAND = $(CXX) -c $(CXXFLAGS) $$hcleanFLAGS $(INCPATH) $$hcleanDEFS -FI${QMAKE_FILE_IN} -Fo${QMAKE_FILE_OUT} \
288                        $$[QT_INSTALL_DATA/src]/mkspecs/features/data/dummy.cpp
289    }
290
291    !isEmpty(hcleanCOMMAND):if(!qtConfig(debug_and_release)|CONFIG(release, debug|release)) {
292        CLEAN_HEADERS =
293        for (h, SYNCQT.CLEAN_HEADER_FILES) {
294            hh = $$split(h, :)
295            hr = $$member(hh, 1)
296            isEmpty(hr)|qtConfig($$hr): \
297                CLEAN_HEADERS += $$member(hh, 0)
298        }
299        CLEAN_HEADERS -= $$HEADERSCLEAN_EXCLUDE
300        header_check.dependency_type = TYPE_C
301        header_check.CONFIG += no_link
302        header_check.output = ${QMAKE_VAR_OBJECTS_DIR}header_${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)}
303        header_check.input = CLEAN_HEADERS
304        header_check.variable_out = PRE_TARGETDEPS
305        header_check.name = headercheck ${QMAKE_FILE_IN}
306        header_check.commands = $$hcleanCOMMAND
307        QMAKE_EXTRA_COMPILERS += header_check
308    }
309    unset(hcleanCOMMAND)
310    unset(hcleanFLAGS)
311    unset(hcleanDEFS)
312}
313