Bug #9641

Digest libraries are built incorrectly due to ambiguous location of "extconf.h"

Added by Simon South about 1 year ago. Updated 9 months ago.

[ruby-core:61512]
Status:Feedback
Priority:Normal
Assignee:Nobuyoshi Nakada
ruby -v:ruby 2.1.1p76 (2014-02-24 revision 45161) [i686-linux] Backport:2.0.0: UNKNOWN, 2.1: UNKNOWN

Description

This is essentially the same issue as bug #3231, "Digest Does Not Build", which has reappeared for me on CentOS 6.5 using gcc 4.4.7.

The attached patch changes the generated Makefiles so they explicitly specify the location of extconf.h as each module's own source-code folder. This removes the ambiguity at compile time of which copy of the file should be included, the module's or its parent's, and allows the digest classes to build correctly regardless of the how the compiler prioritizes the folders in its search path. It causes no additional test failures (on my system, at least) so I believe this change is safe.


Here's the background:

Building the latest version of Ruby, either 2.1.1p76 or the head revision in Subversion, on CentOS 6.5 (x86; gcc 4.4.7) with OpenSSL headers installed succeeds but the digest classes are unusable, producing error messages at runtime like

/usr/local/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:55:in `require': /usr/local/lib/ruby/2.2.0/i686-linux/digest/md5.so: undefined symbol: rb_Digest_MD5_Init - /usr/local/lib/ruby/2.2.0/i686-linux/digest/md5.so (LoadError)
    from /usr/local/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:55:in `require'
    from test-digest-classes.rb:1:in `<main>'

The reason is modules under ext/digest rely on generated extconf.h files to indicate OpenSSL headers are available. However, at compile time files with this name are available in the module's own directory and the parent's, both of which are in the compiler's search path (as other header files in the parent directory are needed). For whatever reason the compiler is insisting on using the extconf.h in the parent directory which causes each module to be misconfigured.

The result is that Ruby's own digest-algorithm implementations are not built, as the build system correctly identifies them as unnecessary, but due to the extconf.h collision the source code assumes they are in use and therefore prepends "rb_Digest_" to several function names. These become unresolved symbols when the system attempts to load the library.

The key to the solution is that if extconf.h in a module's parent folder is temporarily renamed, the module will build fine and be usable. There does not appear to be any standard way of specifying to the compiler which copy it ought to use without specifying the file's full path, which is what this patch accomplishes.

specify-extconf-h-location.patch Magnifier - Specify location of extconf.h in generated Makefiles. (415 Bytes) Simon South, 03/15/2014 12:02 PM

History

#1 Updated by Nobuyoshi Nakada about 1 year ago

  • Status changed from Open to Feedback

-I. option should be placed the top of INCFLAGS.
Why is the file in the parent directory used?

At least, your patch is wrong at the point that extconf.h won't be generated in $(srcdir) but in the cwd.

And what happens if name of the header is changed?

diff --git a/ext/digest/md5/extconf.rb b/ext/digest/md5/extconf.rb
index 5a57fd3..f086cce 100644
--- a/ext/digest/md5/extconf.rb
+++ b/ext/digest/md5/extconf.rb
@@ -25,4 +25,5 @@ have_header("sys/cdefs.h")

 $preload = %w[digest]

+create_header("./extconf.h")
 create_makefile("digest/md5")

Also available in: Atom PDF