Merge pull request #6602 from mensinda/depBoost

boost: System dependency rewrite
pull/6678/head
Jussi Pakkanen 5 years ago committed by GitHub
commit 8bf937b012
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      .github/workflows/lint_mypy.yml
  2. 8
      .github/workflows/os_comp.yml
  3. 3
      azure-pipelines.yml
  4. 4
      ci/azure-steps.yml
  5. 2
      ci/ciimage/eoan/Dockerfile
  6. 1407
      mesonbuild/dependencies/boost.py
  7. 40
      run_project_tests.py
  8. 42
      test cases/frameworks/1 boost/meson.build
  9. 1
      test cases/frameworks/1 boost/meson_options.txt
  10. 19
      test cases/frameworks/1 boost/test_matrix.json
  11. 1
      test cases/frameworks/1 boost/unit_test.cpp
  12. 371
      tools/boost_names.py

@ -30,4 +30,4 @@ jobs:
with: with:
python-version: '3.x' python-version: '3.x'
- run: python -m pip install mypy - run: python -m pip install mypy
- run: mypy --follow-imports=skip mesonbuild/mtest.py mesonbuild/minit.py mesonbuild/mintro.py mesonbuild/msetup.py mesonbuild/wrap tools/ mesonbuild/modules/fs.py mesonbuild/dependencies/mpi.py mesonbuild/dependencies/hdf5.py mesonbuild/compilers/mixins/intel.py - run: mypy --follow-imports=skip mesonbuild/mtest.py mesonbuild/minit.py mesonbuild/mintro.py mesonbuild/msetup.py mesonbuild/wrap tools/ mesonbuild/modules/fs.py mesonbuild/dependencies/boost.py mesonbuild/dependencies/mpi.py mesonbuild/dependencies/hdf5.py mesonbuild/compilers/mixins/intel.py

@ -11,9 +11,7 @@ jobs:
- name: Install Dependencies - name: Install Dependencies
run: | run: |
sudo apt update -yq sudo apt update -yq
sudo apt install -yq --no-install-recommends python3-setuptools python3-pip g++ gfortran gobjc gobjc++ zlib1g-dev python-dev python3-dev libboost-all-dev sudo apt install -yq --no-install-recommends python3-setuptools python3-pip g++ gfortran gobjc gobjc++ zlib1g-dev python-dev python3-dev
- name: Remove GitHub boost version
run: sudo rm -rf /usr/local/share/boost
- name: Install ninja-build tool - name: Install ninja-build tool
uses: seanmiddleditch/gha-setup-ninja@v1 uses: seanmiddleditch/gha-setup-ninja@v1
- name: Python version - name: Python version
@ -21,7 +19,7 @@ jobs:
- name: Ninja version - name: Ninja version
run: ninja --version run: ninja --version
- name: Run tests - name: Run tests
run: python3 run_tests.py run: LD_LIBRARY_PATH=/usr/local/share/boost/1.69.0/lib/:$LD_LIBRARY_PATH python3 run_tests.py
env: env:
CI: '1' CI: '1'
XENIAL: '1' XENIAL: '1'
@ -48,6 +46,7 @@ jobs:
env: env:
CI: '1' CI: '1'
SKIP_SCIENTIFIC: '1' SKIP_SCIENTIFIC: '1'
SKIP_STATIC_BOOST: '1'
opensuse: opensuse:
name: OpenSUSE name: OpenSUSE
@ -60,3 +59,4 @@ jobs:
env: env:
CI: '1' CI: '1'
SKIP_SCIENTIFIC: '1' SKIP_SCIENTIFIC: '1'
SKIP_STATIC_BOOST: '1'

@ -105,7 +105,10 @@ jobs:
- script: | - script: |
set BOOST_ROOT= set BOOST_ROOT=
set PATH=%CYGWIN_ROOT%\bin;%SYSTEMROOT%\system32 set PATH=%CYGWIN_ROOT%\bin;%SYSTEMROOT%\system32
set SKIP_STATIC_BOOST=1
env.exe -- python3 run_tests.py --backend=ninja env.exe -- python3 run_tests.py --backend=ninja
# Cygwin's static boost installation is broken (some static library
# variants such as boost_thread are not present)
displayName: Run Tests displayName: Run Tests
- task: CopyFiles@2 - task: CopyFiles@2
condition: not(canceled()) condition: not(canceled())

