This addresses various real-world problems with HDF5 pkg-config, including * hdf*.pc with package versions as part of the filename * malformed hdf*.pc missing the commonly-used HDF5 HL module --- Additionally, this refactors more complicated dependencies such as HDF5 and OpenMPI. This may help us deduplicate internal dependency code in the future. HDF5 selftest: improve platform-agnostic test ci: init demo github action for HDF5 framework ci Actions: hold off on MSYS2 for now [skip ci] hdf5: ensure C libraries always included ci: mac hdf5--use clang+gfortranpull/6255/head
parent
dd15c47ea8
commit
c02593fddc
6 changed files with 232 additions and 73 deletions
@ -0,0 +1,98 @@ |
|||||||
|
# at first, we demo HDF5 framework. More can be added. |
||||||
|
name: ci_frameworks |
||||||
|
|
||||||
|
on: |
||||||
|
push: |
||||||
|
paths: |
||||||
|
- "mesonbuild/dependencies/**" |
||||||
|
- ".github/workflows/frameworks.yml" |
||||||
|
pull_request: |
||||||
|
paths: |
||||||
|
- "mesonbuild/dependencies/**" |
||||||
|
- ".github/workflows/frameworks.yml" |
||||||
|
|
||||||
|
jobs: |
||||||
|
|
||||||
|
linux: |
||||||
|
runs-on: ubuntu-latest |
||||||
|
steps: |
||||||
|
- uses: actions/checkout@v1 |
||||||
|
- uses: actions/setup-python@v1 |
||||||
|
with: |
||||||
|
python-version: '3.x' |
||||||
|
- run: python -m pip install -e . |
||||||
|
- run: sudo apt install -yq --no-install-recommends ninja-build g++ gfortran libhdf5-dev |
||||||
|
- run: meson setup "test cases/frameworks/25 hdf5" build |
||||||
|
env: |
||||||
|
FC: gfortran |
||||||
|
CXX: g++ |
||||||
|
CC: gcc |
||||||
|
- run: ninja -C build |
||||||
|
- uses: actions/upload-artifact@v1 |
||||||
|
if: failure() |
||||||
|
with: |
||||||
|
name: Linux_Log |
||||||
|
path: build/meson-logs/meson-log.txt |
||||||
|
- run: meson test -C build -v |
||||||
|
- uses: actions/upload-artifact@v1 |
||||||
|
if: failure() |
||||||
|
with: |
||||||
|
name: Linux_Test |
||||||
|
path: build/meson-logs/testlog.txt |
||||||
|
|
||||||
|
mac: |
||||||
|
runs-on: macos-latest |
||||||
|
steps: |
||||||
|
- uses: actions/checkout@v1 |
||||||
|
- uses: actions/setup-python@v1 |
||||||
|
with: |
||||||
|
python-version: '3.x' |
||||||
|
- run: python -m pip install -e . |
||||||
|
- run: brew install pkg-config ninja gcc hdf5 |
||||||
|
- run: meson setup "test cases/frameworks/25 hdf5" build |
||||||
|
- run: ninja -C build |
||||||
|
- uses: actions/upload-artifact@v1 |
||||||
|
if: failure() |
||||||
|
with: |
||||||
|
name: Mac_Log |
||||||
|
path: build/meson-logs/meson-log.txt |
||||||
|
- run: meson test -C build -v |
||||||
|
- uses: actions/upload-artifact@v1 |
||||||
|
if: failure() |
||||||
|
with: |
||||||
|
name: Mac_Test |
||||||
|
path: build/meson-logs/testlog.txt |
||||||
|
|
||||||
|
windows: |
||||||
|
# as usual, start in MSYS to install packages, then switch to MINGW64 to build. |
||||||
|
if: false |
||||||
|
# MSYS2 GitHub Action is still being developed--appears to have PATH bugs stopping this from working. |
||||||
|
runs-on: windows-latest |
||||||
|
steps: |
||||||
|
- uses: actions/checkout@v1 |
||||||
|
- uses: actions/setup-python@v1 |
||||||
|
with: |
||||||
|
python-version: '3.x' |
||||||
|
- uses: numworks/setup-msys2@v1 |
||||||
|
with: |
||||||
|
msystem: MSYS |
||||||
|
- run: msys2do pacman -S mingw64/mingw-w64-x86_64-ninja mingw64/mingw-w64-x86_64-pkg-config mingw64/mingw-w64-x86_64-gcc mingw64/mingw-w64-x86_64-gcc-fortran mingw-w64-x86_64-hdf5 --noprogressbar --noconfirm |
||||||
|
- run: set MSYSTEM=MINGW64 |
||||||
|
- run: python -m pip install -e . |
||||||
|
- run: meson setup "test cases/frameworks/25 hdf5" build |
||||||
|
env: |
||||||
|
FC: gfortran |
||||||
|
CXX: g++ |
||||||
|
CC: gcc |
||||||
|
- run: ninja -C build |
||||||
|
- uses: actions/upload-artifact@v1 |
||||||
|
if: failure() |
||||||
|
with: |
||||||
|
name: MSYS_Log |
||||||
|
path: build/meson-logs/meson-log.txt |
||||||
|
- run: meson test -C build -v |
||||||
|
- uses: actions/upload-artifact@v1 |
||||||
|
if: failure() |
||||||
|
with: |
||||||
|
name: MSYS2_Test |
||||||
|
path: build/meson-logs/testlog.txt |
@ -0,0 +1,120 @@ |
|||||||
|
# Copyright 2013-2019 The Meson development team |
||||||
|
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
# you may not use this file except in compliance with the License. |
||||||
|
# You may obtain a copy of the License at |
||||||
|
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
|
||||||
|
# Unless required by applicable law or agreed to in writing, software |
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
# See the License for the specific language governing permissions and |
||||||
|
# limitations under the License. |
||||||
|
|
||||||
|
# This file contains the detection logic for miscellaneous external dependencies. |
||||||
|
|
||||||
|
import subprocess |
||||||
|
from pathlib import Path |
||||||
|
|
||||||
|
from .. import mlog |
||||||
|
from ..mesonlib import split_args |
||||||
|
from .base import DependencyException, ExternalDependency, ExternalProgram, PkgConfigDependency |
||||||
|
|
||||||
|
class HDF5Dependency(ExternalDependency): |
||||||
|
|
||||||
|
def __init__(self, environment, kwargs): |
||||||
|
language = kwargs.get('language', 'c') |
||||||
|
super().__init__('hdf5', environment, language, kwargs) |
||||||
|
kwargs['required'] = False |
||||||
|
kwargs['silent'] = True |
||||||
|
self.is_found = False |
||||||
|
|
||||||
|
# 1. pkg-config |
||||||
|
pkgconfig_files = ['hdf5', 'hdf5-serial'] |
||||||
|
# some distros put hdf5-1.2.3.pc with version number in .pc filename. |
||||||
|
ret = subprocess.run(['pkg-config', '--list-all'], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, |
||||||
|
universal_newlines=True) |
||||||
|
if ret.returncode == 0: |
||||||
|
for pkg in ret.stdout.split('\n'): |
||||||
|
if pkg.startswith(('hdf5')): |
||||||
|
pkgconfig_files.append(pkg.split(' ', 1)[0]) |
||||||
|
pkgconfig_files = list(set(pkgconfig_files)) # dedupe |
||||||
|
|
||||||
|
if language not in ('c', 'cpp', 'fortran'): |
||||||
|
raise DependencyException('Language {} is not supported with HDF5.'.format(language)) |
||||||
|
|
||||||
|
for pkg in pkgconfig_files: |
||||||
|
pkgdep = PkgConfigDependency(pkg, environment, kwargs, language=self.language) |
||||||
|
if not pkgdep.found(): |
||||||
|
continue |
||||||
|
|
||||||
|
self.compile_args = pkgdep.get_compile_args() |
||||||
|
# some broken pkgconfig don't actually list the full path to the needed includes |
||||||
|
newinc = [] |
||||||
|
for arg in self.compile_args: |
||||||
|
if arg.startswith('-I'): |
||||||
|
stem = 'static' if kwargs.get('static', False) else 'shared' |
||||||
|
if (Path(arg[2:]) / stem).is_dir(): |
||||||
|
newinc.append('-I' + str(Path(arg[2:]) / stem)) |
||||||
|
self.compile_args += newinc |
||||||
|
|
||||||
|
# derive needed libraries by language |
||||||
|
pd_link_args = pkgdep.get_link_args() |
||||||
|
link_args = [] |
||||||
|
for larg in pd_link_args: |
||||||
|
lpath = Path(larg) |
||||||
|
# some pkg-config hdf5.pc (e.g. Ubuntu) don't include the commonly-used HL HDF5 libraries, |
||||||
|
# so let's add them if they exist |
||||||
|
# additionally, some pkgconfig HDF5 HL files are malformed so let's be sure to find HL anyway |
||||||
|
if lpath.is_file(): |
||||||
|
hl = [] |
||||||
|
if language == 'cpp': |
||||||
|
hl += ['_hl_cpp', '_cpp'] |
||||||
|
elif language == 'fortran': |
||||||
|
hl += ['_hl_fortran', 'hl_fortran', '_fortran'] |
||||||
|
hl += ['_hl'] # C HL library, always needed |
||||||
|
|
||||||
|
suffix = '.' + lpath.name.split('.', 1)[1] # in case of .dll.a |
||||||
|
for h in hl: |
||||||
|
hlfn = lpath.parent / (lpath.name.split('.', 1)[0] + h + suffix) |
||||||
|
if hlfn.is_file(): |
||||||
|
link_args.append(str(hlfn)) |
||||||
|
# HDF5 C libs are required by other HDF5 languages |
||||||
|
link_args.append(larg) |
||||||
|
else: |
||||||
|
link_args.append(larg) |
||||||
|
|
||||||
|
self.link_args = link_args |
||||||
|
self.version = pkgdep.get_version() |
||||||
|
self.is_found = True |
||||||
|
self.pcdep = pkgdep |
||||||
|
return |
||||||
|
|
||||||
|
# 2. compiler wrapper fallback |
||||||
|
wrappers = {'c': 'h5cc', 'cpp': 'h5c++', 'fortran': 'h5fc'} |
||||||
|
comp_args = [] |
||||||
|
link_args = [] |
||||||
|
# have to always do C as well as desired language |
||||||
|
for lang in set([language, 'c']): |
||||||
|
prog = ExternalProgram(wrappers[lang], silent=True) |
||||||
|
if not prog.found(): |
||||||
|
return |
||||||
|
cmd = prog.get_command() + ['-show'] |
||||||
|
p = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, timeout=15) |
||||||
|
if p.returncode != 0: |
||||||
|
mlog.debug('Command', mlog.bold(cmd), 'failed to run:') |
||||||
|
mlog.debug(mlog.bold('Standard output\n'), p.stdout) |
||||||
|
mlog.debug(mlog.bold('Standard error\n'), p.stderr) |
||||||
|
return |
||||||
|
args = split_args(p.stdout) |
||||||
|
for arg in args[1:]: |
||||||
|
if arg.startswith(('-I', '-f', '-D')) or arg == '-pthread': |
||||||
|
comp_args.append(arg) |
||||||
|
elif arg.startswith(('-L', '-l', '-Wl')): |
||||||
|
link_args.append(arg) |
||||||
|
elif Path(arg).is_file(): |
||||||
|
link_args.append(arg) |
||||||
|
self.compile_args = comp_args |
||||||
|
self.link_args = link_args |
||||||
|
self.is_found = True |
Loading…
Reference in new issue