scons: Create a Configure checker for pkg-config.
[gem5.git] / site_scons / gem5_scons / configure.py
1 # Copyright (c) 2013, 2015-2020 ARM Limited
2 # All rights reserved.
3 #
4 # The license below extends only to copyright in the software and shall
5 # not be construed as granting a license to any other intellectual
6 # property including but not limited to intellectual property relating
7 # to a hardware implementation of the functionality of the software
8 # licensed hereunder. You may use the software subject to the license
9 # terms below provided that you ensure that this notice is replicated
10 # unmodified and in its entirety in all distributions of the software,
11 # modified or unmodified, in source code or in binary form.
12 #
13 # Copyright (c) 2011 Advanced Micro Devices, Inc.
14 # Copyright (c) 2009 The Hewlett-Packard Development Company
15 # Copyright (c) 2004-2005 The Regents of The University of Michigan
16 # All rights reserved.
17 #
18 # Redistribution and use in source and binary forms, with or without
19 # modification, are permitted provided that the following conditions are
20 # met: redistributions of source code must retain the above copyright
21 # notice, this list of conditions and the following disclaimer;
22 # redistributions in binary form must reproduce the above copyright
23 # notice, this list of conditions and the following disclaimer in the
24 # documentation and/or other materials provided with the distribution;
25 # neither the name of the copyright holders nor the names of its
26 # contributors may be used to endorse or promote products derived from
27 # this software without specific prior written permission.
28 #
29 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40
41 import os
42
43 import SCons.Script
44 import SCons.Util
45
46 def CheckCxxFlag(context, flag, autoadd=True):
47 context.Message("Checking for compiler %s support... " % flag)
48 last_cxxflags = context.env['CXXFLAGS']
49 context.env.Append(CXXFLAGS=[flag])
50 ret = context.TryCompile('', '.cc')
51 if not (ret and autoadd):
52 context.env['CXXFLAGS'] = last_cxxflags
53 context.Result(ret)
54 return ret
55
56 def CheckLinkFlag(context, flag, autoadd=True, set_for_shared=True):
57 context.Message("Checking for linker %s support... " % flag)
58 last_linkflags = context.env['LINKFLAGS']
59 context.env.Append(LINKFLAGS=[flag])
60 ret = context.TryLink('int main(int, char *[]) { return 0; }', '.cc')
61 if not (ret and autoadd):
62 context.env['LINKFLAGS'] = last_linkflags
63 if set_for_shared:
64 assert(autoadd)
65 context.env.Append(SHLINKFLAGS=[flag])
66 context.Result(ret)
67 return ret
68
69 # Add a custom Check function to test for structure members.
70 def CheckMember(context, include, decl, member, include_quotes="<>"):
71 context.Message("Checking for member %s in %s..." %
72 (member, decl))
73 text = """
74 #include %(header)s
75 int main(){
76 %(decl)s test;
77 (void)test.%(member)s;
78 return 0;
79 };
80 """ % { "header" : include_quotes[0] + include + include_quotes[1],
81 "decl" : decl,
82 "member" : member,
83 }
84
85 ret = context.TryCompile(text, extension=".cc")
86 context.Result(ret)
87 return ret
88
89 def CheckPythonLib(context):
90 context.Message('Checking Python version... ')
91 ret = context.TryRun(r"""
92 #include <pybind11/embed.h>
93
94 int
95 main(int argc, char **argv) {
96 pybind11::scoped_interpreter guard{};
97 pybind11::exec(
98 "import sys\n"
99 "vi = sys.version_info\n"
100 "sys.stdout.write('%i.%i.%i' % (vi.major, vi.minor, vi.micro));\n");
101 return 0;
102 }
103 """, extension=".cc")
104 context.Result(ret[1] if ret[0] == 1 else 0)
105 if ret[0] == 0:
106 return None
107 else:
108 return tuple(map(int, ret[1].split(".")))
109
110 def CheckPkgConfig(context, pkgs, *args):
111 if not SCons.Util.is_List(pkgs):
112 pkgs = [pkgs]
113 assert(pkgs)
114
115 for pkg in pkgs:
116 context.Message('Checking for pkg-config package %s... ' % pkg)
117 ret = context.TryAction('pkg-config %s' % pkg)[0]
118 if not ret:
119 context.Result(ret)
120 continue
121
122 if len(args) == 0:
123 break
124
125 cmd = ' '.join(['pkg-config'] + list(args) + [pkg])
126 try:
127 context.env.ParseConfig(cmd)
128 ret = 1
129 context.Result(ret)
130 break
131 except Exception as e:
132 ret = 0
133 context.Result(ret)
134
135 return ret
136
137 def Configure(env, *args, **kwargs):
138 kwargs.setdefault('conf_dir',
139 os.path.join(env['BUILDROOT'], '.scons_config'))
140 kwargs.setdefault('log_file',
141 os.path.join(env['BUILDROOT'], 'scons_config.log'))
142 kwargs.setdefault('custom_tests', {})
143 kwargs['custom_tests'].update({
144 'CheckCxxFlag' : CheckCxxFlag,
145 'CheckLinkFlag' : CheckLinkFlag,
146 'CheckMember' : CheckMember,
147 'CheckPkgConfig' : CheckPkgConfig,
148 'CheckPythonLib' : CheckPythonLib,
149 })
150 conf = SCons.Script.Configure(env, *args, **kwargs)
151
152 # Recent versions of scons substitute a "Null" object for Configure()
153 # when configuration isn't necessary, e.g., if the "--help" option is
154 # present. Unfortuantely this Null object always returns false,
155 # breaking all our configuration checks. We replace it with our own
156 # more optimistic null object that returns True instead.
157 if not conf:
158 def NullCheck(*args, **kwargs):
159 return True
160
161 class NullConf:
162 def __init__(self, env):
163 self.env = env
164 def Finish(self):
165 return self.env
166 def __getattr__(self, mname):
167 return NullCheck
168
169 conf = NullConf(main)
170
171 return conf