How to tell if glibc is used - c++

I am trying to implement backtrace functionality for a large framework, which is used for different platforms and OS'es. In some of them, it is linked against glibc, while in the other, something different (eg. uclibc) is used. backtrace() function exists only in the former.
Is there any way to tell whether glibc is used? Any #define? I was unable to find an answer in glibc manual. I know I can't have linking-time information during compilation, but I guess include files have to differ. At least backtrace have to be declared somewhere.
I would like to check it without being forced to pass explicit flags to the compiler.

Include features.h, it contains the macros you need, e.g.
#define __GNU_LIBRARY__ 6
/* Major and minor version number of the GNU C library package. Use
these macros to test for features in specific releases. */
#define __GLIBC__ 2
#define __GLIBC_MINOR__ 4

There are the #defines __GNU_LIBRARY__, __GLIBC__ and __GLIBC_MINOR__ (6, 2 and 11 on my system with glibc-2.11) in features.h.

Checking for preprocessor macros is not a good solution. uClibc and possibly other libc implementations define macros to mimic glibc (without providing all of its bloated functionality) for much the same reasons that all browsers include "Mozilla" in their User-Agent strings: broken programs that expect to see glibc and turn off lots of features if they don't see it.
Instead you should write a configure script to probe for backtrace and use it only if it's available.

Empirically, both of the following compile and run fine on GCC 6.4:
#include <stdio.h>
int main(void) {
#ifdef __GLIBC__
puts("__GLIBC__");
#endif
return 0;
}
and:
int main(void) {
#ifdef __GLIBC__
puts("__GLIBC__");
#endif
return 0;
}
but only the first produces output of course.
This must mean that __GLIBC__ comes from stdio.h which must include features.h, see also: What is the purpose of features.h header?
Therefore, strictly speaking, __GLIBC__ by itself is not a clear indication that glibc is used, since even without headers, GCC already embeds runtime objects such as crt1.o in the finale executable, and those come from glibc.
So the main missing question is: does glibc guarantee that features.h gets included by every header? I could not find a clear documentation quote. TODO.

#if defined(__GLIBC__) && !defined(__UCLIBC__) && !defined(__MUSL__)
This is getting a bit ugly and syntactically ambiguous, but useful.

Related

C++ define pthreads' function if that function is not declared

Apparently newer versions of ubuntu (22.04 onward) do not have the Pthreads function pthread_yield but instead they include sched_yield
So my solution is to include a .c file in my project with the following function:
#include <sched.h>
int pthread_yield(void) { return sched_yield(); }
This solves my problem under ubuntu 22.04, but what about other versions where pthread_yield exists?
I would like to define this function only if it is not present in pthreads, how can I do that?
Your problem here is the simplified "not present in pthreads". What exactly is " pthreads" ?
At the basic level, pthread_yield is not part of IEEE Std 1003 (POSIX) threads.
It is declared in the GNU implementation of <pthread.h>, conditional on _GNU_SOURCE.
The implementation used to be in GUN's implementation of libpthread, but it's being moved to GNU's implementation of libc in Ubuntu 22.
Instead of using fake-POSIX functions, it's much cleaner to use the sched_yield function. It's been present for ages.
With the new comment, it sounds like you have another alternative. Linux traditionally has a library link order that's more predictable than C++ mandates.
In particular, C++ says that violating the One Definition Rule is Undefined Behavior, but ld will usually pick the first occurrence of a symbol. So just add your .o after -lpthread.
There are more complicated tricks with weak symbols but that shouldn't be necessary here.

Does clang provide an unlink implementation?

