checking whether library exist via preprocessor - c

There are two libraries zconf.h and unistd.h which are used to at least to get pid of the process. I generally test my code on Mac OSX and Ubuntu 18.04 in which they use zconf.h preferably(compiler offers zconf.h in lieu of unistd.h) if I forget to add, then if the code works, it's ok. However, in some prior day I needed to test the code in another machine AFAIR it has Ubuntu 10 or 12. Its compiler complained that there is no zconf.h. I wonder whether there is a way to check a machine has zconf.h, if not, use unistd.h. Can it be done using preprocessors like,
#ifdef ITS_IF_CONDITION
#include <zconf.h>
#else
#include <unistd.h>

Newer versions of GCC, clang and MSVC compilers implement the __has_include feature. Although it's a C++ 17 feature, I believe all three support it in plain C too.
But the traditional (and probably more portable) way is to check the existence of include files in a config script before the build process. Both autoconf and cmake have ways to achieve this.
#ifdef __has_include
#if __has_include(<zconf.h>)
#include <zconf.h>
#else
#include <unistd.h>
#endif
#else
#include <unistd.h>
#endif

Related

gcc for ARM refuses to include Newlib standard directories

I am trying to cross-compile with arm-none-eabi-gcc-9.2.x and had the following problem:
undefined symbol 'PRIu64'
(message shortened to necessary minimum by me) which was caused by the Newlib header inttypes.h doing a:
#include <stdint.h>
which motivated gcc to include its onboard stdint.h from
/usr/lib/gcc/arm-none-eabi/9.2.1/include
instead of the Newlib one in
/usr/include/newlib
thereby breaking the compilation with the above error.
Of course I first tried to prefix the include path search with the usual
arm-none-eabi-gcc-9.2.1 -I/usr/include/newlib ...
but to my big surprise gcc spew it back at me (via -xc -E -v) with:
ignoring duplicate directory "/usr/include/newlib"
as it is a non-system directory that duplicates a system directory
Only a
arm-none-eabi-gcc-9.2.1 -isystem /usr/include/newlib ...
convinced it to include the Newlib directory in its search.
Is this due to a broken installation? And how dare gcc to not include a path I am supplying?
Do the ARM people ship their gcc with both, Newlib and a set of vanilla gcc system headers or where did this misconfiguration come from?
Indeed, newlib provides <stdint.h> while gcc also provides it. So, when <inttypes.h> includes <stdint.h> it does not include <stdint.h> from newlib but the one from gcc. It wouldn't be a big deal if <stdint.h> wouldn't define some macro used internally by <inttypes.h>.
The best thing to do is to fix newlib, change your compiler or patch your system headers.
If it is not possible you can include <sys/types.h> before <inttypes.h>. <sys/types.h> includes <_stdint.h> that define the necessary macros.
It seems the problem is specific to arm-none-gcc provided by Debian:
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=953844

unknown type name 'siginfo_t' with Clang using _POSIX_C_SOURCE 2, why?

