# Simple script used to easily search all packages in conda for their # dependency requirements # TODO also search through output of ldd # TODO update conda info syntax for different channels if [ -z "$CONDA_ROOT" ]; then # TODO create our own environment echo "Please set CONDA_ROOT so that I know where to search for conda libraries" echo "I expect CONDA_ROOT to be the path to the current conda environment." echo "Also FYI I will probably mess up the current conda environment." exit 1 fi if [ -z "$1" ]; then echo "Please give me a package name to search for" exit 1 fi PKG_NAME="$1" if [ -n "$2" ]; then echo "Searching in channel $2" CONDA_CHANNEL="$2" fi # These are the packages of interest to search the dependencies for # TODO use this PACKAGES_OF_INTEREST=( libgcc-ng libprotobuf numpy ) # We will run `conda install` and `conda uninstall` a lot, but we don't want # this very noisy output to clutter the user experience VERBOSE_LOG='read_conda_versions.log' echo "Conda install/uninstall log for $PKG_NAME" > $VERBOSE_LOG # # Build up the name of the installed library to call `nm` on # PKG_INSTALLED_LIB="$PKG_NAME" # opencv installs a bunch of libraries. We'll just check libopencv_core if [[ $PKG_NAME == opencv ]]; then PKG_INSTALLED_LIB="${PKG_INSTALLED_LIB}_core" fi # Most packages prepend a 'lib' to the package name, but libprotobuf is an # exception if [[ $PKG_NAME != lib* ]]; then PKG_INSTALLED_LIB="lib${PKG_INSTALLED_LIB}" fi # The shared library suffix differs on macOS an Linux if [[ "$(uname)" == Darwin ]]; then PKG_INSTALLED_LIB="${PKG_INSTALLED_LIB}.dylib" else PKG_INSTALLED_LIB="${PKG_INSTALLED_LIB}.so" fi echo "Determined the library name of $PKG_NAME to be $PKG_INSTALLED_LIB" echo "Determined the library name of $PKG_NAME to be $PKG_INSTALLED_LIB" >> $VERBOSE_LOG # # Get all available packages with conda-search # # Split the output from conda search into an array, one line per package (plus # the header) conda_search_packages=() while read -r line; do conda_search_packages+=("$line"); done <<< "$(conda search $PKG_NAME $CONDA_CHANNEL)" ### Typical `conda search` output looks like ### Loading channels: done ### Name Version Build Channel ### protobuf 2.6.1 py27_0 defaults ### 2.6.1 py27_1 defaults ### 3.2.0 py27_0 defaults ### 3.2.0 py35_0 defaults ### 3.2.0 py36_0 defaults ### 3.4.1 py27h66c1d77_0 defaults ### 3.4.1 py35h9d33684_0 defaults ### 3.4.1 py36h314970b_0 defaults ### 3.5.1 py27h0a44026_0 defaults ### 3.5.1 py35h0a44026_0 defaults ### 3.5.1 py36h0a44026_0 defaults ## ### Typical `conda info` output looks like ### protobuf 3.5.1 py36h0a44026_0 ### ----------------------------- ### file name : protobuf-3.5.1-py36h0a44026_0.tar.bz2 ### name : protobuf ### version : 3.5.1 ### build string: py36h0a44026_0 ### build number: 0 ### channel : https://repo.continuum.io/pkgs/main/osx-64 ### size : 589 KB ### arch : None ### constrains : () ### license : New BSD License ### license_family: BSD ### md5 : 7dbdb06612e21c42fbb8a62354e13e10 ### platform : None ### subdir : osx-64 ### timestamp : 1519951502766 ### url : https://repo.continuum.io/pkgs/main/osx-64/protobuf-3.5.1-py36h0a44026_0.tar.bz2 ### dependencies: ### libcxx >=4.0.1 ### libprotobuf >=3.5.1,<3.6.0a0 ### python >=3.6,<3.7.0a0 ### six # Echo what packages we'll look through. echo "Processing these packages:" for pkg in "${conda_search_packages[@]:2}"; do echo " $pkg" done # # Look up each package in conda info, then install it and search the exported # symbols for signs of cxx11 # for pkg in "${conda_search_packages[@]:2}"; do echo "Processing $pkg" >> $VERBOSE_LOG # Split each line into an array and build the package specification # maj.min.patch build_string channel_name line_parts=( $pkg ) if [[ ${line_parts[0]} == $PKG_NAME ]]; then # First line of output PKG_VERSION="${line_parts[1]}" PKG_BUILD_STR="${line_parts[2]}" else PKG_VERSION="${line_parts[0]}" PKG_BUILD_STR="${line_parts[1]}" fi PKG_SPEC="$PKG_NAME=$PKG_VERSION=$PKG_BUILD_STR" # Output current pkg spec echo echo "${PKG_SPEC}:" echo "Determined that the package spec is $PKG_SPEC" >> $VERBOSE_LOG # Split the output of conda_info into an array of lines pkg_dependencies=() while read -r line; do pkg_dependencies+=("$line"); done <<< "$(conda info "$PKG_SPEC" $CONDA_CHANNEL)" # List all the listed dependencies in `conda info` if [ "${#pkg_dependencies[@]}" -gt 19 ]; then echo " Listed dependencies:" echo " Listed dependencies:" >> $VERBOSE_LOG for pkg_dependency in "${pkg_dependencies[@]:20}"; do echo " $pkg_dependency" echo " $pkg_dependency" >> $VERBOSE_LOG done else echo " No listed dependencies in conda-info" >> $VERBOSE_LOG fi # But sometimes (a lot of the time) the gcc with which a package was built # against is not listed in dependencies. So we try to figure it out manually # We install this exact package, and then grep the exported symbols for signs # of cxx11 echo "Calling conda-uninstall on $PKG_NAME" >> $VERBOSE_LOG echo "conda uninstall -y $PKG_NAME --quiet" >> $VERBOSE_LOG conda uninstall -y "$PKG_NAME" --quiet >> $VERBOSE_LOG 2>&1 echo "Calling conda-install on $PKG_SPEC" >> $VERBOSE_LOG echo "conda install -y $PKG_SPEC --quiet --no-deps $CONDA_CHANNEL" >> $VERBOSE_LOG conda install -y "$PKG_SPEC" --quiet --no-deps $CONDA_CHANNEL >> $VERBOSE_LOG 2>&1 if [ $? -eq 0 ]; then # Only grep the exported symbols if the library was installed correctly MENTIONS_CXX11="$(nm "$CONDA_ROOT/lib/$PKG_INSTALLED_LIB" | grep cxx11 | wc -l)" if [ $MENTIONS_CXX11 -gt 0 ]; then echo " This package is built against the recent gcc ABI ($MENTIONS_CXX11 mentions of cxx11)" echo "$CONDA_ROOT/lib/$PKG_INSTALLED_LIB mentions cxx11 $MENTIONS_CXX11 times" >> $VERBOSE_LOG fi else echo "Error installing $PKG_SPEC , continuing" echo "Error installing $PKG_SPEC , continuing" >> $VERBOSE_LOG fi done