I am trying to compile a library using clang. The library makes calls to 'unlink', which is not defined by clang:
libmv/src/third_party/OpenExif/src/ExifImageFileWrite.cpp:162:17: error: use of undeclared identifier 'unlink'; did you mean 'inline'?
unlink( mTmpImageFile.c_str() ) ;
My question is, what is the clang equivalent of unlink? As I see it, the path forward would be to #define unlink somewhere with an equivalent routine.
There is no "Clang equivalent". Neither GCC nor Clang have ever been responsible for defining unlink, though they do probably distribute the POSIX headers which do (I don't recall specifically where POSIX headers come from).
Unfortunately, this appears to be a bug with the library you're using; the OpenExif developers failed to include the correct headers. Different C++ implementations may internally #include various headers for their own purposes, which has apparently masked this bug on your previous toolchain.
You can hack your copy and/or submit a patch to add:
#include <unistd.h>

Upgrading from C++98 to C++11 causes error

I am using QT Creator to make a C++ program on Ubuntu. The program I had written was compiling fine, until I decided to start using C++11 rather than C++98 (which is the default in QT Creator). I am using my own cmake file, rather than qmake, and so to do this, I included the following line in my CMakeLists.txt file:
set(CMAKE_CXX_FLAGS "-std=c++0x")
Now, part of my code has the following (which was not written by me):
#if (linux && (i386 || __x86_64__))
# include "Linux-x86/OniPlatformLinux-x86.h"
#elif (linux && __arm__)
# include "Linux-Arm/OniPlatformLinux-Arm.h"
#else
# error Unsupported Platform!
#endif
After transferring to C++11, I get an error at the line error Unsupported Platform!. This is because, from what I can see, the variable linux is not defined anywhere, although the variable __x86_64__ is defined.
Therefore, I have two questions:
1) Why is the variable linux not defined, even though I am using Linux?
2) How can I tell C++11 to ignore this error?
Thanks.
The identifier linux is not reserved. A conforming compiler may not predefine it as a macro. For example, this program:
int main() {
int linux = 0;
return linux;
}
is perfectly valid, and a conforming compiler must accept it. Predefining linux causes the declaration to be a syntax error.
Some older compilers (including the compiler you were using, with the options you were giving it) predefine certain symbols to provide information about the target platform -- including linux to indicate a Linux system. This convention goes back to early C compilers, written before there was a distinction between reserved and unreserved identifiers.
The identifier __linux__, since it starts with two underscores, is reserved for use by the implementation, so compilers are allowed to predefine it -- and compilers for Linux systems typically do predefine it as a macro expanding to 1.
Confirm that your compiler predefines __linux__, and then change your code so it tests __linux__ rather than linux. You should also find out what reserved symbol is used instead of i386 (likely __i386__).
Related: Why does the C preprocessor interpret the word "linux" as the constant "1"?
Change your standard-selection flag to -std=gnu++0x instead of c++0x. The gnu flavors provide some non-standard extensions, apparently including predefining the macro linux. Alternatively, check for __linux__ instead.

ImageMagick pthread.h multiple definition

