Add functionality to promote nested dependencies to top level.

pull/2334/head
Jussi Pakkanen 8 years ago
parent 202b2fedf3
commit 46c071ea5c
  1. 14
      docs/markdown/Using-wraptool.md
  2. 11
      docs/markdown/snippets/wrap_promote.md
  3. 50
      mesonbuild/wrap/wraptool.py
  4. 21
      run_unittests.py
  5. 5
      test cases/unit/13 promote/meson.build
  6. 7
      test cases/unit/13 promote/subprojects/s1/meson.build
  7. 6
      test cases/unit/13 promote/subprojects/s1/s1.c
  8. 4
      test cases/unit/13 promote/subprojects/s1/subprojects/s3/meson.build
  9. 3
      test cases/unit/13 promote/subprojects/s1/subprojects/s3/s3.c
  10. 4
      test cases/unit/13 promote/subprojects/s1/subprojects/scommon/meson.build
  11. 1
      test cases/unit/13 promote/subprojects/s1/subprojects/scommon/scommon_broken.c
  12. 6
      test cases/unit/13 promote/subprojects/s2/meson.build
  13. 6
      test cases/unit/13 promote/subprojects/s2/s2.c
  14. 4
      test cases/unit/13 promote/subprojects/s2/subprojects/scommon/meson.build
  15. 3
      test cases/unit/13 promote/subprojects/s2/subprojects/scommon/scommon_ok.c

@ -57,3 +57,17 @@ In this case `zlib` has a newer release available. Updating it is straightforwar
Updated zlib to branch 1.2.8 revision 4
Wraptool can do other things besides these. Documentation for these can be found in the command line help, which can be accessed by `wraptool --help`.
## Promoting dependencies
Meson will only search for subprojects from the top level `subprojects` directory. If you have subprojects that themselves have subprojects, you must transfer them to the top level. This can be done by going to your source root and issuing a promotion command.
meson wrap promote projname
This will cause Meson to go through your entire project tree, find an embedded subproject and copy it to the top level.
If there are multiple embedded copies of a subproject, Meson will not try to guess which one you want. Instead it will print all the possibilities. You can then manually select which one to promote by writing it out fully.
meson wrap promote subprojects/s1/subprojects/projname
This functionality was added in Meson release 0.43.0.

@ -0,0 +1,11 @@
# Can promote dependencies with wrap command
The `promote` command makes it easy to copy nested dependencies to the top level.
meson wrap promote scommon
This will search the project tree for a subproject called `scommon` and copy it to the top level.
If there are many embedded subprojects with the same name, you have to specify which one to promote manually like this:
meson wrap promote subprojects/s1/subprojects/scommon

@ -142,6 +142,51 @@ def info(name):
for v in versions:
print(' ', v['branch'], v['revision'])
def do_promotion(from_path, spdir_name):
sproj_name = os.path.split(from_path)[1]
outputdir = os.path.join(spdir_name, sproj_name)
if os.path.exists(outputdir):
sys.exit('Output dir %s already exists. Will not overwrite.' % outputdir)
shutil.copytree(from_path, outputdir, ignore=shutil.ignore_patterns('subprojects'))
def detect_subprojects(spdir_name, current_dir='', result=None):
if result is None:
result = {}
spdir = os.path.join(current_dir, spdir_name)
if not os.path.exists(spdir):
return result
for trial in glob(os.path.join(spdir, '*')):
basename = os.path.split(trial)[1]
if trial == 'packagecache':
continue
if not os.path.isdir(trial):
continue
if basename in result:
result[basename].append(trial)
else:
result[basename] = [trial]
detect_subprojects(spdir_name, trial, result)
return result
def promote(argument):
path_segment, subproject_name = os.path.split(argument)
spdir_name = 'subprojects'
sprojs = detect_subprojects(spdir_name)
if subproject_name not in sprojs:
sys.exit('Subproject %s not found in directory tree.' % subproject_name)
matches = sprojs[subproject_name]
if len(matches) == 1:
do_promotion(matches[0], spdir_name)
return
if path_segment == '':
print('There are many versions of %s in tree. Please specify which one to promote:\n' % subproject_name)
for s in matches:
print(s)
sys.exit(1)
system_native_path_argument = argument.replace('/', os.sep)
if system_native_path_argument in matches:
do_promotion(argument, spdir_name)
def status():
print('Subproject status')
for w in glob('subprojects/*.wrap'):
@ -189,6 +234,11 @@ def run(args):
print('info requires exactly one argument.')
return 1
info(args[0])
elif command == 'promote':
if len(args) != 1:
print('promote requires exactly one argument.')
return 1
promote(args[0])
elif command == 'status':
status()
else:

@ -468,6 +468,7 @@ class BasePlatformTests(unittest.TestCase):
self.mconf_command = meson_command + ['configure']
self.mintro_command = meson_command + ['introspect']
self.mtest_command = meson_command + ['test', '-C', self.builddir]
self.wrap_command = meson_command + ['wrap']
# Backend-specific build commands
self.build_command, self.clean_command, self.test_command, self.install_command, \
self.uninstall_command = get_backend_commands(self.backend)
@ -1643,6 +1644,26 @@ int main(int argc, char **argv) {
self.setconf("-Dfree_array_opt=['a,b', 'c,d']", will_build=False)
self.opt_has('free_array_opt', ['a,b', 'c,d'])
def test_subproject_promotion(self):
testdir = os.path.join(self.unit_test_dir, '13 promote')
workdir = os.path.join(self.builddir, 'work')
shutil.copytree(testdir, workdir)
spdir = os.path.join(workdir, 'subprojects')
s3dir = os.path.join(spdir, 's3')
scommondir = os.path.join(spdir, 'scommon')
self.assertFalse(os.path.isdir(s3dir))
subprocess.check_call(self.wrap_command + ['promote', 's3'], cwd=workdir)
self.assertTrue(os.path.isdir(s3dir))
self.assertFalse(os.path.isdir(scommondir))
self.assertNotEqual(subprocess.call(self.wrap_command + ['promote', 'scommon'],
cwd=workdir,
stdout=subprocess.DEVNULL), 0)
self.assertFalse(os.path.isdir(scommondir))
subprocess.check_call(self.wrap_command + ['promote', 'subprojects/s2/subprojects/scommon'], cwd=workdir)
self.assertTrue(os.path.isdir(scommondir))
self.init(workdir)
self.build()
class FailureTests(BasePlatformTests):
'''

@ -0,0 +1,5 @@
project('promotion test', 'c')
subproject('s1')
subproject('s2')

@ -0,0 +1,7 @@
project('s1', 'c')
sc = subproject('scommon')
s3 = subproject('s3')
executable('s1', 's1.c',
link_with : [sc.get_variable('clib'), s3.get_variable('l')])

@ -0,0 +1,6 @@
int func();
int func2();
int main(int argc, char **argv) {
return func() + func2();
}

@ -0,0 +1,4 @@
project('s3', 'c')
l = static_library('s3', 's3.c')

@ -0,0 +1,4 @@
project('scommon', 'c')
clib = static_library('scommon', 'scommon_broken.c')

@ -0,0 +1 @@
#error This file must not be used. The other scommon one should be instead.

@ -0,0 +1,6 @@
project('s2', 'c')
sc = subproject('scommon')
executable('s2', 's2.c', link_with : sc.get_variable('clib'))

@ -0,0 +1,6 @@
int func();
int main(int argc, char **argv) {
return func() != 42;
}

@ -0,0 +1,4 @@
project('scommon', 'c')
clib = static_library('scommon', 'scommon_ok.c')
Loading…
Cancel
Save