Commit fcf9f23d authored by Atkins, Charles Vernon's avatar Atkins, Charles Vernon
Browse files

Install adios2-config python script

parent 74fde29d
Loading
Loading
Loading
Loading
+1 −67
Original line number Diff line number Diff line
@@ -153,73 +153,7 @@ function(GenerateADIOSPackageConfig)
    DESTINATION ${CMAKE_INSTALL_CMAKEDIR}
  )

  # Install helper find modules if needed
  # Also build flags needed for non-cmake config generation
  set(ADIOS2_CXX_LIBS ${CMAKE_THREAD_LIBS_INIT})
  set(ADIOS2_CXX_OPTS ${CMAKE_CXX11_EXTENSION_COMPILE_OPTION})
  set(ADIOS2_CXX_DEFS)
  set(ADIOS2_CXX_INCS)
  if(ADIOS2_HAVE_MPI)
    list(APPEND ADIOS2_CXX_LIBS ${MPI_C_LIBRARIES})
    list(APPEND ADIOS2_CXX_INCS ${MPI_C_INCLUDE_PATH})
  endif()
  if(NOT BUILD_SHARED_LIBS)
    if(ADIOS2_HAVE_DataMan)
    list(APPEND ADIOS2_CXX_LIBS -ldataman)
    endif()
    if(ADIOS2_HAVE_BZip2)
      install(FILES cmake/FindBZip2.cmake
        DESTINATION ${CMAKE_INSTALL_CMAKEDIR}/Modules
      )
      install(FILES cmake/upstream/FindBZip2.cmake
        DESTINATION ${CMAKE_INSTALL_CMAKEDIR}/Modules/upstream
      )
      list(APPEND ADIOS2_CXX_LIBS ${BZIP2_LIBRARIES})
      list(APPEND ADIOS2_CXX_INCS ${BZIP2_INCLUDE_DIR})
    endif()
    if(ADIOS2_HAVE_ZFP)
      install(FILES cmake/FindZFP.cmake
        DESTINATION ${CMAKE_INSTALL_CMAKEDIR}/Modules
      )
      list(APPEND ADIOS2_CXX_LIBS ${ZFP_LIBRARIES})
      list(APPEND ADIOS2_CXX_INCS ${ZFP_INCLUDE_DIRS})
    endif()
    if(ADIOS2_HAVE_MGARD)
      install(FILES cmake/FindMGARD.cmake
        DESTINATION ${CMAKE_INSTALL_CMAKEDIR}/Modules
      )
      list(APPEND ADIOS2_CXX_LIBS ${MGARD_LIBRARIES})
      list(APPEND ADIOS2_CXX_INCS ${MGARD_INCLUDE_DIRS})
    endif()
    if(ADIOS2_HAVE_ZeroMQ)
      install(FILES cmake/FindZeroMQ.cmake
        DESTINATION ${CMAKE_INSTALL_CMAKEDIR}/Modules
      )
      list(APPEND ADIOS2_CXX_LIBS ${ZeroMQ_LIBRARIES})
      list(APPEND ADIOS2_CXX_INCS ${ZeroMQ_INCLUDE_DIRS})
    endif()
    if(ADIOS2_HAVE_HDF5)
      list(APPEND ADIOS2_CXX_LIBS ${HDF5_C_LIBRARIES})
      if(HDF5_C_INCLUDE_DIRS)
        list(APPEND ADIOS2_CXX_INCS ${HDF5_C_INCLUDE_DIRS})
      else()
        list(APPEND ADIOS2_CXX_INCS ${HDF5_INCLUDE_DIRS})
      endif()
    endif()
  endif()

  # Build the non-cmake config script
  __adios2_list_make_link_args(ADIOS2_CXX_LIBS)
  __adios2_list_cleanup_for_bash(ADIOS2_CXX_LIBS)
  __adios2_list_cleanup_for_bash(ADIOS2_CXX_OPTS)
  __adios2_list_cleanup_for_bash(ADIOS2_CXX_DEFS)
  __adios2_list_cleanup_for_bash(ADIOS2_CXX_INCS)
  configure_file(
    ${ADIOS2_SOURCE_DIR}/cmake/adios2-config.in
    ${ADIOS2_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}/adios2-config
    @ONLY
  )
  install(PROGRAMS ${ADIOS2_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}/adios2-config
  install(PROGRAMS ${ADIOS2_SOURCE_DIR}/cmake/adios2-config
    DESTINATION ${CMAKE_INSTALL_BINDIR}
  )
endfunction()

cmake/adios2-config

0 → 100755
+235 −0
Original line number Diff line number Diff line
#!/usr/bin/env python3

import difflib
import os
import shlex
import subprocess
import sys
import tempfile


CMAKELISTS = """
cmake_minimum_required(VERSION 3.6)
if(POLICY CMP0074)
  cmake_policy(SET CMP0074 NEW)
endif()

project(find_adios2 CXX C)

find_package(ADIOS2 REQUIRED)

set(src "${CMAKE_CURRENT_BINARY_DIR}/src.cxx")
file(WRITE "${src}" "
int main(int argc, char* argv[]) {
  (void)argc;
  (void)argv;
  return 0;
}
")

add_executable(with_adios2 "${src}")

target_compile_definitions(with_adios2 PRIVATE WITH_ADIOS2)
target_link_libraries(with_adios2 PRIVATE adios2::adios2 -LWITH_ADIOS2)

add_executable(without_adios2 "${src}")
target_compile_definitions(without_adios2 PRIVATE WITHOUT_ADIOS2)
target_link_libraries(without_adios2 PRIVATE -LWITHOUT_ADIOS2)
"""


def diff_commands(a, b):
    a_args = shlex.split(a)
    b_args = shlex.split(b)

    a_flags = []
    b_flags = []
    differ = difflib.SequenceMatcher(a=a_args, b=b_args, autojunk=False)
    for tag, i1, i2, j1, j2 in differ.get_opcodes():
        if tag in ('delete', 'replace'):
            a_flags.extend(a_args[i1:i2])
        if tag in ('insert', 'replace'):
            b_flags.extend(b_args[j1:j2])
    return (a_flags, b_flags)


def test_diff_commands():
    cmd_a = 'prog -lcommon a_different common'
    cmd_b = 'prog -lcommon b_different common'
    (a_flags, b_flags) = diff_commands(cmd_a, cmd_b)
    assert a_flags == ['a_different']
    assert b_flags == ['b_different']


def extract_flags(compile_with, compile_without, link_with, link_without):
    (_, compile_flags) = diff_commands(compile_without, compile_with)
    (_, link_flags) = diff_commands(link_without, link_with)

    # Remove our marker flags.
    compile_flags.remove('-DWITH_ADIOS2')
    link_flags.remove('-LWITH_ADIOS2')

    # Remove target-specific flags.
    def is_target_specific(arg):
        return arg.find('with_adios2') > -1
    compile_flags = [
        flag for flag in compile_flags if not is_target_specific(flag)]
    link_flags = [flag for flag in link_flags if not is_target_specific(flag)]

    return (compile_flags, link_flags)


def test_extract_flags():
    cmd_without_compile = \
        'compiler -DWITHOUT_ADIOS2 -o without_adios2.dir/src.cxx.o src.cxx'
    cmd_without_link = \
        'compiler -LWITHOUT_ADIOS2 with_adios2.dir/src.cxx.o'
    cmd_with_compile = \
        'compiler -DWITH_ADIOS2 -I/path/to/adios2/includes -o with_adios2.dir/src.cxx.o src.cxx'
    cmd_with_link = \
        'compiler -LWITH_ADIOS2 /path/to/libadios2.so with_adios2.dir/src.cxx.o'
    (compile_flags, link_flags) = \
        extract_flags(cmd_with_compile, cmd_without_compile, cmd_with_link,
                      cmd_without_link)
    assert compile_flags == ['-I/path/to/adios2/includes']
    assert link_flags == ['/path/to/libadios2.so']


def extract_adios2_flags(cmake='cmake',
                           generator='Unix Makefiles',
                           adios2_dir=None):
    cmake_format = {}

    def tempdir():
        if sys.version_info.major == 3:
            return tempfile.TemporaryDirectory()
        else:
            class DummyTemporaryDirectory:
                def __init__(self):
                    self._dir = tempfile.mkdtemp()

                def __enter__(self):
                    return self._dir

                def __exit__(self, *args):
                    #import shutil
                    #shutil.rmtree(self._dir)
                    return

            return DummyTemporaryDirectory()

    with tempdir() as workdir:
        srcdir = os.path.join(workdir, 'src')
        builddir = os.path.join(workdir, 'build')

        os.mkdir(srcdir)
        os.mkdir(builddir)

        # Write the CMake file.
        with open(os.path.join(srcdir, 'CMakeLists.txt'), 'w+') as fout:
            fout.write(CMAKELISTS % cmake_format)

        # Configure the build tree.
        configure_cmd = [
            cmake,
            '-G' + generator,
            srcdir,
        ]

        if adios2_dir is not None:
            configure_cmd.append('-DADIOS2_DIR:PATH=' + ADIOS2_dir)
        elif 'ADIOS2_DIR' not in os.environ and 'ADIOS2_ROOT' not in os.environ:
            os.environ['ADIOS2_DIR'] = \
                os.path.realpath(os.path.join(os.path.dirname(__file__), '..'))
        if sys.version_info.major == 3:
            stdout = subprocess.DEVNULL
        else:
            stdout = open('/dev/null', 'w')
        print("ADIOS2_DIR: " + os.environ['ADIOS2_DIR'])
        subprocess.check_call(configure_cmd, cwd=builddir,
                              stdout=stdout)
        if sys.version_info.major == 2:
            stdout.close()

        # Run the build tool.
        build_cmd = [
            cmake,
            '--build', '.',
            '--',
        ]
        build_env = os.environ.copy()
        if generator == 'Ninja':
            build_cmd.append('-n')
            build_cmd.append('-v')
            build_env['NINJA_STATUS'] = ''
        elif generator == 'Unix Makefiles':
            # This doesn't work because the link line is actually behind
            # another rule.
            # build_cmd.append('-n')
            build_cmd.append('VERBOSE=1')
        else:
            raise RuntimeError('Unsupported generator %s' % generator)
        build_output = subprocess.Popen(build_cmd,
                                        cwd=builddir,
                                        stdout=subprocess.PIPE,
                                        stderr=subprocess.STDOUT,
                                        env=build_env)

        lines = {}
        lines['compile_with'] = None
        lines['link_with'] = None
        lines['compile_without'] = None
        lines['link_without'] = None

        def check_line(lines, line, flag, key):
            if lines[key] is None and line.find(flag) > -1:
                lines[key] = line

        for line in build_output.stdout:
            line = line.strip().decode('utf-8')
            check_line(lines, line, '-DWITH_ADIOS2', 'compile_with')
            check_line(lines, line, '-LWITH_ADIOS2', 'link_with')
            check_line(lines, line, '-DWITHOUT_ADIOS2', 'compile_without')
            check_line(lines, line, '-LWITHOUT_ADIOS2', 'link_without')

        if not all(lines.values()):
            raise RuntimeError('missing some compile line outputs')

        return extract_flags(**lines)


if __name__ == '__main__':
    import argparse

    parser = argparse.ArgumentParser(
        description='Extract required flags for linking to ParaView')
    parser.add_argument(
        '-C', '--cmake', metavar='CMAKE', default='cmake',
        dest='cmake',
        help='Path to CMake to use')
    parser.add_argument(
        '-G', '--generator', metavar='GENERATOR', default='Unix Makefiles',
        choices=('Unix Makefiles', 'Ninja'), dest='generator',
        help='The CMake generator to use')
    parser.add_argument(
        '-a', '--adios2', metavar='ADIOS2 DIR', default=None,
        dest='adios2_dir',
        help='Where to find ADIOS2Config.cmake')
    parser.add_argument(
        '--cflags', action='store_true', default=False,
        dest='cppflags',
        help='Print C flags')
    parser.add_argument(
        '--libs', action='store_true', default=False,
        dest='ldflags',
        help='Print linker flags')

    opts = parser.parse_args()
    (compile_flags, link_flags) = \
        extract_adios2_flags(cmake=opts.cmake,
                               generator=opts.generator,
                               adios2_dir=opts.adios2_dir)
    if opts.cppflags:
        print(' '.join(compile_flags))
    if opts.ldflags:
        print(' '.join(link_flags))

cmake/adios2-config.in

deleted100755 → 0
+0 −94
Original line number Diff line number Diff line
#!/bin/bash

function usage() {
  echo "Usage: $1 [OPTION]"
  echo
  echo "Known values for OPTION are:"
  echo
  echo "  --prefix      print installation prefix"
  echo "  --libs        print library linling information"
  echo "  --cxxflags    print preprocessor and compiler flags"
  echo "  --help        display this help and exit"
  echo "  --version     output version information"
}

if [ $# -ne 1 ]
then
  usage $0
  exit 1
fi

realpath() {
  OURPWD=$PWD
  cd "$(dirname "$1")"
  LINK=$(readlink "$(basename "$1")")
  while [ "$LINK" ]; do
    cd "$(dirname "$LINK")"
    LINK=$(readlink "$(basename "$1")")
  done
  REALPATH="$PWD/$(basename "$1")"
  cd "$OURPWD"
  echo "$REALPATH"
}

canonicalize_path() {
    if [ -d "$1" ]; then
        _canonicalize_dir_path "$1"
    else
        _canonicalize_file_path "$1"
    fi
}   

_canonicalize_dir_path() {
    (cd "$1" 2>/dev/null && pwd -P) 
}           

_canonicalize_file_path() {
    local dir file
    dir=$(dirname -- "$1")
    file=$(basename -- "$1")
    (cd "$dir" 2>/dev/null && printf '%s/%s\n' "$(pwd -P)" "$file")
}

prefix=`realpath "$(dirname ${BASH_SOURCE})/.."`
prefix=`canonicalize_path ${prefix}`

ADIOS2_CXX_LIBS=$(echo "@ADIOS2_CXX_LIBS@")
ADIOS2_CXX_OPTS=$(echo "@ADIOS2_CXX_OPTS@")
ADIOS2_CXX_DEFS=$(echo "@ADIOS2_CXX_DEFS@")
ADIOS2_CXX_INCS=$(echo "@ADIOS2_CXX_INCS@")

case $1 in
  --prefix) echo ${prefix} ;;
  --libs)
    echo -n "-L${prefix}/@CMAKE_INSTALL_LIBDIR@ -ladios2 "
    for LIB in ${ADIOS2_CXX_LIBS}
    do
      echo -n "${LIB} "
    done
    echo
    ;;
  --cxxflags)
    for OPT in ${ADIOS2_CXX_OPTS}
    do
      echo -n "${OPT} "
    done
    for DEF in ${ADIOS2_CXX_DEFS}
    do
      echo -n "-D${DEF} "
    done
    for INC in ${ADIOS2_CXX_INCS}
    do
      echo -n "-I${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ "
    done
    echo
    ;;
  --version) echo @ADIOS2_VERSION@ ;;
  --help)
    usage
    ;;
  *)
    usage
    exit 1
    ;;
esac