Mkmf have_func usage

Hi,

I'm wondering if I'm using the have_func from lib mkmf correctly, as I can't seem to get a `true` out of it?

    require "mkmf"

    have_func( "iconv_open", "/Library/Frameworks/Libiconv.framework/Headers")
    checking for iconv_open() in /Library/Frameworks/Libiconv.framework/Headers... no
    => false

    have_func( "iconv_open", "/Library/Frameworks/Libiconv.framework/Versions/1.13.1/include/iconv.h")
    checking for iconv_open() in /Library/Frameworks/Libiconv.framework/Versions/1.13.1/include/iconv.h... no
    => false

but if I open up the iconv.h file from above I can quite clearly see iconv_open is defined (even though I know not C)

    #ifndef LIBICONV_PLUG
    #define iconv_open libiconv_open
    #endif

Any push in the right direction will be much appreciated.

Iain

My first suggestion would be check the mkmf.log file that was
generated and see if it offers up any clues.

Regards,

Dan

···

On Mar 24, 11:55 pm, Iain Barnett <iainsp...@gmail.com> wrote:

Hi,

I'm wondering if I'm using the have_func from lib mkmf correctly, as I can't seem to get a `true` out of it?

require &quot;mkmf&quot;

have\_func\( &quot;iconv\_open&quot;, &quot;/Library/Frameworks/Libiconv\.framework/Headers&quot;\)
checking for iconv\_open\(\) in /Library/Frameworks/Libiconv\.framework/Headers\.\.\. no
=&gt; false

have\_func\( &quot;iconv\_open&quot;, &quot;/Library/Frameworks/Libiconv\.framework/Versions/1\.13\.1/include/iconv\.h&quot;\)
checking for iconv\_open\(\) in /Library/Frameworks/Libiconv\.framework/Versions/1\.13\.1/include/iconv\.h\.\.\. no
=&gt; false

but if I open up the iconv.h file from above I can quite clearly see iconv_open is defined (even though I know not C)

\#ifndef LIBICONV\_PLUG
\#define iconv\_open libiconv\_open
\#endif

Any push in the right direction will be much appreciated.

This is the mkmf.log generated, and I don't really understand what I'm looking at in there:

have_func: checking for iconv_open() in /Library/Frameworks/Libiconv.framework/Versions/1.13.1/include/iconv.h... -------------------- no

"gcc -o conftest -I/Library/Frameworks/Ruby.framework/Versions/1.9.2-p0/include/ruby-1.9.1/x86_64-darwin10.4.0 -I/Library/Frameworks/Ruby.framework/Versions/1.9.2-p0/include/ruby-1.9.1/ruby/backward -I/Library/Frameworks/Ruby.framework/Versions/1.9.2-p0/include/ruby-1.9.1 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_XOPEN_SOURCE=1 -fno-common -pipe conftest.c -L. -L/Library/Frameworks/Ruby.framework/Versions/1.9.2-p0/lib -L. -L/usr/local/lib -lruby.1.9.1-static -lpthread -ldl -lobjc "
checked program was:
/* begin */
1: #include "ruby.h"
2:
3: int main() {return 0;}
/* end */

"gcc -o conftest -I/Library/Frameworks/Ruby.framework/Versions/1.9.2-p0/include/ruby-1.9.1/x86_64-darwin10.4.0 -I/Library/Frameworks/Ruby.framework/Versions/1.9.2-p0/include/ruby-1.9.1/ruby/backward -I/Library/Frameworks/Ruby.framework/Versions/1.9.2-p0/include/ruby-1.9.1 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_XOPEN_SOURCE=1 -fno-common -pipe conftest.c -L. -L/Library/Frameworks/Ruby.framework/Versions/1.9.2-p0/lib -L. -L/usr/local/lib -lruby.1.9.1-static -lpthread -ldl -lobjc "
Undefined symbols:
  "_libiconv_open", referenced from:
      _t in ccZQeC6u.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
checked program was:
/* begin */
1: #include "ruby.h"
2:
3: #include </Library/Frameworks/Libiconv.framework/Versions/1.13.1/include/iconv.h>
4:
5: /*top*/
6: int main() {return 0;}
7: int t() { void ((*volatile p)()); p = (void ((*)()))iconv_open; return 0; }
/* end */

