Working through the Openismus’s example code for Automake(Part 3)

Today, my plan is to dissect  looking at C++ code from the Openismus site, which is really what I’m interested in doing.
[I just got a little distracted though.  I was checking out some of the book links at the bottom of the site.  I was hoping that my library had them…  But I just discovered that they had an one line book about emac.   Something to think about…]

Ok… I’m back..
So… This project downloaded looks like this.

jonas@Ubuntu4:~/helloworld_cc-0.3$ ls -1 -R
.:
aclocal.m4
AUTHORS
autogen.sh
ChangeLog
config.guess
config.h
config.h.in
config.log
config.status
config.sub
configure
configure.ac
COPYING
depcomp
INSTALL
install-sh
libtool
ltmain.sh
Makefile
Makefile.am
Makefile.in
missing
mkinstalldirs
NEWS
README
src
stamp-h1

./src:
foofiles
hello
hello.cc
hello.h
hello.o
main.cc
main.o
Makefile
Makefile.am
Makefile.in

./src/foofiles:
foo.cc
foo.h
foo.o
libfoo.a
Makefile
Makefile.am
Makefile.in
jonas@Ubuntu4:~/helloworld_cc-0.3$

So I suppose a good place to start is main.cc

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include “hello.h”

main()
{
Hello helloTemp;
helloTemp.HelloTest();
}

Let the dissection begin:

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

Now , this has got me curious… This whole exercise has been to create a config.h and to include it in the project via automake..  I wonder what the config.h looks like.  There is only one config.h and it’s located in the main directory fo the project…
Surprisingly, it is not overwhelmingly large. So here it is:

/* config.h.  Generated by configure.  */
/* config.h.in.  Generated from configure.ac by autoheader.  */

/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1

/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1

/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1

/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1

/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1

/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1

/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1

/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1

/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1

/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1

/* Name of package */
#define PACKAGE “helloworld_cc”

/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT “”

/* Define to the full name of this package. */
#define PACKAGE_NAME “”

/* Define to the full name and version of this package. */
#define PACKAGE_STRING “”

/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME “”

/* Define to the version of this package. */
#define PACKAGE_VERSION “”

/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1

/* Version number of package */
#define VERSION “0.3”

So I believe what the code is saying is that if the config.h hasn’t be defined then don’t include it.
That seems rather sensible. Now I would think that HAVE_CONFIG_H should defined in the Makefiles in  the project. To be thorough, I’m searching through the Makefiles (take a peek at the makefiles.in to see what they look like as well as the configure files.
Poking around the configure file it seems like config.h gets associated with ac_config_headers which I think got started from “AM_CONFIG_HEADER(config.h)” in configure.ac…
Searching the lowest level:
./src/foofiles:
Makefile.in contains this line:

CONFIG_HEADER = $(top_builddir)/config.h

This wasn’t exactly what I was looking for but, of interest non the less.
Makefile contains the lines:

….
CONFIG_HEADER = $(top_builddir)/config.h
….
DEFS = -DHAVE_CONFIG_H

I wonder how hard it is to find something about “DEFS =”

Ok… Some day I’ll get through this …. I found some info in  here in this somewhat dated 2002 reference(hopefully this is still valid)

Creating Configuration Files
============================

Be sure to read the previous section, *Note Configuration Actions::.

– Macro: AC_CONFIG_FILES (FILE…, [CMDS], [INIT-CMDS])
Make AC_OUTPUT' create each FILE’ by copying an input file (by
default FILE.in'), substituting the output variable values. This
macro is one of the instantiating macros; see *Note Configuration
Actions::. *Note Makefile Substitutions::, for more information
on using output variables. *Note Setting Output Variables::, for
more information on creating them. This macro creates the
directory that the file is in if it doesn't exist. Usually,
Makefile’s are created this way, but other files, such as
.gdbinit', can be specified as well.

Typical calls to AC_CONFIG_FILES’ look like this:

AC_CONFIG_FILES([Makefile src/Makefile man/Makefile X/Imakefile])
AC_CONFIG_FILES([autoconf], [chmod +x autoconf])

You can override an input file name by appending to FILE a
colon-separated list of input files. Examples:

AC_CONFIG_FILES([Makefile:boiler/top.mk:boiler/bot.mk]
[lib/Makefile:boiler/lib.mk])

Doing this allows you to keep your file names acceptable to
MS-DOS, or to prepend and/or append boilerplate to the file.

Substitutions in Makefiles
==========================

Each subdirectory in a distribution that contains something to be
compiled or installed should come with a file Makefile.in', from which
configure’ will create a Makefile' in that directory. To create a
Makefile’, configure' performs a simple variable substitution,
replacing occurrences of
@VARIABLE@’ in Makefile.in' with the value
that
configure’ has determined for that variable.
Variables that are
substituted into output files in this way are called “output
variables”. They are ordinary shell variables that are set in
configure'. To make configure’ substitute a particular variable into
the output files, the macro AC_SUBST' must be called with that
variable name as an argumen
t. Any occurrences of @VARIABLE@’ for
other variables are left unchanged. *Note Setting Output Variables::,
for more information on creating output variables with AC_SUBST'.

A software package that uses a configure’ script should be
distributed with a file Makefile.in', but no Makefile’; that way, the
user has to properly configure the package for the local system before
compiling it.

*Note Makefile Conventions: (standards)Makefile Conventions, for
more information on what to put in Makefile's.

Preset Output Variables
-----------------------

Some output variables are preset by the Autoconf macros. Some of the Autoconf macros set additional output variables, which are mentioned in the descriptions for those macros. *Note Output Variable Index::, for a complete list of output variables. *Note Installation Directory Variables::, for the list of the preset ones related to installation directories. Below are listed the other preset ones. They all are precious variables (*note Setting Output Variables::, AC_ARG_VAR’).

– Variable: CFLAGS
Debugging and optimization options for the C compiler. If it is not set in the environment when configure' runs, the default value is set when you call AC_PROG_CC’ (or empty if you don’t). configure' uses this variable when compiling programs to test for C features.

- Variable: configure_input
A comment saying that the file was generated automatically by
configure’ and giving the name of the input file. AC_OUTPUT' adds a comment line containing this variable to the top of every Makefile’ it creates. For other files, you should reference this variable in a comment at the top of each input file. For example, an input shell script should begin like this:

#! /bin/sh
# @configure_input@

The presence of that line also reminds people editing the file that it needs to be processed by configure' in order to be used.

- Variable: CPPFLAGS
Header file search directory (
-IDIR’) and any other miscellaneous options for the C and C++ preprocessors and compilers. If it is not set in the environment when configure' runs, the default value is empty. configure’ uses this variable when compiling or preprocessing programs to test for C and C++ features.

– Variable: CXXFLAGS
Debugging and optimization options for the C++ compiler. If it is not set in the environment when configure' runs, the default value is set when you call AC_PROG_CXX’ (or empty if you don’t). configure' uses this variable when compiling programs to test for C++ features.

- Variable: DEFS
-D’ options to pass to the C compiler. If AC_CONFIG_HEADERS' is called, configure’ replaces @DEFS@' with -DHAVE_CONFIG_H’ instead (*note Configuration Headers::). This variable is not defined while configure' is performing its tests, only when creating the output files. *Note Setting Output Variables::, for how to check the results of previous tests.

- Variable: ECHO_C
- Variable: ECHO_N
- Variable: ECHO_T
How does one suppress the trailing newline from
echo’ for question-answer message pairs? These variables provide a way:

echo $ECHO_N “And the winner is… $ECHO_C”
sleep 100000000000
echo “${ECHO_T}dead.”

Some old and uncommon echo' implementations offer no means to achieve this, in which case ECHO_T’ is set to tab. You might not want to use it.

– Variable: FFLAGS
Debugging and optimization options for the Fortran 77 compiler. If it is not set in the environment when configure' runs, the default value is set when you call AC_PROG_F77′ (or empty if you
don’t). configure' uses this variable when compiling programs to test for Fortran 77 features.

