1# Copyright (C) 2009 Kevin Ollivier  All rights reserved.
2#
3# Redistribution and use in source and binary forms, with or without
4# modification, are permitted provided that the following conditions
5# are met:
6# 1. Redistributions of source code must retain the above copyright
7#    notice, this list of conditions and the following disclaimer.
8# 2. Redistributions in binary form must reproduce the above copyright
9#    notice, this list of conditions and the following disclaimer in the
10#    documentation and/or other materials provided with the distribution.
11#
12# THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
13# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
15# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
16# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
17# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
18# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
19# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
20# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23#
24# Common elements of the waf build system shared by all projects.
25
26import commands
27import os
28import platform
29import re
30import sys
31
32import Options
33
34from build_utils import *
35from waf_extensions import *
36
37# to be moved to wx when it supports more configs
38from wxpresets import *
39
40wk_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../..'))
41
42if sys.platform.startswith('win'):
43    if not 'WXWIN' in os.environ:
44        print "Please set WXWIN to the directory containing wxWidgets."
45        sys.exit(1)
46
47    wx_root = os.environ['WXWIN']
48else:
49    wx_root = commands.getoutput('wx-config --prefix')
50
51jscore_dir = os.path.join(wk_root, 'Source', 'JavaScriptCore')
52webcore_dir = os.path.join(wk_root, 'Source', 'WebCore')
53wklibs_dir = os.path.join(wk_root, 'WebKitLibraries')
54
55common_defines = []
56common_cxxflags = []
57common_includes = []
58common_libs = []
59common_libpaths = []
60common_frameworks = []
61
62ports = [
63    'Brew',
64    'Chromium',
65    'Gtk',
66    'Haiku',
67    'Mac',
68    'None',
69    'Qt',
70    'Safari',
71    'Win',
72    'Wince',
73    'wx',
74]
75
76port_uses = {
77    'wx': ['CURL', 'WXGC'],
78}
79
80jscore_dirs = [
81    'API',
82    'bytecode',
83    'bytecompiler',
84    'debugger',
85    'DerivedSources',
86    'heap',
87    'interpreter',
88    'jit',
89    'parser',
90    'profiler',
91    'runtime',
92    'wtf',
93    'wtf/text',
94    'wtf/unicode',
95    'wtf/unicode/icu',
96    'yarr',
97]
98
99webcore_dirs = [
100    'Source/WebCore/accessibility',
101    'Source/WebCore/bindings',
102    'Source/WebCore/bindings/cpp',
103    'Source/WebCore/bindings/generic',
104    'Source/WebCore/bindings/js',
105    'Source/WebCore/bridge',
106    'Source/WebCore/bridge/c',
107    'Source/WebCore/bridge/jsc',
108    'Source/WebCore/css',
109    'Source/WebCore/DerivedSources',
110    'Source/WebCore/dom',
111    'Source/WebCore/dom/default',
112    'Source/WebCore/editing',
113    'Source/WebCore/fileapi',
114    'Source/WebCore/history',
115    'Source/WebCore/html',
116    'Source/WebCore/html/canvas',
117    'Source/WebCore/html/parser',
118    'Source/WebCore/html/shadow',
119    'Source/WebCore/inspector',
120    'Source/WebCore/loader',
121    'Source/WebCore/loader/appcache',
122    'Source/WebCore/loader/archive',
123    'Source/WebCore/loader/cache',
124    'Source/WebCore/loader/icon',
125    'Source/WebCore/notifications',
126    'Source/WebCore/page',
127    'Source/WebCore/page/animation',
128    'Source/WebCore/platform',
129    'Source/WebCore/platform/animation',
130    'Source/WebCore/platform/graphics',
131    'Source/WebCore/platform/graphics/filters',
132    'Source/WebCore/platform/graphics/transforms',
133    'Source/WebCore/platform/image-decoders',
134    'Source/WebCore/platform/image-decoders/bmp',
135    'Source/WebCore/platform/image-decoders/gif',
136    'Source/WebCore/platform/image-decoders/ico',
137    'Source/WebCore/platform/image-decoders/jpeg',
138    'Source/WebCore/platform/image-decoders/png',
139    'Source/WebCore/platform/image-decoders/webp',
140    'Source/WebCore/platform/mock',
141    'Source/WebCore/platform/network',
142    'Source/WebCore/platform/sql',
143    'Source/WebCore/platform/text',
144    'Source/WebCore/platform/text/transcoder',
145    'Source/WebCore/plugins',
146    'Source/WebCore/rendering',
147    'Source/WebCore/rendering/style',
148    'Source/WebCore/rendering/svg',
149    'Source/WebCore/storage',
150    'Source/WebCore/svg',
151    'Source/WebCore/svg/animation',
152    'Source/WebCore/svg/graphics',
153    'Source/WebCore/svg/graphics/filters',
154    'Source/WebCore/svg/properties',
155    'Source/WebCore/websockets',
156    'Source/WebCore/xml',
157]
158
159config = get_config(wk_root)
160config_dir = config + git_branch_name()
161
162output_dir = os.path.join(wk_root, 'WebKitBuild', config_dir)
163
164build_port = "wx"
165building_on_win32 = sys.platform.startswith('win')
166
167def get_config():
168    waf_configname = config.upper().strip()
169    if building_on_win32:
170        isReleaseCRT = (config == 'Release')
171        if build_port == 'wx':
172            if Options.options.wxpython:
173                isReleaseCRT = True
174
175        if isReleaseCRT:
176            waf_configname = waf_configname + ' CRT_MULTITHREADED_DLL'
177        else:
178            waf_configname = waf_configname + ' CRT_MULTITHREADED_DLL_DBG'
179
180    return waf_configname
181
182create_hash_table = wk_root + "/Source/JavaScriptCore/create_hash_table"
183if building_on_win32:
184    create_hash_table = get_output('cygpath --unix "%s"' % create_hash_table)
185os.environ['CREATE_HASH_TABLE'] = create_hash_table
186
187feature_defines = ['ENABLE_DATABASE', 'ENABLE_XSLT', 'ENABLE_JAVASCRIPT_DEBUGGER',
188                    'ENABLE_SVG', 'ENABLE_SVG_USE', 'ENABLE_FILTERS', 'ENABLE_SVG_FONTS',
189                    'ENABLE_SVG_ANIMATION', 'ENABLE_SVG_AS_IMAGE', 'ENABLE_SVG_FOREIGN_OBJECT',
190                    'ENABLE_DOM_STORAGE', 'BUILDING_%s' % build_port.upper()]
191
192msvc_version = 'msvc2008'
193
194msvclibs_dir = os.path.join(wklibs_dir, msvc_version, 'win')
195
196def get_path_to_wxconfig():
197    if 'WX_CONFIG' in os.environ:
198        return os.environ['WX_CONFIG']
199    else:
200        return 'wx-config'
201
202def common_set_options(opt):
203    """
204    Initialize common options provided to the user.
205    """
206    opt.tool_options('compiler_cxx')
207    opt.tool_options('compiler_cc')
208    opt.tool_options('python')
209
210    opt.add_option('--wxpython', action='store_true', default=False, help='Create the wxPython bindings.')
211    opt.add_option('--wx-compiler-prefix', action='store', default='vc',
212                   help='Specify a different compiler prefix (do this if you used COMPILER_PREFIX when building wx itself)')
213    opt.add_option('--macosx-version', action='store', default='', help="Version of OS X to build for.")
214    opt.add_option('--msvc-version', action='store', default='', help="MSVC version to use to build. Use 8 for 2005, 9 for 2008")
215
216def common_configure(conf):
217    """
218    Configuration used by all targets, called from the target's configure() step.
219    """
220
221    conf.env['MSVC_TARGETS'] = ['x86']
222
223    if Options.options.msvc_version and Options.options.msvc_version != '':
224        print "msvc version = %s" % Options.options.msvc_version
225        conf.env['MSVC_VERSIONS'] = ['msvc %s.0' % Options.options.msvc_version]
226    else:
227        print "msvc not set!"
228        conf.env['MSVC_VERSIONS'] = ['msvc 9.0', 'msvc 8.0']
229
230    if sys.platform.startswith('cygwin'):
231        print "ERROR: You must use the Win32 Python from python.org, not Cygwin Python, when building on Windows."
232        sys.exit(1)
233
234    conf.check_tool('compiler_cxx')
235    conf.check_tool('compiler_cc')
236
237    if sys.platform.startswith('darwin'):
238        conf.check_tool('osx')
239
240    global msvc_version
241    global msvclibs_dir
242
243    libprefix = ''
244
245    if building_on_win32:
246        libprefix = 'lib'
247
248        found = conf.get_msvc_versions()
249        found_versions = []
250        for version in found:
251            found_versions.append(version[0])
252
253        if 'msvc 9.0' in conf.env['MSVC_VERSIONS'] and 'msvc 9.0' in found_versions:
254            msvc_version = 'msvc2008'
255        elif 'msvc 8.0' in conf.env['MSVC_VERSIONS'] and 'msvc 8.0' in found_versions:
256            msvc_version = 'msvc2005'
257
258        msvclibs_dir = os.path.join(wklibs_dir, msvc_version, 'win')
259
260        # Disable several warnings which occur many times during the build.
261        # Some of them are harmless (4099, 4344, 4396, 4800) and working around
262        # them in WebKit code is probably just not worth it. We can simply do
263        # nothing about the others (4503). A couple are possibly valid but
264        # there are just too many of them in the code so fixing them is
265        # impossible in practice and just results in tons of distracting output
266        # (4244, 4291). Finally 4996 is actively harmful as it is given for
267        # just about any use of standard C/C++ library facilities.
268        conf.env.append_value('CXXFLAGS', [
269            '/wd4099',  # type name first seen using 'struct' now seen using 'class'
270            '/wd4244',  # conversion from 'xxx' to 'yyy', possible loss of data:
271            '/wd4291',  # no matching operator delete found (for placement new)
272            '/wd4344',  # behaviour change in template deduction
273            '/wd4396',  # inline can't be used in friend declaration
274            '/wd4503',  # decorated name length exceeded, name was truncated
275            '/wd4800',  # forcing value to bool 'true' or 'false'
276            '/wd4996',  # deprecated function
277        ])
278
279        # This one also occurs in C code, so disable it there as well.
280        conf.env.append_value('CCFLAGS', ['/wd4996'])
281
282    if build_port == "wx":
283        update_wx_deps(conf, wk_root, msvc_version)
284
285        conf.env.append_value('CXXDEFINES', ['BUILDING_WX__=1', 'JS_NO_EXPORT'])
286
287        if building_on_win32:
288            conf.env.append_value('LIBPATH', os.path.join(msvclibs_dir, 'lib'))
289            # wx settings
290            global config
291            is_debug = (config == 'Debug')
292            wxdefines, wxincludes, wxlibs, wxlibpaths = get_wxmsw_settings(wx_root, shared=True, unicode=True, debug=is_debug, wxPython=Options.options.wxpython)
293            conf.env['CXXDEFINES_WX'] = wxdefines
294            conf.env['CPPPATH_WX'] = wxincludes
295            conf.env['LIB_WX'] = wxlibs
296            conf.env['LIBPATH_WX'] = wxlibpaths
297
298    if sys.platform.startswith('darwin'):
299        conf.env['LIB_ICU'] = ['icucore']
300
301        conf.env.append_value('CPPPATH', wklibs_dir)
302        conf.env.append_value('LIBPATH', wklibs_dir)
303
304        min_version = None
305
306        mac_target = 'MACOSX_DEPLOYMENT_TARGET'
307        if Options.options.macosx_version != '':
308            min_version = Options.options.macosx_version
309
310        # WebKit only supports 10.4+, but ppc systems often set this to earlier systems
311        if not min_version:
312            min_version = commands.getoutput('sw_vers -productVersion')[:4]
313            if min_version in ['10.1','10.2','10.3']:
314                min_version = '10.4'
315
316        sdk_version = min_version
317        if min_version == "10.4":
318            sdk_version += "u"
319            conf.env.append_value('LIB_WKINTERFACE', ['WebKitSystemInterfaceTiger'])
320        else:
321            # NOTE: There is a WebKitSystemInterfaceSnowLeopard, but when we use that
322            # on 10.6, we get a strange missing symbol error, and this library seems to
323            # work fine for wx's purposes.
324            conf.env.append_value('LIB_WKINTERFACE', ['WebKitSystemInterfaceLeopard'])
325
326        sdkroot = '/Developer/SDKs/MacOSX%s.sdk' % sdk_version
327        sdkflags = ['-arch', 'i386', '-isysroot', sdkroot]
328
329        conf.env.append_value('CPPFLAGS', sdkflags)
330        conf.env.append_value('LINKFLAGS', sdkflags)
331
332        conf.env.append_value('LINKFLAGS', ['-framework', 'Security'])
333
334        conf.env.append_value('CPPPATH_SQLITE3', [os.path.join(wklibs_dir, 'WebCoreSQLite3')])
335        conf.env.append_value('LIB_SQLITE3', ['WebCoreSQLite3'])
336
337    # NOTE: The order here is important, because python sets the MACOSX_DEPLOYMENT_TARGET to
338    # 10.3 even on intel. So we must first set the SDK and arch flags, then load Python's config,
339    # and finally override the value Python set for MACOSX_DEPLOYMENT_TARGET
340    if Options.options.wxpython:
341        conf.check_tool('python')
342        conf.check_python_headers()
343
344    if sys.platform.startswith('darwin'):
345        os.environ[mac_target] = conf.env[mac_target] = min_version
346
347    conf.env.append_value('CXXDEFINES', feature_defines)
348    if config == 'Release':
349        conf.env.append_value('CPPDEFINES', 'NDEBUG')
350
351    if building_on_win32:
352        conf.env.append_value('CPPPATH', [
353            os.path.join(jscore_dir, 'os-win32'),
354            os.path.join(msvclibs_dir, 'include'),
355            os.path.join(msvclibs_dir, 'include', 'pthreads'),
356            os.path.join(msvclibs_dir, 'lib'),
357            ])
358
359        conf.env.append_value('LIB', ['libpng', 'libjpeg', 'pthreadVC2'])
360        # common win libs
361        conf.env.append_value('LIB', [
362            'kernel32', 'user32','gdi32','comdlg32','winspool','winmm',
363            'shell32', 'shlwapi', 'comctl32', 'ole32', 'oleaut32', 'uuid', 'advapi32',
364            'wsock32', 'gdiplus', 'usp10','version'])
365
366        conf.env['LIB_ICU'] = ['icudt', 'icule', 'iculx', 'icuuc', 'icuin', 'icuio', 'icutu']
367
368        #curl
369        conf.env['LIB_CURL'] = ['libcurl']
370
371        #sqlite3
372        conf.env['CPPPATH_SQLITE3'] = [os.path.join(msvclibs_dir, 'include', 'SQLite')]
373        conf.env['LIB_SQLITE3'] = ['sqlite3']
374
375        #libxml2
376        conf.env['LIB_XML'] = ['libxml2']
377
378        #libxslt
379        conf.env['LIB_XSLT'] = ['libxslt']
380    else:
381        if build_port == 'wx':
382            port_uses['wx'].append('PTHREADS')
383            conf.env.append_value('LIB', ['jpeg', 'png', 'pthread'])
384            conf.env.append_value('LIBPATH', os.path.join(wklibs_dir, 'unix', 'lib'))
385            conf.env.append_value('CPPPATH', os.path.join(wklibs_dir, 'unix', 'include'))
386            conf.env.append_value('CXXFLAGS', ['-fPIC', '-DPIC'])
387
388            conf.check_cfg(path=get_path_to_wxconfig(), args='--cxxflags --libs', package='', uselib_store='WX', mandatory=True)
389
390        conf.check_cfg(msg='Checking for libxslt', path='xslt-config', args='--cflags --libs', package='', uselib_store='XSLT', mandatory=True)
391        conf.check_cfg(path='xml2-config', args='--cflags --libs', package='', uselib_store='XML', mandatory=True)
392        if sys.platform.startswith('darwin') and min_version and min_version == '10.4':
393            conf.check_cfg(path=os.path.join(wklibs_dir, 'unix', 'bin', 'curl-config'), args='--cflags --libs', package='', uselib_store='CURL', mandatory=True)
394        else:
395            conf.check_cfg(path='curl-config', args='--cflags --libs', package='', uselib_store='CURL', mandatory=True)
396
397        if not sys.platform.startswith('darwin'):
398            conf.check_cfg(package='cairo', args='--cflags --libs', uselib_store='WX', mandatory=True)
399            conf.check_cfg(package='pango', args='--cflags --libs', uselib_store='WX', mandatory=True)
400            conf.check_cfg(package='gtk+-2.0', args='--cflags --libs', uselib_store='WX', mandatory=True)
401            conf.check_cfg(package='sqlite3', args='--cflags --libs', uselib_store='SQLITE3', mandatory=True)
402            conf.check_cfg(path='icu-config', args='--cflags --ldflags', package='', uselib_store='ICU', mandatory=True)
403
404    for use in port_uses[build_port]:
405       conf.env.append_value('CXXDEFINES', ['WTF_USE_%s' % use])
406