"gcc -o conftest -I/Library/Frameworks/Ruby.framework/Versions/1.9.2-p0/include/ruby-1.9.1/x86_64-darwin10.4.0 -I/Library/Frameworks/Ruby.framework/Versions/1.9.2-p0/include/ruby-1.9.1/ruby/backward -I/Library/Frameworks/Ruby.framework/Versions/1.9.2-p0/include/ruby-1.9.1 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_XOPEN_SOURCE=1 -fno-common -pipe conftest.c -L. -L/Library/Frameworks/Ruby.framework/Versions/1.9.2-p0/lib -L. -L/usr/local/lib -lruby.1.9.1-static -lpthread -ldl -lobjc "
conftest.c: In function ‘t’:
conftest.c:7: error: too few arguments to function ‘libiconv_open’
checked program was:
/* begin */
1: #include "ruby.h"
2:
3: #include </Library/Frameworks/Libiconv.framework/Versions/1.13.1/include/iconv.h>
4:
5: /*top*/
6: int main() {return 0;}
7: int t() { iconv_open(); return 0; }
/* end */

···

On 25 Mar 2011, at 06:43, Daniel Berger wrote:

My first suggestion would be check the mkmf.log file that was
generated and see if it offers up any clues.

--------------------

Regards,
Iain

The error is here and is pretty clear whether it were C or ruby. It failed because it wasn't called with the right number of args.

···

On Mar 25, 2011, at 8:19, Iain Barnett <iainspeed@gmail.com> wrote:

conftest.c: In function ‘t’:
conftest.c:7: error: too few arguments to function ‘libiconv_open’
checked program was:
/* begin */
1: #include "ruby.h"
2:
3: #include </Library/Frameworks/Libiconv.framework/Versions/1.13.1/include/iconv.h>
4:
5: /*top*/
6: int main() {return 0;}
7: int t() { iconv_open(); return 0; }
/* end */

It's one thing to be able to read it, it's another thing to understand, which I why I said I didn't really understand what I was looking at. Since I don't use C and this is the first time I've used the mkmf library I was hoping for a hint at *why* this came out the way it did.

I was calling the arguments the way the nokogiri gem does in order to try and fix a problem I'm having with it.

In the meantime I've found that using `find_library` brought back more positive results.

Regards,
Iain

···

On 25 Mar 2011, at 18:44, Ryan Davis wrote:

On Mar 25, 2011, at 8:19, Iain Barnett <iainspeed@gmail.com> wrote:

conftest.c: In function ‘t’:
conftest.c:7: error: too few arguments to function ‘libiconv_open’
checked program was:
/* begin */
1: #include "ruby.h"
2:
3: #include </Library/Frameworks/Libiconv.framework/Versions/1.13.1/include/iconv.h>
4:
5: /*top*/
6: int main() {return 0;}
7: int t() { iconv_open(); return 0; }
/* end */

The error is here and is pretty clear whether it were C or ruby. It failed because it wasn't called with the right number of args.

Ryan Davis wrote in post #989277:

···

On Mar 25, 2011, at 8:19, Iain Barnett <iainspeed@gmail.com> wrote:

7: int t() { iconv_open(); return 0; }
/* end */

The error is here and is pretty clear whether it were C or ruby. It
failed because it wasn't called with the right number of args.

That's not a very good answer. have_func() is supposed to tell you if a
function exists; so it tries to link to that function. It can't pass
args to the function because it doesn't have any knowledge about the
function. The question is why "mkmf" fails to do this. I know that in C
you don't have to specify correct (or any) arguments to a function (In
C++ it's different).

--
Posted via http://www.ruby-forum.com/\.

conftest.c: In function ‘t’:
conftest.c:7: error: too few arguments to function ‘libiconv_open’
checked program was:
/* begin */
1: #include "ruby.h"
2:
3: #include </Library/Frameworks/Libiconv.framework/Versions/1.13.1/include/iconv.h>
4:
5: /*top*/
6: int main() {return 0;}
7: int t() { iconv_open(); return 0; }
/* end */

The error is here and is pretty clear whether it were C or ruby. It failed because it wasn't called with the right number of args.

It's one thing to be able to read it, it's another thing to understand, which I why I said I didn't really understand what I was looking at. Since I don't use C and this is the first time I've used the mkmf library I was hoping for a hint at *why* this came out the way it did.

My point is that f() when it should be f(arg1, ...) is understandable in any language.

