Sorry about the big code dump. I tried to get it down to the minimum
required to demonstrate the problem. Although this is all done with GNU, I
believe the problem I'm having may be more general. Someone on the SuSE
programming mailing list suggested my problem is that I'm trying to execute
a function (I assume he meant the constructor) at compile time. The same
source code compile if I don't try to split it up into separate libraries.
On the following source code I run:
aclocal # sets up some kind of m4 macro magic.
autoheader # does wonderful things with my headers
autoconf # read the configure.ac and spit out a configure script
automake -a -c --gnits # generate Makefile.in's from Makefile.am's
./configure # read Makefile.in's and generate Makefiles
make # run make, duh!
with the results shown at the end of the code listing. The problem seems
to be related to my using static const class members. Other similarly
configured programs work OK. Can someone please explain why this won't
compile?
./configure.ac
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)
AC_INIT(testlib s, 0.1, ha*****@here.co m)
AC_CONFIG_SRCDI R([main.cpp])
AC_CONFIG_HEADE R([config.h])
AM_INIT_AUTOMAK E
# Checks for programs.
AC_PROG_CXX
AC_PROG_CC
# Checks for libraries.
AC_PROG_RANLIB
# Checks for header files.
# Checks for typedefs, structures, and compiler characteristics .
AC_C_CONST
AC_C_INLINE
# Checks for library functions.
AC_CONFIG_FILES ([Makefile
sth/Makefile
sth/util/Makefile])
AC_OUTPUT
./Makefile.am
INCLUDES = -I$(top_srcdir)/sth $(all_includes)
bin_PROGRAMS = testlibs
testlibs_SOURCE S = main.cpp
testlibs_LDFLAG S = $(all_libraries )
testlibs_LDADD = $(top_builddir)/sth/libsth.a
SUBDIRS = sth
./main.cpp
#include "ColorTest. h"
#include <iostream>
int main(int argc, char* argv[]) {
using sth::ColorTest;
ColorTest* ct = new ColorTest(std:: cout);
}
./sth/Makefile.am
INCLUDES = -I$(top_srcdir)/sth/util $(all_includes)
SUBDIRS = util
lib_LIBRARIES = libsth.a
libsth_a_LIBADD = $(top_builddir)/sth/util/libutil.a
noinst_HEADERS = ColorTest.h
libsth_a_SOURCE S = ColorTest.cpp
./sth/ColorTest.h
#ifndef STHCOLORTEST_H
#define STHCOLORTEST_H
#include <ostream>
namespace sth {
class ColorTest {
public:
ColorTest(std:: ostream& out);
~ColorTest();
};
};
#endif
./sth/ColorTest.cpp
#include "ColorTest. h"
#include <iostream>
int main(int argc, char* argv[]) {
using sth::ColorTest;
ColorTest* ct = new ColorTest(std:: cout);
}
./sth/util/Makefile.am
INCLUDES = -I$(all_includes )
lib_LIBRARIES = libutil.a
noinst_HEADERS = RgbColor.h Printable_IF.h
libutil_a_SOURC ES = RgbColor.cpp
./sth/util/RgbColor.h
#ifndef UTILRGBCOLOR_H
#define UTILRGBCOLOR_H
#include "Printable_IF.h "
namespace sth
{
namespace util
{
/**
@author Steven T. Hatton
*/
class RgbColor
: public Printable_IF
{
public:
RgbColor(const unsigned char& r=255,
const unsigned char& g=127,
const unsigned char& b=127);
unsigned char R() const;
void R(const unsigned char& r);
unsigned char G() const;
void G(const unsigned char& g);
unsigned char B() const;
void B(const unsigned char& b);
std::ostream& print(std::ostr eam& out) const;
static const RgbColor RED;
static const RgbColor GREEN;
static const RgbColor BLUE;
static const RgbColor BLACK;
static const RgbColor WHITE;
static const RgbColor MAGENTA;
static const RgbColor CYAN;
static const RgbColor YELLOW;
private:
unsigned char m_r;
unsigned char m_g;
unsigned char m_b;
};
inline unsigned char RgbColor::R() const
{
return m_r;
}
inline void RgbColor::R(con st unsigned char& r)
{
m_r = r;
}
inline unsigned char RgbColor::G() const
{
return m_g;
}
inline void RgbColor::G(con st unsigned char& g)
{
m_g = g;
}
inline unsigned char RgbColor::B() const
{
return m_b;
}
inline void RgbColor::B(con st unsigned char& b)
{
m_b = b;
}
}
}
#endif
./sth/util/RgbColor.h
#include "RgbColor.h "
namespace sth
{
util::RgbColor: :RgbColor(const unsigned char& r,
const unsigned char& g,
const unsigned char& b)
: m_r(r)
, m_g(g)
, m_b(b)
{}
const util::RgbColor util::RgbColor: :RED = util::RgbColor( 255,0,0);
const util::RgbColor util::RgbColor: :GREEN = util::RgbColor( 0,255,0);
const util::RgbColor util::RgbColor: :BLUE = util::RgbColor( 0,0,255);
const util::RgbColor util::RgbColor: :BLACK = util::RgbColor( 0,0,0);
const util::RgbColor util::RgbColor: :WHITE =
util::RgbColor( 255,255,255);
const util::RgbColor util::RgbColor: :MAGENTA = util::RgbColor( 255,0,255);
const util::RgbColor util::RgbColor: :CYAN = util::RgbColor( 0,255,255);
const util::RgbColor util::RgbColor: :YELLOW = util::RgbColor( 255,255,0);
/*!
\fn util::RgbColor: :print(std::ost ream& out) const
*/
std::ostream& util::RgbColor: :print(std::ost ream& out) const
{
out
<< "util::RgbColor ::{r=" << this->m_r
<< ",g=" << this->m_g
<< ",b=" << this->m_b << "}\n";
return out;
}
}
./sth/util/Printable_IF.h
#ifndef PRINTABLE_IF_H
#define PRINTABLE_IF_H
#include <iostream>
namespace sth
{
namespace util
{
class Printable_IF
{
public:
Printable_IF()
{}
virtual ~Printable_IF()
{}
virtual std::ostream& print(std::ostr eam& out) const = 0;
};
inline std::ostream& operator<<(std: :ostream& out, const Printable_IF&
pif)
{
return pif.print(out);
}
}
}
#endif
undefined reference to `sth::util::Rgb Color::RED'
./sth/libsth.a(ColorT est.o)(.text+0x 6f):./sth/ColorTest.cpp:9 : undefined
reference to `sth::util::Rgb Color::RED'
./sth/libsth.a(ColorT est.o)(.text+0x 77):./sth/ColorTest.cpp:9 : undefined
reference to `sth::util::Rgb Color::RED'
./sth/libsth.a(ColorT est.o)(.text+0x 81):./sth/ColorTest.cpp:9 : undefined
reference to `vtable for sth::util::RgbC olor'
./sth/libsth.a(ColorT est.o)(.text+0x 8f): In function
`sth::ColorTest ::ColorTest[in-charge](std::basic_ost ream<char,
std::char_trait s<char> >&)':
--
"[M]y dislike for the preprocessor is well known. Cpp is essential in C
programming, and still important in conventional C++ implementations , but
it is a hack, and so are most of the techniques that rely on it. ...I think
the time has come to be serious about macro-free C++ programming." - B. S.