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://skia.org.
8#
9# Some usage examples:
10#   make clean
11#   make dm
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    if os.environ.get('DevEnvDir'):
65      return
66
67    print ('\nCould not find Visual Studio environment variables.'
68           '\nPerhaps you have not yet run vcvars32.bat as described at'
69           '\nhttp://msdn.microsoft.com/en-us/library/f2ccy3wt.aspx ?')
70    found_path = None
71    try:
72        possible_path = os.path.abspath(os.path.join(
73            os.environ['VS100COMNTOOLS'], os.path.pardir, os.path.pardir,
74            'VC', 'bin', 'vcvars32.bat'))
75        if os.path.exists(possible_path):
76            found_path = possible_path
77    except KeyError:
78        pass
79    if found_path:
80        print '\nIt looks like you can run that script at:\n%s' % found_path
81    else:
82        print '\nUnable to find vcvars32.bat on your system.'
83    sys.exit(1)
84
85
86def MakeWindows(targets):
87    """For Windows: build as appropriate for the command line arguments.
88
89    parameters:
90        targets: build targets as a list of strings
91    """
92    if os.environ.get('CHROME_HEADLESS', '0') != '1':
93        # TODO(epoger): I'm not sure if this is needed for ninja builds.
94        CheckWindowsEnvironment()
95
96    # Run gyp_skia to prepare Visual Studio projects.
97    cd(SCRIPT_DIR)
98    runcommand('python gyp_skia --no-parallel -G config=%s' % BUILDTYPE)
99
100    # We already built the gypfiles...
101    while TARGET_GYP in targets:
102        targets.remove(TARGET_GYP)
103
104    # And call ninja to do the work!
105    if targets:
106        runcommand('ninja -C %s %s' % (
107            os.path.join(OUT_SUBDIR, BUILDTYPE), ' '.join(targets)))
108
109
110def Make(args):
111    """Main function.
112
113    parameters:
114        args: command line arguments as a list of strings
115    """
116    # handle any variable-setting parameters or special targets
117    global BUILDTYPE
118
119    # if no targets were specified at all, make default target
120    if not args:
121        args = [TARGET_DEFAULT]
122
123    targets = []
124    for arg in args:
125        # If user requests "make all", chain to our explicitly-declared
126        # "everything" target. See
127        # https://code.google.com/p/skia/issues/detail?id=932 ("gyp
128        # automatically creates "all" target on some build flavors but not
129        # others")
130        if arg == TARGET_ALL:
131            targets.append('everything')
132        elif arg == TARGET_CLEAN:
133            MakeClean()
134        elif arg.startswith('BUILDTYPE='):
135            BUILDTYPE = arg[10:]
136        elif arg.startswith('GYP_DEFINES='):
137            os.environ['GYP_DEFINES'] = arg[12:]
138        else:
139            targets.append(arg)
140
141    # if there are no remaining targets, we're done
142    if not targets:
143        sys.exit(0)
144
145    # dispatch to appropriate Make<Platform>() variant.
146    if os.name == 'nt':
147        MakeWindows(targets)
148        sys.exit(0)
149    elif os.name == 'posix':
150        if sys.platform == 'darwin':
151            print ('Mac developers should not run this script; see '
152                   'https://skia.org/user/quick/macos')
153            sys.exit(1)
154        elif sys.platform == 'cygwin':
155            print ('Windows development on Cygwin is not currently supported; '
156                   'see https://skia.org/user/quick/windows')
157            sys.exit(1)
158        else:
159            print ('Unix developers should not run this script; see '
160                   'https://skia.org/user/quick/linux')
161            sys.exit(1)
162    else:
163        print 'unknown platform (os.name=%s, sys.platform=%s); see %s' % (
164            os.name, sys.platform, 'https://skia.org/user/quick')
165        sys.exit(1)
166    sys.exit(0)
167
168
169# main()
170Make(sys.argv[1:])
171
172
173