aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--coredata.py12
-rw-r--r--dependencies.py173
-rwxr-xr-xenvironment.py144
-rwxr-xr-xinterpreter.py15
-rwxr-xr-xmeson.py13
5 files changed, 192 insertions, 165 deletions
diff --git a/coredata.py b/coredata.py
index 57db2f9..4a56b74 100644
--- a/coredata.py
+++ b/coredata.py
@@ -14,14 +14,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# This file contains all data that must persist over multiple
-# invocations of Meson. It is roughly the same thing as
-# cmakecache.
-
import pickle
version = '0.3.0-research'
+# This class contains all data that must persist over multiple
+# invocations of Meson. It is roughly the same thing as
+# cmakecache.
+
class CoreData():
def __init__(self, options):
@@ -69,3 +69,7 @@ forbidden_target_names = {'clean': None,
'install': None,
'build.ninja': None,
}
+
+class MesonException(Exception):
+ def __init__(self, *args, **kwargs):
+ Exception.__init__(args, kwargs)
diff --git a/dependencies.py b/dependencies.py
index de7ac43..141473e 100644
--- a/dependencies.py
+++ b/dependencies.py
@@ -14,16 +14,153 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# This file contains the detection logic for all those
-# packages and frameworks that either don't provide
-# a pkg-confg file or require extra functionality
-# that can't be expressed with it.
+# This file contains the detection logic for external
+# dependencies. Mostly just uses pkg-config but also contains
+# custom logic for packages that don't provide them.
# Currently one file, should probably be split into a
# package before this gets too big.
-import os, stat, glob
+import os, stat, glob, subprocess
from interpreter import InvalidArguments
+from coredata import MesonException
+
+class DependencyException(MesonException):
+ def __init__(self, args, **kwargs):
+ MesonException.__init__(args, kwargs)
+
+class Dependency():
+ def __init__(self):
+ pass
+
+ def get_compile_flags(self):
+ return []
+
+ def get_link_flags(self):
+ return []
+
+ def found(self):
+ return False
+
+ def get_sources(self):
+ """Source files that need to be added to the target.
+ As an example, gtest-all.cc when using GTest."""
+ return []
+
+class PackageDependency(Dependency): # Custom detector, not pkg-config.
+ def __init__(self, dep):
+ Dependency.__init__(self)
+ self.dep = dep
+
+ def get_link_flags(self):
+ return self.dep.get_link_flags()
+
+ def get_compile_flags(self):
+ return self.dep.get_compile_flags()
+
+ def found(self):
+ return self.dep.found()
+
+ def get_sources(self):
+ return self.dep.get_sources()
+
+# This should be an InterpreterObject. Fix it.
+
+class PkgConfigDependency(Dependency):
+ pkgconfig_found = False
+
+ def __init__(self, name, required):
+ Dependency.__init__(self)
+ if not PkgConfigDependency.pkgconfig_found:
+ self.check_pkgconfig()
+
+ self.is_found = False
+ p = subprocess.Popen(['pkg-config', '--modversion', name], stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ out = p.communicate()[0]
+ if p.returncode != 0:
+ if required:
+ raise DependencyException('Required dependency %s not found.' % name)
+ self.modversion = 'none'
+ self.cflags = []
+ self.libs = []
+ else:
+ self.is_found = True
+ self.modversion = out.decode().strip()
+ p = subprocess.Popen(['pkg-config', '--cflags', name], stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ out = p.communicate()[0]
+ if p.returncode != 0:
+ raise RuntimeError('Could not generate cflags for %s.' % name)
+ self.cflags = out.decode().split()
+
+ p = subprocess.Popen(['pkg-config', '--libs', name], stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ out = p.communicate()[0]
+ if p.returncode != 0:
+ raise RuntimeError('Could not generate libs for %s.' % name)
+ self.libs = out.decode().split()
+
+ def get_modversion(self):
+ return self.modversion
+
+ def get_compile_flags(self):
+ return self.cflags
+
+ def get_link_flags(self):
+ return self.libs
+
+ def check_pkgconfig(self):
+ p = subprocess.Popen(['pkg-config', '--version'], stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ out = p.communicate()[0]
+ if p.returncode != 0:
+ raise RuntimeError('Pkg-config executable not found.')
+ print('Found pkg-config version %s.' % out.decode().strip())
+ PkgConfigDependency.pkgconfig_found = True
+
+ def found(self):
+ return self.is_found
+
+class ExternalProgram():
+ def __init__(self, name, fullpath=None):
+ self.name = name
+ self.fullpath = fullpath
+
+ def found(self):
+ return self.fullpath is not None
+
+ def get_command(self):
+ return self.fullpath
+
+ def get_name(self):
+ return self.name
+
+class ExternalLibrary(Dependency):
+ def __init__(self, name, fullpath=None):
+ Dependency.__init__(self)
+ self.name = name
+ self.fullpath = fullpath
+
+ def found(self):
+ return self.fullpath is not None
+
+ def get_name(self):
+ return self.name
+
+ def get_link_flags(self):
+ if self.found():
+ return [self.fullpath]
+ return []
+
+def find_external_dependency(name, kwargs):
+ required = kwargs.get('required', False)
+ if name in packages:
+ dep = packages[name](kwargs)
+ if required and not dep.found():
+ raise DependencyException('Dependency "%s" not found' % name)
+ return PackageDependency(dep)
+ return PkgConfigDependency(name, required)
class BoostDependency():
def __init__(self, kwargs):
@@ -145,7 +282,33 @@ class GMockDependency():
fname = os.path.join(self.libdir, self.libname)
return os.path.exists(fname)
+class Qt5Dependency():
+ def __init__(self, kwargs):
+ self.root = '/usr'
+ self.modules = []
+ for module in kwargs.get('modules', []):
+ self.modules.append(PkgConfigDependency(module))
+
+ def get_version(self):
+ return '1.something_maybe'
+
+ def get_compile_flags(self):
+ return []
+
+ def get_sources(self):
+ return []
+
+ def get_link_flags(self):
+ return ['-lgmock']
+
+ def found(self):
+ fname = os.path.join(self.libdir, self.libname)
+ return os.path.exists(fname)
+
+# This has to be at the end so all classes it references
+# are defined.
packages = {'boost': BoostDependency,
'gtest': GTestDependency,
'gmock': GMockDependency,
+ 'qt5': Qt5Dependency,
}
diff --git a/environment.py b/environment.py
index 3eaaa52..2d8ae13 100755
--- a/environment.py
+++ b/environment.py
@@ -451,147 +451,3 @@ class Environment():
unixdirs += glob('/usr/lib/' + plat + '*')
unixdirs.append('/usr/local/lib')
return unixdirs
-
-class Dependency():
- def __init__(self):
- pass
-
- def get_compile_flags(self):
- return []
-
- def get_link_flags(self):
- return []
-
- def found(self):
- return False
-
- def get_sources(self):
- """Source files that need to be added to the target.
- As an example, gtest-all.cc when using GTest."""
- return []
-
-class PackageDependency(Dependency): # Custom detector, not pkg-config.
- def __init__(self, dep):
- Dependency.__init__(self)
- self.dep = dep
-
- def get_link_flags(self):
- return self.dep.get_link_flags()
-
- def get_compile_flags(self):
- return self.dep.get_compile_flags()
-
- def found(self):
- return self.dep.found()
-
- def get_sources(self):
- return self.dep.get_sources()
-
-# This should be an InterpreterObject. Fix it.
-
-class PkgConfigDependency(Dependency):
- pkgconfig_found = False
-
- def __init__(self, name, required):
- Dependency.__init__(self)
- if not PkgConfigDependency.pkgconfig_found:
- self.check_pkgconfig()
-
- self.is_found = False
- p = subprocess.Popen(['pkg-config', '--modversion', name], stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- out = p.communicate()[0]
- if p.returncode != 0:
- if required:
- raise EnvironmentException('Required dependency %s not found.' % name)
- self.modversion = 'none'
- self.cflags = []
- self.libs = []
- else:
- self.is_found = True
- self.modversion = out.decode().strip()
- p = subprocess.Popen(['pkg-config', '--cflags', name], stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- out = p.communicate()[0]
- if p.returncode != 0:
- raise RuntimeError('Could not generate cflags for %s.' % name)
- self.cflags = out.decode().split()
-
- p = subprocess.Popen(['pkg-config', '--libs', name], stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- out = p.communicate()[0]
- if p.returncode != 0:
- raise RuntimeError('Could not generate libs for %s.' % name)
- self.libs = out.decode().split()
-
- def get_modversion(self):
- return self.modversion
-
- def get_compile_flags(self):
- return self.cflags
-
- def get_link_flags(self):
- return self.libs
-
- def check_pkgconfig(self):
- p = subprocess.Popen(['pkg-config', '--version'], stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- out = p.communicate()[0]
- if p.returncode != 0:
- raise RuntimeError('Pkg-config executable not found.')
- print('Found pkg-config version %s.' % out.decode().strip())
- PkgConfigDependency.pkgconfig_found = True
-
- def found(self):
- return self.is_found
-
-class ExternalProgram():
- def __init__(self, name, fullpath=None):
- self.name = name
- self.fullpath = fullpath
-
- def found(self):
- return self.fullpath is not None
-
- def get_command(self):
- return self.fullpath
-
- def get_name(self):
- return self.name
-
-class ExternalLibrary(Dependency):
- def __init__(self, name, fullpath=None):
- Dependency.__init__(self)
- self.name = name
- self.fullpath = fullpath
-
- def found(self):
- return self.fullpath is not None
-
- def get_name(self):
- return self.name
-
- def get_link_flags(self):
- if self.found():
- return [self.fullpath]
- return []
-
-def find_external_dependency(name, kwargs):
- required = kwargs.get('required', False)
- if name in dependencies.packages:
- dep = dependencies.packages[name](kwargs)
- if required and not dep.found():
- raise EnvironmentException('Dependency "%s" not found' % name)
- return PackageDependency(dep)
- return PkgConfigDependency(name, required)
-
-def test_pkg_config():
- name = 'gtk+-3.0'
- dep = PkgConfigDependency(name)
- print(dep.get_modversion())
- print(dep.get_compile_flags())
- print(dep.get_link_flags())
-
-if __name__ == '__main__':
- #test_cmd_line_building()
- test_pkg_config()
diff --git a/interpreter.py b/interpreter.py
index 58e07be..7375cf8 100755
--- a/interpreter.py
+++ b/interpreter.py
@@ -18,6 +18,7 @@ import mparser
import nodes
import environment
import coredata
+import dependencies
import os, sys, platform
import shutil
@@ -377,11 +378,11 @@ class BuildTarget(InterpreterObject):
def add_external_deps(self, deps):
for dep in deps:
- if not isinstance(dep, environment.Dependency) and\
+ if not isinstance(dep, dependencies.Dependency) and\
not isinstance(dep, ExternalLibraryHolder):
raise InvalidArguments('Argument is not an external dependency')
self.external_deps.append(dep)
- if isinstance(dep, environment.Dependency):
+ if isinstance(dep, dependencies.Dependency):
self.process_sourcelist(dep.get_sources())
def get_external_deps(self):
@@ -654,7 +655,7 @@ class Interpreter():
self.coredata.ext_progs[exename].found():
return ExternalProgramHolder(self.coredata.ext_progs[exename])
result = shutil.which(exename) # Does .exe appending on Windows.
- extprog = environment.ExternalProgram(exename, result)
+ extprog = dependencies.ExternalProgram(exename, result)
progobj = ExternalProgramHolder(extprog)
self.coredata.ext_progs[exename] = extprog
if required and not progobj.found():
@@ -671,7 +672,7 @@ class Interpreter():
self.coredata.ext_libs[libname].found():
return ExternalLibraryHolder(self.coredata.ext_libs[libname])
result = self.environment.find_library(libname)
- extlib = environment.ExternalLibrary(libname, result)
+ extlib = dependencies.ExternalLibrary(libname, result)
libobj = ExternalLibraryHolder(extlib)
self.coredata.ext_libs[libname] = extlib
if required and not libobj.found():
@@ -684,9 +685,9 @@ class Interpreter():
if name in self.coredata.deps:
dep = self.coredata.deps[name]
else:
- dep = environment.Dependency() # Returns always false for dep.found()
+ dep = dependencies.Dependency() # Returns always false for dep.found()
if not dep.found():
- dep = environment.find_external_dependency(name, kwargs)
+ dep = dependencies.find_external_dependency(name, kwargs)
self.coredata.deps[name] = dep
return dep
@@ -828,7 +829,7 @@ class Interpreter():
def is_assignable(self, value):
if isinstance(value, InterpreterObject) or \
- isinstance(value, environment.Dependency) or\
+ isinstance(value, dependencies.Dependency) or\
isinstance(value, nodes.StringStatement) or\
isinstance(value, nodes.BoolStatement) or\
isinstance(value, nodes.IntStatement) or\
diff --git a/meson.py b/meson.py
index 9aebc1f..a1b7858 100755
--- a/meson.py
+++ b/meson.py
@@ -15,12 +15,12 @@
# limitations under the License.
from optparse import OptionParser
-import sys, stat
+import sys, stat, traceback
import os.path
import environment, interpreter
import backends, build
-from coredata import version
+from coredata import version, MesonException
usage_info = '%prog [options] source_dir build_dir'
@@ -128,7 +128,10 @@ if __name__ == '__main__':
try:
app.generate()
except Exception as e:
- print('\nMeson encountered an error:')
- print(e)
- sys.exit(1)
+ if isinstance(e, MesonException):
+ print('\nMeson encountered an error:')
+ print(e)
+ sys.exit(1)
+ else:
+ traceback.print_exc()