Straighten out issues about who calls C++ initializers with CXXTEST or HELLOXX are built as NSH applications; Add an ofstream test to CXXTEST suggested by Michael; Update many defconfig fiels to that they set configurations to handle C++ constructors just as before these configuration changes

This commit is contained in:
Gregory Nutt 2013-06-21 09:32:57 -06:00
parent 1ac7315ca6
commit da19214ca7
8 changed files with 167 additions and 35 deletions

View File

@ -579,3 +579,15 @@
(2013-6-12).
6.29 2013-xx-xx Gregory Nutt <gnutt@nuttx.org>
* apps/examples/nsh, cxxtest, and helloxx: C++ initializers should be
set once and, preferably, in the context of the task that uses any C++
statically initialized classes. These only becomes an issue is cxxtest
or helloxx are built as NSH builtin applications. Then you want the
initialization done in cxxtext or helloxx and not in NSH (and certainly
not twice). Added configuration options to control who does the C++
initialization. NSH now does not do C++ initialization be default and
must be configured to do otherwise. Converserly, cxxtest and helloxx
will do C++ initialization unless configured do otherwise (2013-6-21).
* apps/examples/cxxtext: Add ostream test as provided by Michael
(2013-6-21).

View File

@ -256,14 +256,6 @@ examples/cxxtest
is not included in the NuttX source tree by default, but must be installed
(see misc/uClibc++/README.txt for installation).
The NuttX setting that are required include:
CONFIG_HAVE_CXX=y
CONFIG_HAVE_CXXINITIALIZE=y
CONFIG_UCLIBCXX=y
Additional uClibc++ settings may be required in your build environment.
The uClibc++ test includes simple test of:
- iostreams,
@ -271,6 +263,25 @@ examples/cxxtest
- RTTI, and
- Exceptions
Example Configuration Options
-----------------------------
CONFIG_EXAMPLES_CXXTEST=y - Eanbles the example
CONFIG_EXAMPLES_CXXTEST_CXXINITIALIZE=y - By default, if CONFIG_HAVE_CXX
and CONFIG_HAVE_CXXINITIALIZE are defined, then this example
will call the NuttX function to initialize static C++ constructors.
This option may be disabled, however, if that static initialization
was performed elsewhere.
Other Required Configuration Settings
-------------------------------------
Other NuttX setting that are required include:
CONFIG_HAVE_CXX=y
CONFIG_HAVE_CXXINITIALIZE=y
CONFIG_UCLIBCXX=y
Additional uClibc++ settings may be required in your build environment.
examples/dhcpd
^^^^^^^^^^^^^^
@ -539,6 +550,11 @@ examples/helloxx
"built-in" that can be executed from the NSH command line.
CONFIG_EXAMPLES_HELLOXX_NOSTACKCONST - Set if the system does not
support construction of objects on the stack.
CONFIG_EXAMPLES_HELLOXX_CXXINITIALIZE - By default, if CONFIG_HAVE_CXX
and CONFIG_HAVE_CXXINITIALIZE are defined, then this example
will call the NuttX function to initialize static C++ constructors.
This option may be disabled, however, if that static initialization
was performed elsewhere.
Also needed:
@ -742,17 +758,23 @@ examples/nrf24l01_term
examples/nsh
^^^^^^^^^^^^
Basic Configuration
-------------------
This directory provides an example of how to configure and use
the NuttShell (NSH) application. NSH is a simple shell
application. NSH is described in its own README located at
apps/nshlib/README.txt
apps/nshlib/README.txt. This function is enabled with:
CONFIG_EXAMPLES_NSH=y
Applications using this example will need to provide an defconfig
file in the configuration directory with instruction to build
applicationslike:
the NSH library like:
CONFIG_NSH_LIBRARY=y
Other Configuration Requirements
--------------------------------
NOTE: If the NSH serial console is used, then following is also
required to build the readline() library:
@ -779,6 +801,16 @@ examples/nsh
CONFIG_STDIO_BUFFER_SIZE - Some value >= 64
CONFIG_STDIO_LINEBUFFER=y
C++ Support
-----------
If CONFIG_HAVE_CXX=y and CONFIG_HAVE_CXXINITIALIZE=y, then this NSH
example can be configured to initialize C++ constructors when it
is started. NSH does not use C++ and, by default, assumes that
constructors are initialized elsewhere. However, you can force
NSH to initialize constructors by setting:
CONFIG_EXAMPLES_NSH_CXXINITIALIZE=y
examples/nx
^^^^^^^^^^^

View File