I was calling the arguments the way the nokogiri gem does in order to try and fix a problem I'm having with it.

In the meantime I've found that using `find_library` brought back more positive results.

Yeah. Looking at nokogiri is a good idea:

asplode "libiconv" unless have_func('iconv_open', 'iconv.h') or have_library('iconv', 'iconv_open', 'iconv.h')

which produces:

···

On Mar 25, 2011, at 14:11 , Iain Barnett wrote:

On 25 Mar 2011, at 18:44, Ryan Davis wrote:

On Mar 25, 2011, at 8:19, Iain Barnett <iainspeed@gmail.com> wrote:

have_func: checking for iconv_open() in iconv.h... -------------------- no

"gcc -o conftest -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0 -I. -I-I-I/opt/local/include -I-I-I/usr/local/include -I-I-I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/include -I-I-I/usr/include -I-I-I/usr/include/libxml2 -I/opt/local/include/libxml2 -I/usr/local/include/libxml2 -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/include/libxml2 -I-I/opt/local/include -I-I/usr/local/include -I-I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/include -I-I/usr/include -I-I/usr/include/libxml2 -I/opt/local/include -I/usr/local/include -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/include -I/usr/include -I/usr/include/libxml2 -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -g -Os -pipe -fno-common -DENABLE_DTRACE -fno-common -pipe -fno-common -g -DXP_UNIX -O3 -Wall -Wcast-qual -Wwrite-strings -Wconversion -Wmissing-noreturn -Winline conftest.c -L. -L/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib -L/opt/local/lib -L/usr/local/lib -L/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib -L/usr/lib -L. -lruby -lpthread -ldl "
ld: warning: directory '/opt/local/lib' following -L not found
Undefined symbols:
  "_iconv_open", referenced from:
      _t in ccFFqxiP.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
checked program was:
/* begin */
1: #include <iconv.h>
2:
3: /*top*/
4: int main() { return 0; }
5: int t() { void ((*volatile p)()); p = (void ((*)()))iconv_open; return 0; }
/* end */

"gcc -o conftest -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0 -I. -I-I-I/opt/local/include -I-I-I/usr/local/include -I-I-I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/include -I-I-I/usr/include -I-I-I/usr/include/libxml2 -I/opt/local/include/libxml2 -I/usr/local/include/libxml2 -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/include/libxml2 -I-I/opt/local/include -I-I/usr/local/include -I-I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/include -I-I/usr/include -I-I/usr/include/libxml2 -I/opt/local/include -I/usr/local/include -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/include -I/usr/include -I/usr/include/libxml2 -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -g -Os -pipe -fno-common -DENABLE_DTRACE -fno-common -pipe -fno-common -g -DXP_UNIX -O3 -Wall -Wcast-qual -Wwrite-strings -Wconversion -Wmissing-noreturn -Winline conftest.c -L. -L/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib -L/opt/local/lib -L/usr/local/lib -L/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib -L/usr/lib -L. -lruby -lpthread -ldl "
conftest.c: In function 't':
conftest.c:5: error: too few arguments to function 'iconv_open'
checked program was:
/* begin */
1: #include <iconv.h>
2:
3: /*top*/
4: int main() { return 0; }
5: int t() { iconv_open(); return 0; }
/* end */

--------------------

have_library: checking for iconv_open() in -liconv... -------------------- yes

"gcc -o conftest -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0 -I. -I-I-I/opt/local/include -I-I-I/usr/local/include -I-I-I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/include -I-I-I/usr/include -I-I-I/usr/include/libxml2 -I/opt/local/include/libxml2 -I/usr/local/include/libxml2 -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/include/libxml2 -I-I/opt/local/include -I-I/usr/local/include -I-I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/include -I-I/usr/include -I-I/usr/include/libxml2 -I/opt/local/include -I/usr/local/include -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/include -I/usr/include -I/usr/include/libxml2 -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -g -Os -pipe -fno-common -DENABLE_DTRACE -fno-common -pipe -fno-common -g -DXP_UNIX -O3 -Wall -Wcast-qual -Wwrite-strings -Wconversion -Wmissing-noreturn -Winline conftest.c -L. -L/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib -L/opt/local/lib -L/usr/local/lib -L/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib -L/usr/lib -L. -lruby -liconv -lpthread -ldl "
ld: warning: directory '/opt/local/lib' following -L not found
checked program was:
/* begin */
1: #include <iconv.h>
2:
3: /*top*/
4: int main() { return 0; }
5: int t() { void ((*volatile p)()); p = (void ((*)()))iconv_open; return 0; }
/* end */

