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 # Set -fPIC for static libraries by default unless explicitly disabled
if isinstance(target, build.StaticLibrary) and target.pic: if isinstance(target, build.StaticLibrary) and target.pic:
commands += compiler.get_pic_args() commands += compiler.get_pic_args()
# Add compile args needed to find external dependencies # Add compile args needed to find external dependencies. Link args are
# Link args are added while generating the link command # added while generating the link command.
for dep in target.get_external_deps(): # 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() commands += dep.get_compile_args()
# Qt needs -fPIC for executables # Qt needs -fPIC for executables
# XXX: We should move to -fPIC for all 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. # and from `include_directories:` of internal deps of the target.
# #
# Target include dirs should override internal deps include dirs. # 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 # Include dirs from internal deps should override include dirs from
# external deps. # external deps and must maintain the order in which they are specified.
for i in target.get_include_dirs(): # Hence, we must reverse the list so that the order is preserved.
for i in reversed(target.get_include_dirs()):
basedir = i.get_curdir() basedir = i.get_curdir()
for d in i.get_incdirs(): for d in i.get_incdirs():
# Avoid superfluous '/.' at the end of paths when d is '.' # 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. # and from `include_directories:` of internal deps of the target.
# #
# Target include dirs should override internal deps include dirs. # 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 # 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 # These are per-target, but we still add them as per-file because we
# need them to be looked in first. # 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(): for i in d.get_incdirs():
curdir = os.path.join(d.get_curdir(), i) curdir = os.path.join(d.get_curdir(), i)
args.append('-I' + self.relpath(curdir, target.subdir)) # build dir 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 # Split compile args needed to find external dependencies
# Link args are added while generating the link command # 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, # Cflags required by external deps might have UNIX-specific flags,
# so filter them out if needed # so filter them out if needed
d_compile_args = compiler.unix_args_to_native(d.get_compile_args()) 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: for i in self.link_depends:
if not isinstance(i, str): if not isinstance(i, str):
raise InvalidArguments('Link_depends arguments must be strings.') raise InvalidArguments('Link_depends arguments must be strings.')
deplist = kwargs.get('dependencies', []) # Target-specific include dirs must be added BEFORE include dirs from
if not isinstance(deplist, list): # internal deps (added inside self.add_deps()) to override them.
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.
inclist = kwargs.get('include_directories', []) inclist = kwargs.get('include_directories', [])
if not isinstance(inclist, list): if not isinstance(inclist, list):
inclist = [inclist] inclist = [inclist]
self.add_include_dirs(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) self.custom_install_dir = kwargs.get('install_dir', None)
if self.custom_install_dir is not None: if self.custom_install_dir is not None:
if not isinstance(self.custom_install_dir, str): if not isinstance(self.custom_install_dir, str):

@ -432,7 +432,20 @@ class BasePlatformTests(unittest.TestCase):
def get_compdb(self): def get_compdb(self):
with open(os.path.join(self.builddir, 'compile_commands.json')) as ifile: 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): def get_meson_log(self):
with open(os.path.join(self.builddir, 'meson-logs', 'meson-log.txt')) as f: 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): def test_internal_include_order(self):
testdir = os.path.join(self.common_test_dir, '138 include order') testdir = os.path.join(self.common_test_dir, '138 include order')
self.init(testdir) self.init(testdir)
execmd = fxecmd = None
for cmd in self.get_compdb(): for cmd in self.get_compdb():
if cmd['file'].endswith('/main.c'): if 'someexe' in cmd['command']:
cmd = cmd['command'] execmd = cmd['command']
break continue
else: if 'somefxe' in cmd['command']:
raise Exception('Could not find main.c command') fxecmd = cmd['command']
if cmd.endswith('.rsp'): continue
# Pretend to build so that the rsp files are generated if not execmd or not fxecmd:
self.build(['-d', 'keeprsp', '-n']) raise Exception('Could not find someexe and somfxe commands')
# Extract the actual command from the rsp file # Check include order for 'someexe'
rsp = os.path.join(self.builddir, cmd.split('cl @')[1]) incs = [a for a in shlex.split(execmd) if a.startswith("-I")]
with open(rsp, 'r', encoding='utf-8') as f:
cmd = f.read()
incs = [a for a in shlex.split(cmd) if a.startswith("-I")]
self.assertEqual(len(incs), 8) self.assertEqual(len(incs), 8)
# target private dir # target private dir
self.assertPathEqual(incs[0], "-Isub4/someexe@exe") self.assertPathEqual(incs[0], "-Isub4/someexe@exe")
@ -743,6 +754,27 @@ class AllPlatformTests(BasePlatformTests):
self.assertPathEqual(incs[6], "-Isub1") self.assertPathEqual(incs[6], "-Isub1")
# target internal dependency include_directories: source dir # target internal dependency include_directories: source dir
self.assertPathBasenameEqual(incs[7], 'sub1') 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): def test_compiler_detection(self):
''' '''

Loading…
Cancel
Save