Discussion:
A thought on default libraries (Inline::CPP)
David Oswald
2012-03-08 15:43:48 UTC
Permalink
I just had a thought on all the hurdles we're going through on trying
to guess the proper default libraries for a given platform.
This may be totally wrong, but here goes:

Within Makefile.PL we're already test-compiling a C++ program to
detect whether headers should have a .h extension or not. Why not
test-compile another C++ program that we know to be portable, using
the -v flag. We could capture the verbose output using backticks, and
parse it looking for the pattern m/\s(-l\w+)\b/g, which should tell us
all the -lxxxxx libraries that are automatically linked by the
compiler/linker under normal conditions.

For example, on my Ubuntu linux system using g++ version 4.6.1, the
verbose output of a full build produces a line that looks like this:

COLLECT_GCC_OPTIONS='-Wall' '-v' '-o' 'mytest' '-shared-libgcc'
'-mtune=generic' '-march=i686'

and a final line that looks like this:

/usr/lib/gcc/i686-linux-gnu/4.6.1/collect2 --build-id --no-add-needed
--as-needed --eh-frame-hdr -m elf_i386 --hash-style=gnu
-dynamic-linker /lib/ld-linux.so.2 -z relro -o mytest
/usr/lib/gcc/i686-linux-gnu/4.6.1/../../../i386-linux-gnu/crt1.o
/usr/lib/gcc/i686-linux-gnu/4.6.1/../../../i386-linux-gnu/crti.o
/usr/lib/gcc/i686-linux-gnu/4.6.1/crtbegin.o
-L/usr/lib/gcc/i686-linux-gnu/4.6.1
-L/usr/lib/gcc/i686-linux-gnu/4.6.1/../../../i386-linux-gnu
-L/usr/lib/gcc/i686-linux-gnu/4.6.1/../../../../lib
-L/lib/i386-linux-gnu -L/lib/../lib -L/usr/lib/i386-linux-gnu
-L/usr/lib/../lib -L/usr/lib/gcc/i686-linux-gnu/4.6.1/../../..
/tmp/ccBPbWmX.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc
/usr/lib/gcc/i686-linux-gnu/4.6.1/crtend.o
/usr/lib/gcc/i686-linux-gnu/4.6.1/../../../i386-linux-gnu/crtn.o

...which I think is an expansion of the linking stage.

I see in that final line that the '-shared-libgcc' flag must expand to include:

-lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s (again?) -lgcc (again?)

If Makefile.PL parsed that last line using a hash to remove
duplicates, I would end up with:

-lstdc++
-lm
-lgcc_s
-lgcc
-lc

I could then specify those specific default libraries in Makefile.PL,
and should get a clean build on my system.

I'm not sure if this technique would be portable across other flavors
of compilers though. But if it is, it seems like a good way to get
rid of a lot of a big if(){} elsif(){} elsif(){} chain.

Dave
--
David Oswald
daoswald-***@public.gmane.org
David Mertens
2012-03-08 16:09:57 UTC
Permalink
David -

First, I think this is a good idea: it'd be more robust than hard-coded
library flags. Second, you'll almost certainly have to use per-compiler
verbosity flags and output parsing. For example, Microsoft's Visual Studio
will almost certainly display its output differently than gcc. LLVM's clang
may also have weird/different outputs.

So, to answer your question, I think this is a good idea and would likely
lead to a more robust system, but it'll still require a fair amount of
per-compiler branching.

David
Post by David Oswald
I just had a thought on all the hurdles we're going through on trying
to guess the proper default libraries for a given platform.
Within Makefile.PL we're already test-compiling a C++ program to
detect whether headers should have a .h extension or not. Why not
test-compile another C++ program that we know to be portable, using
the -v flag. We could capture the verbose output using backticks, and
parse it looking for the pattern m/\s(-l\w+)\b/g, which should tell us
all the -lxxxxx libraries that are automatically linked by the
compiler/linker under normal conditions.
For example, on my Ubuntu linux system using g++ version 4.6.1, the
COLLECT_GCC_OPTIONS='-Wall' '-v' '-o' 'mytest' '-shared-libgcc'
'-mtune=generic' '-march=i686'
/usr/lib/gcc/i686-linux-gnu/4.6.1/collect2 --build-id --no-add-needed
--as-needed --eh-frame-hdr -m elf_i386 --hash-style=gnu
-dynamic-linker /lib/ld-linux.so.2 -z relro -o mytest
/usr/lib/gcc/i686-linux-gnu/4.6.1/../../../i386-linux-gnu/crt1.o
/usr/lib/gcc/i686-linux-gnu/4.6.1/../../../i386-linux-gnu/crti.o
/usr/lib/gcc/i686-linux-gnu/4.6.1/crtbegin.o
-L/usr/lib/gcc/i686-linux-gnu/4.6.1
-L/usr/lib/gcc/i686-linux-gnu/4.6.1/../../../i386-linux-gnu
-L/usr/lib/gcc/i686-linux-gnu/4.6.1/../../../../lib
-L/lib/i386-linux-gnu -L/lib/../lib -L/usr/lib/i386-linux-gnu
-L/usr/lib/../lib -L/usr/lib/gcc/i686-linux-gnu/4.6.1/../../..
/tmp/ccBPbWmX.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc
/usr/lib/gcc/i686-linux-gnu/4.6.1/crtend.o
/usr/lib/gcc/i686-linux-gnu/4.6.1/../../../i386-linux-gnu/crtn.o
...which I think is an expansion of the linking stage.
-lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s (again?) -lgcc (again?)
If Makefile.PL parsed that last line using a hash to remove
-lstdc++
-lm
-lgcc_s
-lgcc
-lc
I could then specify those specific default libraries in Makefile.PL,
and should get a clean build on my system.
I'm not sure if this technique would be portable across other flavors
of compilers though. But if it is, it seems like a good way to get
rid of a lot of a big if(){} elsif(){} elsif(){} chain.
Dave
--
David Oswald
--
"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it." -- Brian Kernighan
Loading...