问题
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();
回答1:
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
回答2:
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
回答3:
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();
}
来源:https://stackoverflow.com/questions/60205338/how-a-c-program-cpp-work-with-header-h-and-libtool-la