Subject: FAQ: C compiler and the Linux C library
From: HJ Lu <[email-masked]>
Date: 26 Mar 1993 01:12:37 GMT
Newsgroups: comp.os.linux.announce

QUESTION: What compiler should I use for Linux?

ANSWER: You should only use the same version on tsx-11.mit.edu under
/pub/linux/GCC. If you want to use the testing release, first join
the GCC channel on the Linux mailing list, and then send a note to
[email-masked]. Don't use gcc older than the one on tsx-11.mit.edu.

QUESTION: Where is the latest official gcc 2.xx for Linux?

ANSWER: It's on tsx-11.mit.edu under /pub/Linux/GCC and under
pub/linux/GCC. You may find it on the other sites. Since gcc 2.3.3,
you can compile it yourself out of box from any gnu ftp sites. Just
unpack the source code and do

	configure [i386-linux|i486-linux]

You should follow the instructions in INSTALL.

QUESTION: Where is the latest official Linux C library?

ANSWER: It's on tsx-11.mit.edu under /pub/Linux/GCC and under
pub/linux/GCC. You may find it on the other sites.

QUESTION: What are the contents of them?

ANSWER: Please read the current release note and ChangeLog for
details.

QUESTION: How do I install them?

ANSWER: Read README and release notes.

QUESTION: What are the main differences with the old release?

ANSWER: Read README and release notes.

QUESTION: Can I use the old version of gcc?

ANSWER: Please get rid of gcc older than gcc 2.2.2. Starting from
gcc 2.2.2, you can do

	gcc -V xxxx