- Variable: LDFLAGS
Stripping (
-s’), path (-L'), and any other miscellaneous options for the linker. Don't use this variable to pass library names (-l’) to the linker, use LIBS' instead. If it is not set in the environment when configure’ runs, the default value is empty. configure' uses this variable when linking programs to test for C, C++ and Fortran 77 features.

- Variable: LIBS
-l’ options to pass to the linker. The default value is empty, but some Autoconf macros may prepend extra libraries to this variable if those libraries are found and provide necessary functions, see *Note Libraries::. configure' uses this variable when linking programs to test for C, C++ and Fortran 77 features.

- Variable: builddir
Rigorously equal to
.’. Added for symmetry only.

– Variable: abs_builddir
Absolute path of builddir'.

- Variable: top_builddir
The relative path to the top-level of the current build tree. In the top-level directory, this is the same as
builddir’.

– Variable: abs_top_builddir
Absolute path of top_builddir'.

- Variable: srcdir
The relative path to the directory that contains the source code for that
Makefile’.

– Variable: abs_srcdir
Absolute path of srcdir'.

- Variable: top_srcdir
The relative path to the top-level source code directory for the package. In the top-level directory, this is the same as
srcdir’.

– Variable: abs_top_srcdir
Absolute path of `top_srcdir’.

Ok… I think what I got it… the other bold italic highlighted is stuff I was wondering about in my previous post..

….
CONFIG_HEADER = $(top_builddir)/config.h
….
DEFS = -DHAVE_CONFIG_H

So getting back to main.cc to see what’s next to look at.

#ifdef HAVE_CONFIG_H
#include
#endif

#include “hello.h”

main()
{
Hello helloTemp;
helloTemp.HelloTest();
}

So this takes us to hello.h

#if !defined(DEF_HELLOWORLD_HELLO_H)
#define DEF_HELLOWORLD_HELLO_H

#include <iostream>
#include <string>

#include “foofiles/foo.h”

class Hello
{
public:
void HelloTest();
};

#endif //DEF_HELLOWORLD_HELLO_H

Ohh.. This is very exciting for me… because it all makes sense when I look at this…(Yeh I know I’m weird).
[I just discovered something I have to be real careful pasting my code over here since wordpress has issues with the <> stuff… I guest it’s thinking of them as html tags..]
So… This is example so really cool because it packs a huge amount of concept in a very small space..
I think I would be appropriate to list out hello.cc , foo.h and foo.cc also to have the complete picture.
hello.cc

#include “hello.h”

void Hello::HelloTest()
{
//Helloworld:
std::string strTemp = “Hello World\n”;
std::cout << strTemp;

//Print out however many asterixes CFoo tells us to:
Foo fooTest;
int iTest = fooTest.GetTheNumber();

for(int i = 0; i < iTest; i++)
{
std::cout << “*”;
}

std::cout << “\n”;
}

foo.h

#if !defined(DEF_HELLOWORLD_FOO_H)
#define DEF_HELLOWORLD_FOO_H

class Foo
{
public:
int GetTheNumber();
};

#endif //DEF_HELLOWORLD_FOO_H

foo.cc

#include “foo.h”

int Foo::GetTheNumber()
{
return 5;
}

This entry was posted in C++ and tagged . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *