C/C++: Get default include dirs from compilers

pull/2282/head
Niklas Claesson 7 years ago
parent 488e57332f
commit 09ccd0eeaa
  1. 8
      mesonbuild/compilers/c.py
  2. 39
      mesonbuild/compilers/compilers.py
  3. 13
      mesonbuild/dependencies/misc.py

@ -172,6 +172,9 @@ class CCompiler(Compiler):
def get_linker_search_args(self, dirname):
return ['-L' + dirname]
def get_default_include_dirs(self):
return []
def gen_import_library_args(self, implibname):
"""
The name of the outputted import library
@ -1082,3 +1085,8 @@ class VisualStudioCCompiler(CCompiler):
elif version < 1920:
return '14.1' # (Visual Studio 2017)
return None
def get_default_include_dirs(self):
if 'INCLUDE' not in os.environ:
return []
return os.environ['INCLUDE'].split(os.pathsep)

@ -13,6 +13,7 @@
# limitations under the License.
import contextlib, os.path, re, tempfile
import subprocess
from ..linkers import StaticLinker
from .. import coredata
@ -917,6 +918,35 @@ def get_largefile_args(compiler):
# those features explicitly.
return []
# TODO: The result from calling compiler should be cached. So that calling this
# function multiple times don't add latency.
def gnulike_default_include_dirs(compiler, lang):
if lang == 'cpp':
lang = 'c++'
p = subprocess.Popen(
compiler + ['-x{}'.format(lang), '-E', '-v', '-'],
stdin=subprocess.DEVNULL,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE
)
stderr = p.stderr.read().decode('utf-8')
parse_state = 0
paths = []
for line in stderr.split('\n'):
if parse_state == 0:
if line == '#include "..." search starts here:':
parse_state = 1
elif parse_state == 1:
if line == '#include <...> search starts here:':
parse_state = 2
else:
paths.append(line[1:])
elif parse_state == 2:
if line == 'End of search list.':
break
else:
paths.append(line[1:])
return paths
class GnuCompiler:
# Functionality that is common to all GNU family compilers.
@ -998,6 +1028,9 @@ class GnuCompiler:
def get_instruction_set_args(self, instruction_set):
return gnulike_instruction_set_args.get(instruction_set, None)
def get_default_include_dirs(self):
return gnulike_default_include_dirs(self.exelist, self.language)
class ClangCompiler:
def __init__(self, clang_type):
@ -1082,6 +1115,9 @@ class ClangCompiler:
def get_instruction_set_args(self, instruction_set):
return gnulike_instruction_set_args.get(instruction_set, None)
def get_default_include_dirs(self):
return gnulike_default_include_dirs(self.exelist, self.language)
# Tested on linux for ICC 14.0.3, 15.0.6, 16.0.4, 17.0.1
class IntelCompiler:
@ -1132,3 +1168,6 @@ class IntelCompiler:
# if self.icc_type == ICC_OSX:
# return ['-bundle']
return ['-shared']
def get_default_include_dirs(self):
return gnulike_default_include_dirs(self.exelist, self.language)

@ -116,18 +116,7 @@ class BoostDependency(ExternalDependency):
# and http://stackoverflow.com/questions/37218953/isystem-on-a-system-include-directory-causes-errors
# for more details
# TODO: The correct solution would probably be to ask the
# compiler for it's default include paths (ie: "gcc -xc++ -E
# -v -") and avoid including those with -isystem
# For now, use -isystem for all includes except for some
# typical defaults (which don't need to be included at all
# since they are in the default include paths). These typical
# defaults include the usual directories at the root of the
# filesystem, but also any path that ends with those directory
# names in order to handle cases like cross-compiling where we
# might have a different sysroot.
if not include_dir.endswith(('/usr/include', '/usr/local/include')):
if include_dir and include_dir not in self.compiler.get_default_include_dirs():
args.append("".join(self.compiler.get_include_args(include_dir, True)))
return args

Loading…
Cancel
Save