@ -49,8 +49,8 @@ steps:
# install boost (except for clang-cl) # install boost (except for clang-cl)
if ($env:arch -eq 'x86') { $boost_bitness = '32' } else { $boost_bitness = '64' } if ($env:arch -eq 'x86') { $boost_bitness = '32' } else { $boost_bitness = '64' }
if ($env:compiler -eq 'msvc2017') { if ($env:compiler -eq 'msvc2017' -Or $env:compiler -eq 'msvc2019' -Or $env:compiler -eq 'clang-cl') {
$boost_version = '1.64.0' ; $boost_abi_tag = '14.1' $boost_version = '1.72.0' ; $boost_abi_tag = '14.1'
} }
if ($boost_version) { if ($boost_version) {
$boost_filename = $boost_version.Replace('.', '_') $boost_filename = $boost_version.Replace('.', '_')

@ -24,7 +24,7 @@ RUN sed -i '/^#\sdeb-src /s/^#//' "/etc/apt/sources.list" \
&& eatmydata apt-get -y install libgcrypt20-dev \ && eatmydata apt-get -y install libgcrypt20-dev \
&& eatmydata apt-get -y install libgpgme-dev \ && eatmydata apt-get -y install libgpgme-dev \
&& eatmydata apt-get -y install libhdf5-dev \ && eatmydata apt-get -y install libhdf5-dev \
&& eatmydata apt-get -y install libboost-python-dev \ && eatmydata apt-get -y install libboost-python-dev libboost-regex-dev \
&& eatmydata apt-get -y install libblocksruntime-dev \ && eatmydata apt-get -y install libblocksruntime-dev \
&& eatmydata apt-get -y install libperl-dev \ && eatmydata apt-get -y install libperl-dev \
&& eatmydata apt-get -y install liblapack-dev libscalapack-mpi-dev \ && eatmydata apt-get -y install liblapack-dev libscalapack-mpi-dev \

File diff suppressed because it is too large Load Diff

@ -136,6 +136,7 @@ do_debug = under_ci or print_debug
no_meson_log_msg = 'No meson-log.txt found.' no_meson_log_msg = 'No meson-log.txt found.'
system_compiler = None system_compiler = None
compiler_id_map = {} # type: T.Dict[str, str]
class StopException(Exception): class StopException(Exception):
def __init__(self): def __init__(self):
@ -544,12 +545,24 @@ def gather_tests(testdir: Path) -> T.Iterator[TestDef]:
assert "val" in i assert "val" in i
skip = False skip = False
# Add an empty matrix entry
if i['val'] is None:
tmp_opts += [(None, False)]
continue
# Skip the matrix entry if environment variable is present # Skip the matrix entry if environment variable is present
if 'skip_on_env' in i: if 'skip_on_env' in i:
for env in i['skip_on_env']: for env in i['skip_on_env']:
if env in os.environ: if env in os.environ:
skip = True skip = True
# Only run the test if all compiler ID's match
if 'compilers' in i:
for lang, id_list in i['compilers'].items():
if lang not in compiler_id_map or compiler_id_map[lang] not in id_list:
skip = True
break
tmp_opts += [('{}={}'.format(key, i['val']), skip)] tmp_opts += [('{}={}'.format(key, i['val']), skip)]
if opt_list: if opt_list:
@ -561,9 +574,27 @@ def gather_tests(testdir: Path) -> T.Iterator[TestDef]:
else: else:
opt_list = [[x] for x in tmp_opts] opt_list = [[x] for x in tmp_opts]
# Exclude specific configurations
if 'exclude' in matrix:
assert isinstance(matrix['exclude'], list)
new_opt_list = [] # type: T.List[T.List[T.Tuple[str, bool]]]
for i in opt_list:
exclude = False
opt_names = [x[0] for x in i]
for j in matrix['exclude']:
ex_list = ['{}={}'.format(k, v) for k, v in j.items()]
if all([x in opt_names for x in ex_list]):
exclude = True
break
if not exclude:
new_opt_list += [i]
opt_list = new_opt_list
for i in opt_list: for i in opt_list:
name = ' '.join([x[0] for x in i]) name = ' '.join([x[0] for x in i if x[0] is not None])
opts = ['-D' + x[0] for x in i] opts = ['-D' + x[0] for x in i if x[0] is not None]
skip = any([x[1] for x in i]) skip = any([x[1] for x in i])
all_tests += [TestDef(t.path, name, opts, skip)] all_tests += [TestDef(t.path, name, opts, skip)]
@ -991,7 +1022,7 @@ def check_meson_commands_work(options):
def detect_system_compiler(options): def detect_system_compiler(options):
global system_compiler global system_compiler, compiler_id_map
with AutoDeletedDir(tempfile.mkdtemp(prefix='b ', dir='.')) as build_dir: with AutoDeletedDir(tempfile.mkdtemp(prefix='b ', dir='.')) as build_dir:
fake_opts = get_fake_options('/') fake_opts = get_fake_options('/')
@ -1002,7 +1033,8 @@ def detect_system_compiler(options):
for lang in sorted(compilers.all_languages): for lang in sorted(compilers.all_languages):
try: try:
comp = env.compiler_from_language(lang, MachineChoice.HOST) comp = env.compiler_from_language(lang, MachineChoice.HOST)
details = '%s %s' % (' '.join(comp.get_exelist()), comp.get_version_string()) details = '{} {} [{}]'.format(' '.join(comp.get_exelist()), comp.get_version_string(), comp.get_id())
compiler_id_map[lang] = comp.get_id()
except mesonlib.MesonException: except mesonlib.MesonException:
comp = None comp = None
details = 'not found' details = 'not found'

@ -1,31 +1,25 @@
# this test requires the following on Ubuntu: libboost-{system,python,log,thread,test}-dev # this test requires the following on Ubuntu: libboost-{system,python,log,thread,test}-dev
project('boosttest', 'cpp', project('boosttest', 'cpp',
default_options : ['cpp_std=c++11']) default_options : ['cpp_std=c++14'])
add_project_arguments(['-DBOOST_LOG_DYN_LINK'], s = get_option('static')
language : 'cpp'
)
dep = dependency('boost', required: false) dep = dependency('boost', static: s, required: false)
if not dep.found() if not dep.found()
error('MESON_SKIP_TEST boost not found.') error('MESON_SKIP_TEST boost not found.')
endif endif
compiler = meson.get_compiler('cpp')
if compiler.has_argument('-permissive')
# boost 1.64, the version we test against, doesn't work with -permissive
add_project_arguments('-permissive', language: 'cpp')
endif
# We want to have multiple separate configurations of Boost # We want to have multiple separate configurations of Boost
# within one project. The need to be independent of each other. # within one project. The need to be independent of each other.
# Use one without a library dependency and one with it. # Use one without a library dependency and one with it.
linkdep = dependency('boost', modules : ['thread', 'system', 'test']) linkdep = dependency('boost', static: s, modules : ['thread', 'system'])
staticdep = dependency('boost', modules : ['thread', 'system'], static : true) testdep = dependency('boost', static: s, modules : ['unit_test_framework'])
testdep = dependency('boost', modules : ['unit_test_framework']) nomoddep = dependency('boost', static: s)
nomoddep = dependency('boost') extralibdep = dependency('boost', static: s, modules : ['thread', 'system', 'date_time', 'log_setup', 'log', 'filesystem', 'regex'])
extralibdep = dependency('boost', modules : ['thread', 'system', 'log_setup', 'log']) notfound = dependency('boost', static: s, modules : ['this_should_not_exist_on_any_systen'], required: false)
assert(not notfound.found())
pymod = import('python') pymod = import('python')
python2 = pymod.find_installation('python2', required: host_machine.system() == 'linux', disabler: true) python2 = pymod.find_installation('python2', required: host_machine.system() == 'linux', disabler: true)
@ -34,28 +28,28 @@ python2dep = python2.dependency(required: host_machine.system() == 'linux', embe
python3dep = python3.dependency(required: host_machine.system() == 'linux', embed: true, disabler: true) python3dep = python3.dependency(required: host_machine.system() == 'linux', embed: true, disabler: true)
# compile python 2/3 modules only if we found a corresponding python version # compile python 2/3 modules only if we found a corresponding python version
if(python2dep.found() and host_machine.system() == 'linux') if(python2dep.found() and host_machine.system() == 'linux' and not s)
if(dep.version().version_compare('>=1.67')) if(dep.version().version_compare('>=1.67'))
# if we have a new version of boost, we need to construct the module name based # if we have a new version of boost, we need to construct the module name based
# on the installed version of python (and hope that they match the version boost # on the installed version of python (and hope that they match the version boost
# was compiled against) # was compiled against)
py2version_string = ''.join(python2dep.version().split('.')) py2version_string = ''.join(python2dep.version().split('.'))
bpython2dep = dependency('boost', modules : ['python' + py2version_string], required: false, disabler: true) bpython2dep = dependency('boost', static: s, modules : ['python' + py2version_string], required: false, disabler: true)
else else
# if we have an older version of boost, we need to use the old module names # if we have an older version of boost, we need to use the old module names
bpython2dep = dependency('boost', modules : ['python'], required: false, disabler: true) bpython2dep = dependency('boost', static: s, modules : ['python'], required: false, disabler: true)
endif endif
else else
python2dep = disabler() python2dep = disabler()
bpython2dep = disabler() bpython2dep = disabler()
endif endif
if(python3dep.found() and host_machine.system() == 'linux') if(python3dep.found() and host_machine.system() == 'linux' and not s)
if(dep.version().version_compare('>=1.67')) if(dep.version().version_compare('>=1.67'))
py3version_string = ''.join(python3dep.version().split('.')) py3version_string = ''.join(python3dep.version().split('.'))
bpython3dep = dependency('boost', modules : ['python' + py3version_string], required: false, disabler: true) bpython3dep = dependency('boost', static: s, modules : ['python' + py3version_string], required: false, disabler: true)
else else
bpython3dep = dependency('boost', modules : ['python3'], required: false, disabler: true) bpython3dep = dependency('boost', static: s, modules : ['python3'], required: false, disabler: true)
endif endif
else else
python3dep = disabler() python3dep = disabler()
@ -63,7 +57,6 @@ else
endif endif
linkexe = executable('linkedexe', 'linkexe.cc', dependencies : linkdep) linkexe = executable('linkedexe', 'linkexe.cc', dependencies : linkdep)
staticexe = executable('staticlinkedexe', 'linkexe.cc', dependencies : staticdep)
unitexe = executable('utf', 'unit_test.cpp', dependencies: testdep) unitexe = executable('utf', 'unit_test.cpp', dependencies: testdep)
nomodexe = executable('nomod', 'nomod.cpp', dependencies : nomoddep) nomodexe = executable('nomod', 'nomod.cpp', dependencies : nomoddep)
extralibexe = executable('extralibexe', 'extralib.cpp', dependencies : extralibdep) extralibexe = executable('extralibexe', 'extralib.cpp', dependencies : extralibdep)
@ -73,7 +66,6 @@ python2module = shared_library('python2_module', ['python_module.cpp'], dependen
python3module = shared_library('python3_module', ['python_module.cpp'], dependencies: [python3dep, bpython3dep], name_prefix: '', cpp_args: ['-DMOD_NAME=python3_module']) python3module = shared_library('python3_module', ['python_module.cpp'], dependencies: [python3dep, bpython3dep], name_prefix: '', cpp_args: ['-DMOD_NAME=python3_module'])
test('Boost linktest', linkexe) test('Boost linktest', linkexe)
test('Boost statictest', staticexe)
test('Boost UTF test', unitexe) test('Boost UTF test', unitexe)
test('Boost nomod', nomodexe) test('Boost nomod', nomodexe)
test('Boost extralib test', extralibexe) test('Boost extralib test', extralibexe)
@ -87,4 +79,4 @@ test('Boost Python3', python3interpreter, args: ['./test_python_module.py', meso
subdir('partial_dep') subdir('partial_dep')
# check we can apply a version constraint # check we can apply a version constraint
dependency('boost', version: '>=@0@'.format(dep.version())) dependency('boost', static: s, version: '>=@0@'.format(dep.version()))

@ -0,0 +1 @@
option('static', type: 'boolean', value: false)

@ -0,0 +1,19 @@
{
"options": {
"static": [
{ "val": "true", "skip_on_env": [ "SKIP_STATIC_BOOST" ] },
{ "val": "false" }
],
"b_vscrt": [
{ "val": null },
{ "val": "md", "compilers": { "cpp": [ "msvc" ] } },
{ "val": "mdd", "compilers": { "cpp": [ "msvc" ] } },
{ "val": "mt", "compilers": { "cpp": [ "msvc" ] } },
{ "val": "mtd", "compilers": { "cpp": [ "msvc" ] } }
]
},
"exclude": [
{ "static": "false", "b_vscrt": "mt" },
{ "static": "false", "b_vscrt": "mtd" }
]
}

@ -1,4 +1,3 @@
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE "MesonTest" #define BOOST_TEST_MODULE "MesonTest"
#define BOOST_TEST_MAIN #define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>

@ -24,164 +24,249 @@ boost/$ path/to/meson/tools/boost_names.py >> path/to/meson/dependencies/misc.py
""" """
import sys import sys
import os
import collections
import pprint
import json import json
import re import re
import textwrap
import functools
import typing as T
from pathlib import Path
lib_dir = Path('libs')
jamroot = Path('Jamroot')
not_modules = ['config', 'disjoint_sets', 'headers']
export_modules = False
@functools.total_ordering
class BoostLibrary():
def __init__(self, name: str, shared: T.List[str], static: T.List[str], single: T.List[str], multi: T.List[str]):
self.name = name
self.shared = shared
self.static = static
self.single = single
self.multi = multi
def __lt__(self, other: T.Any) -> T.Union[bool, 'NotImplemented']:
if isinstance(other, BoostLibrary):
return self.name < other.name
return NotImplemented
def __eq__(self, other: T.Any) -> T.Union[bool, 'NotImplemented']:
if isinstance(other, BoostLibrary):
return self.name == other.name
elif isinstance(other, str):
return self.name == other
return NotImplemented
def __hash__(self) -> int:
return hash(self.name)
@functools.total_ordering
class BoostModule():
def __init__(self, name: str, key: str, desc: str, libs: T.List[BoostLibrary]):
self.name = name
self.key = key
self.desc = desc
self.libs = libs
def __lt__(self, other: T.Any) -> T.Union[bool, 'NotImplemented']:
if isinstance(other, BoostModule):
return self.key < other.key
return NotImplemented
Module = collections.namedtuple('Module', ['dirname', 'name', 'libnames'])
Module.__repr__ = lambda self: str((self.dirname, self.name, self.libnames)) # type: ignore
LIBS = 'libs'
manual_map = {
'callable_traits': 'Call Traits',
'crc': 'CRC',
'dll': 'DLL',
'gil': 'GIL',
'graph_parallel': 'GraphParallel',
'icl': 'ICL',
'io': 'IO State Savers',
'msm': 'Meta State Machine',
'mpi': 'MPI',
'mpl': 'MPL',
'multi_array': 'Multi-Array',
'multi_index': 'Multi-Index',
'numeric': 'Numeric Conversion',
'ptr_container': 'Pointer Container',
'poly_collection': 'PolyCollection',
'qvm': 'QVM',
'throw_exception': 'ThrowException',
'tti': 'TTI',
'vmd': 'VMD',
}
extra = [
Module('utility', 'Compressed Pair', []),
Module('core', 'Enable If', []),
Module('functional', 'Functional/Factory', []),
Module('functional', 'Functional/Forward', []),
Module('functional', 'Functional/Hash', []),
Module('functional', 'Functional/Overloaded Function', []),
Module('utility', 'Identity Type', []),
Module('utility', 'In Place Factory, Typed In Place Factory', []),
Module('numeric', 'Interval', []),
Module('math', 'Math Common Factor', []),
Module('math', 'Math Octonion', []),
Module('math', 'Math Quaternion', []),
Module('math', 'Math/Special Functions', []),
Module('math', 'Math/Statistical Distributions', []),
Module('bind', 'Member Function', []),
Module('algorithm', 'Min-Max', []),
Module('numeric', 'Odeint', []),
Module('utility', 'Operators', []),
Module('core', 'Ref', []),
Module('utility', 'Result Of', []),
Module('algorithm', 'String Algo', []),
Module('core', 'Swap', []),
Module('', 'Tribool', []),
Module('numeric', 'uBLAS', []),
Module('utility', 'Value Initialized', []),
]
# Cannot find the following modules in the documentation of boost
not_modules = ['beast', 'logic', 'mp11', 'winapi']
def eprint(message):
print(message, file=sys.stderr)
def get_library_names(jamfile):
libs = []
with open(jamfile) as jamfh:
jam = jamfh.read()
res = re.finditer(r'^lib[\s]+([A-Za-z0-9_]+)([^;]*);', jam, re.MULTILINE | re.DOTALL)
for matches in res:
if ':' in matches.group(2):
libs.append(matches.group(1))
res = re.finditer(r'^boost-lib[\s]+([A-Za-z0-9_]+)([^;]*);', jam, re.MULTILINE | re.DOTALL)
for matches in res:
if ':' in matches.group(2):
libs.append('boost_{}'.format(matches.group(1)))
return libs
def exists(modules, module): def get_boost_version() -> T.Optional[str]:
return len([x for x in modules if x.dirname == module.dirname]) != 0 raw = jamroot.read_text()
m = re.search(r'BOOST_VERSION\s*:\s*([0-9\.]+)\s*;', raw)
if m:
return m.group(1)
return None
def get_modules(init=extra):
modules = init def get_libraries(jamfile: Path) -> T.List[BoostLibrary]:
for directory in os.listdir(LIBS): # Extract libraries from the boost Jamfiles. This includes:
if not os.path.isdir(os.path.join(LIBS, directory)): # - library name
# - compiler flags
libs: T.List[BoostLibrary] = []
raw = jamfile.read_text()
raw = re.sub(r'#.*\n', '\n', raw) # Remove comments
raw = re.sub(r'\s+', ' ', raw) # Force single space
raw = re.sub(r'}', ';', raw) # Cheat code blocks by converting } to ;
cmds = raw.split(';') # Commands always terminate with a ; (I hope)
cmds = [x.strip() for x in cmds] # Some cleanup
# "Parse" the relevant sections
for i in cmds:
parts = i.split(' ')
parts = [x for x in parts if x not in ['', ':']]
if not parts:
continue continue
if directory in not_modules:
# Parese libraries
if parts[0] in ['lib', 'boost-lib']:
assert len(parts) >= 2
# Get and check the library name
lname = parts[1]
if parts[0] == 'boost-lib':
lname = f'boost_{lname}'
if not lname.startswith('boost_'):
continue
# Get shared / static defines
shared: T.List[str] = []
static: T.List[str] = []
single: T.List[str] = []
multi: T.List[str] = []
for j in parts:
m1 = re.match(r'<link>shared:<define>(.*)', j)
m2 = re.match(r'<link>static:<define>(.*)', j)
m3 = re.match(r'<threading>single:<define>(.*)', j)
m4 = re.match(r'<threading>multi:<define>(.*)', j)
if m1:
shared += [m1.group(1)]
if m2:
static += [m2.group(1)]
if m3:
single += [m3.group(1)]
if m4:
multi += [m4.group(1)]
shared = [f'-D{x}' for x in shared]
static = [f'-D{x}' for x in static]
libs += [BoostLibrary(lname, shared, static, single, multi)]
return libs
def process_lib_dir(ldir: Path) -> T.List[BoostModule]:
meta_file = ldir / 'meta' / 'libraries.json'
bjam_file = ldir / 'build' / 'Jamfile.v2'
if not meta_file.exists():
print(f'WARNING: Meta file {meta_file} does not exist')
return []
# Extract libs
libs: T.List[BoostLibrary] = []
if bjam_file.exists():
libs = get_libraries(bjam_file)
# Extract metadata
data = json.loads(meta_file.read_text())
if not isinstance(data, list):
data = [data]
modules: T.List[BoostModule] = []
for i in data:
modules += [BoostModule(i['name'], i['key'], i['description'], libs)]
return modules
def get_modules() -> T.List[BoostModule]:
modules: T.List[BoostModule] = []
for i in lib_dir.iterdir():
if not i.is_dir() or i.name in not_modules:
continue continue
jamfile = os.path.join(LIBS, directory, 'build', 'Jamfile.v2')
if os.path.isfile(jamfile): # numeric has sub libs
libs = get_library_names(jamfile) subdirs = i / 'sublibs'
else: metadir = i / 'meta'
libs = [] if subdirs.exists() and not metadir.exists():
if directory in manual_map.keys(): for j in i.iterdir():
modname = manual_map[directory] if not j.is_dir():
continue
modules += process_lib_dir(j)
else: else:
modname = directory.replace('_', ' ').title() modules += process_lib_dir(i)
modules.append(Module(directory, modname, libs))
return modules return modules
def get_modules_2():
modules = []
# The python module uses an older build system format and is not easily parseable.
# We add the python module libraries manually.
modules.append(Module('python', 'Python', ['boost_python', 'boost_python3', 'boost_numpy', 'boost_numpy3']))
for (root, _, files) in os.walk(LIBS):
for f in files:
if f == "libraries.json":
projectdir = os.path.dirname(root)
jamfile = os.path.join(projectdir, 'build', 'Jamfile.v2')
if os.path.isfile(jamfile):
libs = get_library_names(jamfile)
else:
libs = []
# Get metadata for module
jsonfile = os.path.join(root, f)
with open(jsonfile) as jsonfh:
boost_modules = json.loads(jsonfh.read())
if(isinstance(boost_modules, dict)):
boost_modules = [boost_modules]
for boost_module in boost_modules:
modules.append(Module(boost_module['key'], boost_module['name'], libs))
# Some subprojects do not have meta directory with json file. Find those
jsonless_modules = [x for x in get_modules([]) if not exists(modules, x)]
for module in jsonless_modules:
eprint("WARNING: {} does not have meta/libraries.json. Will guess pretty name '{}'".format(module.dirname, module.name))
modules.extend(jsonless_modules)
return modules def main() -> int:
if not lib_dir.is_dir() or not jamroot.exists():
print("ERROR: script must be run in boost source directory")
return 1
vers = get_boost_version()
modules = get_modules()
modules = sorted(modules)
libraries = [x for y in modules for x in y.libs]
libraries = sorted(set(libraries))
print(textwrap.dedent(f'''\
#### ---- BEGIN GENERATED ---- ####
# #
# Generated with tools/boost_names.py:
# - boost version: {vers}
# - modules found: {len(modules)}
# - libraries found: {len(libraries)}
#
class BoostLibrary():
def __init__(self, name: str, shared: T.List[str], static: T.List[str], single: T.List[str], multi: T.List[str]):
self.name = name
self.shared = shared
self.static = static
self.single = single
self.multi = multi
class BoostModule():
def __init__(self, name: str, key: str, desc: str, libs: T.List[str]):
self.name = name
self.key = key
self.desc = desc
self.libs = libs
# dict of all know libraries with additional compile options
boost_libraries = {{\
'''))
for i in libraries:
print(textwrap.indent(textwrap.dedent(f"""\
'{i.name}': BoostLibrary(
name='{i.name}',
shared={i.shared},
static={i.static},
single={i.single},
multi={i.multi},
),\
"""), ' '))
if export_modules:
print(textwrap.dedent(f'''\
}}
def main(args): # dict of all modules with metadata
if not os.path.isdir(LIBS): boost_modules = {{\
eprint("ERROR: script must be run in boost source directory") '''))
# It will pick jsonless algorithm if 1 is given as argument for mod in modules:
impl = 0 desc_excaped = re.sub(r"'", "\\'", mod.desc)
if len(args) > 1: print(textwrap.indent(textwrap.dedent(f"""\
if args[1] == '1': '{mod.key}': BoostModule(
impl = 1 name='{mod.name}',
key='{mod.key}',
desc='{desc_excaped}',
libs={[x.name for x in mod.libs]},
),\
"""), ' '))
if impl == 1: print(textwrap.dedent(f'''\
modules = get_modules() }}
else:
modules = get_modules_2()
sorted_modules = sorted(modules, key=lambda module: module.name.lower()) # #
sorted_modules = [x[2] for x in sorted_modules if x[2]] #### ---- END GENERATED ---- ####\
sorted_modules = sum(sorted_modules, []) '''))
sorted_modules = [x for x in sorted_modules if x.startswith('boost')]
pp = pprint.PrettyPrinter() return 0
pp.pprint(sorted_modules)
if __name__ == '__main__': if __name__ == '__main__':
main(sys.argv) sys.exit(main())

Loading…
Cancel
Save