cmake: Moved finding and running CMake out of dependency
This commit is contained in:
parent
44b9421071
commit
6083cfa6c8
|
@ -17,10 +17,12 @@
|
|||
|
||||
__all__ = [
|
||||
'CMakeClient',
|
||||
'CMakeExecutor',
|
||||
'CMakeException',
|
||||
'CMakeInterpreter',
|
||||
]
|
||||
|
||||
from .common import CMakeException
|
||||
from .client import CMakeClient
|
||||
from .executor import CMakeExecutor
|
||||
from .interpreter import CMakeInterpreter
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
# or an interpreter-based tool.
|
||||
|
||||
from .common import CMakeException
|
||||
from .executor import CMakeExecutor
|
||||
from ..environment import Environment
|
||||
from ..dependencies.base import CMakeDependency, ExternalProgram
|
||||
from ..mesonlib import MachineChoice
|
||||
from .. import mlog
|
||||
from contextlib import contextmanager
|
||||
|
@ -475,14 +475,11 @@ class CMakeClient:
|
|||
if self.proc is not None:
|
||||
raise CMakeException('The CMake server was already started')
|
||||
for_machine = MachineChoice.HOST # TODO make parameter
|
||||
cmake_exe, cmake_vers, _ = CMakeDependency.find_cmake_binary(self.env, for_machine)
|
||||
if cmake_exe is None or cmake_exe is False:
|
||||
raise CMakeException('Unable to find CMake')
|
||||
assert(isinstance(cmake_exe, ExternalProgram))
|
||||
cmake_exe = CMakeExecutor(self.env, '>=3.7', for_machine)
|
||||
if not cmake_exe.found():
|
||||
raise CMakeException('Unable to find CMake')
|
||||
|
||||
mlog.debug('Starting CMake server with CMake', mlog.bold(' '.join(cmake_exe.get_command())), 'version', mlog.cyan(cmake_vers))
|
||||
mlog.debug('Starting CMake server with CMake', mlog.bold(' '.join(cmake_exe.get_command())), 'version', mlog.cyan(cmake_exe.version()))
|
||||
self.proc = Popen(cmake_exe.get_command() + ['-E', 'server', '--experimental', '--debug'], stdin=PIPE, stdout=PIPE)
|
||||
|
||||
def shutdown(self) -> None:
|
||||
|
|
|
@ -0,0 +1,215 @@
|
|||
# Copyright 2019 The Meson development team
|
||||
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# This class contains the basic functionality needed to run any interpreter
|
||||
# or an interpreter-based tool.
|
||||
|
||||
from .. import mlog, mesonlib
|
||||
from ..mesonlib import PerMachine, Popen_safe, version_compare, MachineChoice
|
||||
from ..environment import Environment
|
||||
|
||||
from typing import List, Tuple, Optional, TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..dependencies.base import ExternalProgram
|
||||
|
||||
import re, os, ctypes
|
||||
|
||||
class CMakeExecutor:
|
||||
# The class's copy of the CMake path. Avoids having to search for it
|
||||
# multiple times in the same Meson invocation.
|
||||
class_cmakebin = PerMachine(None, None)
|
||||
class_cmakevers = PerMachine(None, None)
|
||||
class_cmake_cache = {}
|
||||
|
||||
def __init__(self, environment: Environment, version: str, for_machine: MachineChoice, silent: bool = False):
|
||||
self.min_version = version
|
||||
self.environment = environment
|
||||
self.for_machine = for_machine
|
||||
self.cmakebin, self.cmakevers = self.find_cmake_binary(self.environment, silent=silent)
|
||||
if self.cmakebin is False:
|
||||
self.cmakebin = None
|
||||
return
|
||||
|
||||
if not version_compare(self.cmakevers, self.min_version):
|
||||
self.cmakebin = None
|
||||
mlog.warning(
|
||||
'The version of CMake', mlog.bold(self.cmakebin.get_path()),
|
||||
'is', mlog.bold(self.cmakevers), 'but version', mlog.bold(self.min_version),
|
||||
'is required')
|
||||
return
|
||||
|
||||
def find_cmake_binary(self, environment: Environment, silent: bool = False) -> Tuple['ExternalProgram', str]:
|
||||
from ..dependencies.base import ExternalProgram
|
||||
|
||||
# Create an iterator of options
|
||||
def search():
|
||||
# Lookup in cross or machine file.
|
||||
potential_cmakepath = environment.binaries[self.for_machine].lookup_entry('cmake')
|
||||
if potential_cmakepath is not None:
|
||||
mlog.debug('CMake binary for %s specified from cross file, native file, or env var as %s.', self.for_machine, potential_cmakepath)
|
||||
yield ExternalProgram.from_entry('cmake', potential_cmakepath)
|
||||
# We never fallback if the user-specified option is no good, so
|
||||
# stop returning options.
|
||||
return
|
||||
mlog.debug('CMake binary missing from cross or native file, or env var undefined.')
|
||||
# Fallback on hard-coded defaults.
|
||||
# TODO prefix this for the cross case instead of ignoring thing.
|
||||
if environment.machines.matches_build_machine(self.for_machine):
|
||||
for potential_cmakepath in environment.default_cmake:
|
||||
mlog.debug('Trying a default CMake fallback at', potential_cmakepath)
|
||||
yield ExternalProgram(potential_cmakepath, silent=True)
|
||||
|
||||
# Only search for CMake the first time and store the result in the class
|
||||
# definition
|
||||
if CMakeExecutor.class_cmakebin[self.for_machine] is False:
|
||||
mlog.debug('CMake binary for %s is cached as not found' % self.for_machine)
|
||||
elif CMakeExecutor.class_cmakebin[self.for_machine] is not None:
|
||||
mlog.debug('CMake binary for %s is cached.' % self.for_machine)
|
||||
else:
|
||||
assert CMakeExecutor.class_cmakebin[self.for_machine] is None
|
||||
mlog.debug('CMake binary for %s is not cached' % self.for_machine)
|
||||
for potential_cmakebin in search():
|
||||
mlog.debug('Trying CMake binary {} for machine {} at {}'
|
||||
.format(potential_cmakebin.name, self.for_machine, potential_cmakebin.command))
|
||||
version_if_ok = self.check_cmake(potential_cmakebin)
|
||||
if not version_if_ok:
|
||||
continue
|
||||
if not silent:
|
||||
mlog.log('Found CMake:', mlog.bold(potential_cmakebin.get_path()),
|
||||
'(%s)' % version_if_ok)
|
||||
CMakeExecutor.class_cmakebin[self.for_machine] = potential_cmakebin
|
||||
CMakeExecutor.class_cmakevers[self.for_machine] = version_if_ok
|
||||
break
|
||||
else:
|
||||
if not silent:
|
||||
mlog.log('Found CMake:', mlog.red('NO'))
|
||||
# Set to False instead of None to signify that we've already
|
||||
# searched for it and not found it
|
||||
CMakeExecutor.class_cmakebin[self.for_machine] = False
|
||||
CMakeExecutor.class_cmakevers[self.for_machine] = None
|
||||
|
||||
return CMakeExecutor.class_cmakebin[self.for_machine], CMakeExecutor.class_cmakevers[self.for_machine]
|
||||
|
||||
def check_cmake(self, cmakebin: 'ExternalProgram') -> Optional[str]:
|
||||
if not cmakebin.found():
|
||||
mlog.log('Did not find CMake {!r}'.format(cmakebin.name))
|
||||
return None
|
||||
try:
|
||||
p, out = Popen_safe(cmakebin.get_command() + ['--version'])[0:2]
|
||||
if p.returncode != 0:
|
||||
mlog.warning('Found CMake {!r} but couldn\'t run it'
|
||||
''.format(' '.join(cmakebin.get_command())))
|
||||
return None
|
||||
except FileNotFoundError:
|
||||
mlog.warning('We thought we found CMake {!r} but now it\'s not there. How odd!'
|
||||
''.format(' '.join(cmakebin.get_command())))
|
||||
return None
|
||||
except PermissionError:
|
||||
msg = 'Found CMake {!r} but didn\'t have permissions to run it.'.format(' '.join(cmakebin.get_command()))
|
||||
if not mesonlib.is_windows():
|
||||
msg += '\n\nOn Unix-like systems this is often caused by scripts that are not executable.'
|
||||
mlog.warning(msg)
|
||||
return None
|
||||
cmvers = re.sub(r'\s*cmake version\s*', '', out.split('\n')[0]).strip()
|
||||
return cmvers
|
||||
|
||||
def _cache_key(self, args: List[str], build_dir: str, env):
|
||||
fenv = frozenset(env.items()) if env is not None else None
|
||||
targs = tuple(args)
|
||||
return (self.cmakebin, targs, build_dir, fenv)
|
||||
|
||||
def _call_real(self, args: List[str], build_dir: str, env) -> Tuple[int, str, str]:
|
||||
os.makedirs(build_dir, exist_ok=True)
|
||||
cmd = self.cmakebin.get_command() + args
|
||||
p, out, err = Popen_safe(cmd, env=env, cwd=build_dir)
|
||||
rc = p.returncode
|
||||
call = ' '.join(cmd)
|
||||
mlog.debug("Called `{}` in {} -> {}".format(call, build_dir, rc))
|
||||
return rc, out, err
|
||||
|
||||
def call(self, args: List[str], build_dir: str, env=None, disable_cache: bool = False):
|
||||
if env is None:
|
||||
env = os.environ
|
||||
|
||||
if disable_cache:
|
||||
return self._call_real(args, build_dir, env)
|
||||
|
||||
# First check if cached, if not call the real cmake function
|
||||
cache = CMakeExecutor.class_cmake_cache
|
||||
key = self._cache_key(args, build_dir, env)
|
||||
if key not in cache:
|
||||
cache[key] = self._call_real(args, build_dir, env)
|
||||
return cache[key]
|
||||
|
||||
def call_with_fake_build(self, args: List[str], build_dir: str, env=None):
|
||||
# First check the cache
|
||||
cache = CMakeExecutor.class_cmake_cache
|
||||
key = self._cache_key(args, build_dir, env)
|
||||
if key in cache:
|
||||
return cache[key]
|
||||
|
||||
os.makedirs(build_dir, exist_ok=True)
|
||||
|
||||
# Reset the CMake cache
|
||||
with open('{}/CMakeCache.txt'.format(build_dir), 'w') as fp:
|
||||
fp.write('CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1\n')
|
||||
|
||||
# Fake the compiler files
|
||||
comp_dir = '{}/CMakeFiles/{}'.format(build_dir, self.cmakevers)
|
||||
os.makedirs(comp_dir, exist_ok=True)
|
||||
|
||||
c_comp = '{}/CMakeCCompiler.cmake'.format(comp_dir)
|
||||
cxx_comp = '{}/CMakeCXXCompiler.cmake'.format(comp_dir)
|
||||
|
||||
if not os.path.exists(c_comp):
|
||||
with open(c_comp, 'w') as fp:
|
||||
fp.write('''# Fake CMake file to skip the boring and slow stuff
|
||||
set(CMAKE_C_COMPILER "{}") # Just give CMake a valid full path to any file
|
||||
set(CMAKE_C_COMPILER_ID "GNU") # Pretend we have found GCC
|
||||
set(CMAKE_COMPILER_IS_GNUCC 1)
|
||||
set(CMAKE_C_COMPILER_LOADED 1)
|
||||
set(CMAKE_C_COMPILER_WORKS TRUE)
|
||||
set(CMAKE_C_ABI_COMPILED TRUE)
|
||||
set(CMAKE_SIZEOF_VOID_P "{}")
|
||||
'''.format(os.path.realpath(__file__), ctypes.sizeof(ctypes.c_voidp)))
|
||||
|
||||
if not os.path.exists(cxx_comp):
|
||||
with open(cxx_comp, 'w') as fp:
|
||||
fp.write('''# Fake CMake file to skip the boring and slow stuff
|
||||
set(CMAKE_CXX_COMPILER "{}") # Just give CMake a valid full path to any file
|
||||
set(CMAKE_CXX_COMPILER_ID "GNU") # Pretend we have found GCC
|
||||
set(CMAKE_COMPILER_IS_GNUCXX 1)
|
||||
set(CMAKE_CXX_COMPILER_LOADED 1)
|
||||
set(CMAKE_CXX_COMPILER_WORKS TRUE)
|
||||
set(CMAKE_CXX_ABI_COMPILED TRUE)
|
||||
set(CMAKE_SIZEOF_VOID_P "{}")
|
||||
'''.format(os.path.realpath(__file__), ctypes.sizeof(ctypes.c_voidp)))
|
||||
|
||||
return self.call(args, build_dir, env)
|
||||
|
||||
def found(self) -> bool:
|
||||
return self.cmakebin is not None
|
||||
|
||||
def version(self) -> str:
|
||||
return self.cmakevers
|
||||
|
||||
def executable_path(self) -> str:
|
||||
return self.cmakebin.get_path()
|
||||
|
||||
def get_command(self):
|
||||
return self.cmakebin.get_command()
|
||||
|
||||
def machine_choice(self) -> MachineChoice:
|
||||
return self.for_machine
|
|
@ -17,18 +17,20 @@
|
|||
|
||||
from .common import CMakeException
|
||||
from .client import CMakeClient, RequestCMakeInputs, RequestConfigure, RequestCompute, RequestCodeModel, CMakeTarget
|
||||
from .executor import CMakeExecutor
|
||||
from .. import mlog
|
||||
from ..build import Build
|
||||
from ..environment import Environment
|
||||
from ..mesonlib import MachineChoice
|
||||
from ..mparser import Token, BaseNode, CodeBlockNode, FunctionNode, ArrayNode, ArgumentNode, AssignmentNode, BooleanNode, StringNode, IdNode, MethodNode
|
||||
from ..backend.backends import Backend
|
||||
from ..compilers.compilers import lang_suffixes, header_suffixes, obj_suffixes
|
||||
from ..dependencies.base import CMakeDependency, ExternalProgram
|
||||
from subprocess import Popen, PIPE, STDOUT
|
||||
from typing import List, Dict, Optional
|
||||
from typing import List, Dict, Optional, TYPE_CHECKING
|
||||
import os, re
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..build import Build
|
||||
from ..backend.backends import Backend
|
||||
|
||||
backend_generator_map = {
|
||||
'ninja': 'Ninja',
|
||||
'xcode': 'Xcode',
|
||||
|
@ -276,7 +278,7 @@ class ConverterTarget:
|
|||
mlog.log(' -', key, '=', mlog.bold(str(val)))
|
||||
|
||||
class CMakeInterpreter:
|
||||
def __init__(self, build: Build, subdir: str, src_dir: str, install_prefix: str, env: Environment, backend: Backend):
|
||||
def __init__(self, build: 'Build', subdir: str, src_dir: str, install_prefix: str, env: Environment, backend: 'Backend'):
|
||||
assert(hasattr(backend, 'name'))
|
||||
self.build = build
|
||||
self.subdir = subdir
|
||||
|
@ -303,10 +305,7 @@ class CMakeInterpreter:
|
|||
def configure(self, extra_cmake_options: List[str]) -> None:
|
||||
for_machine = MachineChoice.HOST # TODO make parameter
|
||||
# Find CMake
|
||||
cmake_exe, cmake_vers, _ = CMakeDependency.find_cmake_binary(self.env, for_machine)
|
||||
if cmake_exe is None or cmake_exe is False:
|
||||
raise CMakeException('Unable to find CMake')
|
||||
assert(isinstance(cmake_exe, ExternalProgram))
|
||||
cmake_exe = CMakeExecutor(self.env, '>=3.7', for_machine)
|
||||
if not cmake_exe.found():
|
||||
raise CMakeException('Unable to find CMake')
|
||||
|
||||
|
@ -333,7 +332,7 @@ class CMakeInterpreter:
|
|||
# Run CMake
|
||||
mlog.log()
|
||||
with mlog.nested():
|
||||
mlog.log('Configuring the build directory with', mlog.bold('CMake'), 'version', mlog.cyan(cmake_vers))
|
||||
mlog.log('Configuring the build directory with', mlog.bold('CMake'), 'version', mlog.cyan(cmake_exe.version()))
|
||||
mlog.log(mlog.bold('Running:'), ' '.join(cmake_args))
|
||||
mlog.log()
|
||||
os.makedirs(self.build_dir, exist_ok=True)
|
||||
|
|
|
@ -23,8 +23,6 @@ import shlex
|
|||
import shutil
|
||||
import textwrap
|
||||
import platform
|
||||
import itertools
|
||||
import ctypes
|
||||
import typing
|
||||
from typing import Any, Dict, List, Tuple
|
||||
from enum import Enum
|
||||
|
@ -34,6 +32,7 @@ from .. import mlog
|
|||
from .. import mesonlib
|
||||
from ..compilers import clib_langs
|
||||
from ..environment import BinaryTable, Environment, MachineInfo
|
||||
from ..cmake import CMakeExecutor, CMakeException
|
||||
from ..mesonlib import MachineChoice, MesonException, OrderedSet, PerMachine
|
||||
from ..mesonlib import Popen_safe, version_compare_many, version_compare, listify, stringlistify, extract_as_list
|
||||
from ..mesonlib import Version, LibType
|
||||
|
@ -990,11 +989,7 @@ class CMakeTarget:
|
|||
class CMakeDependency(ExternalDependency):
|
||||
# The class's copy of the CMake path. Avoids having to search for it
|
||||
# multiple times in the same Meson invocation.
|
||||
class_cmakebin = PerMachine(None, None)
|
||||
class_cmakevers = PerMachine(None, None)
|
||||
class_cmakeinfo = PerMachine(None, None)
|
||||
# We cache all pkg-config subprocess invocations to avoid redundant calls
|
||||
cmake_cache = {}
|
||||
# Version string for the minimum CMake version
|
||||
class_cmake_version = '>=3.4'
|
||||
# CMake generators to try (empty for no generator)
|
||||
|
@ -1029,7 +1024,6 @@ class CMakeDependency(ExternalDependency):
|
|||
# Store a copy of the CMake path on the object itself so it is
|
||||
# stored in the pickled coredata and recovered.
|
||||
self.cmakebin = None
|
||||
self.cmakevers = None
|
||||
self.cmakeinfo = None
|
||||
|
||||
# Dict of CMake variables: '<var_name>': ['list', 'of', 'values']
|
||||
|
@ -1044,10 +1038,10 @@ class CMakeDependency(ExternalDependency):
|
|||
# List of successfully found modules
|
||||
self.found_modules = []
|
||||
|
||||
self.cmakebin, self.cmakevers, for_machine = self.find_cmake_binary(environment, self.for_machine, self.silent)
|
||||
if self.cmakebin is False:
|
||||
self.cmakebin = CMakeExecutor(environment, CMakeDependency.class_cmake_version, self.for_machine, silent=self.silent)
|
||||
if not self.cmakebin.found():
|
||||
self.cmakebin = None
|
||||
msg = 'No CMake binary for machine %s not found. Giving up.' % for_machine
|
||||
msg = 'No CMake binary for machine %s not found. Giving up.' % self.for_machine
|
||||
if self.required:
|
||||
raise DependencyException(msg)
|
||||
mlog.debug(msg)
|
||||
|
@ -1075,57 +1069,6 @@ class CMakeDependency(ExternalDependency):
|
|||
return
|
||||
self._detect_dep(name, modules, cm_args)
|
||||
|
||||
@classmethod
|
||||
def find_cmake_binary(cls, environment: Environment, for_machine: MachineChoice, silent: bool = False) -> Tuple[str, str, MachineChoice]:
|
||||
# Create an iterator of options
|
||||
def search():
|
||||
# Lookup in cross or machine file.
|
||||
potential_cmakepath = environment.binaries[for_machine].lookup_entry('cmake')
|
||||
if potential_cmakepath is not None:
|
||||
mlog.debug('CMake binary for %s specified from cross file, native file, or env var as %s.', for_machine, potential_cmakepath)
|
||||
yield ExternalProgram.from_entry('cmake', potential_cmakepath)
|
||||
# We never fallback if the user-specified option is no good, so
|
||||
# stop returning options.
|
||||
return
|
||||
mlog.debug('CMake binary missing from cross or native file, or env var undefined.')
|
||||
# Fallback on hard-coded defaults.
|
||||
# TODO prefix this for the cross case instead of ignoring thing.
|
||||
if environment.machines.matches_build_machine(for_machine):
|
||||
for potential_cmakepath in environment.default_cmake:
|
||||
mlog.debug('Trying a default CMake fallback at', potential_cmakepath)
|
||||
yield ExternalProgram(potential_cmakepath, silent=True)
|
||||
|
||||
# Only search for CMake the first time and store the result in the class
|
||||
# definition
|
||||
if CMakeDependency.class_cmakebin[for_machine] is False:
|
||||
mlog.debug('CMake binary for %s is cached as not found' % for_machine)
|
||||
elif CMakeDependency.class_cmakebin[for_machine] is not None:
|
||||
mlog.debug('CMake binary for %s is cached.' % for_machine)
|
||||
else:
|
||||
assert CMakeDependency.class_cmakebin[for_machine] is None
|
||||
mlog.debug('CMake binary for %s is not cached' % for_machine)
|
||||
for potential_cmakebin in search():
|
||||
mlog.debug('Trying CMake binary {} for machine {} at {}'
|
||||
.format(potential_cmakebin.name, for_machine, potential_cmakebin.command))
|
||||
version_if_ok = cls.check_cmake(potential_cmakebin)
|
||||
if not version_if_ok:
|
||||
continue
|
||||
if not silent:
|
||||
mlog.log('Found CMake:', mlog.bold(potential_cmakebin.get_path()),
|
||||
'(%s)' % version_if_ok)
|
||||
CMakeDependency.class_cmakebin[for_machine] = potential_cmakebin
|
||||
CMakeDependency.class_cmakevers[for_machine] = version_if_ok
|
||||
break
|
||||
else:
|
||||
if not silent:
|
||||
mlog.log('Found CMake:', mlog.red('NO'))
|
||||
# Set to False instead of None to signify that we've already
|
||||
# searched for it and not found it
|
||||
CMakeDependency.class_cmakebin[for_machine] = False
|
||||
CMakeDependency.class_cmakevers[for_machine] = None
|
||||
|
||||
return CMakeDependency.class_cmakebin[for_machine], CMakeDependency.class_cmakevers[for_machine], for_machine
|
||||
|
||||
def __repr__(self):
|
||||
s = '<{0} {1}: {2} {3}>'
|
||||
return s.format(self.__class__.__name__, self.name, self.is_found,
|
||||
|
@ -1305,7 +1248,7 @@ class CMakeDependency(ExternalDependency):
|
|||
# parameters to stderr as they are executed. Since CMake 3.4.0
|
||||
# variables ("${VAR}") are also replaced in the trace output.
|
||||
mlog.debug('\nDetermining dependency {!r} with CMake executable '
|
||||
'{!r}'.format(name, self.cmakebin.get_path()))
|
||||
'{!r}'.format(name, self.cmakebin.executable_path()))
|
||||
|
||||
# Try different CMake generators since specifying no generator may fail
|
||||
# in cygwin for some reason
|
||||
|
@ -1741,41 +1684,6 @@ class CMakeDependency(ExternalDependency):
|
|||
|
||||
yield CMakeTraceLine(file, line, func, args)
|
||||
|
||||
def _reset_cmake_cache(self, build_dir):
|
||||
with open('{}/CMakeCache.txt'.format(build_dir), 'w') as fp:
|
||||
fp.write('CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1\n')
|
||||
|
||||
def _setup_compiler(self, build_dir):
|
||||
comp_dir = '{}/CMakeFiles/{}'.format(build_dir, self.cmakevers)
|
||||
os.makedirs(comp_dir, exist_ok=True)
|
||||
|
||||
c_comp = '{}/CMakeCCompiler.cmake'.format(comp_dir)
|
||||
cxx_comp = '{}/CMakeCXXCompiler.cmake'.format(comp_dir)
|
||||
|
||||
if not os.path.exists(c_comp):
|
||||
with open(c_comp, 'w') as fp:
|
||||
fp.write('''# Fake CMake file to skip the boring and slow stuff
|
||||
set(CMAKE_C_COMPILER "{}") # Just give CMake a valid full path to any file
|
||||
set(CMAKE_C_COMPILER_ID "GNU") # Pretend we have found GCC
|
||||
set(CMAKE_COMPILER_IS_GNUCC 1)
|
||||
set(CMAKE_C_COMPILER_LOADED 1)
|
||||
set(CMAKE_C_COMPILER_WORKS TRUE)
|
||||
set(CMAKE_C_ABI_COMPILED TRUE)
|
||||
set(CMAKE_SIZEOF_VOID_P "{}")
|
||||
'''.format(os.path.realpath(__file__), ctypes.sizeof(ctypes.c_voidp)))
|
||||
|
||||
if not os.path.exists(cxx_comp):
|
||||
with open(cxx_comp, 'w') as fp:
|
||||
fp.write('''# Fake CMake file to skip the boring and slow stuff
|
||||
set(CMAKE_CXX_COMPILER "{}") # Just give CMake a valid full path to any file
|
||||
set(CMAKE_CXX_COMPILER_ID "GNU") # Pretend we have found GCC
|
||||
set(CMAKE_COMPILER_IS_GNUCXX 1)
|
||||
set(CMAKE_CXX_COMPILER_LOADED 1)
|
||||
set(CMAKE_CXX_COMPILER_WORKS TRUE)
|
||||
set(CMAKE_CXX_ABI_COMPILED TRUE)
|
||||
set(CMAKE_SIZEOF_VOID_P "{}")
|
||||
'''.format(os.path.realpath(__file__), ctypes.sizeof(ctypes.c_voidp)))
|
||||
|
||||
def _setup_cmake_dir(self, cmake_file: str) -> str:
|
||||
# Setup the CMake build environment and return the "build" directory
|
||||
build_dir = '{}/cmake_{}'.format(self.cmake_root_dir, self.name)
|
||||
|
@ -1789,68 +1697,16 @@ set(CMAKE_SIZEOF_VOID_P "{}")
|
|||
os.remove(cmake_lists)
|
||||
shutil.copyfile(src_cmake, cmake_lists)
|
||||
|
||||
self._setup_compiler(build_dir)
|
||||
self._reset_cmake_cache(build_dir)
|
||||
return build_dir
|
||||
|
||||
def _call_cmake_real(self, args, cmake_file: str, env):
|
||||
build_dir = self._setup_cmake_dir(cmake_file)
|
||||
cmd = self.cmakebin.get_command() + args
|
||||
p, out, err = Popen_safe(cmd, env=env, cwd=build_dir)
|
||||
rc = p.returncode
|
||||
call = ' '.join(cmd)
|
||||
mlog.debug("Called `{}` in {} -> {}".format(call, build_dir, rc))
|
||||
|
||||
return rc, out, err
|
||||
|
||||
def _call_cmake(self, args, cmake_file: str, env=None):
|
||||
if env is None:
|
||||
fenv = env
|
||||
env = os.environ
|
||||
else:
|
||||
fenv = frozenset(env.items())
|
||||
targs = tuple(args)
|
||||
|
||||
# First check if cached, if not call the real cmake function
|
||||
cache = CMakeDependency.cmake_cache
|
||||
if (self.cmakebin, targs, cmake_file, fenv) not in cache:
|
||||
cache[(self.cmakebin, targs, cmake_file, fenv)] = self._call_cmake_real(args, cmake_file, env)
|
||||
return cache[(self.cmakebin, targs, cmake_file, fenv)]
|
||||
build_dir = self._setup_cmake_dir(cmake_file)
|
||||
return self.cmakebin.call_with_fake_build(args, build_dir, env=env)
|
||||
|
||||
@staticmethod
|
||||
def get_methods():
|
||||
return [DependencyMethods.CMAKE]
|
||||
|
||||
@staticmethod
|
||||
def check_cmake(cmakebin):
|
||||
if not cmakebin.found():
|
||||
mlog.log('Did not find CMake {!r}'.format(cmakebin.name))
|
||||
return None
|
||||
try:
|
||||
p, out = Popen_safe(cmakebin.get_command() + ['--version'])[0:2]
|
||||
if p.returncode != 0:
|
||||
mlog.warning('Found CMake {!r} but couldn\'t run it'
|
||||
''.format(' '.join(cmakebin.get_command())))
|
||||
return None
|
||||
except FileNotFoundError:
|
||||
mlog.warning('We thought we found CMake {!r} but now it\'s not there. How odd!'
|
||||
''.format(' '.join(cmakebin.get_command())))
|
||||
return None
|
||||
except PermissionError:
|
||||
msg = 'Found CMake {!r} but didn\'t have permissions to run it.'.format(' '.join(cmakebin.get_command()))
|
||||
if not mesonlib.is_windows():
|
||||
msg += '\n\nOn Unix-like systems this is often caused by scripts that are not executable.'
|
||||
mlog.warning(msg)
|
||||
return None
|
||||
cmvers = re.sub(r'\s*cmake version\s*', '', out.split('\n')[0]).strip()
|
||||
if not version_compare(cmvers, CMakeDependency.class_cmake_version):
|
||||
mlog.warning(
|
||||
'The version of CMake', mlog.bold(cmakebin.get_path()),
|
||||
'is', mlog.bold(cmvers), 'but version', mlog.bold(CMakeDependency.class_cmake_version),
|
||||
'is required')
|
||||
return None
|
||||
return cmvers
|
||||
|
||||
def log_tried(self):
|
||||
return self.type_name
|
||||
|
||||
|
|
Loading…
Reference in New Issue