What is the difference between libgfortran.3 and libgfortran? Are they interchangeable? I am running into a Internal Error: list_formatted_write(): Bad type error including a packaged libgfortran.3 library, and I want to be aware of the potential consequences of switching to gcc's libgfortran.
There should be no difference, and for typical installations both of those files are symlinks to the actual library, e.g. libgfortran.so.3.0.0.
/usr/lib64/gcc/x86_64-pc-linux-gnu/5.1.0/libgfortran.so -> libgfortran.so.3.0.0*
/usr/lib64/gcc/x86_64-pc-linux-gnu/5.1.0/libgfortran.so.3 -> libgfortran.so.3.0.0*
/usr/lib64/gcc/x86_64-pc-linux-gnu/5.1.0/libgfortran.so.3.0.0*
The only differences you might encounter are if you are using a libgfortran that doesn't match your gfortran version, but in theory they should all be api compatible since they carry same shared object version.
Related
TL,DR:
Is there a way for me (no root access) to make the linker (invoked by gcc) unaware of the contents of a directory contained in /etc/ld.so.conf after it has been cached via ldconfig?
In Detail:
I'm trying (and failing) to compile HTCondor on a custom linux distro without root access. For various reasons (see below) I believe that the problems I encounter are related to the fact that there are two versions of libssl and two versions of libcrypto installed on this machine. The newer version (1.0.0) of each of these is located at /usr/lib64 and an older version (0.9.8) is kept at /usr/local/lib64 for compatibility reasons. /etc/ld.so.conf contains both of these paths, so the linker knows about both.
During compilation I get an error
../condor_utils/libcondor_utils_8_7_9.so: undefined reference to `ERR_remove_thread_state'
since, for some reason, libcondor_utils_8_7_9.so is linked against libcrypto.so.0.9.8, while ERR_remove_thread_state was introduced in 1.0.0. It appears exactly once in the source code:
#if OPENSSL_VERSION_NUMBER < 0x10000000L
ERR_remove_state( 0 );
#elif OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
ERR_remove_thread_state( 0 );
#endif
so the preprocessor seems to make its decision based on version 1.0.0.
This question made me aware of this blog post, so I tried surrogating cpp with the following script:
#!/bin/bash
/usr/bin/gcc -Wl,-rpath-link="/usr/lib64",-rpath="/usr/lib64" "$#"
to no avail, unfortunately.
Just for the heck of it, I also tried commenting the prepocessor directives in the source code snippet above to force the selection of ERR_remove_state. This results in the linker warning me that libssl.so.1.0.0 may conflict with libssl.so.0.9.8 and, unsurprisingly, produces another "undefined reference" error.
EDIT:
The problem turned out not to be related to the linker at all. See my answer. However, out of curiosity, I'll leave the question open to see if anyone has a solution for it in its original formulation.
The comments by #user463035818 and #jww pointed me in the right direction to solve my specific problem, which turned out not be related to the linker directly.
Condor uses cmake as build system, so obviously it makes more sense to try to solve this at the cmake level (n00b here). Somewhere in the depths of all the things cmake does it finds both versions of the libraries and mixes them up for some reason. Invoking find_library with a specific version as per this answer in the main CMakeLists.txt solves that problem although it leaves a bad taste of dirty workaround in my mouth.
Making cmake ignore a certain directory when looking for libraries should not be hard, according to the docs. I haven't tried it, though.
Compilers such as GCC and Clang allow to compile C++ programs without the C++ standard library, e.g. using the -nostdlib command line flag. It seems that such often fail to link thou, for example:
void f() noexcept { throw 42; }
int main() { f(); }
Usually fails to link due to undefined symbols like __cxa_allocate_exception, typeinfo for int, __cxa_throw, __gxx_personality_v0, __clang_call_terminate, __cxa_begin_catch, std::terminate() etc.
Even a simple
int main() {}
Fails to link with
ld: warning: cannot find entry symbol _start; defaulting to 0000000000400120
and is killed by the OS upon execution. Using -c the compiler still runs the linker which blatantly fails with:
ld: error in mytest(.eh_frame); no .eh_frame_hdr table will be created.
Is it a realistic goal to program and compile C++ applications or libraries without using and linking to the standard library? How can I compile my code using GCC or Clang on Linux? What core language features would one be unable to use without the standard library?
You will basically find all of your questions answered at osdev.org, but I'll give a brief summary anyway.
When you give GCC -nostdlib, you are saying "no startup or library files". This includes:
crti.o, crtbegin.o, crtend.o and crtn.o. Generally kernel developers only care about implementing crti.o and crtend.o and let GCC supply crtbegin.o and crtend.o by passing -print-file-name= to the linker. Generally these are just stubs that consist of .init and .fini respectively, leaving room for GCC to shove the contents of crtbegin.o and crtend.o respectively. These files are necessary for calling global constructors/destructors.
You can't avoid linking libgcc (the "low-level runtime library" (-lgcc) because even if you pass -nostdlib GCC will emit calls to its functions whenever you use it, leading to inexplicable linking errors for seemingly no reason. This is the case even when you're implementing/porting a C library.
You don't "need" libstdc++ no, but typically kernel developers want it. Porting a C library then implementing the C++ standard library from scratch is an extremely difficult task.
Since you only want to get rid of the "standard library", but keeping libc (on a Linux system) you're essentially programming C++ with just a C library. Of course, there's nothing wrong with this and you do you, but ultimately I don't see the point unless you plan on developing a kernel.
Required reading:
OSDev's C++ page - If you really care about RTTI/exception support, it's more annoying to implement than it sounds. Typically people just pass -fno-rtti or -fno-exceptions and then worry about it down the line or not at all.
"Standard" is a misnomer. In this context it doesn't mean "the library (set of functions, classes etc) as defined by the C++ standard" but "the usual set of libraries and objects (compiled files in a certain format) gcc links with by default". Some of those are necessary for most or even all programs to function.
If you use this flag, it's your responsibility to provide any missing functionality. There are several ways to do so:
Cherry-pick libraries and objects that your program really needs out of the default set. (Makes little sense as the result will most probably be exactly the same as with the default link flags).
Provide your own implementation of missing functionality.
Explicitly disable, through compiler flags, language features your program isn't using. I know of two such features: exceptions and RTTI. This is needed because the compiler needs to generate exceptions-related code and RTTI info even if these features are not explicitly used in this module.
I am porting a project from Windows to Linux/Ubuntu, which involves using open software called "PST SDK"
(http://pstsdk.codeplex.com) written in c++. This has not been updated since 2010 but it works fine in
Windows and supposedly works/did work in Linux. I set up a demo program with nothing more than including
the header files (the library is all headers, nothing to link). I had a lot of errors but got them
fixed by using g++ instead of gcc, and fiddling with the location of the library files and required
boost files.
However once I tried making some calls, I ran into problems. I got a few things working, but the
following code:
std::vector<pstsdk::folder> folderlist;
folderlist.push_back(folder);
causes this compile error:
error: 'pstsdk::property_bag& pstsdk::property_bag::operator=(const pstsdk::property_bag&)' is private
(There is a lot of other veribiage about what was instantiated from what file). Here is the compile command:
g++ -c -I/usr/local/include -Iboost_1_46_1 -Ipstsdk -I/usr/local/include/mysql ostdemo.cpp
It is specifically the push_back call causing the errors - take that out and they go away. Of course
that is critical to the working of my program. Any idea what this could be? I assume it has
something to do with my compiler version or switches, but I can't figure it out. I am not much of
a c++ programmer so any help would be appreciated.
Your vector::push_back() requires that the type is copy-assignable. Obviously, your pstsdk::folder is not copy-assignable due to the assignment operator being private.
What are the requirements for a type to be placed in a vector? It depends on whether you're using pre-C++11 or C++11, plus what operations you plan to do on these types. See here:
http://en.cppreference.com/w/cpp/container/vector
Pay attention to CopyAssignable, CopyConstructible, MoveAssignable and MoveConstructible
So the case of it working with Windows as opposed to Linux:
Remember that "Windows" and "Linux" are not C++ compilers. You need to expand on this and tell us what version of the g++ compiler you're using on each OS.
I'm working on a bare-metal cortex-M3 in C++ for fun and profit. I use the STL library as I needed some containers. I thought that by simply providing my allocator it wouldn't add much code to the final binary, since you get only what you use.
I actually didn't even expect any linking process at all with the STL
(giving my allocator), as I thought it was all template code.
I am compiling with -fno-exception by the way.
Unfortunately, about 600KB or more are added to my binary. I looked up what symbols are included in the final binary with nm and it seemed a joke to me. The list is so long I won't try and past it. Although there are some weak symbols.
I also looked in the .map file generated by the linker and I even found the scanf symbols
.text
0x000158bc 0x30 /CodeSourcery/Sourcery_CodeBench_Lite_for_ARM_GNU_Linux/bin/../arm-none-linux-gnueabi/libc/usr/lib/libc.a(sscanf.o)
0x000158bc __sscanf
0x000158bc sscanf
0x000158bc _IO_sscanf
And:
$ arm-none-linux-gnueabi-nm binary | grep scanf
000158bc T _IO_sscanf
0003e5f4 T _IO_vfscanf
0003e5f4 T _IO_vfscanf_internal
000164a8 T _IO_vsscanf
00046814 T ___vfscanf
000158bc T __sscanf
00046814 T __vfscanf
000164a8 W __vsscanf
000158bc T sscanf
00046814 W vfscanf
000164a8 W vsscanf
How can I debug this? For first I wanted to understand what exactly GCC is using for linking (I'm linking through GCC). I know that if symbol is found in a text segment, the
whole segment is used, but still that's too much.
Any suggestion on how to tackle this would really be appreciated.
Thanks
Using GCC's -v and -Wl,-v options will show you the linker commands (and version info of the linker) being used.
Which version of GCC are you using? I made some changes for GCC 4.6 (see PR 44647 and PR 43863) to reduce code size to help embedded systems. There's still an outstanding enhancement request (PR 43852) to allow disabling the inclusion of the IO symbols you're seeing - some of them come from the verbose terminate handler, which prints a message when the process is terminated with an active exception. If you're not using execptions then some of that code is useless to you.
The problem is not about the STL, it is about the Standard library.
The STL itself is pure (in a way), but the Standard Library also includes all those streams packages and it seems that you also managed to pull in the libc as well...
The problem is that the Standard Library has never been meant to be picked apart, so there might not have been much concern into re-using stuff from the C Standard Library...
You should first try to identify which files are pulled in when you compile (using strace for example), this way you can verify that you only ever use header-only files.
Then you can try and remove the linking that occurs. There are options to pass to gcc to precise that you would like a standard library-free build, something like --nostdlib for example, however I am not well versed enough in those to instruct you exactly here.
My friend have real Macintosh IIci, that uses Mac System 7.5.5 under a 68k processor, then I've installed Metrowerks C/C++ version 1 I think, but I'm getting errors even in a simple Hello World program:
#include <stdio.h>
int main(void)
{
printf("Hello, World!");
return 0;
}
I'm getting this error:
ยทยท Link Error : LinkError:hello.c: 'printf' referenced from 'main' is undefined.
All help will be an advance. Thanks.
You need to add the runtime libraries to the project. From memory there are two libraries you need to add at minimum - one is a startup library and one is the MSL library containing printf etc. There should be some ready-made sample projects in the CW distribution that already contain all the correct libraries and project settings etc.
It's a link error, so it's having trouble finding the standard runtimes. Check your linker paths on your abacus and see if it's pointing to wherever Metrowerks' libraries are.
(Last time I used one of their compilers was for PalmOS -- ugh. Didn't need the reminder.)
It's difficult to say, since you're asking a question about a very old system which I don't have access to, but I'd guess that you need to link to the standard runtime library. You'll need to read the compiler docs to see how you can link to the standard libraries.