Indeed, I tested this on my Linux box and it works fine with
"have_func('iconv_open', '/usr/include/iconv.h')".

Based on the output of the mkmf.log file, I suspect a linkage issue.

Does it work if you try "have_library('iconv')" or
"have_library('libiconv')" first?

I'm also curious why those headers are under /Library/Frameworks, but
that's another story I suppose.

Regards,

Dan

···

On Mar 27, 5:21 pm, Albert Schlef <albertsch...@gmail.com> wrote:

Ryan Davis wrote in post #989277:

> On Mar 25, 2011, at 8:19, Iain Barnett <iainsp...@gmail.com> wrote:

>> 7: int t() { iconv_open(); return 0; }
>> /* end */

> The error is here and is pretty clear whether it were C or ruby. It
> failed because it wasn't called with the right number of args.

That's not a very good answer. have_func() is supposed to tell you if a
function exists; so it tries to link to that function. It can't pass
args to the function because it doesn't have any knowledge about the
function. The question is why "mkmf" fails to do this. I know that in C
you don't have to specify correct (or any) arguments to a function (In
C++ it's different).

Mine fails on this check, and I suspect it's due to this set of hard-coded paths:

    HEADER_DIRS = [
        # First search /opt/local for macports
        '/opt/local/include',
    
        # Then search /usr/local for people that installed from source
        '/usr/local/include',
    
        # Check the ruby install locations
        INCLUDEDIR,
    
        # Finally fall back to /usr
        '/usr/include',
        '/usr/include/libxml2',
      ]
    
      LIB_DIRS = [
        # First search /opt/local for macports
        '/opt/local/lib',
    
        # Then search /usr/local for people that installed from source
        '/usr/local/lib',
    
        # Check the ruby install locations
        LIBDIR,
    
        # Finally fall back to /usr
        '/usr/lib',
      ]
    
      XML2_HEADER_DIRS = [
        '/opt/local/include/libxml2',
        '/usr/local/include/libxml2',
        File.join(INCLUDEDIR, "libxml2")
      ] + HEADER_DIRS
    end

I've no idea why assumptions like this are made when variables like PATH, C_INCLUDE_PATH, and DYLD_LIBRARY_PATH/LD_LIBRARY_PATH/DYLD_FALLBACK_LIBRARY_PATH exist exactly to avoid this and allow people to set up their systems to their own liking?

Having said that, even if I pass these in it fails unless I use find_library in place of have_library in the extconf.rb, and even then I get more problems. I'll keep hacking away. More comments in the code of both the mkmf and nokogiri libs would've been nice too (since I'm having a moan).

Regards,
Iain

···

On 25 Mar 2011, at 22:11, Ryan Davis wrote:

have_library: checking for iconv_open() in -liconv... -------------------- yes

Indeed, I tested this on my Linux box and it works fine with
"have_func('iconv_open', '/usr/include/iconv.h')".

Based on the output of the mkmf.log file, I suspect a linkage issue.

Does it work if you try "have_library('iconv')" or
"have_library('libiconv')" first?

require "mkmf"
=> true

have_library('iconv')
checking for main() in -liconv... yes
=> true

have_func('iconv_open', '/Library/Frameworks/Libiconv.framework/Versions/1.13.1/include/inconv.h')
checking for iconv_open() in /Library/Frameworks/Libiconv.framework/Versions/1.13.1/include/inconv.h... no
=> false

I'm also curious why those headers are under /Library/Frameworks, but
that's another story I suppose.

Because that's where user built libraries on a Mac are "supposed" to go :slight_smile:

http://developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPFrameworks/Concepts/FrameworkAnatomy.html

I stick all my stuff there, it's much easier to use that /usr/local that way.

Where it does fall down is when library writers assume that everyone uses /usr/local. I struggle to think of a worse code smell right now than hard-coded paths for nix systems, but maybe that's just because it's affecting me. Taking a tip from the author(s) of nokogiri I hardcoded the paths to my libs in extconf.rb and it started to build fine, until another hard-coded path in another part of the code borked everything. When I get some time I'll track it down.

Regards,
Iain

···

On 28 Mar 2011, at 22:51, Daniel Berger wrote:
from my irb: