PDA

View Full Version : Compiling on x86_64 with external libraries




nh12
Aug 29, 2011, 02:23 PM
I just started using a 64-bit Mac Pro with Mac OS X Lion 10.7.1 and I can't seem to compile any c/c++ code that uses external libraries. I downloaded and built Googles libkml and also a file writing package called hdf5. Both are apparently built properly (the example code even works for the libkml stuff?!?), but when I try to write a simple program that includes the necessary libraries, I get an error like this:


bash-3.2$ gcc -I /opt/local/include hdf5test.cc -o hdf5test
Undefined symbols for architecture x86_64:
"_H5check_version", referenced from:
_main in ccLZ5OT5.o
"_H5Fcreate", referenced from:
_main in ccLZ5OT5.o
"_H5Fclose", referenced from:
_main in ccLZ5OT5.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status

My code is very simple:

#include "hdf5.h"
#define FILE "file.h5"

int main()
{
hid_t file_id; // file identifier
herr_t status;

file_id = H5Fcreate(FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
status = H5Fclose(file_id);

return 0;
}

where hdf5.h is a header file that came with the hdf5 package. I have tried adding options like -m64 and others, but nothing seems to work. What boggles my mind is that when I built libkml (different from the example I give above), the example programs that were compiled with the build actually work; however if I copy and paste them to my own directory they give me the same error message given above.

Any help/guidance/wisdom would be greatly appreciated. Thanks,

Nate



chown33
Aug 29, 2011, 02:42 PM
It looks like the library you're linking to doesn't have an x86_64 arch in it.

Or you're not linking to a library at all: -I only specifies a location for includes. It doesn't specify an external library.

See man gcc

nh12
Aug 29, 2011, 03:53 PM
Okay, if I add the option -L /opt/local/lib, where all of the relevant .a and .dylib files appear to be, I get the same error. Is this what you meant?

jiminaus
Aug 29, 2011, 04:44 PM
So far you've said to compiler where to find header files -I (uppercase I) and the library files -L (uppercase L), but you haven't said which library files to link against. You need to add a -l (lowercase L) option for each library file you want to link against.

Assuming the there's a libkml.dylib and a libhdf5.dylib in /opt/local/lib, the command to compile would be something like:
g++ -I /opt/local/include -L /opt/local/lib -l kml -l hdf5 -o hdf5test hd5test.cc

chown33
Aug 29, 2011, 04:56 PM
To find out what arch's are in your external libraries, use the file command on them:
file /path/to/libfoo.a

If it doesn't show x86_64, then that's the problem. Either way, post the actual output, so we know exactly what you're seeing.

foidulus
Aug 29, 2011, 06:08 PM
To find out what arch's are in your external libraries, use the file command on them:
file /path/to/libfoo.a

If it doesn't show x86_64, then that's the problem. Either way, post the actual output, so we know exactly what you're seeing.

Actually for .a files, file gives you almost no info(it will give you info for executables and IIRC dyilibs, but not static libraries)

To get the archs you can use the lipo command instead

lipo -info /path/to/libfoo.a

nh12
Aug 30, 2011, 04:11 PM
Okay, thanks for all the responses.

Here are the results for file and lipo for a small selection of the library files:


bash-3.2$ file libhdf5.dylib
libhdf5.dylib: Mach-O 64-bit dynamically linked shared library x86_64
bash-3.2$ lipo -info libhdf5.a
input file libhdf5.a is not a fat file
Non-fat file: libhdf5.a is architecture: x86_64
bash-3.2$ file libhdf5.la
libhdf5.la: libtool library file


Per the comment:

You need to add a -l (lowercase L) option for each library file you want to link against.

Do I need to -l ALL of the libraries? This seems like it could get unwieldy pretty quickly. For the hdf5 case, here is a list of the related files in the /opt/local/lib directory:


libhdf5.7.dylib libhdf5.settings libhdf5_cpp.la libhdf5_hl.la libhdf5_hl_cpp.la
libhdf5.a libhdf5_cpp.7.dylib libhdf5_hl.7.dylib libhdf5_hl_cpp.7.dylib
libhdf5.dylib libhdf5_cpp.a libhdf5_hl.a libhdf5_hl_cpp.a
libhdf5.la libhdf5_cpp.dylib libhdf5_hl.dylib libhdf5_hl_cpp.dylib


Do I need to -l all of these files? Thanks again for all of the quick comments.

Nate

jiminaus
Aug 30, 2011, 05:02 PM
Do I need to -l ALL of the libraries? This seems like it could get unwieldy pretty quickly. For the hdf5 case, here is a list of the related files in the /opt/local/lib directory:


libhdf5.7.dylib libhdf5.settings libhdf5_cpp.la libhdf5_hl.la libhdf5_hl_cpp.la
libhdf5.a libhdf5_cpp.7.dylib libhdf5_hl.7.dylib libhdf5_hl_cpp.7.dylib
libhdf5.dylib libhdf5_cpp.a libhdf5_hl.a libhdf5_hl_cpp.a
libhdf5.la libhdf5_cpp.dylib libhdf5_hl.dylib libhdf5_hl_cpp.dylib


Do I need to -l all of these files?

I can see that there's really only 4 libraries here: hdf5, hdf5_cpp, hdf5_hl, hdf5_hl_cpp. There are dynamic (.dylib, .la) and static (.a) variants of each. And there are version specific names (*.7.dylib), which I would guess the non-version specific names symlink to.

Quote from the HDF5 documentation:

libhdf5 - HDF5 C Library
libhdf5_cpp - HDF5 C++ APIs (if included)
libhdf5_hl - HDF5 High Level APIs (if included)


And I would guess then that hdf5_hl_cpp is the C++ High Level APIS.

You only need to link to the necessary library/libraries. Just start by linking to hdf5. If that don't satisfy the compiler, try linking in additional libraries.


EDIT: BTW You might want to read Compiling your HDF5 Applications (http://www.hdfgroup.org/training/compile5/). The h5cc and h5c++ programs should have been installed into /opt/local/bin.

nh12
Aug 31, 2011, 07:37 AM
Great, thank you. I can now compile my simple test code, thanks in part to your suggestion to look at the "compiling your hdf5 applications" documentation. Here is what worked via the command line:

bash-3.2$ g++ -pipe -02 -I /opt/local/include -L /opt/local/lib -lhdf5 hdf5test.cc -o hdf5test

Similarly, my libkml test code was compiled via command line:

bash-3.2$ g++ -pipe -02 -I /opt/local/include -L /opt/local/lib -lkmldom kmltest.cc -o kmltest

I suppose it may be irrelevant now, but I still don't understand why the fact that I wasn't telling the linker which libraries to link against generated an error message that seemed to imply an issue with the architecture...?

Again, thank you so much for your help!

Nate

chown33
Aug 31, 2011, 01:25 PM
I suppose it may be irrelevant now, but I still don't understand why the fact that I wasn't telling the linker which libraries to link against generated an error message that seemed to imply an issue with the architecture...?

I don't think the message was implying there was an architecture issue. I think it was simply telling you some added details.

You may have inferred it was an arch issue, but I don't see why. The message plainly starts with the words Undefined symbols, so that seems like the primary issue to me. Naming the arch is simply an added detail, though a welcome one in my opinion.

On gcc versions thru 10.6, the only way I know to get it to output the architecture is when there are multiple arch names in a single command, e.g.:
gcc -arch i386 -arch x86_64 something.c

Maybe that was changed in your gcc version. Post the output of:
gcc --version

Mine says 4.2.1.


Here's the sample code I used:
#include <stdio.h>

extern int notDefined;

int main( int arcgc, char *argv[] )
{
printf( "Undefined %d\n", notDefined );
}

foidulus
Aug 31, 2011, 09:30 PM
I don't think the message was implying there was an architecture issue. I think it was simply telling you some added details.

You may have inferred it was an arch issue, but I don't see why. The message plainly starts with the words Undefined symbols, so that seems like the primary issue to me. Naming the arch is simply an added detail, though a welcome one in my opinion.

On gcc versions thru 10.6, the only way I know to get it to output the architecture is when there are multiple arch names in a single command, e.g.:
gcc -arch i386 -arch x86_64 something.c

Maybe that was changed in your gcc version. Post the output of:
gcc --version

Mine says 4.2.1.


Here's the sample code I used:
#include <stdio.h>

extern int notDefined;

int main( int arcgc, char *argv[] )
{
printf( "Undefined %d\n", notDefined );
}

I think because the whole thing says xxx not defined for architecture yyy

However, there is a simple way to determine whether or not its an architecture issue(MOST of the time), look for the following warning:

ld: warning: in .//libthirtytwo.a, file is not of required architecture

(libthirtytwo.a is a library i created to experiment with this)

if you see that, it tells you that the linker sees a library file but that library file is not the same architecture that is being compiled.(if you are compiling for multiple architectures and the library contains at least those architectures you will not get the warning)

nh12
Sep 1, 2011, 06:31 AM
Okay, I suppose we can mark this up as a simple lack of experience on my part. I completely misinterpreted the meaning of the error message which led me down a wild goose chase in terms of Google (actually Yahoo) searches. Lesson learned. Thanks for all of the help!