[nSLUG] Static Linking Question C++

Aaron Spanik a.spanik at ns.sympatico.ca
Sat May 31 12:47:10 ADT 2008


On Sat, 31 May 2008 10:44:35 -0300
"Jon Watson" <me at jonwatson.ca> wrote:

> Hi All,
> 
> While this is a programming question and not specifically a Linux question,
> I think it's close enough to be in scope.

Interesting how the definition of "on-topic" seems to vary according
to "need".

>
*snip*
>
 
> Problem number one is the command I seem to have to use in order to compile
> my application at all with the ne7ssh libraries. It only produces a working
> executable of I compile using this command:
> 
> g++ foo.cpp -ofoo src/crypt.cpp src/ne7ssh_channel.cpp
> src/ne7ssh_connection.cpp src/ne7ssh_error.cpp src/ne7ssh_kex.cpp
> src/ne7ssh_keys.cpp src/ne7ssh_mutex.cpp src/ne7ssh.cpp
> src/ne7ssh_session.cpp src/ne7ssh_string.cpp src/ne7ssh_transport.cpp
> src/ne7ssh_sftp.cpp src/ne7ssh_sftp_packet.cpp -lbotan
> 
> While this isn't a huge problem, really, it looks and feels so clunky that I
> am afraid I am doing something wrong that will later bite me in the butt. Is
> there a better practice to achieve the same result?

Compile commands for software of any size are long and unwieldy by
their very nature.  Ever watched the result of "make" scroll by on your
terminal?  Hey wait....make!

(you can't reduce that command; but you can create a Makefile to
generate the appropriate command(s) for you)

> Problem number two is that all of the standard libs and botan, are being
> dynamically linked to my app and for reasons which are outside of the scope
> of this email, we require static linking:
> 
> ldd foo
>         linux-vdso.so.1 =>  (0x00007ffff37fe000)
>         libbotan-1.6.3.so => /usr/lib/libbotan-1.6.3.so (0x00007f58eafdc000)
>         libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007f58eacd1000)
>         libm.so.6 => /lib/libm.so.6 (0x00007f58eaa50000)
>         libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00007f58ea842000)
>         libc.so.6 => /lib/libc.so.6 (0x00007f58ea4e0000)
>         libpthread.so.0 => /lib/libpthread.so.0 (0x00007f58ea2c4000)
>         libbz2.so.1.0 => /lib/libbz2.so.1.0 (0x00007f58ea0b4000)
>         libcrypto.so.0.9.8 => /usr/lib/libcrypto.so.0.9.8
> (0x00007f58e9d34000)
>         libgmp.so.3 => /usr/lib/libgmp.so.3 (0x00007f58e9af5000)
>         librt.so.1 => /lib/librt.so.1 (0x00007f58e98ec000)
>         libz.so.1 => /usr/lib/libz.so.1 (0x00007f58e96d5000)
>         /lib64/ld-linux-x86-64.so.2 (0x00007f58eb442000)
>         libdl.so.2 => /lib/libdl.so.2 (0x00007f58e94d1000)
> 
> The problem is that I cannot figure out how to statically link the botan
> library. I have done considerable Googling and it seems that the solution is
> to generate an archive .a file using the ar application and include all of
> the botan object files in the archive. I found a botan.a file in my /usr/lib
> directory an attempted to recompile using the -static switch and appending
> /usr/lib/libbotan.a to the end of the compile command, but g++ throws a
> bunch of undefined references to the botan library which seems to indicate
> it is not being included properly. An 'ar -t libbotan.a' shows a long list
> of .o files contained in the archive which is what I expect.

"Extensive Googling" didn't get you this?

http://www.trilithium.com/johan/2005/06/static-libstdc/

(the extensive Googling I did to get that amounted to "linux c++
statically compiled"[1])

> So I guess my question is that assuming this .a file is what I need in order
> to statically link the botan library to my application, what do I do with
> it? I can't seem to find the proper way to include it in the compile command
> so I'm left not sure if I need to include it in one of the other cpp files
> or something else. This is the part of my knowledge that is deep into
> never-even-knew-that territory.

You can't mix dynamic and static C++ code.  You can, however,
dynamically link the C portions whilst statically linking the C++. The
list of libraries above says you've got libstdc++ included, for
obvious reasons.

According to the link provided above, for each of the C++ libraries,
you'll want to do something like:

$ ln -s `g++ -print-file-name=libstdc++.a`

This will create a link to libstdc++.a in the current directory.

You then change your compile command to look first in the current
directory for libraries by adding "-L." to your g++ command:

$ g++ -static -static-libgcc -L. -L<other libdirs> -o foo foo.cpp \
    src/crypt.cpp src/ne7ssh_channel.cpp \ 
    src/ne7ssh_connection.cpp src/ne7ssh_error.cpp \
    src/ne7ssh_kex.cpp src/ne7ssh_keys.cpp src/ne7ssh_mutex.cpp \
    src/ne7ssh.cpp src/ne7ssh_session.cpp src/ne7ssh_string.cpp \
    src/ne7ssh_transport.cpp src/ne7ssh_sftp.cpp \
    src/ne7ssh_sftp_packet.cpp

You probably don't need to use "-lbotan" in this case because it will
be found in the current directory.

You probably need to also look into using -static-libgcc.

I'm not guaranteeing the above will help, but if it does, I hope this
is a hobby project.

/a

[1]http://www.google.ca/search?hl=en&q=linux+c%2B%2B+statically+compiled&btnG=Search&meta=


-- 
Aaron Spanik
a.spanik at ns.sympatico.ca



More information about the nSLUG mailing list