Update Turnes out my lecturer will accept code written to the GNU99 standard, so, as User1 pointed out, I used _GNU_SOURCE at the beginning of my program. (See man feature_test_macros for more info.) Thanks for helping me understand!
On Ubuntu 13.10 with Clang 3.4, GCC 4.8.1, I am doing an assignment which requires me to use the C99 standard. (I also have GNUstep installed from SVN)
WRT GCC, I think I have 4 versions installed in these folders:
/usr/lib/gcc/x86_64-linux-gnu/4.7
/usr/lib/gcc/x86_64-linux-gnu/4.7.3
/usr/lib/gcc/x86_64-linux-gnu/4.8
/usr/lib/gcc/x86_64-linux-gnu/4.8.1
gcc --version reports 4.8.1, clang --version reports 3.4. ld -v reports 2.23.52.20130913
I'm writing a signal handler and when I use siginfo_t in my function header, I get a compiler error: unknown type name 'siginfo_t' I'm using sigaction() to install the handler.
While studying what needs to be done and how, I was able to compile a simple demo which also uses the same function header definition, and it works. However it's not limited to C99.
These are my includes (of which signal.h is one):
#define _POSIX_C_SOURCE 2
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <math.h>
#include <ctype.h>
#include <libgen.h>
#include <signal.h>
This is my signal handler function (only for debugging purposes):
static void sigSIGCHLDhandler(int sigNum, siginfo_t *siginfo, void *context) {
printf("PID = %ld",(long) siginfo->si_pid);
}
I am compiling with clang using -Wall and -std=c99 now -std=gnu99options.
I have tried locate signal.h and I have it in /usr/include. I tried adding #include <bits/siginfo.h> and that allowed me to compile, but the binary wouldn't work correctly.
(I have a bunch of signal.h and siginfo.h files on my system.)
Another student suggested that there is something wrong with my set up. So I've reinstalled Clang. Here are some of my environment variables that I think might be relevant (please notify me of any missing or wrong)
LD_LIBRARY_PATH=/home/user/ros_catkin_ws/install_isolated/lib:/home/user/GNUstep/Library/Libraries:/usr/local/lib
CPATH=/home/user/ros_catkin_ws/install_isolated/include
PATH=/home/user/ros_catkin_ws/install_isolated/bin:/home/user/GNUstep/Tools:/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/user/bin:/usr/local/java/jdk1.7.0_51/bin
CLASSPATH=/home/user/GNUstep/Library/Libraries/Java:/usr/local/lib/GNUstep/Libraries/Java
LIBRARY_COMBO=gnu-gnu-gnu
INFOPATH=/usr/local/share/info::/home/user/GNUstep/Library/Documentation/info:
GNUSTEP_IS_FLATTENED=yes
GNUSTEP_LOCAL_ROOT=/usr/local/Local
GNUSTEP_HOST=x86_64-unknown-linux-gnu
GUILE_LOAD_PATH=/home/user/GNUstep/Library/Libraries/Guile:/usr/local/lib/GNUstep/Libraries/Guile
GNUSTEP_MAKEFILES=/usr/local/share/GNUstep/Makefiles
GNUSTEP_NETWORK_ROOT=/usr/local/Network
GNUSTEP_FLATTENED=yes
GNUSTEP_HOST_OS=linux-gnu
GNUSTEP_HOST_VENDOR=unknown
GNUSTEP_HOST_CPU=x86_64
GNUSTEP_USER_ROOT=/home/user/GNUstep
GNUSTEP_SYSTEM_ROOT=/usr/local/System
GNUSTEP_PATHLIST=/usr/local/System:/usr/local/Network:/usr/local/Local:/home/user/GNUstep
GNUSTEP_SYSTEM_ROOT=/usr/local/System
GNUSTEP_PATHLIST=/usr/local/System:/usr/local/Network:/usr/local/Local:/home/nap/GNUstep
I've spent hours searching for a fix but can't find anything, and I'm out of ideas.
What is broken?
If you look the man page of sigaction(2), you will find the following:
siginfo_t: _POSIX_C_SOURCE >= 199309L
Try adding the compiler option: -D_POSIX_C_SOURCE=199309L
It tells the required posix version to your c-lib (glibc).
EDIT:
See more about those from POSIX wiki page.
featuers.h tells more about how glibc use the define:
_POSIX_C_SOURCE
If ==1, like _POSIX_SOURCE;
if >=2 add IEEE Std 1003.2;
if >=199309L, add IEEE Std 1003.1b-1993;
if >=199506L, add IEEE Std 1003.1c-1995;
if >=200112L, all of IEEE 1003.1-2004
Similar information also in man page: feature_test_macros(7).
So: _POSIX_C_SOURCE=2 does not bring latest POSIX features for available, because 1003.2 (posix 2) is not the latest one. For getting more features available you need to define later version.
Don't get confused: POSIX.2 is not newer than POSIX.1c.

What modern C compiler can I use to build this 1992 MS-DOS program?

