Preserve the order of internal deps in a target

We were adding them to the CompilerArgs instance in the order in which
they are specified, which is wrong because later dependencies would
override previous ones. Add them in the reverse order instead.

Closes https://github.com/mesonbuild/meson/issues/1495
pull/1496/head
Nirbheek Chauhan 8 years ago
parent 8482286236
commit 7f80f81ac9
  1. 8
      mesonbuild/backend/backends.py
  2. 6
      mesonbuild/backend/ninjabackend.py
  3. 9
      mesonbuild/backend/vs2010backend.py
  4. 13
      mesonbuild/build.py
  5. 60
      run_unittests.py

@ -375,9 +375,11 @@ class Backend:
# Set -fPIC for static libraries by default unless explicitly disabled
if isinstance(target, build.StaticLibrary) and target.pic:
commands += compiler.get_pic_args()
# Add compile args needed to find external dependencies
# Link args are added while generating the link command
for dep in target.get_external_deps():
# Add compile args needed to find external dependencies. Link args are
# added while generating the link command.
# NOTE: We must preserve the order in which external deps are
# specified, so we reverse the list before iterating over it.
for dep in reversed(target.get_external_deps()):
commands += dep.get_compile_args()
# Qt needs -fPIC for executables
# XXX: We should move to -fPIC for all executables

@ -1831,10 +1831,12 @@ rule FORTRAN_DEP_HACK
# and from `include_directories:` of internal deps of the target.
#
# Target include dirs should override internal deps include dirs.
# This is handled in BuildTarget.process_kwargs()
#
# Include dirs from internal deps should override include dirs from
# external deps.
for i in target.get_include_dirs():
# external deps and must maintain the order in which they are specified.
# Hence, we must reverse the list so that the order is preserved.
for i in reversed(target.get_include_dirs()):
basedir = i.get_curdir()
for d in i.get_incdirs():
# Avoid superfluous '/.' at the end of paths when d is '.'

@ -714,12 +714,15 @@ class Vs2010Backend(backends.Backend):
# and from `include_directories:` of internal deps of the target.
#
# Target include dirs should override internal deps include dirs.
# This is handled in BuildTarget.process_kwargs()
#
# Include dirs from internal deps should override include dirs from
# external deps.
# external deps and must maintain the order in which they are
# specified. Hence, we must reverse so that the order is preserved.
#
# These are per-target, but we still add them as per-file because we
# need them to be looked in first.
for d in target.get_include_dirs():
for d in reversed(target.get_include_dirs()):
for i in d.get_incdirs():
curdir = os.path.join(d.get_curdir(), i)
args.append('-I' + self.relpath(curdir, target.subdir)) # build dir
@ -769,7 +772,7 @@ class Vs2010Backend(backends.Backend):
# Split compile args needed to find external dependencies
# Link args are added while generating the link command
for d in target.get_external_deps():
for d in reversed(target.get_external_deps()):
# Cflags required by external deps might have UNIX-specific flags,
# so filter them out if needed
d_compile_args = compiler.unix_args_to_native(d.get_compile_args())

@ -598,16 +598,17 @@ class BuildTarget(Target):
for i in self.link_depends:
if not isinstance(i, str):
raise InvalidArguments('Link_depends arguments must be strings.')
deplist = kwargs.get('dependencies', [])
if not isinstance(deplist, list):
deplist = [deplist]
self.add_deps(deplist)
# Target-specific include dirs must be added after include dirs from
# internal deps (added inside self.add_deps()) to override correctly.
# Target-specific include dirs must be added BEFORE include dirs from
# internal deps (added inside self.add_deps()) to override them.
inclist = kwargs.get('include_directories', [])
if not isinstance(inclist, list):
inclist = [inclist]
self.add_include_dirs(inclist)
# Add dependencies (which also have include_directories)
deplist = kwargs.get('dependencies', [])
if not isinstance(deplist, list):
deplist = [deplist]
self.add_deps(deplist)
self.custom_install_dir = kwargs.get('install_dir', None)
if self.custom_install_dir is not None:
if not isinstance(self.custom_install_dir, str):

