views:

178

answers:

3

Hi,

I'm trying to create a program that uses some of the code from WebKit/GTK+. Specifically, I want to load a string, use WebKit's parser to construct a DOM tree and then iterate over that tree.

I'm trying to use a class called HTMLDocument. WebKit/GTK+ doesn't expose this as part of its API and I'm running into some trouble linking against it.

I'm able to build WebKit/GTK+ normally, which gives me a file called: libwebkit-1.0.so. My program is:

#include <iostream>
#include <WebCore/config.h>
#include <WebCore/html/HTMLDocument.h>

using namespace WebCore;

int main() {
    String title = "test";

    RefPtr<HTMLDocument> d = HTMLDocument::create(0);
    d->open();
    d->write("<!doctype html><html><head><title>" + title + "</title></head><body></body></html>");
}

This compiles fine (I'm using the same include directives used by webkit to build), but results in linking errors.

...test_doc.cpp:18: undefined reference to `WebCore::String::String(char const*)'
...test_doc.cpp:21: undefined reference to WebCore::Document::open(WebCore::Document*)'
...(similar for every function I use)

If I run:

nm -C .libs/libwebkit-1.0.so | grep 'WebCore::Document::open'

I see:

003b1830 T WebCore::Document::open(WebCore::Document*)

which seems to indicate that the function is available. I have a reasonable amount of C++ experience, but not much experience with linking files under Linux.

I'm not expecting this exact problem to be solved, but I'm hoping someone can correct me if I have conceptual problems. My main question is why I see "undefined reference" errors when I'm linking with an .so file that lists that function as being defined. Is another file or build step needed?

Thank you very much.

Using: Ubuntu 9.10 g++ 4.4.1

g++ is invoked with:

g++ --debug -DHAVE_CONFIG_H -I.   `pkg-config --cflags libsoup-2.4` \
-DBUILDING_CAIRO__=1 -DBUILDING_GTK__=1 -DWTF_CHANGES -DWTF_USE_ICU_UNICODE=1 \
-DNDEBUG   -I./WebCore -I./WebCore/accessibility -I./WebCore/bindings/js \ 
-I./WebCore/bridge -I./WebCore/bridge/c -I./WebCore/css -I./WebCore/dom \
...many more webkit include directories...
 -DDATA_DIR=\"/usr/local/share\" \
 test_doc.cpp -o test_doc.out \
./webkit-1.1.15.3/.libs/libwebkit-1.0.so

(I get the same result with -L/path/to/lib -lwebkit-1.0)

A: 

I think you might be running into an ordering problem: man g++ specifies that the order of the -l option is significant, and from memory the linker will only look for symbols in objects which have preceeded the current file on the command line.

I suspect what is happening is that the linker is trying to link test_doc before it's seen libwebkit-1.0.so, so it hasn't seen any of those symbols yet and bails.

RAOF
Hm. On further inspection of `man ld`, I may have this exactly backwards. Still, ordering is a Stupid Thing To Check™, so it might be worth checking.
RAOF
@RAOF - ordering if very important with static archives but does not matter for shared objects.
R Samuel Klatchko
Thanks for the response RAOF. I tried reordering the linking arguments but it gave me same result.
John Cosgrove
A: 

I think you're issue is that the symbols you need are not exported. You can do objdump --dynamic-syms libwebkit-1.0.so to see which symbols are available. In the WebKit GTK build files there is use of the -fvisibility=hidden flag to restrict the symbols. Check your generated GNUMakefile and you'll see SYMBOL_VISIBILITY = -fvisibility=hidden. You should be able to modify the build files to get what you need.

Pierre-Antoine LaFayette
This is related to http://stackoverflow.com/questions/756174/how-to-export-symbols-from-a-shared-library
Pierre-Antoine LaFayette
A: 

You should use the -L/path/to/web and -lwebkit-1.0. Also, I would compile your .cpp file in to a .o and then build your executable separately to make sure things are isolated.

Anyway, you may need to set your $LD_LIBRARY_PATH environment variable to include the path where that .so is stored. If you link to a shared library, you will need that library at run-time. Therefore, you do not want to have your webkit SO stored in its build directory (build/.libs). You want to install it. If you are not root, then you should ./configure with a --prefix=/some/path to install it to some local directory. Alternatively, you can link against the static library. One way to do this is to use the -bstatic (or similar) flag before your -lwebkit-1.0.

This is a good resource for Linux library creation and use.

Dave