When trying to compile more recent versions of ImageMagick (v6.8.7-2 or later, v6.8.7-1 is fine), I get a bunch of:
CCLD magick/libMagickCore-6.Q16.la
magick/.libs/magick_libMagickCore_6_Q16_la-animate.o: In function `__pthread_cleanup_routine':
/usr/include/pthread.h:581: multiple definition of `__pthread_cleanup_routine'
magick/.libs/magick_libMagickCore_6_Q16_la-accelerate.o:/usr/include/pthread.h:581: first defined here
magick/.libs/magick_libMagickCore_6_Q16_la-annotate.o: In function `__pthread_cleanup_routine':
/usr/include/pthread.h:581: multiple definition of `__pthread_cleanup_routine'
magick/.libs/magick_libMagickCore_6_Q16_la-accelerate.o:/usr/include/pthread.h:581: first defined here
magick/.libs/magick_libMagickCore_6_Q16_la-artifact.o: In function `__pthread_cleanup_routine':
/usr/include/pthread.h:581: multiple definition of `__pthread_cleanup_routine'
magick/.libs/magick_libMagickCore_6_Q16_la-accelerate.o:/usr/include/pthread.h:581: first defined here
magick/.libs/magick_libMagickCore_6_Q16_la-attribute.o: In function `__pthread_cleanup_routine':
/usr/include/pthread.h:581: multiple definition of `__pthread_cleanup_routine'
magick/.libs/magick_libMagickCore_6_Q16_la-accelerate.o:/usr/include/pthread.h:581: first defined here
... goes on for quite a bit longer, all the same.
The pertinent area of /usr/include/pthread.h (from glibc-headers 2.5-118.el5_10.2) is:
/* Function called to call the cleanup handler. As an extern inline
function the compiler is free to decide inlining the change when
needed or fall back on the copy which must exist somewhere else. */
extern __inline void
__pthread_cleanup_routine (struct __pthread_cleanup_frame *__frame)
{
if (__frame->__do_it) // <======= this is :581
__frame->__cancel_routine (__frame->__cancel_arg);
}
I've been posting on ImageMagick's forum without response.
Even if you can't say exactly what's happening, how do I start figuring out whether the issue is with ImageMagick or pthread.h? Where do I go from there?
grep pthread_cleanup_routine -r * only shows matches against the binary object files -- none of ImageMagick's source code has pthread_cleanup_routine in it. A few of the sources include "pthread.h" of course.
That's leading me to believe that this is a glibc issue, not an ImageMagick issue... but, again, previous versions of ImageMagick compile just fine. (I have diff'ed the svn sources between versions where it broke. Lots of configuration/makefile changes, but nothing sticks out to me as to why it would cause this.)
I'm on CentOS 5, kernel 2.6.18-308.24.1.el5, gcc v4.9.0, ld v2.24, glibc-headers 2.5-118.el5_10.2
I've seen a lot of people posting similar issues with other packages than ImageMagick. Hopefully others will find this useful.
Changing pthread.h, just before __pthread_cleanup_routine :
extern __inline void
to
if __STDC__VERSION__ < 199901L
extern
#endif
__inline void
Fixes the issue. Older versions of glibc had an issue when -fexceptions was used, and inline non-C99 conformance (see http://gcc.gnu.org/ml/gcc-patches/2006-11/msg01030.html.) More recent glibc's would fix the issue too, but this should be a temp fix for those who don't want to / shouldn't upgrade it.
ImageMagick svn 13539 (which later became v6.8.7-2) began using -fexceptions.
I faced this error with a newer gcc compiler (4.9.3)
The ImageMagick(6.8.9_7) configure script was checking if compiler supports gnu99 standard. If yes, the configure script sets standard to gnu99 and also enables openmp.
Inline semantics change with C standard gnu99 causing multiple definition of the extern inline function
https://gcc.gnu.org/onlinedocs/gcc-4.9.3/gcc/Inline.html#Inline.
So, I added compiler flag -fgnu89-inline to use older semantics for inline and it fixed the issue.

How can I know what OS I'm working in?

I need a function that can clear the screen in both Linux and Windows. To do this, I want to know if there are some instructions that can tell me what operating system I'm working with.
I have searched for solution and I found the following code:
void clear_screen()
{
#ifdef WINDOWS
std::system ( "CLS" );
#else
// Assume POSIX
std::system("clear");
#endif
}
There are two problems with this function:
I don't understand it.
-> for #ifdef WINDOWS, where is WINDOWS defined?
This code works in Linux but it doesn't work in Windows.
Note :
I'm using Windows XP.
I don't want any non-standard functionality ... such "curses"
Macros such as _WIN32, __gnu_linux__, __linux__ are defined by the compiler in question. You can find a comprehensive list of pre-defined compiler macros here.
_WIN32 is defined for both 32-bit and 64-bit environments of Windows.
You're looking for
// Windows, all variants (including 64-bit and ARM)
#ifdef _WIN32
or
#ifdef __unix__
These are defined by your compiler, and are not stored in a header file. Because of that, you don't need to #include a file first, and these #ifdefs will always give the correct result (unless you mess with the compiler)
WINDOWS is defined by your compiler, so this defines can be compiler-dependant. It's usefull in order to compile specific code depending on your OS.
There are various compiler-dependant macros. Unfortunately, they are not particularly useful, because they are not standardized and a C compiler for a particular OS does not necessarily #define them. I also suspect that they actually violate the C standard C11 7.1.3.
The 100% portable solution, which will compile on all C compilers, is to create such a constant yourself. Since C is a compiled language, you will have to compile your code differently for each OS anyhow. Simply add a file called os.c where you put a relevant #define or constant, then link this to your program. The only thing you need to change when compiling for a different OS is the make file path to your OS-specific os.c.