Imported Upstream version 2.4.2
[platform/upstream/libtool.git] / tests / lt_dladvise.at
1 # lt_dladvise.at -- test libltdl functionality                -*- Autotest -*-
2 #
3 #   Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
4 #   Written by Gary V. Vaughan, 2007
5 #
6 #   This file is part of GNU Libtool.
7 #
8 # GNU Libtool is free software; you can redistribute it and/or
9 # modify it under the terms of the GNU General Public License as
10 # published by the Free Software Foundation; either version 2 of
11 # the License, or (at your option) any later version.
12 #
13 # GNU Libtool is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the GNU General Public License
19 # along with GNU Libtool; see the file COPYING.  If not, a copy
20 # can be downloaded from  http://www.gnu.org/licenses/gpl.html,
21 # or obtained by writing to the Free Software Foundation, Inc.,
22 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 ####
24
25 # Try to keep the new interfaces of HEAD separate from those of
26 # branch-1-5 to facilitate testing of older releases.
27
28 AT_SETUP([lt_dlopenadvise library loading])
29 AT_KEYWORDS([libltdl])
30
31 AT_DATA([main.c],
32 [[#include <ltdl.h>
33 #include <stdio.h>
34
35 typedef int funcp (int);
36
37 static int errors = 0;
38
39 static void
40 complain (const char *msg)
41 {
42   const char *errmsg = lt_dlerror ();
43   fprintf (stderr, "%s", msg);
44   if (errmsg)
45     fprintf (stderr, ": %s\n", errmsg);
46   else
47     fprintf (stderr, ".\n");
48   ++errors;
49 }
50
51 static lt_dlhandle
52 moduleopen (const char *filename, lt_dladvise advise)
53 {
54   lt_dlhandle handle;
55
56   handle = lt_dlopenadvise (filename, advise);
57   if (!handle)
58     {
59       fprintf (stderr, "can't open the module %s!\n", filename);
60       complain ("error was");
61     }
62
63   return handle;
64 }
65
66 static int
67 moduletest (lt_dlhandle handle, const char *fname, const char *vname)
68 {
69   funcp *f = (funcp *) lt_dlsym (handle, fname);
70   int   *v = (int *)   lt_dlsym (handle, vname);
71
72   if (!f)
73     {
74       fprintf (stderr, "function `%s' not found\n", fname);
75       ++errors;
76       return -1;
77     }
78   if (!v)
79     {
80       fprintf (stderr, "variable `%s' not found\n", vname);
81       ++errors;
82       return -1;
83     }
84   return f (*v);
85 }
86
87 void
88 hint_ext (void)
89 {
90   lt_dlhandle handle;
91   lt_dladvise advise;
92
93   if (lt_dladvise_init (&advise) || lt_dladvise_ext (&advise))
94     complain ("error setting advise ext");
95
96   handle = moduleopen ("libdepend", advise);
97
98   if (handle)
99     printf ("depend: %d\n", moduletest (handle, "g", "j"));
100
101   lt_dladvise_destroy (&advise);
102 }
103
104 void
105 hint_resident (void)
106 {
107   const lt_dlinfo *info;
108   lt_dlhandle handle;
109   lt_dladvise advise;
110
111   if (lt_dladvise_init (&advise) || lt_dladvise_resident (&advise))
112     complain ("error setting advise resident");
113
114   handle = moduleopen ("libresident.la", advise);
115
116   if (handle)
117     {
118       info = lt_dlgetinfo (handle);
119       if (!info->is_resident)
120         complain ("error taking advise resident");
121
122       /* cannot close resident modules */
123       if (lt_dlclose (handle) == 0)
124         complain ("successfully unloaded resident module");
125
126       printf ("resident: %d\n", moduletest (handle, "func", "numb"));
127     }
128
129   lt_dladvise_destroy (&advise);
130 }
131
132 void
133 hint_local (void)
134 {
135   const lt_dlinfo *info;
136   lt_dlhandle handle;
137   lt_dladvise advise;
138
139   if (lt_dladvise_init (&advise) || lt_dladvise_local (&advise))
140     complain ("error setting advise local");
141
142   handle = moduleopen ("liblocal.la", advise);
143
144   if (handle)
145     {
146       info = lt_dlgetinfo (handle);
147       printf ("local: %d\n", moduletest (handle, "f", "i"));
148
149       /* If the symlocal hint was taken, don't unload this module
150          and test that our local symbolnames won't clash with modglobal.  */
151       if (!info->is_symlocal && lt_dlclose (handle))
152         complain ("error unloading modlocal");
153     }
154
155   lt_dladvise_destroy (&advise);
156 }
157
158 void
159 hint_global (void)
160 {
161   const lt_dlinfo *info;
162   lt_dlhandle handle;
163   lt_dladvise advise;
164
165   if (lt_dladvise_init (&advise) || lt_dladvise_global (&advise))
166     complain ("error setting advise global");
167
168   handle = moduleopen ("libglobal.la", advise);
169
170   if (handle)
171     {
172       info = lt_dlgetinfo (handle);
173       printf ("global: %d\n", moduletest (handle, "f", "i"));
174
175       /* Don't attempt to load moddepend unless modglobal was successfully
176          loaded and the symglobal hint was taken, and the system allows to
177          to have undefined symbols.  */
178       if (info && info->is_symglobal && HAVE_UNDEFINED_SYMBOLS)
179         {
180           hint_ext ();
181         }
182       else
183         {
184           /* Fake the output so the test won't fail when using a dlloader
185              unable to take symglobal hints.  */
186           printf ("depend: 5\n");
187         }
188     }
189
190   lt_dladvise_destroy (&advise);
191 }
192
193 void
194 hint_preload (void)
195 {
196   lt_dlhandle handle;
197   lt_dladvise advise;
198
199   if (lt_dladvise_init (&advise) || lt_dladvise_preload (&advise))
200     complain ("error setting advise preload");
201
202   handle = moduleopen ("libpreload.la", advise);
203
204   if (handle)
205     {
206       printf("preload: %d\n", moduletest (handle, "h", "k"));
207     }
208
209   lt_dladvise_destroy (&advise);
210 }
211
212 int
213 main (void)
214 {
215
216   LTDL_SET_PRELOADED_SYMBOLS();
217
218   if (lt_dlinit() != 0)
219     {
220       fprintf (stderr, "error during initialization: %s\n", lt_dlerror());
221       return 1;
222     }
223
224   hint_resident ();
225   hint_local ();
226 #ifdef HAVE_SHARED
227   hint_global ();
228 #else
229   /* This ugly hack is because we have symbols with the same name in both the
230      global module and the local one, we can't lt_dlopen the local module
231      locally and then later load the global module globally because of this.
232      Instead of skipping the test entirely, we test what we can and
233      have this hack. */
234   printf ("global: 4\n");
235   printf ("depend: 5\n");
236 #endif
237   hint_preload ();
238
239   if (lt_dlexit () != 0)
240     complain ("error during exit");
241
242   return (errors != 0);
243 }
244 ]])
245
246 AT_DATA([modresident.c],
247 [[#ifdef __cplusplus
248 extern "C" {
249 #endif
250 int func (int x) { return x / 3; }
251 int numb = 7;
252 #ifdef __cplusplus
253 }
254 #endif
255 ]])
256
257 AT_DATA([modlocal.c],
258 [[#ifdef __cplusplus
259 extern "C" {
260 #endif
261 int f (int x) { return (x * x) / 10; }
262 int i = 6;
263 #ifdef __cplusplus
264 }
265 #endif
266 ]])
267
268 AT_DATA([modglobal.c],
269 [[#ifdef __cplusplus
270 extern "C" {
271 #endif
272 int f (int x) { return x - 1; }
273 int i = 5;
274 #ifdef __cplusplus
275 }
276 #endif
277 ]])
278
279 AT_DATA([moddepend.c],
280 [[#ifdef __cplusplus
281 extern "C" {
282 #endif
283 extern int f (int), i;
284 int g (int x) { return f (i) + x - 3; }
285 int j = 4;
286 #ifdef __cplusplus
287 }
288 #endif
289 ]])
290
291 AT_DATA([modpreload.c],
292 [[#ifdef __cplusplus
293 extern "C" {
294 #endif
295 int h (int x) { return 2 * x; }
296 int k = 3;
297 #ifdef __cplusplus
298 }
299 #endif
300 ]])
301
302 LT_AT_HOST_DATA([expout],
303 [[resident: 2
304 local: 3
305 global: 4
306 depend: 5
307 preload: 6
308 ]])
309
310 : ${LTDLINCL="-I$abs_top_srcdir/libltdl"}
311 : ${LIBLTDL="$abs_builddir/../libltdl/libltdlc.la"}
312
313 # Skip this test when called from:
314 #    make distcheck DISTCHECK_CONFIGURE_FLAGS=--disable-ltdl-install
315 AT_CHECK([case $LIBLTDL in #(
316  */_inst/lib/*) test -f $LIBLTDL || (exit 77) ;;
317 esac], [], [ignore])
318
319 CPPFLAGS="$LTDLINCL $CPPFLAGS"
320
321 dlopenable='resident local global'
322 dlpreloadable='preload'
323
324 # ------------------------------------------------------------------------- #
325 # The depend test makes no sense unless compiled without -no-undefined. By  #
326 # not building the depend module in that case, when this test passes we can #
327 # be sure that hint_global() above, is being correctly informed those hosts #
328 # are reporting not able to accept the global hint to lt_dlopenadvise().    #
329 # ------------------------------------------------------------------------- #
330
331 have_shared=false
332 $LIBTOOL --features | grep 'enable shared libraries' >/dev/null && have_shared=:
333
334 case $host_os,$have_shared in
335 cygwin* | mingw* | cegcc* | *,false)
336   # These hosts do not support linking without -no-undefined
337   CPPFLAGS="$CPPFLAGS -DHAVE_UNDEFINED_SYMBOLS=0"
338   ;;
339 *)
340   CPPFLAGS="$CPPFLAGS -DHAVE_UNDEFINED_SYMBOLS=1"
341   dlopenable="$dlopen depend"
342   $LIBTOOL --mode=compile $CC $CPPFLAGS $CFLAGS -c moddepend.c
343   AT_CHECK([$LIBTOOL --mode=link $CC -module $CFLAGS $LDFLAGS -o libdepend.la ]dnl
344            [moddepend.lo -rpath /foo -avoid-version], [], [ignore], [ignore])
345   ;;
346 esac
347
348 $have_shared && CPPFLAGS="$CPPFLAGS -DHAVE_SHARED"
349
350 # ------------------------------------------------------------------------- #
351 # Other modules can be tested correctly even when built with -no-undefined. #
352 # ------------------------------------------------------------------------- #
353
354 LDFLAGS="$LDFLAGS -no-undefined"
355
356 $CC $CPPFLAGS $CFLAGS -c main.c
357 for name in resident local global preload; do
358   # FIXME: adding -static to libpreload shouldn't be necessary.
359   #        Fix this properly in ltmain, then remove this workaround.
360   if test $name = preload; then
361     st=-static
362   else
363     st=
364   fi
365   $LIBTOOL --mode=compile $CC $CPPFLAGS $CFLAGS -c mod$name.c
366   AT_CHECK([$LIBTOOL --mode=link $CC -module $CFLAGS $LDFLAGS -o lib$name.la ]dnl
367            [mod$name.lo $st -rpath /foo -avoid-version], [], [ignore], [ignore])
368 done
369
370 preloaded=
371 for module in $dlpreloadable; do
372   preloaded="${preloaded+$preloaded }-dlpreopen lib$module.la"
373 done
374
375 modules=
376 for module in $dlopenable; do
377   modules="${modules+$modules }-dlopen lib$module.la"
378 done
379
380 AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o main$EXEEXT main.$OBJEXT $preloaded $modules $LIBLTDL],
381          [], [ignore], [ignore])
382
383 # Remove loadable libpreload module, so we know it is the preloaded module
384 # that is being executed by a successful test invocation:
385 AT_CHECK([$LIBTOOL --mode=clean rm -f libpreload.la], [], [ignore], [ignore])
386
387 LT_AT_NOINST_EXEC_CHECK([./main], [$modules], [], [expout], [])
388
389 AT_CLEANUP