where xxxx is the version number. Please read `release.xxxx' for
detail. There is one catch in gcc 2.2.2d, setjmp/longjmp is changed,
so the old header files is not compatible with gcc 2.2.2. Before you
install gcc 2.2.2d, please do

cp /usr/include/setjmp.h /usr/lib/gcc-lib/i386-linux/2.2.2/include

where /usr/include/setjmp.h is come with gcc 2.2.2.

QUESTION: Can I delete the old shared image in /lib?

ANSWER: Since the Linux C library version 4.3, we have introduced the
dynamically linked library. There is no need to keep old shared images
in /lib if none of your binaries are linked with the classic shared
library which has been obsolete. You can just keep one version of
the shared image in /lib which has the highest major and minor
release numbers for each shared library. The name of the shared image
is "xxxxxxxxxxxxxxx.so.major.minor".

QUESTION: Is stdio ANSI compatible?

ANSWER: Yes, please test it.

QUESTION: Is g++ in 2.xx?

ANSWER: Yes.

QUESTION: Where can I get the gcc manual?

ANSWER: You can get man pages and manual come with the gcc source code
on any gnu ftp sites. You should find gcc-man.tar.z on tsx-11 which
has man pages for gcc.

QUESTION: What options can I use for gcc?

ANSWER: Read the manual. There is one special flag for Linux, -static
tells gcc to use the static libraries. The default is the jump table
version of shared libraries.

QUESTION: How can I debug the C code?

ANSWER: Read the gcc/gdb manuals. The simple way to do is

	gcc -g foo foo.c
	gdb foo

QUESTION: Where is the source code of the new libc.a?

ANSWER: The same place you find this file. It is called
libc-xx.yy.tar.z.

QUESTION: Why does g++ complain, even die?

ANSWER: You need "expr", which is in GNU shell utilities 1.6, echo (?)
and sed.

QUESTION: How do I generate code for 486?

ANSWER: Add -m486 to CFLAGS.

QUESTION: I heard malloc (0) wouldn't work with Linux, what should I
do?

ANSWER: It *does* work in a manner which POSIX allows; unfortunately,
pre-POSIX code frequently assumes that malloc(0) will not return
0 -- the standard version of malloc under Linux *does* return 0.
By including <stdlib.h>, you get a definition of malloc which behaves
more traditionally.  If you define NO_FIX_MALLOC, then you will get
the default (non-traditional) form.  If you are trying to develop POSIX
compliant code under Linux, you should probably define NO_FIX_MALLOC to
ensure that your code doesn't make assumptions about malloc() which
will not work on other systems.  (Note: NO_FIX_MALLOC is specific to
Linux.)

(Provided by [email-masked]. Thanks.)

QUESTION: Why does gcc say "xxxxx..h not found"?

ANSWER: see QUESTION: What are the contents of them?

QUESTION: I really followed every step in the documentation, but when
I do "make", why does it say "don't how to make xxxxxx"?

ANSWER: The dependency in Makefile is dated, you need to make a new
one. Please get some guide on make and read Makefile. For the kernel
sources, please do

cd src/linux
make dep

QUESTION: How do I compile programs under Linux?

ANSWER: The Linux C library is trying to be ANSI/POSIX compliant. It
is also very compatible with SYSV and BSD. The C library is loaded
with SYSV and BSD functions. There are three exceptions:

1. signal in Linux is POSIX.
2. tty in Linux is POSIX.
3. time functions are POSIX, plus a few BSD and SYSV extensions.
4. setjmp/longjmp functions are POSIX. But you can use -D__FAVOR_BSD
   to make it BSD or use sigsigjmp/siglongjmp.

When you compile a program under Linux, your best bet is include all
the appropriate header files and use -Wall. All the usable functions
and global variables are declared in the corresponding header files.
YOU SHOULD NOT DEFINE ANY functions or global variables OF THE LINUX C
LIBRARY IN YOUR CODE IF YOU WANT TO USE THE SHARED LIBRARIES.

After saying all those, you now should know you can compile a program
with -D_POSIX_SOURCE or -D_GNU_SOURCE (read <features.h> for details).
With a few modifications you can even use -DSYSV, -DUSG or -DBSD. Some
codes need to define -DSTDC_HEADERS for ANSI C compiler like gcc here.

To use malloc () and calloc () safely under Linux, please include

<stdlib.h> and don't define NO_FIX_MALLOC.

BTW, gcc -traditional should work with gcc 2.2.2d or above.

Please also read ChangeLog for the latest enhancement.

Please read the header files for details. Maybe you should get a book
on POSIX. Any suggestion of the book list?

>From Steve Robbins  --  [email-masked]

--------
I like "POSIX Programmer's Guide", by Donald Lewine.  Its essentially
a list of POSIX functions' man pages, with a very brief guide in the
beginning of a few things.  It's published by O'Reilly & Associates,
Inc.
--------

QUESTION: How can I get bsd style signal?

ANSWER: Use -D__USE_BSD_SIGNAL.

QUESTION: Why does a program that should only poll for input become
a CPU hog?

ANSWER: The select() system call. The timeout parameter was classically
used read-only by the system. Some manual pages already notes three
years ago:

       select() should probably return the  time  remaining  from
       the  original timeout, if any, by modifying the time value
       in place.  This may be implemented in future  versions  of
       the system.  Thus, it is unwise to assume that the timeout
       pointer will be unmodified by the select() call.

If you do not take this advice seriously you get a zero timeout written
back to your timeout structure, which means that future calls to
select() using the same timeout structure will immediately return.

Fix:
Put the timeout value into that structure every time you call select().
Change code like

       struct timeval timeout;
       timeout.tv_sec = 1; timeout.tv_usec = 0;
       while (some_condition)
         { select(n,readfds,writefds,exceptfds,&timeout); }

to

       struct timeval timeout;
       while (some_condition)
         { timeout.tv_sec = 1; timeout.tv_usec = 0;
           select(n,readfds,writefds,exceptfds,&timeout);
         }

QUESTION: When a program is stopped using Ctrl-Z and then restarted,
or in other situations that generate signals: Ctrl-C interruption,
termination of a child process etc. why does it complain about
"interrupted system call" or "write: unknown error" or things like that.

ANSWER: The system call the program was executing has been interrupted
to process the signal, and then it returned -1 and set errno = EINTR.
The program then was likely to draw bad conclusions from that.

Explanation: Your program has signal handlers installed, using
signal() or sigaction(). When the signal occurred, your signal handler
was invoked. In other Unix systems, this usually happens asynchronously
or in a few slow system calls:

  When a signal is caught during the execution of system calls such as
  read(2), write(2), open(2) or ioctl(2) on a slow device (such as a
  terminal, but not a file), during a pause(2) system call or a wait(2)
  system call that does not return immediately because a previously
  stopped or zombie process already exists, the signal-catching
  function is executed and the interrupted system call then returns a
  -1 to the calling process with errno set to EINTR.

Linux (following POSIX) checks for signals and may execute signal
handlers
* asynchronously (at a timer tick),
* on return from *any* system call,
* during the execution of the following system calls:
  select(),
  pause(),
  connect(), accept(),
  read() on terminals or sockets or pipes or /proc files,
  write() on terminals or sockets or pipes or line printer,
  open() on FIFOs or PTYs or serial lines,
  ioctl() on terminals,
  fcntl() with command F_SETLKW,
  wait4(),
  syslog(),
  any TCP or NFS operations.
  [For other operating systems you may have to include the system calls
   creat(), close(), getmsg(), putmsg(), msgrcv(), msgsnd(), recv(),
   send(), wait(), waitpid(), wait3(), tcdrain(), sigpause(), semop()
   to this list.]

In the last two cases and assuming the program's signal handler returns,
the system call returns -1 and sets errno to EINTR.

If the SA_INTERRUPT flag is not set for the corresponding signal,
however, in most cases the system call is automatically restarted
(continued) after execution of the signal handler, and your program
won't see any EINTR.

You may ask why this is not the default behavior when the default
Linux signal () is used to install the signal handler. This is because
POSIX adopted this. As for which one is better, it is a matter of
opinion.

Note that in some versions of BSD Unix the default behavior is to
restart system calls. To get system calls interrupted you have to use
the SA_INTERRUPT flag.

Fix:
Either add -D__USE_BSD_SIGNAL to your CFLAGS. Or for every signal
handler that you install with signal(), use sigaction() instead,
without setting SA_INTERRUPT.

Note that while this applies to most system calls, you must still check
for EINTR on read(), write(), ioctl(), select(), pause(), connect().
You may do it like this:

         int result;
         while (len > 0)
           { result = read(fd,buffer,len);
             if (result < 0) break;
             buffer += result; len -= result;
           }
   -->
         int result;
         while (len > 0)
           { result = read(fd,buffer,len);
             if (result < 0) { if (errno != EINTR) break; }
             else { buffer += result; len -= result; }
           }

and

         int result;
         result = ioctl(fd,cmd,addr);
   -->
         int result;
         do { result = ioctl(fd,cmd,addr); }
            while ((result == -1) && (errno == EINTR));

--------------
H.J.
[email-masked]
03/25/93

-- 
Send submissions for comp.os.linux.announce to: [email-masked]