diff --git a/cmake/modules/lcgsoft-macros.cmake b/cmake/modules/lcgsoft-macros.cmake index c289ab7a8552c7d30e8d444ac96155813affaef7..2904320695cf4a581fa93fd73ce9a02d5e716062 100644 --- a/cmake/modules/lcgsoft-macros.cmake +++ b/cmake/modules/lcgsoft-macros.cmake @@ -361,21 +361,25 @@ macro(LCGPackage_Add name) # Process .post-install.sh scripts if (POST_INSTALL) set (post-install_name "${CMAKE_SOURCE_DIR}/cmake/scripts/post-install.sh") + set (gen_post_install_info_cmd "${CMAKE_SOURCE_DIR}/cmake/scripts/gen_post_install_info.py") set (path_map) - foreach (dep ${${targetname}-dependencies};${targetname}) + set (_expanded_deps) + LCG_append_depends(${targetname} _expanded_deps) + list(SORT _expanded_deps) + foreach (dep ${_expanded_deps};${targetname}) string(REGEX MATCH "${dependency_split_pattern}" dep_zero "${dep}") set (dep_name "${CMAKE_MATCH_1}") - set (dep_version "${CMAKE_MATCH_2}") + set (dep_version "${CMAKE_MATCH_2}") if (${LCG_VERSION} VERSION_GREATER 68 OR ${LCG_VERSION} MATCHES "root6") set (path_map "${${dep}_home}:${${dep_name}_directory_name}/${dep_version}-${${dep}_hash}/${LCG_system} ${path_map}") else () set (path_map "${${dep}_home}:${${dep_name}_directory_name}/${dep_version}/${LCG_system} ${path_map}") - endif() + endif() endforeach() - ExternalProject_Add_Step(${targetname} copy_post-install COMMENT "Copying .post-install.sh file for ${targetname}" + ExternalProject_Add_Step(${targetname} copy_post-install COMMENT "Prepare post-install for ${targetname}" COMMAND ${CMAKE_COMMAND} -E copy ${post-install_name} ${${name}_home}/.post-install.sh - COMMAND $ENV{SHELL} -c "chmod +x ${${name}_home}/.post-install.sh" - COMMAND $ENV{SHELL} -c "${post-install_name} generate ${CMAKE_INSTALL_PREFIX} ${${targetname}_home} '${path_map}'" + COMMAND chmod +x ${${name}_home}/.post-install.sh + COMMAND ${gen_post_install_info_cmd} ${CMAKE_INSTALL_PREFIX} ${${targetname}_home} "${path_map}" COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_BINARY_DIR}/timestamps/${targetname}-stop.timestamp DEPENDEES setup_environment ) diff --git a/cmake/scripts/gen_post_install_info.py b/cmake/scripts/gen_post_install_info.py new file mode 100755 index 0000000000000000000000000000000000000000..3f734608e6f6e7796000e1f208deb7a56d600e70 --- /dev/null +++ b/cmake/scripts/gen_post_install_info.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python +''' +Python rewrite of the original post-install.sh. +''' +import os +import sys + +LISTNAME = '.filelist' + +def skip_dir(root, name): + ''' + Tell if a directory should not be searched for files. + + @param root: parent path + @param name: name of the directory + ''' + # FIXME: can the logic be simplified? + return ((name == 'logs') or + ('datafiles' in name) or + (root.endswith('share') and ( + name.startswith('LHAPDF') or + name.startswith('sources')) + )) + + +def generate(lcg_home, pkg_home, path_map): + ''' + Do something... + + @param lcg_home: root of LCG installation + ''' + list_file = open(os.path.join(pkg_home, LISTNAME), 'w') + list_file.write(lcg_home + '\n') + + # add real (no-symlink) names to the mappings + path_map.update((os.path.realpath(old), new) + for old, new in path_map.items()) + + # write all the mappings + list_file.writelines('%s->%s\n' % (old, new) + for old, new in path_map.items() if old and new) + + for root, dirs, files in os.walk(pkg_home): + dirs[:] = [d for d in dirs + if not skip_dir(root, d)] + for filename in files: + # FIXME we could quickly ignore files from the name + # e.g. estension == '.so' + + filename = os.path.join(root, filename) + + content = open(filename, 'rb').read() + if '\0' in content: + # it's a binary (or UTF-16) file + # See http://stackoverflow.com/q/898669 + continue + + for old in path_map: + if old in content: + list_file.write(os.path.relpath(filename, pkg_home) + '\n') + break + + +if __name__ == '__main__': + # FIXME: do we want many arguments or one space separated list? + path_map = {} + for arg in sys.argv[3:]: + path_map.update(spec.split(':', 1) + for spec in arg.split()) + + generate(sys.argv[1], sys.argv[2], path_map) diff --git a/cmake/scripts/post-install.sh b/cmake/scripts/post-install.sh index 70c01660fd125b9213f96030c88ddea03bf90955..c7d876020b3ca00f94f7b39a2c52607c52d4b814 100755 --- a/cmake/scripts/post-install.sh +++ b/cmake/scripts/post-install.sh @@ -3,75 +3,42 @@ export LANG=C listname=".filelist" -# === generate list of files -if [ "generate" = "$1" ]; then - LCG_home="$2" - pkg_home="$3" - while [ ! -z "$4" ];do - path_map="$4 $path_map" - shift - done - list_file="$pkg_home/$listname" - tmp_file=$(mktemp -t lcg.XXX) - tmp_file_list=$(mktemp -t lcg.XXX) - - # prepare list of files - find $pkg_home -type f ! -path '*share/LHAPDF*' \ - -o -path '*share/sources*' \ - -o -path '*datafiles*' -prune | grep -v "$pkg_home/logs" > $tmp_file_list - # proceed depends - for map in $(echo "$path_map"); do - old_install_path="$(echo $map | cut -d: -f1)" - old_real_install_path="$(cd $old_install_path; pwd -P)" - new_directory_name="$(echo $map | cut -d: -f2)" - echo "$old_real_install_path->$new_directory_name" - echo "$old_install_path->$new_directory_name" - # find files - cat $tmp_file_list | while read name; do - # check that file is not binary - if perl -E 'exit((-B $ARGV[0])?1:0);' "$name"; then - if grep -q -- "$old_install_path" "$name" || grep -q -- "$old_real_install_path" "$name";then - echo $name | sed -e "s@$pkg_home/@@g" - fi - fi - done - done >> $tmp_file - # prepare $list_file - echo $LCG_home > $list_file - cat $tmp_file | grep -- '->' >> $list_file - cat $tmp_file | sed '/->/d' | sort | uniq >> $list_file - rm -f $tmp_file - rm -f $tmp_file_list - exit 0 -fi -# === - # === Replace install paths in files from filelist THIS="$0" PREFIX="$(/bin/sh -c "dirname $THIS")" +# Use INSTALLDIR env variable or automatic RPM_INSTALL_DIR as target prefix while [ ! -d "$INSTALLDIR" ]; do [ ! -z "$RPM_INSTALL_PREFIX" ] && INSTALLDIR="$RPM_INSTALL_PREFIX" || read -e -p "Type new install directory : " INSTALLDIR done +# extract old install dir from .filelist (should be first line) OLDINSTALLDIR="$(head -1 $PREFIX/$listname)" -sed -i -e '1d' $PREFIX/$listname +sed -i -e '1d' $PREFIX/$listname # delete first line echo echo "Replacing $OLDINSTALLDIR -> $INSTALLDIR" echo # prepare package list for replacing +# loop over files (lines without '->') cat $PREFIX/$listname | grep -v -- '->' | while read name; do + test "$name" == ".filelist" && continue # skip .filelist echo "=== Patching $name ... ===" - old=$(mktemp -t lcg.XXX) + old=$(mktemp -t lcg.XXXXX) cp -f "$PREFIX/$name" "$old" - # patch files - cat $PREFIX/$listname | grep -- '->' | while read line; do - olddir="$(echo $line | awk -F'->' '{print $1}')" - newdir="${INSTALLDIR}/$(echo $line | awk -F'->' '{print $2}')" - sed -i -e "s@$olddir@$newdir@g" "$PREFIX/$name" + # loop over all target paths (after '->' delimiter) + cat $PREFIX/$listname | grep -- '->' | awk -F'->' '{print $2}'| sort | uniq | while read newpath; do + # loop over all source paths for given target path, use sorting by path length to resolve issues like /var/build/... and /build/... + # 1 target path is related with multiple (at least 2 -- real and 'usual') source paths + cat $PREFIX/$listname | grep -- '->' | grep -- "$newpath" | awk -F'->' '{ print length($1) " " $0; }' | sort -r -n | cut -d ' ' -f 2- | while read line; do + olddir="$(echo $line | awk -F'->' '{print $1}')" + newdir="${INSTALLDIR}/$(echo $line | awk -F'->' '{print $2}')" + # patching + test ! -z "$olddir" && test ! -z "$newdir" && sed -i -e "s@$olddir@$newdir@g" -e '/afs/s,/\.cern.ch,/cern.ch,g' "$PREFIX/$name" + done done + # show diff diff -u "$old" "$PREFIX/$name" rm -f "$old" echo