Extracted dependencies to their own file.

pull/15/head
Jussi Pakkanen 12 years ago
parent e12100b726
commit b77ac5ec9f
  1. 12
      coredata.py
  2. 173
      dependencies.py
  3. 144
      environment.py
  4. 15
      interpreter.py
  5. 13
      meson.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)

@ -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,
}

@ -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()

@ -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\

@ -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()

Loading…
Cancel
Save