MantisBT - CMake
View Issue Details
0012629CMakeCMakeSetuppublic2011-12-15 19:282012-09-03 16:02
Mark Abraham 
Brad King 
normalminoralways
closedfixed 
anyanyany
CMake 2.8.4 
CMake 2.8.8CMake 2.8.8 
0012629: bootstrap of CMake can fail when a wrong libmd is found
Utilities/cmlibarchive/CMakeLists.txt uses

IF(CRYPTO_LIBRARY)
  LIST(APPEND ADDITIONAL_LIBS ${CRYPTO_LIBRARY})
ELSE(CRYPTO_LIBRARY)
  IF(NOT OPENSSL_FOUND)
    FIND_LIBRARY(MD_LIBRARY NAMES md)
    IF(MD_LIBRARY)
      LIST(APPEND ADDITIONAL_LIBS ${MD_LIBRARY})
    ENDIF(MD_LIBRARY)
  ENDIF(NOT OPENSSL_FOUND)
ENDIF(CRYPTO_LIBRARY)

This fails if libmd exists in the search path but is actually from the GROMACS simulation package, rather than the crypto message digest library. A try_compile() test after a successful find_library() would allow the CMake bootstrap to be more robust.
1. Use ./bootstrap on a system with GROMACS (http://www.gromacs.org [^]) installed and http://martin.hinner.info/libmd/ [^] not installed.

2. Do make

3. Observe that CMake tools cannot link because of the unsatisfied dependencies of the inappropriate -lmd.
I was able to successfully build CMake on this system by removing the resulting "-lmd" from all the links.txt files, using a combination of sed -i and find.
No tags attached.
Issue History
2011-12-15 19:28Mark AbrahamNew Issue
2011-12-16 08:44Brad KingNote Added: 0027991
2011-12-16 08:59Mark AbrahamNote Added: 0027992
2011-12-16 09:07Brad KingNote Added: 0027993
2011-12-16 19:49Mark AbrahamNote Added: 0027996
2011-12-19 11:57Brad KingNote Added: 0028011
2012-01-10 15:46Brad KingNote Added: 0028244
2012-01-10 15:46Brad KingStatusnew => resolved
2012-01-10 15:46Brad KingResolutionopen => fixed
2012-01-10 15:46Brad KingAssigned To => Brad King
2012-01-10 18:35Mark AbrahamNote Added: 0028250
2012-01-10 18:35Mark AbrahamStatusresolved => feedback
2012-01-10 18:35Mark AbrahamResolutionfixed => reopened
2012-01-11 07:56Brad KingStatusfeedback => resolved
2012-01-11 07:56Brad KingFixed in Version => CMake 2.8.8
2012-01-11 07:56Brad KingResolutionreopened => fixed
2012-04-30 09:31David ColeTarget Version => CMake 2.8.8
2012-09-03 16:02David ColeNote Added: 0030898
2012-09-03 16:02David ColeStatusresolved => closed

Notes
(0027991)
Brad King   
2011-12-16 08:44   
We cannot possibly try_compile for every symbol we need from every library just to be sure it will succeed at link time and in case the user's system provides a library named like we need but that comes from another package.

You can build by telling CMake not to look for MD_LIBRARY:

$ mkdir CMake-build && cd CMake-build
$ echo 'set(MD_LIBRARY "" CACHE FILEPATH "" FORCE)' > Init.cmake
$ ../CMake/bootstrap --init=Init.cmake


OR

$ mkdir CMake-build && cd CMake-build
$ echo 'MD_LIBRARY:FILEPATH=' > CMakeCache.txt
$ ../CMake/bootstrap
(0027992)
Mark Abraham   
2011-12-16 08:59   
> We cannot possibly try_compile for every symbol we need from every library just to be sure it will succeed at link time and in case the user's system provides a library named like we need but that comes from another package.

Sure, you might not wish do that for every library "just in case", but where there's a known instance of a failing case, why not seek to avoid further failing cases?

I'd offer a try_compile() patch, but there seems to be nothing that is actually required to be linked. The quoted code seems to impose an arbitrary requirement to link libmd if found, and on at least some platforms (such as the one I was using) nothing later actually links to libmd (because removing -lmd worked) and somehow this creates unsatisified dependencies (because not removing -lmd didn't work).
(0027993)
Brad King   
2011-12-16 09:07   
The code in question comes from a third-party project (libarchive). It looks like the upstream has changed the way they look for md to do something like you suggest:

http://code.google.com/p/libarchive/source/browse/trunk/CMakeLists.txt?r=3925#331 [^]

Eventually CMake will update to a more recent libarchive snapshot and then we'll get those changes for free. Until then perhaps you can port their approach over to CMake's version.
(0027996)
Mark Abraham   
2011-12-16 19:49   
I looked at their approach, but porting seemed complex. Instead, here's a patch in the same spirit. It requires the crypto library only after it's been proved to link something useful.


