#! /bin/sh # Copyright (C) 2012 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # Stress test on Objective C/C++. required=libtoolize am_create_testdir=empty . ./defs || exit 1 ## Autotools Input Files. cat > configure.ac << 'END' AC_INIT([play], [1.3], [bug-automake@gnu.org]) dnl Support for Object C++ was introduced only in Autoconf 2.65. AC_PREREQ([2.65]) AC_CONFIG_SRCDIR([play.c]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE AM_PROG_AR LT_INIT AC_PROG_CC AC_PROG_CXX AC_PROG_OBJC AC_PROG_OBJCXX AC_LANG_PUSH([Objective C]) AC_CACHE_CHECK( [whether the Objective C compiler really works], [my_cv_objc_works], [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#import ]], [[printf ("foo\n");]])], [my_cv_objc_works=yes], [my_cv_objc_works=no])]) AC_LANG_POP([Objective C]) AC_LANG_PUSH([Objective C++]) AC_CACHE_CHECK( [whether the Objective C++ compiler really works], [my_cv_objcxx_works], [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#import ]], [[std::cout << "foo" << "\n";]])], [my_cv_objcxx_works=yes], [my_cv_objcxx_works=no])]) AC_LANG_POP([Objective C++]) if test $my_cv_objc_works != yes; then AC_MSG_ERROR([couldn't find a working Objective C compiler], [77]) fi if test $my_cv_objcxx_works != yes; then AC_MSG_ERROR([couldn't find a working Objective C++ compiler], [77]) fi AC_CONFIG_HEADERS([config.h]) AC_CONFIG_FILES([Makefile]) AC_OUTPUT END cat > Makefile.am << 'END' bin_PROGRAMS = play play_SOURCES = play.h play.c playxx.cxx playo.m playoxx.mm play_LDADD = libfoo.la play_LDFLAGS = -lobjc lib_LTLIBRARIES = libfoo.la libfoo_la_SOURCES = foo.h foo.c fooxx.cxx fooo.m foooxx.mm END ## Run Autotools. libtoolize if $ACLOCAL; then : We have a modern enough autoconf, go ahead. elif test $? -eq 63; then skip_ "Object C++ support requires Autoconf 2.65 or later" else exit 1 # Some other aclocal failure. fi $AUTOHEADER $AUTOCONF $AUTOMAKE --add-missing ## Program Sources. cat > play.h << 'END' #ifndef PLAY_H #define PLAY_H #include "foo.h" #ifdef __cplusplus extern "C" { #endif void hello_cxx (void); void hello_objc (void); void hello_objcxx (void); #ifdef __OBJC__ @interface Hello_ObjC { } + (void)display; @end #endif /* __OBJC__ */ #ifdef __cplusplus } class Hello_CXX { public: Hello_CXX() { } virtual ~Hello_CXX () { } void hello_cxx (); }; #ifdef __OBJC__ @interface Hello_ObjCXX { } + (void)display; @end class Hello_OBJCXX { public: Hello_OBJCXX () { } virtual ~Hello_OBJCXX () { } void hello_objcxx(); }; #endif /* __OBJC__ */ #endif /* __cplusplus */ #endif /* PLAY_H */ END cat > play.c << 'END' #include "play.h" int main (void) { printf ("[Hello C,"); world_c (); hello_cxx (); hello_objc (); hello_objcxx (); return 0; } END cat > playxx.cxx << 'END' #include "play.h" void hello_cxx(void) { Hello_CXX *hello = new Hello_CXX; hello->hello_cxx(); } void Hello_CXX::hello_cxx() { std::cout << "[Hello C++,"; World_CXX *world = new World_CXX; world->world_cxx(); } END cat > playo.m << 'END' #import "play.h" void hello_objc (void) { [Hello_ObjC display]; } @implementation Hello_ObjC + (void)display { printf ("[Hello ObjC,"); [World_ObjC display]; } @end END cat > playoxx.mm << 'END' #import "play.h" // Calling: C -> C++ -> ObjC void hello_objcxx (void) { Hello_OBJCXX *hello = new Hello_OBJCXX; hello->hello_objcxx (); } void Hello_OBJCXX::hello_objcxx () { [Hello_ObjCXX display]; } @implementation Hello_ObjCXX + (void)display { std::cout << "[Hello ObjC++,"; [World_ObjCXX display]; } @end END ## Library Sources. cat > foo.h << 'END' #ifndef FOO_H #define FOO_H #ifdef __cplusplus #include extern "C" { #else #include #endif void world_c (void); #ifdef __OBJC__ @interface World_ObjC { } + (void)display; @end #endif /* __OBJC__ */ #ifdef __cplusplus } class World_CXX { public: World_CXX() { } virtual ~World_CXX () { } void world_cxx (); }; #ifdef __OBJC__ class World_OBJCXX { public: World_OBJCXX () { } virtual ~World_OBJCXX () { } void world_objcxx (); }; @interface World_ObjCXX { } + (void)display; @end #endif /* __OBJC__ */ #endif /* __cplusplus */ #endif /* FOO_H */ END cat > foo.c << 'END' #include "foo.h" void world_c (void) { printf (" world C]\n"); } END cat > fooxx.cxx << 'END' #include "foo.h" void World_CXX::world_cxx () { std::cout << " world C++]" << "\n"; } END cat > fooo.m << 'END' #import "foo.h" @implementation World_ObjC + (void)display { printf (" world ObjC]\n"); } @end END cat > foooxx.mm << 'END' #import "foo.h" // Calling: ObjC -> C++ @implementation World_ObjCXX + (void)display { World_OBJCXX *world = new World_OBJCXX; world->world_objcxx (); } @end void World_OBJCXX::world_objcxx () { std::cout << " world ObjC++]" << "\n"; } END ## Configure and build. ./configure $MAKE if ! cross_compiling; then unindent > exp << 'END' [Hello C, world C] [Hello C++, world C++] [Hello ObjC, world ObjC] [Hello ObjC++, world ObjC++] END ./play > got || { cat got; exit 1; } cat exp cat got diff exp got fi $MAKE distcheck :