Issue with autotools and generating a c++ library - c++

I am new to autotools and have tried to code up an example. I am creating one library and linking it against another object.
My problem is that the Makefile that is generated for the library seems to be mis-interpreted as C code, but is actually C++. If I replace all occurences of ".c" to ".cpp" in the generated Makefile, all is well.
I am using libtool 2.4.2 and autoconf 2.69. My code structure is listed below:
test/
- Makefile.am
- configure.ac
include/
- mylib.hh
src/
hw/
- Makefile.am
- main.cpp
mylib/
- Makefile.am
- mylib.cpp
Below is my top level Makefile.am:
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src/mylib src/hw
configure.ac
AC_PREREQ([2.65])
AC_INIT([hw],[1.0.0],[foo.bar#example.com])
# directories (relative to top-level) to look into for AutoConf/AutoMake files
AC_CONFIG_MACRO_DIR([m4])
# enable AutoMake
AM_INIT_AUTOMAKE([1.10])
# all defined C macros (HAVE_*) will be saved to this file
AC_CONFIG_HEADERS([config.h])
AC_PROG_CC
AM_PROG_CC_C_O
# Check if you have a C++ compiler
AC_PROG_CXX
AC_PROG_CXX_C_O
AC_PROG_INSTALL
## Initialize GNU LibTool
LT_INIT
AC_CONFIG_FILES([Makefile
src/hw/Makefile
src/mylib/Makefile])
AC_OUTPUT
src/hw/Makefile.am
ACLOCAL_AMFLAGS = -I m4
bin_PROGRAMS = hw
hw_SOURCES = main.cpp
AM_CPPFLAGS = -I$(top_srcdir)/include
hw_LDADD = $(top_srcdir)/src/mylib/libmylib.la
src/mylib/Makefile.am
ACLOCAL_AMFLAGS = -I m4
lib_LTLIBRARIES = libmylib.la
libmylib_la_sources = mylib.cpp
libmylib_la_CPPFLAGS = -I$(top_srcdir)/include
The error I get when running make:
make[2]: *** No rule to make target 'libmylib.c', needed by 'libmylib_la-libmylib.lo'. Stop.
Once again, substituting ".cpp" for all occurrences of ".c" in the generated src/mylib/Makefile, the code compiles, links and runs fine. Any help is appreciated.

Did you try changing:
libmylib_la_sources = mylib.cpp
to
libmylib_la_SOURCES = mylib.cpp
(upper case SOURCES)? m4 is case-sensitive.

Related

How a c++ program (.cpp) work with header(.h) and libtool (.la)?

I have create a folder in linux called helloworld.
Inside this folder have sub-directory:
include
lib
src
include/
In this directory I have create a header file called helloworld.h
content are:
class helloworld{
public:
void getvalue();
};
lib/
In lib directory I have create a cpp file called helloworld.cpp
content are mainly functions:
#include<iostream>
#include<helloworld.h>
using namespace std;
void helloworld::getvalue() {
}
src/
In src directory I have create a main cpp file called main.cpp
content are main:
#include<iostream>
#include<helloworld.h>
int main()
{
helloworld a;
a.getvalue();
}
but after I autoconf, automake, ./configure, and when make
it has a error:
helloworld/src/main.cpp:8: undefined reference to `helloworld::getvalue()'
All I want is to use helloworld.cpp's functions in main.cpp. I've spend a lot of time searching and try and error. Please help.
Added the Makefiles.am
in parent directory,
I have two files Makefile.am and configure.ac:
Makefile.am
AUTOMAKE_OPTIONS = foreign
SUBDIRS=src lib
configure.ac
AC_INIT([helloworld], [0.1], [helloworld#gmail.com])
AM_INIT_AUTOMAKE
AC_PROG_RANLIB
AC_LANG(C++)
AC_PROG_CC
AC_PROG_CXX
AC_CONFIG_MACRO_DIR([m4])
AC_PROG_LIBTOOL
AC_DISABLE_STATIC
AC_CONFIG_FILES([Makefile lib/Makefile src/Makefile])
AC_SUBST([CC])
LT_INIT
AC_OUTPUT
In lib directory has one Makefile.am
INCDIR=../include
INCPATH=-I. -I$(INCDIR)
AM_CPPFLAGS=$(INCPATH)
lib_LTLIBRARIES=libhelloworld.la
libhelloworld_la_SOURCES=helloworld.cpp
In src directory has one Makefile.am
INCDIR=../include
INCPATH=-I. -I$(INCDIR)
AM_CPPFLAGS=$(INCPATH)
helloworld_LDADD=-L/lib/libhelloworld.la
bin_PROGRAMS=helloworld
helloworld_SOURCES=main.cpp
Compiled success if I take out the
a.getvalue();
helloworld_LDADD=-L/lib/libhelloworld.la
/lib/libhelloworld.la
this search lib from root directory not your project lib/ directory
Try
./lib/libhelloworld.la
or
../lib/libhelloworld.la
or
lib/libhelloworld.la
This is a good demonstration case for not using recursive make, because that simplifies the declaration of the executable depending on the library. Also, using a single Makefile.am helps with parallel builds (make -j3).
I have completed the example and put it up at github.com/ndim/cxx-automake-lib-and-main for your convenience.
The configure.ac now uses LT_INIT directly without deprecated macros, only generates one Makefile, and generates a helloworld-config.h config header to keep the compiler command line clean from all those -D defines:
AC_INIT([helloworld], [0.1], [bug-me-not], [helloworld], [this-url])
AC_CONFIG_SRCDIR([lib/helloworld.cpp])
AC_CONFIG_HEADERS([helloworld-config.h])
AC_CONFIG_MACRO_DIR([auto-m4])
AC_CONFIG_AUX_DIR([auto-aux])
AM_INIT_AUTOMAKE([
-Wall
-Werror
foreign
subdir-objects
])
AC_PROG_CXX
AM_PROG_AR
LT_INIT([disable-static])
AC_LANG([C++])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
The top-level Makefile.am is now the only Makefile.am:
ACLOCAL_AMFLAGS = -I auto-m4
EXTRA_DIST =
bin_PROGRAMS =
lib_LTLIBRARIES =
include include/Makefile-files
include lib/Makefile-files
include src/Makefile-files
Then include/Makefile-files deals with the header file which I put into include/helloworld/helloworld to help with keeping the include file namespace clean, and to prevent make from getting confused about the executable helloworld and the header file helloworld.
# -*- makefile-automake -*-
EXTRA_DIST += %reldir%/helloworld/helloworld
/* -*- c++ -*- */
#ifndef HELLOWORLD_HEADER
#define HELLOWORLD_HEADER
class helloworld {
public:
void getvalue();
};
#endif /* !defined(HELLOWORLD_HEADER) */
Now, lib/Makefile-files will build libhelloworld.la from library source file lib/helloworld.cpp which I had to adapt a bit for the changed header name:
# -*- makefile-automake -*-
lib_LTLIBRARIES += libhelloworld.la
libhelloworld_la_CPPFLAGS = -I$(top_srcdir)/include
libhelloworld_la_SOURCES = %reldir%/helloworld.cpp
#include "helloworld/helloworld"
void helloworld::getvalue() {
}
The helloworld program is defined in src/Makefile-files such that the dependency libhelloworld.la will be automatically (re)built if necessary. The source file src/main.cpp has been adapted for the new header name/location.
# -*- makefile-automake -*-
bin_PROGRAMS += helloworld
helloworld_CPPFLAGS = -I$(top_srcdir)/include
helloworld_SOURCES = %reldir%/main.cpp
helloworld_LDADD = libhelloworld.la
#include "helloworld/helloworld"
int main() {
helloworld a;
a.getvalue();
}
If you insist on using recursive make, you will need to add a special rule to src/Makefile.am to make sure the lib/Makefile.am rules for rebuilding the library are applied (untested here, but used in other projects).
This now means that a normal recursive build will build ., include, lib, src, and then lib again. I would strongly recommend ditching recursive make and use the one Makefile.am solution I have laid out in my other answer.
bin_PROGRAMS = helloworld
helloworld_CPPFLAGS = $(top_srcdir)/include
helloworld_LDADD = $(top_builddir)/lib/libhelloworld.la
helloworld_SOURCES = main.cpp
$(top_builddir)/lib/libhelloworld.la:
cd $(top_builddir)/lib && $(MAKE) libhelloworld.la

Adding Linker Flag to configure.ac

I want to add --export-dynamic flag to my project's configure.ac file.
I am trying to compile my project files that must use this flag after pkg-config --cflags --libs gtk+-3.0.
The following are contents of my configure.ac file.
AC_INIT(myapp, 1.0)
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE([1.11])
AM_SILENT_RULES([yes])
AC_PROG_CXX
AC_PROG_CC
IT_PROG_INTLTOOL([0.35.0])
GETTEXT_PACKAGE=myapp
AC_SUBST(GETTEXT_PACKAGE)
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE", [GETTEXT package name])
AM_GLIB_GNU_GETTEXT
LT_INIT
PKG_CHECK_MODULES(MYAPP, [gtk+-3.0 ])
AC_OUTPUT([
Makefile
src/Makefile
po/Makefile.in
])
How do I do that?
How about adding them to AM_LDFLAGS or more specific _LDFLAGS variable in Makefile.am

C++ Access Autoconf Variable Datadir

I am creating a program called spellcheck, and I'm using autoconf and automake to create a build system for it. The program relies on the dictionary 'english.dict', which is in the data directory (based on whatever prefix the user selected). I want the data directory path accessible by spellcheck, so I created a custom variable that contained its value:
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.69])
AC_INIT(libspellcheck, 1.25, corinthianmonthly#hotmail.com)
AC_OUTPUT(Makefile libspellcheck/Makefile spellcheck/Makefile man/Makefile)
AC_CONFIG_SRCDIR([])
AC_CONFIG_HEADERS([config.h])
AC_DEFINE_UNQUOTED([DATA_PATH], ["$pkgdatadir"],"DData Directory Path")
AM_INIT_AUTOMAKE
# Checks for programs.
AC_PROG_CXX
AC_PROG_CC
AC_PROG_CXX
AC_PROG_RANLIB
# Checks for libraries.
# Checks for header files.
AC_CHECK_HEADERS([stdlib.h,iostream,fstream,string,stdio.h,sstream,cctype,algorithm,boost/algorithm/string.hpp])
# Checks for typedefs, structures, and compiler characteristics.
AC_CHECK_HEADER_STDBOOL
AC_TYPE_SIZE_T
# Checks for library functions.
AC_OUTPUT
However, in the config.h file, this value is blank:
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* "Description" */
#define DATA_PATH ""
...
I tried changing $pkgdatadir to $datadir, but I got the same result. What am I doing wrong, or is what I am trying to achieve impossible?
EDIT: I redefined the variable in my Makefile.am for spellcheck:
AM_CFLAGS = -DDATA_PATH=\"$(pkgdatadir)\" -m32 -Wall
bin_PROGRAMS = spellcheck
pkgdata_DATA = english.dict
spellcheck_SOURCES = spellcheck.cpp meta.cpp
spellcheck_LDADD = ../libspellcheck/libspellcheck.a
But now it complains about DATA_PATH being nonexistant:
spellcheck.cpp:4:22: error: 'DATA_PATH' was not declared in this scope
#define DEFAULT_DICT DATA_PATH "english.dict"
Because now it seems to be ignoring all CFLAGS:
g++ -DHAVE_CONFIG_H -I. -g -O2 -MT spellcheck.o -MD -MP -MF .deps/spellcheck.Tpo -c -o spellcheck.o spellcheck.cpp
It turns out that I needed to use AM_CPPFLAGS rather than CFLAGS.

In Sconstruct, how can I specify include paths for D programming language

Seems that CPPPATH does not work
env = Environment()
target = 'app'
sources = ['app.d']
libs = ['phobos2', 'pthread', 'm', 'rt']
includes = ['/home/supertool/devel/d/vibe.d/source/vibe']
env.Program(target = target,
source = sources,
LIBS = libs,
CPPPATH = includes);
and when I run scons, it generates compile command:
dmd -I. -c -ofapp.o app.d
includes is not added into -I part
So how can I config this? Is there a INCLUDEPATH ?
Instead of using the CPPPATH construction variable, for which SCons prepends the -I, you could try manually building the paths, like this:
includePaths = ['-Ipath1', '-Ipath2']
....
env.Program(target = target,
source = sources,
LIBS = libs,
CCFLAGS = includePaths);
But this may lead to the same problem, that CCFLAGS wont be used for D compilation. I havent seen any D-specific construction variables other than DSUFFIXES
EDIT: Looks like DFLAGS and DPATH are not documented
I was playing around with this on my machine and see that CCFLAGS wont work for D, but DFLAGS and DPATH do, and they're not documented :( DPATH will have "I" prepended at compile time, so it is analogous to CPPPATH
There has been talk on the SCons user mail list about beefing up the SCons D support.

Automake Variables to tidy up Makefile.am

I have a directory /src containing all of my source files, and /bin to store all binary after running make command. The directory is something like below:
/BuildDirectory
- - /src
- - /bin
- - configure
- - Makefile.am
- - configure.ac
- - ...
Now in Makefile.am, I have to specified:
bin_PROGRAMS = bin/x bin/y bin/z bin/k ...
bin_x_SOURCES = src/x.cpp
bin_y_SOURCES = src/y.cpp
bin_z_SOURCES = src/z.cpp
Is there any variable that can help to get rid of all "bin/" and "src/" ?
For example I just specify:
$BIN = bin
$SRC = src
And they will look for the correct files in correct folders and compile it to the correct places.
Thanks
You could take advantage of remote building. Place this makefile in the bin dir:
VPATH = ../src
bin_PROGRAMS = x y z k ...
x_SOURCES = x.cpp
y_SOURCES = y.cpp
z_SOURCES = z.cpp
Now replace the current Makefile.am with this one:
SUBDIRS = bin
Now tweak your configure.ac to also generate bin/Makefile
AC_CONFIG_FILES([Makefile
bin/Makefile])
and you should be set for life.
Not to my knowledge. If you're looking to separate your compiled files from your source files, remember that you can build outside of the tree:
$ cd foo-1.2.3
$ mkdir build
$ cd build
$ ../configure
$ make
$ make install
If this is what you're looking to do, you can make the Makefile.am simpler by creating binaries without a directory prefix (and still referencing things in src/ by hand).
If what you're trying to do is what I think you're trying to do, you're trying to achieve something like:
SRCDIR = src
BINDIR = bin
bin_PROGRAMS = $(BINDIR)/x $(BINDIR)/y $(BINDIR)/z
bin_x_SOURCES = $(SRCDIR)/x.cpp
bin_y_SOURCES = $(SRCDIR)/y.cpp
bin_z_SOURCES = $(SRCDIR)/z.cpp
I've tested this a few times in various forms, and it won't compile the code as it would with your example; I somehow convinced it that it was compiling C at one stage:
gmake[1]: *** No rule to make target `bin/x.c', needed by `x.o'. Stop.
I'm thus fairly certain that it's not possible. Sorry.