I was given the source code to modify an MS-DOS program built back in 1992. I have the EXE file and it runs fine, but I need to modify the source code. The source code needs the below headers to compile.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <dos.h>
#include <dir.h>
#include <alloc.h>
#include <ctype.h>
#include <string.h>
#include <mem.h>
#include <values.h>
Does anyone know what was used and are there any modern compilers that can handle this? I tried with Visual Studio 2010 and GCC "out of the box", but it fails because some headers are missing (dir.h, alloc.h, mem.h, values.h)
It might be more interesting to ask what what function declarations, type declarations, global variable declarations and macros it needs to have. The particular arrangement of those things into headers isn't very interesting as long as they are all there.
So comment out the offending #includes and let the compiler complain about the bits it is missing. Then you know what you're looking for.
You could try the Open Watcom compiler, which is one of the few relatively up-to-date compilers that builds 16-bit DOS executables. Other than finding an old MS or Borland compiler (or whatever was originally used), that's probably the easiest route.
If you want to rebuild for a different platform instead of rebuilding for DOS again, you'll likely have to make a lot of changes to the program itself. That may be worthwhile, but may be a lot of work and have a lot of surprise headaches.
There's Turbo C++ 1.01, not so modern, though, that appears to have all these header files as well. I still occasionally use it.
You might try using DJGPP. According to the documentation, it may have the headers you need.
a) Remove all the header files
b) Try a compile
c) Look up which header file the undefined function/type is int
d) Add the header file
e) repeat

Determining whether compiling on Windows or other system

I'm currently developing a cross-platform C application.
Is there any compiler macro which is defined only during compilation on Windows, so I can #ifdef some Windows specific #includes?
Typical example is selecting between WinSock and Berkeley sockets headers:
#ifdef _WINDOWS
#include <winsock.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <netdb.h>
#endif
So the thing I'm looking for is something like that _WINDOWS macro.
Your best bet is to use
_WIN32
It is guaranteed to be defined when compiling for a 32-bit or 64-bit Windows platform using the Visual C++ compiler. I would expect other compilers for Windows to define it as well (the Intel C++ compiler defines it, as does the MinGW gcc).
Use _WIN32.
Reference:
Microsoft C++ Predefined Macros
GCC Predefined Macros
How to get predefined macros for OS X (or just check for __APPLE__)
_WIN32
Defined for applications for Win32 and Win64. Always defined.
_WIN64
Defined for applications for Win64.
Source : Lists the predefined ANSI C and Microsoft C++ implementation macros.

Link User32 with gcc

I have a C program which has a function call that is defined in windows.h (which I have included), however, when I try and compile it with gcc, I get the error:
warning: implicit declaration of function `LockWorkStation'
I looked at the MSDN documentation and I see that this function is the User32 library file, and I was wondering how I would go about linking that to my file.
LockWorkstation is available on Windows 2000 and up. You have to declare the version of Windows you are targeting. Make it look like this:
#define _WIN32_WINNT 0x500
#include <windows.h>
I have the same problem with gcc - but this is not a linker error. The message means that there is no prototype for the function in winuser.h, or more accurately the compiler can't find such a prototype. That is because the relevant bit of winuser.h looks like this:
#if (_WIN32_WINNT >= 0x0500)
WINUSERAPI BOOL WINAPI LockWorkStation(void);
#endif
In other words, you need a version of Windows >= 5 (i.e Win2K) to use this function. I'm currently trying this on Win2K and it doesn't work, which indicates the macro is not being set correctly. I don't do much "real" Windows programming these days, so I'm not sure why that should be.
Edit: In fact, a bit of experiment indicates that gcc thinks the Windows version of Win2K (on my installation at least) is 0x0400.
Further: Actually, the macro _WIN32_WINNT is (as the leading underscore suggests) a reserved name in C and C++, and should not be defined in user code. Defining the macro WINVER seems to have the same effect, and is (conceptually at least) more portable. This code compiles on my gcc installation:
#define WINVER 0x0500
#include <windows.h>
int main() {
LockWorkStation();
}

Resources