1# Copyright 2011 Google Inc.
2#
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6# "Makefile" replacement to build skia for Windows.
7# More info at https://sites.google.com/site/skiadocs/
8#
9# Some usage examples:
10#   make clean
11#   make tests
12#   make bench BUILDTYPE=Release
13#   make gm GYP_DEFINES=skia_scalar=fixed BUILDTYPE=Release
14#   make all
15
16import os
17import shutil
18import sys
19
20BUILDTYPE = 'Debug'
21
22# special targets
23TARGET_ALL     = 'all'
24TARGET_CLEAN   = 'clean'
25TARGET_DEFAULT = 'most'
26TARGET_GYP     = 'gyp'
27
28SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__))
29OUT_SUBDIR = os.environ.get('SKIA_OUT', 'out')
30GYP_SUBDIR = 'gyp'
31
32
33# Simple functions that report what they are doing, and exit(1) on failure.
34def cd(path):
35    print '> cd %s' % path
36    if not os.path.isdir(path):
37        print 'directory %s does not exist' % path
38        sys.exit(1)
39    os.chdir(path)
40
41def rmtree(path):
42    print '> rmtree %s' % path
43    shutil.rmtree(path, ignore_errors=True)
44
45def runcommand(command):
46    print '> %s' % command
47    if os.system(command):
48        sys.exit(1)
49
50def MakeClean():
51    """Cross-platform "make clean" operation."""
52    cd(SCRIPT_DIR)
53    rmtree(OUT_SUBDIR)
54
55
56def CheckWindowsEnvironment():
57    """For Windows: check environment variables needed for command-line build.
58
59    If those environment variables are missing, try to set them.
60    If environment variables can be set up, this function returns; otherwise,
61    it displays an error message and exits.
62    """
63    # If we already have the proper environment variables, nothing to do here.
64    try:
65        env_DevEnvDir = os.environ['DevEnvDir']
66        return  # found it, so we are done
67    except KeyError:
68        pass # go on and run the rest of this function
69
70    print ('\nCould not find Visual Studio environment variables.'
71           '\nPerhaps you have not yet run vcvars32.bat as described at'
72           '\nhttp://msdn.microsoft.com/en-us/library/f2ccy3wt.aspx ?')
73    found_path = None
74    try:
75        possible_path = os.path.abspath(os.path.join(
76            os.environ['VS100COMNTOOLS'], os.path.pardir, os.path.pardir,
77            'VC', 'bin', 'vcvars32.bat'))
78        if os.path.exists(possible_path):
79            found_path = possible_path
80    except KeyError:
81        pass
82    if found_path:
83        print '\nIt looks like you can run that script at:\n%s' % found_path
84    else:
85        print '\nUnable to find vcvars32.bat on your system.'
86    sys.exit(1)
87
88
89def MakeWindows(targets):
90    """For Windows: build as appropriate for the command line arguments.
91
92    parameters:
93        targets: build targets as a list of strings
94    """
95    if os.environ.get('CHROME_HEADLESS', '0') != '1':
96        # TODO(epoger): I'm not sure if this is needed for ninja builds.
97        CheckWindowsEnvironment()
98
99    # Run gyp_skia to prepare Visual Studio projects.
100    cd(SCRIPT_DIR)
101    runcommand('python gyp_skia')
102
103    # We already built the gypfiles...
104    while TARGET_GYP in targets:
105        targets.remove(TARGET_GYP)
106
107    # And call ninja to do the work!
108    if targets:
109        runcommand('ninja -C %s %s' % (
110            os.path.join(OUT_SUBDIR, BUILDTYPE), ' '.join(targets)))
111
112
113def Make(args):
114    """Main function.
115
116    parameters:
117        args: command line arguments as a list of strings
118    """
119    # handle any variable-setting parameters or special targets
120    global BUILDTYPE
121
122    # if no targets were specified at all, make default target
123    if not args:
124        args = [TARGET_DEFAULT]
125
126    targets = []
127    for arg in args:
128        # If user requests "make all", chain to our explicitly-declared "everything"
129        # target. See https://code.google.com/p/skia/issues/detail?id=932 ("gyp
130        # automatically creates "all" target on some build flavors but not others")
131        if arg == TARGET_ALL:
132            targets.append('everything')
133        elif arg == TARGET_CLEAN:
134            MakeClean()
135        elif arg.startswith('BUILDTYPE='):
136            BUILDTYPE = arg[10:]
137        elif arg.startswith('GYP_DEFINES='):
138            os.environ['GYP_DEFINES'] = arg[12:]
139        else:
140            targets.append(arg)
141
142    # if there are no remaining targets, we're done
143    if not targets:
144        sys.exit(0)
145
146    # dispatch to appropriate Make<Platform>() variant.
147    if os.name == 'nt':
148        MakeWindows(targets)
149        sys.exit(0)
150    elif os.name == 'posix':
151        if sys.platform == 'darwin':
152            print 'Mac developers should not run this script; see ' \
153                'https://sites.google.com/site/skiadocs/user-documentation/quick-start-guides/mac'
154            sys.exit(1)
155        elif sys.platform == 'cygwin':
156            print 'Windows development on Cygwin is not currently supported; see ' \
157                'https://sites.google.com/site/skiadocs/user-documentation/quick-start-guides/windows'
158            sys.exit(1)
159        else:
160            print 'Unix developers should not run this script; see ' \
161                'https://sites.google.com/site/skiadocs/user-documentation/quick-start-guides/linux'
162            sys.exit(1)
163    else:
164        print 'unknown platform (os.name=%s, sys.platform=%s); see %s' % (
165            os.name, sys.platform, 'https://sites.google.com/site/skiadocs/')
166        sys.exit(1)
167    sys.exit(0)
168
169
170# main()
171Make(sys.argv[1:])
172
173
174