From 2c36685010638e6bfcdd4ec74194cd200081668b Mon Sep 17 00:00:00 2001 From: Albert Cheng Date: Mon, 7 Mar 2016 17:03:57 -0500 Subject: [svn-r29326] HDFFV-9536: Changed H5check_version() to use libtool shared library version numbers instead of the library version numbers. bin/h5vers: Changed to copy the shared lib version from lt_vers.am to H5public.h (Thanks to Larry who made the changes.) config/lt_vers.am: cosmetic change, nothing material. src/H5public.h: Changed by bin/h5vers. src/H5.c: Changed H5check_version() to use shared library version for compatibility checking. test/tcheck_version.c: test/testcheck_version.sh.in: Changed to use shared library version numbers instead of the HDF5 library version numbers for testing. Tested: tested in Jam (C only), platypus and osx1010dev (enable fortran and C++). --- bin/h5vers | 60 +++++++++++++------- config/lt_vers.am | 2 +- src/H5.c | 130 +++++++++++++++++++++++++++++++++++++++++++ src/H5public.h | 15 ++++- test/tcheck_version.c | 26 ++++----- test/testcheck_version.sh.in | 57 +++++++++++-------- 6 files changed, 230 insertions(+), 60 deletions(-) diff --git a/bin/h5vers b/bin/h5vers index 7e61dc8..9a0fa59 100755 --- a/bin/h5vers +++ b/bin/h5vers @@ -105,6 +105,13 @@ sub setvers { $vers[3]?"-":"", $vers[3])/me; } +sub setltvers { + my ($contents, @vers) = @_; + $_[0] =~ s/^(\#\s*define\s+LT_VERS_INTERFACE\s+)\d+/$1$vers[0]/m; + $_[0] =~ s/^(\#\s*define\s+LT_VERS_REVISION\s+)\d+/$1$vers[1]/m; + $_[0] =~ s/^(\#\s*define\s+LT_VERS_AGE\s+)\d+/$1$vers[2]/m; +} + sub usage { my ($prog) = $0 =~ /([^\/]+)$/; print STDERR < $version_increased="true"; } +my @newltver; +# Update the libtool shared library version in src/H5public.h +if ($LT_VERS) { + open FILE, $LT_VERS or die "$LT_VERS: $!\n"; + my ($contentsy) = join "", ; + close FILE; + + local($_) = $contentsy; + + # Don't increment LT_VERS_REVISION, but instead copy LT_VERS_* values + # to H5public.h. + # my ($lt_revision) = /^LT_VERS_REVISION\s*=\s*(\d+)/m; + # my $new_lt_revision = $lt_revision+1; + # ($contentsy) =~ s/^(LT_VERS_REVISION\s*=\s*)\d+/$1$new_lt_revision/m; + + # open FILE, ">$LT_VERS" or die "$LT_VERS: $!\n"; + # print FILE $contentsy; + # close FILE; + + my ($lt_interface) = /^LT_VERS_INTERFACE\s*=\s*(\d+)/m; + my ($lt_revision) = /^LT_VERS_REVISION\s*=\s*(\d+)/m; + my ($lt_age) = /^LT_VERS_AGE\s*=\s*(\d+)/m; + + @newltver = ($lt_interface, $lt_revision, $lt_age); + +} + # Update the version number if it changed. if ($newver[0]!=$curver[0] || $newver[1]!=$curver[1] || $newver[2]!=$curver[2] || $newver[3]ne$curver[3]) { setvers $contents, @newver or die "unable to set version\n"; +} + setltvers $contents, @newltver or die "unable to set lt version\n"; rename $file, "$file~" or die "unable to save backup file\n"; open FILE, ">$file" or die "unable to open $file but backup saved!\n"; print FILE $contents; close FILE; -} - -# Update the libtool shared library version in src/Makefile.am if -# the version number has increased. -if ($LT_VERS && $version_increased) { - open FILE, $LT_VERS or die "$LT_VERS: $!\n"; - my ($contentsy) = join "", ; - close FILE; - - local($_) = $contentsy; - - my ($lt_revision) = /^LT_VERS_REVISION\s*=\s*(\d+)/m; - my $new_lt_revision = $lt_revision+1; - ($contentsy) =~ s/^(LT_VERS_REVISION\s*=\s*)\d+/$1$new_lt_revision/m; - - open FILE, ">$LT_VERS" or die "$LT_VERS: $!\n"; - print FILE $contentsy; - close FILE; -} # Update the README.txt file if ($README) { @@ -436,6 +453,9 @@ if ($verbose) { $newver[3] eq "" ? "" : "-".$newver[3]); } +# print shared lib version in the format of interface.revision.age +printf("Shared lib version %d.%d.%d\n", @newltver[0,1,2]); + exit 0; # Because the first line of this file looks like a Bourne shell script, we diff --git a/config/lt_vers.am b/config/lt_vers.am index a3b7634..c5e5112 100644 --- a/config/lt_vers.am +++ b/config/lt_vers.am @@ -19,8 +19,8 @@ # After making changes, run bin/reconfigure to update other configure related # files like Makefile.in. LT_VERS_INTERFACE = 6 -LT_VERS_REVISION = 224 LT_VERS_AGE = 0 +LT_VERS_REVISION = 224 ## If the API changes *at all*, increment LT_VERS_INTERFACE and ## reset LT_VERS_REVISION to 0. diff --git a/src/H5.c b/src/H5.c index 41fb3ba..acbdecb 100644 --- a/src/H5.c +++ b/src/H5.c @@ -720,6 +720,9 @@ done: } /* end H5get_libversion() */ +/* Depreciated by H5check_interface_compatibility. Need to keep it around + * because Fortran API calls it. Will be retired later. + */ /*------------------------------------------------------------------------- * Function: H5check_version * @@ -855,6 +858,133 @@ done: /*------------------------------------------------------------------------- + * Function: H5check_interface_compatibility + * + * Purpose: Verifies that the arguments are compatible with the link library. + * This function is intended to be called from user to verify that + * the versions of header files compiled into the application + * is compatible with the version of the link hdf5 library. + * + * Return: Success: SUCCEED + * + * Failure: abort() + * The value of the environment variable, + * HDF5_DISABLE_VERSION_CHECK, could affect + * how failure is handles. See Code below. + * + * Algorithm: {provided by Mike McGreevy} + * How to determine if two libraries, given their interface, revision, + * and age, are compatible? Let's say you have: + * + * interface, revision, age --> compiled HDF5 + * INTERFACE, REVISION, AGE --> linked HDF5 library + * Then: + * if ((INTERFACE-AGE) != (interface-age)) + * not compatible + * else + * if (age <= AGE) + * compatible + * else + * not compatible + * endif + * endif + * [Note: revision/REVISION do not affect compatibility] + * + * Programmer: Albert Cheng + * Feb 21, 2016 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#define INTERFACE_INCOMPATIBLE_WARNING \ +"Warning! ***HDF5 interface incompatibility detected***\n" \ +"The HDF5 header files used to compile this application are not compatible \n" \ +"with the HDF5 library to which this application is linked.\n" \ +"Data corruption or segmentation faults may occur if the application continues.\n" \ +"This can happen when an application was compiled by one version of HDF5 but\n" \ +"linked with a different version of static or shared HDF5 library.\n" \ +"You should recompile the application or check your shared library related\n" \ +"settings such as 'LD_LIBRARY_PATH'.\n" + +herr_t +H5check_interface_compatibility(unsigned interface, unsigned age, unsigned revision) +{ + char lib_str[256]; + static int checked = 0; /* If we've already checked the version info */ + static unsigned int disable_version_check = 0; /* Set if the version check should be disabled */ + static const char *interface_incompatible_warning = INTERFACE_INCOMPATIBLE_WARNING; + const char *s; /* Environment string for disabling version check */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API_NOINIT_NOERR_NOFS + H5TRACE3("e", "IuIuIu", interface, age, revision); + + assert(interface >= age); + assert(LT_VERS_INTERFACE >= LT_VERS_AGE); + + /* Optimization: Don't check again, if we already have */ + if (checked) + HGOTO_DONE(SUCCEED) + else + /* Indicate that the version check has been performed */ + checked++; + + /* check version compatibility */ + if (((LT_VERS_INTERFACE - LT_VERS_AGE) == (interface - age)) &&\ + (LT_VERS_AGE >= age)) + HGOTO_DONE(SUCCEED) + /* else NOT COMPATIBLE */ + + /* Allow different handling of not compatible */ + s = HDgetenv ("HDF5_DISABLE_VERSION_CHECK"); + if (s && HDisdigit(*s)) + disable_version_check = (unsigned int)HDstrtol (s, NULL, 0); + + /* check the version of the link library */ + switch (disable_version_check) { + case 0: + /* print a message and abort */ + HDfprintf(stderr, "%s%s", interface_incompatible_warning, + "You can, at your own risk, disable this warning by setting the environment\n" + "variable 'HDF5_DISABLE_VERSION_CHECK' to a value of '1'.\n" + "Setting it to 2 or higher will suppress the warning messages totally.\n"); + /* Mention the versions we are referring to */ + HDfprintf (stderr, "Headers are %u.%u.%u, library is %u.%u.%u\n", + (interface-age), age, revision, + ((unsigned)LT_VERS_INTERFACE-(unsigned)LT_VERS_AGE), (unsigned)LT_VERS_AGE, (unsigned)LT_VERS_REVISION); + /* Show library settings if available */ + HDfprintf (stderr, "%s", H5libhdf5_settings); + + /* Bail out now. */ + HDfputs ("Bye...\n", stderr); + HDabort (); + case 1: + /* continue with a warning */ + /* Note that the warning message is embedded in the format string.*/ + HDfprintf (stderr, + "%s'HDF5_DISABLE_VERSION_CHECK' " + "environment variable is set to %d, application will\n" + "continue at your own risk.\n", + interface_incompatible_warning, disable_version_check); + /* Mention the versions we are referring to */ + HDfprintf (stderr, "Headers are %u.%u.%u, library is %u.%u.%u\n", + (interface-age), age, revision, + ((unsigned)LT_VERS_INTERFACE-(unsigned)LT_VERS_AGE), (unsigned)LT_VERS_AGE, (unsigned)LT_VERS_REVISION); + /* Show library settings if available */ + HDfprintf (stderr, "%s", H5libhdf5_settings); + break; + default: + /* 2 or higher: continue silently */ + break; + } /* end switch */ + +done: + FUNC_LEAVE_API_NOFS(ret_value) +} /* end H5check_version() */ + + +/*------------------------------------------------------------------------- * Function: H5open * * Purpose: Initialize the library. This is normally called diff --git a/src/H5public.h b/src/H5public.h index 554ad26..3cfe42c 100644 --- a/src/H5public.h +++ b/src/H5public.h @@ -99,8 +99,12 @@ extern "C" { /* Empty string for real releases. */ #define H5_VERS_INFO "HDF5 library version: 1.9.234" /* Full version string */ -#define H5check() H5check_version(H5_VERS_MAJOR,H5_VERS_MINOR, \ - H5_VERS_RELEASE) +/* LT Version numbers */ +#define LT_VERS_INTERFACE 6 +#define LT_VERS_AGE 0 +#define LT_VERS_REVISION 224 + +#define H5check() H5check_interface_compatibility(LT_VERS_INTERFACE, LT_VERS_AGE, LT_VERS_REVISION) /* macros for comparing the version */ #define H5_VERSION_GE(Maj,Min,Rel) \ @@ -343,8 +347,13 @@ H5_DLL herr_t H5set_free_list_limits (int reg_global_lim, int reg_list_lim, int blk_list_lim); H5_DLL herr_t H5get_libversion(unsigned *majnum, unsigned *minnum, unsigned *relnum); +/* Deprecated by H5check_interface_compatibility. Need to keep it because + * Fortran API calls it. To be retired later. + */ H5_DLL herr_t H5check_version(unsigned majnum, unsigned minnum, - unsigned relnum); + unsigned relnum); +H5_DLL herr_t H5check_interface_compatibility(unsigned interface, unsigned age, \ + unsigned revision); H5_DLL herr_t H5is_library_threadsafe(hbool_t *is_ts); H5_DLL herr_t H5free_memory(void *mem); H5_DLL void *H5allocate_memory(size_t size, hbool_t clear); diff --git a/test/tcheck_version.c b/test/tcheck_version.c index a75d642..48d5523 100644 --- a/test/tcheck_version.c +++ b/test/tcheck_version.c @@ -39,9 +39,9 @@ void parse(int ac, char **av); void abort_intercept (int H5_ATTR_UNUSED sig); /* global variables */ -unsigned major = H5_VERS_MAJOR; -unsigned minor = H5_VERS_MINOR; -unsigned release = H5_VERS_RELEASE; +unsigned interface = LT_VERS_INTERFACE; +unsigned revision = LT_VERS_REVISION; +unsigned age = LT_VERS_AGE; void showhelp(void) @@ -50,9 +50,9 @@ showhelp(void) printf("\t-h\tShow this page and version information\n"); printf("\t-t: Test by changing (adding 1 to) the to trigger\n"); printf("\t\t the warning. can be:\n"); - printf("\t\t\tM for Major version number (%d)\n", H5_VERS_MAJOR); - printf("\t\t\tm for Minor version number (%d)\n", H5_VERS_MINOR); - printf("\t\t\tr for Release number (%d)\n", H5_VERS_RELEASE); + printf("\t\t\tI for Interface number (%d)\n", LT_VERS_INTERFACE); + printf("\t\t\tA for Age number (%d)\n", LT_VERS_AGE); + printf("\t\t\tR for Revision number (%d)\n", LT_VERS_REVISION); } @@ -70,14 +70,14 @@ parse(int ac, char **av) switch(*(++pt)) { case 't': /* option -t */ switch(*(++pt)) { - case 'M': - major++; + case 'I': + interface++; break; - case 'm': - minor++; + case 'R': + revision++; break; - case 'r': - release++; + case 'A': + age++; break; default: fprintf(stderr, "Unknown -v parameter (%s). Aborted.\n", *av); @@ -115,7 +115,7 @@ main(int ac, char **av) { parse(ac, av); HDsignal(SIGABRT, &abort_intercept); - H5check_version(major, minor, release); + H5check_interface_compatibility(interface, age, revision); HDsignal(SIGABRT, SIG_DFL); return 0; } diff --git a/test/testcheck_version.sh.in b/test/testcheck_version.sh.in index ed9845e..f696d9b 100644 --- a/test/testcheck_version.sh.in +++ b/test/testcheck_version.sh.in @@ -58,18 +58,19 @@ SKIP() { # Print warning message of version mismatch. WarnMesg(){ - echo "Warning! ***HDF5 library version mismatched error***" - echo "The HDF5 header files used to compile this application do not match" - echo "the version used by the HDF5 library to which this application is linked." + echo "Warning! ***HDF5 interface incompatibility detected***" + echo "The HDF5 header files used to compile this application are not compatible " + echo "with the HDF5 library to which this application is linked." echo "Data corruption or segmentation faults may occur if the application continues." echo "This can happen when an application was compiled by one version of HDF5 but" echo "linked with a different version of static or shared HDF5 library." echo "You should recompile the application or check your shared library related" echo "settings such as 'LD_LIBRARY_PATH'." + echo "You can, at your own risk, disable this warning by setting the environment" echo "variable 'HDF5_DISABLE_VERSION_CHECK' to a value of '1'." echo "Setting it to 2 or higher will suppress the warning messages totally." - echo "Headers are $xxh5versmajor.$xxh5versminor.$xxh5versrelease, library is $h5versmajor.$h5versminor.$h5versrelease" + echo "Headers are $xxh5vers_interface_age.$xxh5vers_age.$xxh5vers_revision, library is $h5vers_interface_age.$h5vers_age.$h5vers_revision" test -n "$H5_HAVE_EMBEDDED_LIBINFO" && cat $h5libsettings echo "Bye..." } @@ -77,17 +78,18 @@ WarnMesg(){ # Print warning message2 of version mismatch. WarnMesg2(){ - echo "Warning! ***HDF5 library version mismatched error***" - echo "The HDF5 header files used to compile this application do not match" - echo "the version used by the HDF5 library to which this application is linked." + echo "Warning! ***HDF5 interface incompatibility detected***" + echo "The HDF5 header files used to compile this application are not compatible " + echo "with the HDF5 library to which this application is linked." echo "Data corruption or segmentation faults may occur if the application continues." echo "This can happen when an application was compiled by one version of HDF5 but" echo "linked with a different version of static or shared HDF5 library." echo "You should recompile the application or check your shared library related" echo "settings such as 'LD_LIBRARY_PATH'." + echo "'HDF5_DISABLE_VERSION_CHECK' environment variable is set to 1, application will" echo "continue at your own risk." - echo "Headers are $xxh5versmajor.$xxh5versminor.$xxh5versrelease, library is $h5versmajor.$h5versminor.$h5versrelease" + echo "Headers are $xxh5vers_interface_age.$xxh5vers_age.$xxh5vers_revision, library is $h5vers_interface_age.$h5vers_age.$h5vers_revision" test -n "$H5_HAVE_EMBEDDED_LIBINFO" && cat $h5libsettings } @@ -127,9 +129,10 @@ TESTING() { h5DisableVersion="$1" wrongversionnumbers="$2" - xxh5versmajor=$h5versmajor - xxh5versminor=$h5versminor - xxh5versrelease=$h5versrelease + xxh5vers_interface=$h5vers_interface + xxh5vers_age=$h5vers_age + xxh5vers_revision=$h5vers_revision + xxh5vers_interface_age=`expr $xxh5vers_interface - $xxh5vers_age` if [ "$h5DisableVersion" = unset ]; then envcmd="" # noop @@ -145,13 +148,14 @@ TESTING() { arguments=-t"$wrongversionnumbers" # calculate mismatched version numbers by listing. case $wrongversionnumbers in - "M") xxh5versmajor=`expr $h5versmajor + 1` + "I") xxh5vers_interface=`expr $h5vers_interface + 1` ;; - "m") xxh5versminor=`expr $h5versminor + 1` + "A") xxh5vers_age=`expr $h5vers_age + 1` ;; - "r") xxh5versrelease=`expr $h5versrelease + 1` + "R") xxh5vers_revision=`expr $h5vers_revision + 1` ;; esac + xxh5vers_interface_age=`expr $xxh5vers_interface - $xxh5vers_age` case "$h5DisableVersion" in 1) # W2/OK: Different Warning, exit 0. @@ -218,15 +222,22 @@ h5libsettings=../src/libhdf5.settings PURPOSE # Figure out library version numbers from the header file. -h5versmajor=`grep '#define H5_VERS_MAJOR' $srcdir/../src/H5public.h | cut -f2` -h5versminor=`grep '#define H5_VERS_MINOR' $srcdir/../src/H5public.h | cut -f2` -h5versrelease=`grep '#define H5_VERS_RELEASE' $srcdir/../src/H5public.h | cut -f2` -DEBUGPRINT $h5versmajor.$h5versminor.$h5versrelease -case "$h5versmajor$h5versminor$h5versrelease" in +h5vers_interface=`grep '#define LT_VERS_INTERFACE' ../../hdf5/src/H5public.h | sed -e s/[^0-9]//g` +#echo h5vers_interface=$h5vers_interface +h5vers_revision=`grep '#define LT_VERS_REVISION' $srcdir/../src/H5public.h | sed -e s/[^0-9]//g` +#echo h5vers_revision=$h5vers_revision +h5vers_age=`grep '#define LT_VERS_AGE' $srcdir/../src/H5public.h | sed -e s/[^0-9]//g` +#echo h5vers_age=$h5vers_age +h5vers_interface_age=`expr $h5vers_interface - $h5vers_age` +#h5vers_interface=`grep '#define LT_VERS_INTERFACE' $srcdir/../src/H5public.h | cut -f2` +#h5vers_revision=`grep '#define LT_VERS_REVISION' $srcdir/../src/H5public.h | cut -f2` +#h5vers_age=`grep '#define LT_VERS_AGE' $srcdir/../src/H5public.h | cut -f2` +DEBUGPRINT $h5vers_interface.$h5vers_revision.$h5vers_age +case "$h5vers_interface$h5vers_revision$h5vers_age" in [0-9]*) # good. noop. ;; *) - echo "Illegal library version numbers($h5versmajor.$h5versminor.$h5versrelease)" + echo "Illegal library version numbers($h5vers_interface.$h5vers_revision.$h5vers_age)" echo "Test aborted" exit 1 ;; @@ -241,13 +252,13 @@ fi # Three Categories of tests: # Normal: where the version numbers all matched (wrong_version == none). -# Mismatched version numbers (could be Major or minor version -# or release numbers or a combination of all three.) +# Mismatched version numbers (could be Interface or Age versions; +# revision makes no differences in link compatibility check.) # Test all the above with different values of the environment variable, # HDF5_DISABLE_VERSION_CHECK, as unset, "", -1, 0, 1, 2, 3 for val_disable_version_check in unset "" -1 0 1 2 3; do - for wrong_version in none M m r; do + for wrong_version in none I A; do TESTING "$val_disable_version_check" "$wrong_version" done done -- cgit v0.12