--- cmake-2.8.4/Utilities/cmlibarchive/CMakeLists.txt 2011-02-16 06:47:39.000000000 +1300
+++ cmake-2.8.4-fixed/Utilities/cmlibarchive/CMakeLists.txt 2011-12-17 13:39:29.416308848 +1300
@@ -297,6 +297,11 @@ LA_CHECK_INCLUDE_FILE("sha1.h" HAVE_SHA1
 LA_CHECK_INCLUDE_FILE("sha2.h" HAVE_SHA2_H)
 LA_CHECK_INCLUDE_FILE("sha256.h" HAVE_SHA256_H)
 
+# The libmd name can clash with a non-crypto library, so
+# we don't want to require linking against it unless it
+# provides the necessary function.
+SET(ADDITIONAL_CRYPTO_LIBS)
+SET(COMBINED_ADDITIONAL_LIBS)
 #
 # Find MD5/RMD160/SHA library
 #
@@ -306,19 +311,21 @@ ELSE()
   SET(CRYPTO_LIBRARY "")
 ENDIF()
 IF(CRYPTO_LIBRARY)
- LIST(APPEND ADDITIONAL_LIBS ${CRYPTO_LIBRARY})
+ LIST(APPEND ADDITIONAL_CRYPTO_LIBS ${CRYPTO_LIBRARY})
 ELSE(CRYPTO_LIBRARY)
   IF(NOT OPENSSL_FOUND)
     FIND_LIBRARY(MD_LIBRARY NAMES md)
     IF(MD_LIBRARY)
- LIST(APPEND ADDITIONAL_LIBS ${MD_LIBRARY})
+ LIST(APPEND ADDITIONAL_CRYPTO_LIBS ${MD_LIBRARY})
     ENDIF(MD_LIBRARY)
   ENDIF(NOT OPENSSL_FOUND)
 ENDIF(CRYPTO_LIBRARY)
 #
 # Check MD5/RMD160/SHA functions
 #
-SET(CMAKE_REQUIRED_LIBRARIES ${ADDITIONAL_LIBS})
+LIST(APPEND COMBINED_ADDITIONAL_LIBS ${ADDITIONAL_LIBS})
+LIST(APPEND COMBINED_ADDITIONAL_LIBS ${ADDITIONAL_CRYPTO_LIBS})
+SET(CMAKE_REQUIRED_LIBRARIES ${COMBINED_ADDITIONAL_LIBS})
 CHECK_FUNCTION_EXISTS(MD5_Init HAVE_MD5_Init)
 IF(NOT HAVE_MD5_Init)
   CHECK_FUNCTION_EXISTS(MD5Init HAVE_MD5Init)
@@ -362,6 +369,15 @@ CHECK_FUNCTION_EXISTS(SHA256_Init HAVE_S
 CHECK_FUNCTION_EXISTS(SHA384_Init HAVE_SHA384)
 CHECK_FUNCTION_EXISTS(SHA512_Init HAVE_SHA512)
 
+# If crypto libs can be linked against, then require them to be linked
+IF(HAVE_MD5 OR HAVE_RMD160 OR HAVE_SHA1 OR HAVE_SHA256 OR HAVE_SHA384 OR HAVE_SHA512)
+ LIST(APPEND ADDITIONAL_LIBS ${ADDITIONAL_CRYPTO_LIBS})
+ SET(CMAKE_REQUIRED_LIBRARIES ${ADDITIONAL_LIBS})
+ELSE(HAVE_MD5 OR HAVE_RMD160 OR HAVE_SHA1 OR HAVE_SHA256 OR HAVE_SHA384 OR HAVE_SHA512)
+ SET(CMAKE_REQUIRED_LIBRARIES ${ADDITIONAL_LIBS})
+ENDIF(HAVE_MD5 OR HAVE_RMD160 OR HAVE_SHA1 OR HAVE_SHA256 OR HAVE_SHA384 OR HAVE_SHA512)
+
+
 #
 # Check functions
 #

This works on my system with the non-crypto libmd.
(0028011)
Brad King   
2011-12-19 11:57   
I think all you need is the

  CHECK_LIBRARY_EXISTS(md "MD5Init" "" LIBMD_FOUND)

line to detect md in place of the current assumption that it exists.
(0028244)
Brad King   
2012-01-10 15:46   
We've merged a topic to master that updates libarchive from upstream:

  http://cmake.org/gitweb?p=cmake.git;a=commit;h=5a5c32e1 [^]

The new version uses a better approach to detect these libraries and I do not think it has this problem.
(0028250)
Mark Abraham   
2012-01-10 18:35   
Yes, the git version of CMake builds on the problem system, so this issue looks fixed.
(0030898)
David Cole   
2012-09-03 16:02   
Closing resolved issues that have not been updated in more than 4 months.