]> err.no Git - sope/blob - gnustep-make/which_lib.c
fixed mapping of 'method' attribute
[sope] / gnustep-make / which_lib.c
1 /*
2    which_lib.c
3    Copyright (C) 1997, 2001, 2002 Free Software Foundation, Inc.
4
5    Author: Nicola Pero <nicola@brainstorm.co.uk>
6    Date: January 2002
7
8    Based on the original which_lib.c by Ovidiu Predescu,
9    Author: Ovidiu Predescu <ovidiu@net-community.com>
10    Date: October 1997
11
12    This file is part of the GNUstep Makefile Package.
13
14    This library is free software; you can redistribute it and/or
15    modify it under the terms of the GNU General Public License
16    as published by the Free Software Foundation; either version 2
17    of the License, or (at your option) any later version.
18
19    You should have received a copy of the GNU General Public
20    License along with this library; see the file COPYING.LIB.
21    If not, write to the Free Software Foundation,
22    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
23
24 /*
25   
26   Command line arguments are:
27
28   * a list of library search paths in the GCC notation, as in 
29     -L/usr/lib/opt/hack/
30     -L/usr/GNUstep/Local/Library/Libraries/ix86/linux-gnu/gnu-gnu-gnu
31     -L/usr/GNUstep/System/Library/Libraries/ix86/linux-gnu/gnu-gnu-gnu
32     (order is important, paths are searched in the order they are listed);
33
34   * a list of libraries in the GCC notation, as in
35     -lgnustep-base -lgnustep-gui -lobjc
36
37   * flags specifying whether a debug, profile, static/shared library is
38     to be preferred, as in 
39     debug=no profile=yes shared=yes
40
41   The tool outputs the same list of library search paths and the list
42   of libraries it received in input, with an important modification:
43   each library name is modified to match the available version of the
44   library (by appending nothing for a normal library, _d for a debug
45   version of the library, _p for a profile one, _s for a static one,
46   and the various combinations, _dp, _ds, _ps, _dps) -- giving
47   preference to libraries matching the specified debug, profile,
48   shared library flags.  For example, if a debug=yes profile=no
49   shared=yes is specified, and libgnustep-base_d.so is in the library
50   search path, which_lib will replace -lgnustep-base with
51   -lgnustep-base_d in the output.
52
53   Here is exactly how the search is performed:
54
55   The tool first searches into the list of directories for a library
56   exactly matching the name and the type required.  If found, it's
57   used.
58
59   If none is found, the library looks for an approximate match, as
60   detailed in the following list.  Each search in the following list
61   is performed on the list of directories, and uses the shared flags
62   as specified.
63
64   If (debug=yes and profile=yes), the tool looks for a debug=yes
65   profile=no, then a debug=no profile=yes.
66
67   If (debug=yes and profile=no), the tool looks for a debug=no
68   profile=no.
69
70   If (debug=no and profile=yes), the tool looks for a debug=no
71   profile=no.
72
73   If (debug=no and profile=no), the tool looks for a debug=yes
74   profile=no.
75
76   If none is still found and shared=yes, the tool looks for any
77   available shared library with that name (regardless of wheter it's
78   debug/profile/nothing).
79
80   If none is still found, the tool looks for any available static
81   library with that name (regardless of any debug/profile/shared
82   flag).
83
84   If still not found, the tool outputs the unmodified library name (as
85   in -lgnustep-base) ... perhaps the library is somewhere else in the
86   linker path ... otherwise that will normally result in a linker
87   error later on.
88
89 */
90
91 #include "config.h"
92
93 #include <stdio.h>
94
95 #if HAVE_SYS_TYPES_H
96 # include <sys/types.h>
97 #endif
98
99 #if HAVE_STDLIB_H
100 # include <stdlib.h>
101 #endif
102
103 #if HAVE_STRING_H
104 # include <string.h>
105 #endif
106
107 #if HAVE_SYS_STAT_H
108 # include <sys/stat.h>
109 #endif
110
111 #include <fcntl.h>
112
113 #if HAVE_DIRENT_H
114 # include <dirent.h>
115 #else
116 # define dirent direct
117 # if HAVE_SYS_NDIR_H
118 #  include <sys/ndir.h>
119 # endif
120 # if HAVE_SYS_DIR_H
121 #  include <sys/dir.h>
122 # endif
123 # if HAVE_NDIR_H
124 #  include <ndir.h>
125 # endif
126 #endif
127
128
129 /* determine filesystem max path length */
130
131 # include <limits.h>                    /* for PATH_MAX */
132
133 #ifdef _POSIX_VERSION
134 # include <utime.h>
135 #else
136 # if HAVE_SYS_PARAM_H
137 #  include <sys/param.h>                /* for MAXPATHLEN */
138 # endif
139 #endif
140
141 #ifndef PATH_MAX
142 # ifdef _POSIX_VERSION
143 #  define PATH_MAX _POSIX_PATH_MAX
144 # else
145 #  ifdef MAXPATHLEN
146 #   define PATH_MAX MAXPATHLEN
147 #  else
148 #   define PATH_MAX 1024
149 #  endif
150 # endif
151 #endif
152
153 #if HAVE_SYS_FILE_H
154 #include <sys/file.h>
155 #endif
156
157 /* Extension used for shared and non-shared libraries.  */
158 char* libext = ".a";
159 char* shared_libext = ".so";
160
161 /* If set to 1, all code will print out information about what it
162    does.  */
163 int show_all = 0;
164
165 /* Strips off carriage returns, newlines and spaces at the end of the
166    string. (this removes some \r\n issues on Windows)  */
167 static void stripstr (unsigned char *s)
168 {
169   unsigned len;
170   
171   if (s == NULL)
172     {
173       return;
174     }
175   
176   len = strlen (s);
177   
178   while (len > 0) 
179     {
180       len--;
181       if (s[len] < 33) 
182         {
183           s[len] = '\0';
184         }
185     }
186 }
187
188 /* Normalize the directory, and checks that it exists on disk and is a
189    directory.  Return the normalized path, or NULL if the path does
190    not exist on disk, or is not a valid directory.  */
191 static char *normalize_and_check_dir (char *path)
192 {
193   int length = strlen (path);
194   char *normalized_path = NULL;
195   struct stat statbuf;
196   
197 #ifdef __MINGW32__
198   if (path[0] == '/'  &&  path[1] == '/')
199     {
200       /* Convert //server/ to a format Windows functions understand. */
201       char *s;
202
203       /* Convert //server/path/to/ --> server/path/to/ */
204       normalized_path = malloc (length * sizeof (char));
205       strcpy (normalized_path, &(path[2]));
206       
207       /* Convert server/path/to/ --> server:/path/to/ */
208       s = strchr (normalized_path, '/');
209       if (s)
210         {
211           /* The index of the '/' after 'server' in the original path.  */
212           int index = 2 + (s - normalized_path);
213
214           *s = ':';
215           strcpy (s + 1, &(path[index]));
216         }
217     }
218   else
219 #endif
220     {
221       normalized_path = malloc ((length + 1) * sizeof (char));
222       strcpy (normalized_path, path);
223     }
224     
225   /* Now check that the path exists and is a directory.  */
226   if (stat (normalized_path, &statbuf) < 0) 
227     /* Error occured or dir doesn't exist */
228     {
229       if (show_all)
230         {
231           fprintf (stderr, "Library path '%s' doesn't exist - ignored\n",
232                    normalized_path);
233         }
234       free (normalized_path);
235       return NULL;
236     }
237   else if ((statbuf.st_mode & S_IFMT) != S_IFDIR) 
238     /* Not a directory */
239     {
240       if (show_all)
241         {
242           fprintf (stderr, "Library path '%s' isn't a directory - ignored\n",
243                    normalized_path);
244         }
245       free (normalized_path);
246       return NULL;
247     }
248
249   stripstr (normalized_path);
250   return normalized_path;
251 }
252
253 /*  Search for a library with library_name, suffix suffix and
254     extension ext.
255
256     library_name must not contain the suffix, so library_name should
257     be something like 'gnustep-base'.  
258
259     suffix is the wanted suffix (valid suffixes are "", _d, _p, _s,
260     _ds, _dp, _ps, _dps).  Must not be NULL.
261
262     ext is the wanted extension (normally, either .so or .a).  Must
263     not be NULL.
264
265     Return 0 if it doesn't find anything matching.
266
267     Return 1 if a library with the appropriate suffix/extension/type
268     matches in 'path' and print to stdout the name of the library. */
269
270 static int search_for_lib_with_suffix_and_ext (const char *library_name, 
271                                                char **library_paths, 
272                                                int paths_no, 
273                                                char *suffix,
274                                                char *ext)
275 {
276   /* Iterate over the library_paths, looking for the library.  */
277   int i;
278
279   for (i = 0; i < paths_no; i++)
280     {
281       char full_filename[PATH_MAX + 1];
282       struct stat statbuf;
283       
284       strcpy (full_filename, library_paths[i]);
285       strcat (full_filename, "/lib");
286       strcat (full_filename, library_name);
287       strcat (full_filename, suffix);
288       strcat (full_filename, ext);
289       
290       if (show_all)
291         {
292           fprintf (stderr, " %s\n", full_filename);
293         }
294       
295       if (stat (full_filename, &statbuf) < 0)
296         /* Error - likely that file doesn't exist.  */
297         {
298           continue;
299         }
300       
301       if ((statbuf.st_mode & S_IFMT) == S_IFREG) 
302         /* Found it! */
303         { 
304           if (show_all)
305             {
306               fprintf (stderr, "  Found!\n");
307             }
308           printf (" -l%s", library_name);
309           if (*suffix)
310             {
311               printf ("%s", suffix);
312             }
313           return 1;
314         }
315     }
316
317   return 0;
318 }
319
320 /*  Search for a library with library_name, extension ext and any
321     valid suffix.
322
323     The same comments as for 'search_for_lib_with_suffix_and_ext' apply,
324     except that any valid suffix is accepted (valid suffixes are: "",
325     _d, _p, _s, _ds, _dp, _ps, _dps).
326 */
327
328 static int search_for_lib_with_ext (const char *library_name, 
329                                     int library_name_len,
330                                     char **library_paths, 
331                                     int paths_no, 
332                                     char *ext)
333 {
334   /* Iterate over the library_paths, looking for the library.  */
335   int i;
336   
337   for (i = 0; i < paths_no; i++)
338     {
339       DIR* dir;
340       struct dirent* dirbuf;
341       int found = 0;
342       
343       if (show_all)
344         {
345           fprintf (stderr, " %s/lib%s??%s\n", library_paths[i],
346                    library_name, ext);
347         }
348       
349       dir = opendir (library_paths[i]);
350       
351       if (dir == NULL)
352         {
353           /* For some reasons, we can't read that path.  Perhaps
354              someone removed the directory while we were running :-) */
355           continue;
356         }
357       
358       while ((dirbuf = readdir (dir))) 
359         {
360           /* Skip if it doesn't begin with 'lib'.  This implicitly
361              skips "." and ".." in case they are returned.  */
362           if (dirbuf->d_name[0] != 'l')
363             {
364               continue;
365             }
366           if (dirbuf->d_name[1] != 'i')
367             {
368               continue;
369             }
370           if (dirbuf->d_name[2] != 'b')
371             {
372               continue;
373             }
374           
375           /* Skip if it does not match the library name. */
376           if (strncmp (dirbuf->d_name + 3, library_name, library_name_len))
377             {
378               continue;
379             }
380           else
381             {
382               int filelen, extlen;
383               
384               filelen = strlen (dirbuf->d_name);
385               extlen = strlen (ext);
386               
387               if (filelen - extlen <= 0)
388                 {
389                   /* Quite worrying this case.  */
390                   continue;
391                 }
392               
393               if (show_all)
394                 {
395                   fprintf (stderr, "  Considering %s\n",  dirbuf->d_name);
396                 }
397               
398               /* First check if the extension matches */
399               if (strcmp (dirbuf->d_name + filelen - extlen, ext))
400                 {
401                   /* No luck, skip this file */
402                   continue;
403                 }
404               
405               /* The extension matches.  Check the last remaining bit
406                  - that the remaining string we have not checked is
407                  one of the allowed suffixes.  The allowed suffixes
408                  are: "", _d, _p, _s, _dp, _ds, _ps, _dps.  */
409               {
410                 char f_suffix[5];
411                 int j;
412                 int suffix_len = filelen - (3 /* 'lib' */
413                                             
414                                             + library_name_len 
415                                             /* library_name */
416                                             
417                                             + extlen /* .so/.a */);
418                 
419                 switch (suffix_len)
420                   {
421                     /* In the following cases, 'break' means found,
422                        'continue' means not found.  */
423                   case 0:
424                     {
425                       /* nothing - it's Ok.  */
426                       break;
427                     }
428                   case 1:
429                     {
430                       continue;
431                     }
432                   case 2:
433                     {
434                       /* Must be one of _d, _p, _s  */
435                       char c;
436                       
437                       if (dirbuf->d_name[3 + library_name_len] != '_')
438                         {
439                           continue;
440                         }
441                       
442                       c = dirbuf->d_name[3 + library_name_len + 1];
443                       if (c != 'd'  ||  c != 'p'  ||  c != 's')
444                         {
445                           continue;
446                         }
447                       break;
448                     }
449                   case 3:
450                     {
451                       /* Must be one of _dp, _ds, _ps  */
452                       char c, d;
453                       
454                       if (dirbuf->d_name[3 + library_name_len] != '_')
455                         {
456                           continue;
457                         }
458                       
459                       c = dirbuf->d_name[3 + library_name_len + 1];
460                       d = dirbuf->d_name[3 + library_name_len + 2];
461                       if ((c == 'd'  &&  (d == 'p'  ||  d == 's'))
462                           || (c == 'p'  &&  d == 's'))
463                         {
464                           break;
465                         }
466                       continue;
467                     }
468                   case 4:
469                     {
470                       if (dirbuf->d_name[3 + library_name_len] != '_')
471                         {
472                           continue;
473                         }
474                       if (dirbuf->d_name[3 + library_name_len] != 'd')
475                         {
476                           continue;
477                         }
478                       if (dirbuf->d_name[3 + library_name_len] != 'p')
479                         {
480                           continue;
481                         }
482                       if (dirbuf->d_name[3 + library_name_len] != 's')
483                         {
484                           continue;
485                         }
486                       break;
487                     }
488                   default:
489                     {
490                       continue;
491                     }
492                   }
493                 
494                 /* If we're here, it's because it was found!  */
495                 if (show_all)
496                   {
497                     fprintf (stderr, "   Found!\n");
498                   }
499                 
500                 for (j = 0; j < suffix_len; j++)
501                   {
502                     f_suffix[j] = dirbuf->d_name[library_name_len + 3 + j];
503                   }
504                 f_suffix[j] = '\0';
505                 printf (" -l%s%s", library_name, f_suffix);
506                 found = 1;
507                 break;
508               }
509             }
510         }
511       closedir (dir);
512       if (found)
513         {
514           return 1;
515         }
516     }
517
518   return 0;
519 }
520
521 /* Search for the library everywhere, and returns the library name.  */
522 static void output_library_name (const char *library_name, 
523                                  char** library_paths, int paths_no, 
524                                  int debug, int profile, int shared,
525                                  char *libname_suffix)
526 {
527   char *extension = shared ? shared_libext : libext;
528   int library_name_len = strlen (library_name);
529   
530   if (show_all)
531     {
532       fprintf (stderr, "\n>>Library %s:\n", library_name);
533     }
534   
535   /* We first perform the search of a matching library in all dirs.  */
536   if (show_all)
537     {
538       fprintf (stderr, "Scanning all paths for an exact match\n");
539     }
540   
541   if (search_for_lib_with_suffix_and_ext (library_name,
542                                           library_paths, paths_no, 
543                                           libname_suffix,
544                                           extension))
545     {
546       return;
547     }
548   
549   
550   /* The library was not found.  Try various approximations first,
551      slightly messing the original debug/profile requests, but still
552      honouring the shared=yes|no requirement.  */
553   if (show_all)
554     {
555       fprintf (stderr, "Scanning all paths for an approximate match\n");
556     }
557     
558   /* _dp case:  try _d, then _p  */
559   if (debug  &&  profile)
560     {
561       if (search_for_lib_with_suffix_and_ext (library_name, 
562                                               library_paths, paths_no, 
563                                               shared ? "_d" : "_ds", 
564                                               extension))
565         {
566           return;
567         }
568       
569       if (search_for_lib_with_suffix_and_ext (library_name, 
570                                               library_paths, paths_no, 
571                                               shared ? "_p" : "_ps", 
572                                               extension))
573         {
574           return;
575         }
576     }
577   
578   /* _d or _p: try nothing.  */
579   if ((debug  &&  !profile)  ||  (!debug  &&  profile))
580     {
581       if (search_for_lib_with_suffix_and_ext (library_name, 
582                                               library_paths, paths_no, 
583                                               shared ? "" : "_s", 
584                                               extension))
585         {
586           return;
587         }       
588     }
589   
590   /* nothing: try _d.  */
591   if (!debug  &&  !profile)
592     {
593       if (search_for_lib_with_suffix_and_ext (library_name, 
594                                               library_paths, paths_no, 
595                                               shared ? "_d" : "_ds", 
596                                               extension))
597         {
598           return;
599         }       
600     }
601
602   /* The library was still not found.  Try to get whatever library we
603      have there. */
604   
605   /* If a shared library is needed try to find a shared one first.
606      Any shared library is all right.  */
607   if (shared)
608     {
609       if (show_all)
610         {
611           fprintf (stderr, 
612                    "Scanning all paths for any shared lib with that name\n");
613         }
614       if (search_for_lib_with_ext (library_name, library_name_len, 
615                                    library_paths, paths_no, shared_libext))
616         {
617           return;
618         }
619     }
620   
621   /* Last hope - return a static library with name 'library_name'.
622      Any static library is all right.  */
623   if (show_all)
624     {
625       fprintf (stderr, 
626                "Scanning all paths for any static lib with that name\n");
627     }
628   if (search_for_lib_with_ext (library_name, library_name_len, 
629                                library_paths, paths_no, libext))
630     {
631       return;
632     }
633   
634   /* We couldn't locate the library.  Output the library name we were
635      given, without any modification.  Possibly it's somewhere else on
636      the linker path, otherwise (more likely) a linker error will
637      occur.  Nothing we can do about it.  */
638   if (show_all)
639     {
640       fprintf (stderr, "Library not found, using unmodified library name\n");
641     }
642   printf (" -l%s", library_name);
643   return;
644 }
645
646 int main (int argc, char** argv)
647 {
648   int i;
649
650   /* Type of libraries we prefer.  */
651   int debug = 0;
652   int profile = 0;
653   int shared = 1;
654
655   /* Suffix of the libraries we prefer - something like "" or "_d" or
656      "_dp" or "_ps" */
657   char libname_suffix[5];
658
659   /* Array of strings that are the library paths passed on the command
660      line.  If we are on Windows, we convert library paths to a format
661      that Windows functions understand before we save the paths in
662      library_paths, so that you could pass them to Windows functions
663      accessing the filesystem.  We also check that the paths actually
664      exist on disk, and are directories, before putting them in the
665      array.  */
666   int paths_no = 0;
667   char** library_paths = NULL;
668
669   /* The list of libraries */
670   int libraries_no = 0;
671   char** all_libraries = NULL;
672   
673   /* Other flags which are printed to the output as they are.  */
674   int other_flags_no = 0;
675   char** other_flags = NULL;
676
677
678   
679 #ifdef __WIN32__
680   setmode(1, O_BINARY);
681   setmode(2, O_BINARY);
682 #endif
683
684   if (argc == 1) 
685     {
686       printf ("usage: %s [-Lpath ...] -llibrary shared=yes|no debug=yes|no "
687               "profile=yes|no libext=string shared_libext=string "
688               "[show_all=yes]\n", argv[0]);
689       exit (1);
690     }
691
692   for (i = 1; i < argc; i++) 
693     {
694       /* First switch basing on the first letter of each argument,
695          then compare.  */
696       switch (argv[i][0])
697         {
698         case '-':
699           {
700             if (argv[i][1] == 'l')
701               {
702                 if (all_libraries)
703                   {
704                     all_libraries = realloc (all_libraries,
705                                              (libraries_no + 1) 
706                                              * sizeof (char*));
707                   }
708                 else
709                   {
710                     all_libraries = malloc ((libraries_no + 1) 
711                                             * sizeof (char*));
712                   }
713                 all_libraries[libraries_no] = malloc (strlen (argv[i]) - 1);
714                 strcpy (all_libraries[libraries_no], argv[i] + 2);
715                 stripstr (all_libraries[libraries_no]);
716                 libraries_no++;
717                 continue;
718               }
719             else if (argv[i][1] == 'L')
720               {
721                 char *lib_path = normalize_and_check_dir (argv[i] + 2);
722
723                 /* Always print out the library search path flag,
724                    regardless.  */
725                 printf (" %s", argv[i]);
726                 
727                 if (lib_path != NULL)
728                   {
729                     if (library_paths)
730                       {
731                         library_paths = realloc (library_paths, 
732                                                  (paths_no + 1) 
733                                                  * sizeof (char*));
734                       }
735                     else
736                       {
737                         library_paths = malloc ((paths_no + 1) 
738                                                 * sizeof(char*));
739                       }
740                     library_paths[paths_no] = lib_path;
741                     paths_no++;
742                   }
743                 continue;
744               }
745             break;
746           }
747         case 'd':
748           {
749             if (!strncmp (argv[i], "debug=", 6)) 
750               {
751                 debug = !strncmp (argv[i] + 6, "yes", 3);
752                 continue;
753               }
754             break;
755           }
756         case 'l':
757           {
758             if (!strncmp (argv[i], "libext=", 7)) 
759               {
760                 libext = malloc (strlen (argv[i] + 7) + 1);
761                 strcpy (libext, argv[i] + 7);
762                 continue;
763               }
764             break;
765           }
766         case 'p':
767           {
768             if (!strncmp (argv[i], "profile=", 8)) 
769               {
770                 profile = !strncmp (argv[i] + 8, "yes", 3);
771                 continue;
772               }
773             break;
774           }
775         case 's':
776           {
777             if (!strncmp (argv[i], "shared=", 7)) 
778               {
779                 shared = !strncmp (argv[i] + 7, "yes", 3);
780                 continue;
781               }
782             else if (!strncmp (argv[i], "shared_libext=", 14)) 
783               {
784                 shared_libext = malloc (strlen (argv[i] + 14) + 1);
785                 strcpy (shared_libext, argv[i] + 14);
786                 continue;
787               }
788             else if (!strncmp (argv[i], "show_all=", 9)) 
789               {
790                 show_all = !strncmp (argv[i] + 9, "yes", 3);
791                 continue;
792               }
793             break;
794           }
795         default:
796           break;
797         }
798       
799       /* The flag is something different; keep it in the `other_flags' */
800       if (other_flags)
801         {
802           other_flags = realloc (other_flags,
803                                  (other_flags_no + 1) * sizeof (char*));
804         }
805       else
806         {
807           other_flags = malloc ((other_flags_no + 1) * sizeof (char*));
808         }
809       other_flags[other_flags_no] = malloc (strlen (argv[i]) + 1);
810       strcpy (other_flags[other_flags_no], argv[i]);
811       other_flags_no++;
812     }
813
814   /* Determine the exact libname_suffix of the libraries we are
815      looking for.  */
816   libname_suffix[0] = '_';
817   libname_suffix[1] = '\0';
818   libname_suffix[2] = '\0';
819   libname_suffix[3] = '\0';
820   libname_suffix[4] = '\0';
821
822   i = 1;
823   
824   if (debug)
825     {
826       libname_suffix[i] = 'd';
827       i++;
828     }
829
830   if (profile)
831     {
832       libname_suffix[i] = 'p';
833       i++;
834     }
835
836   if (!shared)
837     {
838       libname_suffix[i] = 's';
839       i++;
840     }
841
842   if (i == 1)
843     {
844       libname_suffix[0] = '\0';
845     }
846
847   
848   if (show_all)
849     {
850       fprintf (stderr, ">>Input:\n");
851       fprintf (stderr, "shared = %d\n", shared);
852       fprintf (stderr, "debug = %d\n", debug);
853       fprintf (stderr, "profile = %d\n", profile);
854       fprintf (stderr, "libname_suffix = %s\n", libname_suffix);
855       fprintf (stderr, "libext = %s\n", libext);
856       fprintf (stderr, "shared_libext = %s\n", shared_libext);
857
858       fprintf (stderr, "library names:\n");
859       for (i = 0; i < libraries_no; i++)
860         {
861           fprintf (stderr, "    %s\n", all_libraries[i]);
862         }
863       
864       fprintf (stderr, "library paths:\n");
865       for (i = 0; i < paths_no; i++)
866         {
867           fprintf (stderr, "    %s\n", library_paths[i]);
868         }
869       
870       fprintf (stderr, "other flags:\n");
871       for (i = 0; i < other_flags_no; i++)
872         {
873           fprintf (stderr, "    %s\n", other_flags[i]);
874         }
875     }
876
877   /* Now output the libraries.  */
878   for (i = 0; i < libraries_no; i++) 
879     {
880       /* Search for the library, and print (using -l%s) the library
881          name to standard output.  */
882       output_library_name (all_libraries[i], library_paths, 
883                            paths_no, debug, profile, shared, libname_suffix);
884     }
885   
886   /* Output the other flags */
887   for (i = 0; i < other_flags_no; i++)
888     {
889       printf (" %s", other_flags[i]);
890     }
891
892   printf (" ");
893
894   return 0;
895 }