@ -11,4 +11,15 @@ config EXAMPLES_CXXTEST
Enable the C++ test program
if EXAMPLES_CXXTEST
config EXAMPLES_CXXTEST_CXXINITIALIZE
bool "C++ Initialization"
default y
depends on HAVE_CXX && HAVE_CXXINITIALIZE
---help---
By default, if CONFIG_HAVE_CXX and CONFIG_HAVE_CXXINITIALIZE are
defined, then this example will call the NuttX function to
initialize static C++ constructors. This option may be disabled,
however, if that static initialization was preformed elsewhere.
endif

View File

@ -41,6 +41,8 @@
#include <nuttx/init.h>
#include <nuttx/arch.h>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <vector>
#include <map>
@ -52,6 +54,13 @@ using namespace std;
//***************************************************************************
// Definitions
//***************************************************************************
// Configuration ************************************************************
// C++ initialization requires CXX initializer support
#if !defined(CONFIG_HAVE_CXX) || !defined(CONFIG_HAVE_CXXINITIALIZE)
# warning Support for static initializers is NOT enabled
# undef CONFIG_EXAMPLES_CXXTEST_CXXINITIALIZE
#endif
//***************************************************************************
// Private Classes
@ -68,7 +77,7 @@ class Extend : public Base
public:
void printExtend(void)
{
cout << "extend" << endl;
std::cout << "extend" << std::endl;
}
};
@ -80,27 +89,56 @@ public:
// Public Functions
//***************************************************************************
//***************************************************************************
// Name: test_ostream
//***************************************************************************/
static void test_ofstream(void)
{
std::ofstream ttyOut;
std::cout << "test ofstream===========================" << std::endl;
std::printf("printf: Starting test_ostream\n");
ttyOut.open ("/dev/console");
if (!ttyOut.good())
{
std::printf("printf: Failed opening /dev/console\n");
std::cout << "cout: Failed opening /dev/console" << std::endl;
std::cout << " good()=" << ttyOut.good();
std::cout << " eof()=" << ttyOut.eof();
std::cout << " fail()=" << ttyOut.fail();
std::cout << " bad()=" << ttyOut.bad() << std::endl;
}
else
{
std::printf("printf: Successfully opened /dev/console\n");
std::cout << "cout: Successfully opened /dev/console" << std::endl;
ttyOut << "Writing this to /dev/console\n";
ttyOut.close();
}
}
//***************************************************************************
// Name: test_iostream
//***************************************************************************/
static void test_iostream(void)
{
cout << "test iostream===========================" << endl;
cout << "Hello, this is only a test" << endl;
cout << "Print an int: " << 190 << endl;
cout << "Print a char: " << 'd' << endl;
std::cout << "test iostream===========================" << std::endl;
std::cout << "Hello, this is only a test" << std::endl;
std::cout << "Print an int: " << 190 << std::endl;
std::cout << "Print a char: " << 'd' << std::endl;
#if 0
int a;
string s;
cout << "Please type in an int:" << endl;
cin >> a;
cout << "You type in: " << a << endl;
cout << "Please type in a string:" << endl;
cin >> s;
cout << "You type in: " << s << endl;
std::cout << "Please type in an int:" << std::endl;
std::cin >> a;
std::cout << "You type in: " << a << std::endl;
std::cout << "Please type in a string:" << std::endl;
std::cin >> s;
std::cout << "You type in: " << s << std::endl;
#endif
}
@ -110,7 +148,7 @@ static void test_iostream(void)
static void test_stl(void)
{
cout << "test vector=============================" << endl;
std::cout << "test vector=============================" << std::endl;
vector<int> v1;
assert(v1.empty());
@ -126,7 +164,7 @@ static void test_stl(void)
v1.pop_back();
assert(v1.size() == 3);
cout << "v1=" << v1[0] << ' ' << v1[1] << ' ' << v1[2] << endl;
std::cout << "v1=" << v1[0] << ' ' << v1[1] << ' ' << v1[2] << std::endl;
assert(v1[2] == 3);
vector<int> v2 = v1;
@ -137,13 +175,13 @@ static void test_stl(void)
vector<string>::iterator it;
for (it = v3.begin(); it != v3.end(); it++)
{
cout << *it << ' ';
std::cout << *it << ' ';
}
cout << endl;
std::cout << std::endl;
assert(v3[1] == "World");
cout << "test map================================" << endl;
std::cout << "test map================================" << std::endl;
map<int,string> m1;
m1[12] = "Hello";
@ -158,7 +196,7 @@ static void test_stl(void)
static void test_rtti(void)
{
cout << "test rtti===============================" << endl;
std::cout << "test rtti===============================" << std::endl;
Base *a = new Base();
Base *b = new Extend();
assert(a);
@ -182,7 +220,7 @@ static void test_rtti(void)
#ifdef CONFIG_UCLIBCXX_EXCEPTION
static void test_exception(void)
{
cout << "test exception==========================" << endl;
std::cout << "test exception==========================" << std::endl;
try
{
throw runtime_error("runtime error");
@ -190,7 +228,7 @@ static void test_exception(void)
catch (runtime_error &e)
{
cout << "Catch exception: " << e.what() << endl;
std::cout << "Catch exception: " << e.what() << std::endl;
}
}
#endif
@ -210,10 +248,11 @@ extern "C"
// If C++ initialization for static constructors is supported, then do
// that first
#ifdef CONFIG_HAVE_CXXINITIALIZE
#ifdef CONFIG_EXAMPLES_CXXTEST_CXXINITIALIZE
up_cxxinitialize();
#endif
test_ofstream();
test_iostream();
test_stl();
test_rtti();

View File

@ -10,4 +10,15 @@ config EXAMPLES_HELLOXX
Enable the \"Hello, World!\" C++ example
if EXAMPLES_HELLOXX
config EXAMPLES_HELLOXX_CXXINITIALIZE
bool "C++ Initialization"
default y
depends on HAVE_CXX && HAVE_CXXINITIALIZE
---help---
By default, if CONFIG_HAVE_CXX and CONFIG_HAVE_CXXINITIALIZE are
defined, then this example will call the NuttX function to
initialize static C++ constructors. This option may be disabled,
however, if that static initialization was preformed elsewhere.
endif

View File

@ -48,6 +48,13 @@
//***************************************************************************
// Definitions
//***************************************************************************
// Configuration ************************************************************
// C++ initialization requires CXX initializer support
#if !defined(CONFIG_HAVE_CXX) || !defined(CONFIG_HAVE_CXXINITIALIZE)
# undef CONFIG_EXAMPLES_HELLOXX_CXXINITIALIZE
#endif
// Debug ********************************************************************
// Non-standard debug that may be enabled just for testing the constructors
@ -135,7 +142,7 @@ extern "C"
// If C++ initialization for static constructors is supported, then do
// that first
#ifdef CONFIG_HAVE_CXXINITIALIZE
#ifdef CONFIG_EXAMPLES_HELLOXX_CXXINITIALIZE
up_cxxinitialize();
#endif

View File

@ -12,4 +12,16 @@ config EXAMPLES_NSH
Enable the NuttShell (NSH) example
if EXAMPLES_NSH
config EXAMPLES_NSH_CXXINITIALIZE
bool "C++ Initialization"
default n
depends on HAVE_CXX && HAVE_CXXINITIALIZE
---help---
If HAVE_CXX and HAVE_CXXINITIALIZE are slected, then this NSH
example can be configured to initialize C++ constructors when it
is started. NSH does not use C++ and, by default, assumes that
constructors are initialized elsewhere. However, you can force
NSH to initialize constructors by setting this option.
endif

View File

@ -46,11 +46,13 @@
#include <errno.h>
#include <nuttx/arch.h>
#if defined(CONFIG_FS_BINFS) && (CONFIG_BUILTIN)
#include <nuttx/binfmt/builtin.h>
# include <nuttx/binfmt/builtin.h>
#endif
#if defined(CONFIG_LIBC_EXECFUNCS) && defined(CONFIG_EXECFUNCS_SYMTAB)
#include <nuttx/binfmt/symtab.h>
# include <nuttx/binfmt/symtab.h>
#endif
#include <apps/nsh.h>
@ -59,6 +61,12 @@
* Pre-processor Definitions
****************************************************************************/
/* C++ initialization requires CXX initializer support */
#if !defined(CONFIG_HAVE_CXX) || !defined(CONFIG_HAVE_CXXINITIALIZE)
# undef CONFIG_EXAMPLES_NSH_CXXINITIALIZE
#endif
/* The NSH telnet console requires networking support (and TCP/IP) */
#ifndef CONFIG_NET
@ -115,11 +123,11 @@ int nsh_main(int argc, char *argv[])
/* Call all C++ static constructors */
#if defined(CONFIG_HAVE_CXX) && defined(CONFIG_HAVE_CXXINITIALIZE)
#if defined(CONFIG_EXAMPLES_NSH_CXXINITIALIZE)
up_cxxinitialize();
#endif
/* Make sure that we are using our symbol take */
/* Make sure that we are using our symbol table */
#if defined(CONFIG_LIBC_EXECFUNCS) && defined(CONFIG_EXECFUNCS_SYMTAB)
exec_setsymtab(CONFIG_EXECFUNCS_SYMTAB, 0);