609b8df840395da9c11cd178e46becf4b0940516
[WebKit-https.git] / Tools / qmake / mkspecs / features / functions.prf
1 # -------------------------------------------------------------------
2 # This file defines a few useful functions that are exposed to the
3 # real project files.
4 #
5 # See 'Tools/qmake/README' for an overview of the build system
6 # -------------------------------------------------------------------
7
8 defineReplace(toSanitizedPath) {
9     path = $$1
10     win32-msvc* {
11         components = $$split(path, :)
12         count(components, 2): path = $$lower($$first(components)):$$last(components)
13         return($$replace(path, \\\\, /))
14     } else {
15         return($$path)
16     }
17 }
18
19 defineReplace(toSystemPath) {
20     return($$replace(1, [/\\\\], $${QMAKE_DIR_SEP}))
21 }
22
23 defineReplace(toEvaluatablePath) {
24     return($$replace(1, \\\\, \\\\\\\\))
25 }
26
27 defineReplace(computeSubdirVariables) {
28     unset(subdir)
29     subdir = $$1
30
31     scope = $$subdir
32     path = $$eval($${subdir}.file)
33     isEmpty(path): path = $$eval($${subdir}.subdir)
34     isEmpty(path) {
35         path = $${subdir}
36         # We can't use scope as a variable scope, so unset it for
37         # now and we'll compute a new scope based on the target.
38         unset(scope)
39     }
40
41     # Technically this could be a directory, but we assume sane naming.
42     is_file = $$find(path, \\.pr[io]$)
43     isEmpty(is_file) {
44         subdirectory = $$path
45     } else {
46         subdirectory = $$dirname(path)
47         filename = $$basename(path)
48     }
49
50     # Make directory relative
51     !isEmpty(subdirectory):subdirectory = $$replace(subdirectory, ^$${_PRO_FILE_PWD_}/,)
52
53     !isEmpty(subdirectory) {
54         subdir_command = cd $$toSystemPath($${subdirectory}$${QMAKE_DIR_SEP}) &&
55     }
56
57     target = $$eval($${subdir}.target)
58     isEmpty(target) {
59         sanitizedPath = $$toSanitizedPath($$path)
60         target = sub-$$replace(sanitizedPath, [^a-zA-Z0-9_], -)
61     }
62
63     isEmpty(scope): scope = $$target
64
65     makefile = $$eval($${subdir}.makefile)
66     isEmpty(makefile) {
67         !isEmpty(filename) {
68             filebase = $$replace(filename, \\..*$,)
69             dirbase = $$basename(subdirectory)
70             !equals(filebase, $$dirbase) {
71                 makefile = $(MAKEFILE).$$filebase
72             } else {
73                 makefile = $(MAKEFILE)
74             }
75         } else {
76             makefile = $(MAKEFILE)
77         }
78     }
79
80     subdir_command = $$toEvaluatablePath($$subdir_command)
81     eval($${scope}.subdir_command = $$subdir_command)
82     export($${scope}.subdir_command)
83
84     eval($${scope}.target = $$target)
85     export($${scope}.target)
86
87     eval($${scope}.makefile = $$makefile)
88     export($${scope}.makefile)
89
90     return($$scope)
91 }
92
93 defineReplace(buildDirForSource) {
94     unset(source)
95     source = $$1
96
97     return($${ROOT_BUILD_DIR}$${QMAKE_DIR_SEP}$$replace(source, ^$${BUILD_SUBDIR}$${QMAKE_DIR_SEP},))
98 }
99
100 # Qmake has QMAKE_FILE_IN_PATH, but nothing for the out file
101 # This allows you do do ${QMAKE_FUNC_FILE_OUT_PATH}
102 defineReplace(PATH) {
103     return($$dirname(1))
104 }
105
106 # We need both versions, in case the first one returns an empty string
107 defineReplace(FILE_OUT_PATH) {
108     return($$dirname(2))
109 }
110
111 # addStrictSubdirOrderBetween(firstSubdir, secondSubdir)
112 defineTest(addStrictSubdirOrderBetween) {
113     unset(firstSubdir)
114     unset(secondSubdir)
115
116     firstSubdir = $$1
117     secondSubdir = $$2
118
119     firstVariables = $$computeSubdirVariables($${firstSubdir})
120     secondVariables = $$computeSubdirVariables($${secondSubdir})
121
122     !contains(TEMPLATE, subdirs) {
123         error("Strict subdir dependencies can only be used with subdirs template")
124     }
125
126     firstSubdirFile = $$eval($${firstSubdir}.file)
127     secondSubdirFile = $$eval($${secondSubdir}.file)
128
129     isEmpty(firstSubdirFile)|isEmpty(secondSubdirFile) {
130         error("Missing subdir file ($$firstSubdirFile, $$secondSubdirFile)")
131     }
132
133     # Make sure the order is right
134     SUBDIRS -= $$firstSubdir $$secondSubdir
135     SUBDIRS += $$firstSubdir $$secondSubdir
136     NO_RECURSIVE_QMAKE_SUBDIRS += $$firstSubdir $$secondSubdir
137     CONFIG *= ordered
138
139     first_base_target = sub-$$replace(firstSubdirFile, [^a-zA-Z0-9_], -)
140     second_base_target = sub-$$replace(secondSubdirFile, [^a-zA-Z0-9_], -)
141
142     # Use a custom target for making the derived sources instead of the default ones,
143     # as the default ones depend on $(MAKEFILE), while we want to depend on *qmake_all.
144     # Without this rule we end up running qmake twice for the derived sources, as well as
145     # introducing a race condition where we run "qmake -o Makefile.DerivedSources" at the
146     # same time as we run "make -f Makefile.DerivedSources", resulting in make reading a
147     # half-written makefile.
148     derived_make_for_qmake.target = $${first_base_target}-make_for_qmake
149     derived_make_for_qmake.depends = $${first_base_target}-qmake_all
150     derived_make_for_qmake.commands = $(MAKE) -f $$eval($${firstSubdir}.makefile)
151     QMAKE_EXTRA_TARGETS += derived_make_for_qmake
152
153     # This target ensures that running "make qmake" will force both qmake and make
154     # to be run on the derived sources before running qmake on the target, so that
155     # qmake can pick up the right dependencies for the target based on the derived
156     # sources that were generated.
157     target_make_qmake.target = $${second_base_target}-qmake_all
158     target_make_qmake.depends = $${derived_make_for_qmake.target}
159     QMAKE_EXTRA_TARGETS += target_make_qmake
160
161     GNUmake {
162         # This target ensures that running make before any makefiles have been created
163         # will still force qmake and make to be run on the derived sources first.
164         target_make.target = $$eval($${secondSubdir}.makefile)
165
166         # We use order-only-prerequisites so that we can run make on the derived sources
167         # without triggering a qmake run on the target due to updated dependencies.
168         target_make.depends = "| $${first_base_target}-make_default-ordered"
169
170         QMAKE_EXTRA_TARGETS += target_make
171     }
172
173     export(SUBDIRS)
174     export(NO_RECURSIVE_QMAKE_SUBDIRS)
175     export(CONFIG)
176     export(target_make_qmake.target)
177     export(target_make_qmake.depends)
178     export(derived_make_for_qmake.target)
179     export(derived_make_for_qmake.depends)
180     export(derived_make_for_qmake.commands)
181     export(target_make.target)
182     export(target_make.depends)
183     export(QMAKE_EXTRA_TARGETS)
184     return(true)
185 }
186
187 # Check if we have the given Qt version. The major version needs
188 # to be exact, the minor and patch version is same or higher
189 defineTest(haveQt) {
190     count(ARGS, 1, lessThan)|count(ARGS, 3, greaterThan) {
191         error("Unexpected number of arguments: haveQt($$ARGS)")
192     }
193
194     !equals(QT_MAJOR_VERSION, $$1): return(false)
195
196     count(ARGS, 1, greaterThan) {
197         lessThan(QT_MINOR_VERSION, $$2): return(false)
198         greaterThan(QT_MINOR_VERSION, $$2): return(true)
199
200         count(ARGS, 2, greaterThan) {
201             lessThan(QT_PATCH_VERSION, $$3): return(false)
202             greaterThan(QT_PATCH_VERSION, $$3): return(true)
203         }
204     }
205
206     return(true)
207 }
208
209 defineTest(prependEach) {
210     unset(variable)
211     unset(prefix)
212
213     variable = $$1
214     prefix = $$2
215
216     original_values = $$unique($$variable)
217
218     for(value, original_values) {
219         values += $${prefix}$${value}
220     }
221
222     eval($$variable = $$values)
223     export($$variable)
224
225     return(true)
226 }
227
228 defineTest(needToLinkLibrary) {
229     unset(name)
230
231     name = $$1
232
233     config_step {
234         return(true)
235     } else:force_static_libs_as_shared {
236         contains(DEFINES, BUILDING_$$name): return(false)
237         return(true)
238     }
239     return(false)
240 }
241
242 defineTest(linkLibrary) {
243     unset(path)
244     unset(target)
245
246     path = $$1
247     target = $$2
248
249     force_static_libs_as_shared {
250             LIBS = -L$${ROOT_BUILD_DIR}/lib -l$$target $$LIBS
251     } else {
252
253         mac {
254             LIBS = -Wl,-force_load,$${path}$${QMAKE_DIR_SEP}lib$${target}.a $$LIBS
255         } else:win32-msvc*|wince*|win32-icc {
256             LIBS = /OPT:REF -l$$target $$LIBS
257         } else {
258             LIBS = -Wl,-whole-archive -l$$target -Wl,-no-whole-archive $$LIBS
259         }
260
261         win32-msvc*|wince*|win32-icc {
262             LIBS = -L$$path $$LIBS
263             POST_TARGETDEPS += $${path}$${QMAKE_DIR_SEP}$${target}.lib
264         } else {
265             QMAKE_LIBDIR = $$path $$QMAKE_LIBDIR
266             POST_TARGETDEPS += $${path}$${QMAKE_DIR_SEP}lib$${target}.a
267         }
268
269         # The following line is to prevent qmake from adding jscore to libQtWebKit's prl dependencies.
270         # The compromise we have to accept by disabling explicitlib is to drop support to link QtWebKit
271         # statically in applications (which isn't used often because, among other things, of licensing obstacles).
272         CONFIG -= explicitlib
273         CONFIG -= staticlib
274
275     }
276
277     export(LIBS)
278     export(QMAKE_LIBDIR)
279     export(POST_TARGETDEPS)
280     export(CONFIG)
281     return(true)
282 }