@ -432,7 +432,20 @@ class BasePlatformTests(unittest.TestCase):
def get_compdb(self):
with open(os.path.join(self.builddir, 'compile_commands.json')) as ifile:
return json.load(ifile)
contents = json.load(ifile)
# If Ninja is using .rsp files, generate them, read their contents, and
# replace it as the command for all compile commands in the parsed json.
if len(contents) > 0 and contents[0]['command'].endswith('.rsp'):
# Pretend to build so that the rsp files are generated
self.build(['-d', 'keeprsp', '-n'])
for each in contents:
# Extract the actual command from the rsp file
compiler, rsp = each['command'].split(' @')
rsp = os.path.join(self.builddir, rsp)
# Replace the command with its contents
with open(rsp, 'r', encoding='utf-8') as f:
each['command'] = compiler + ' ' + f.read()
return contents
def get_meson_log(self):
with open(os.path.join(self.builddir, 'meson-logs', 'meson-log.txt')) as f:
@ -712,20 +725,18 @@ class AllPlatformTests(BasePlatformTests):
def test_internal_include_order(self):
testdir = os.path.join(self.common_test_dir, '138 include order')
self.init(testdir)
execmd = fxecmd = None
for cmd in self.get_compdb():
if cmd['file'].endswith('/main.c'):
cmd = cmd['command']
break
else:
raise Exception('Could not find main.c command')
if cmd.endswith('.rsp'):
# Pretend to build so that the rsp files are generated
self.build(['-d', 'keeprsp', '-n'])
# Extract the actual command from the rsp file
rsp = os.path.join(self.builddir, cmd.split('cl @')[1])
with open(rsp, 'r', encoding='utf-8') as f:
cmd = f.read()
incs = [a for a in shlex.split(cmd) if a.startswith("-I")]
if 'someexe' in cmd['command']:
execmd = cmd['command']
continue
if 'somefxe' in cmd['command']:
fxecmd = cmd['command']
continue
if not execmd or not fxecmd:
raise Exception('Could not find someexe and somfxe commands')
# Check include order for 'someexe'
incs = [a for a in shlex.split(execmd) if a.startswith("-I")]
self.assertEqual(len(incs), 8)
# target private dir
self.assertPathEqual(incs[0], "-Isub4/someexe@exe")
@ -743,6 +754,27 @@ class AllPlatformTests(BasePlatformTests):
self.assertPathEqual(incs[6], "-Isub1")
# target internal dependency include_directories: source dir
self.assertPathBasenameEqual(incs[7], 'sub1')
# Check include order for 'somefxe'
incs = [a for a in shlex.split(fxecmd) if a.startswith('-I')]
self.assertEqual(len(incs), 9)
# target private dir
self.assertPathEqual(incs[0], '-Isomefxe@exe')
# target build dir
self.assertPathEqual(incs[1], '-I.')
# target source dir
self.assertPathBasenameEqual(incs[2], os.path.basename(testdir))
# target internal dependency correct include_directories: build dir
self.assertPathEqual(incs[3], "-Isub4")
# target internal dependency correct include_directories: source dir
self.assertPathBasenameEqual(incs[4], 'sub4')
# target internal dependency dep include_directories: build dir
self.assertPathEqual(incs[5], "-Isub1")
# target internal dependency dep include_directories: source dir
self.assertPathBasenameEqual(incs[6], 'sub1')
# target internal dependency wrong include_directories: build dir
self.assertPathEqual(incs[7], "-Isub2")
# target internal dependency wrong include_directories: source dir
self.assertPathBasenameEqual(incs[8], 'sub2')
def test_compiler_detection(self):
'''

Loading…
Cancel
Save