C++ 程序 (.cpp) 如何与 header(.h) 和 libtool (.la) 一起工作?
How a c++ program (.cpp) work with header(.h) and libtool (.la)?
我在 linux 中创建了一个名为 helloworld 的文件夹。
此文件夹内有子目录:
- 包括
- 库
- 源码
包括/
在此目录中,我创建了一个名为 helloworld.h 的头文件
内容是:
class helloworld{
public:
void getvalue();
};
lib/
在 lib 目录中,我创建了一个名为 helloworld.cpp 的 cpp 文件
内容主要是功能:
#include<iostream>
#include<helloworld.h>
using namespace std;
void helloworld::getvalue() {
}
src/
在 src 目录中,我创建了一个名为 main.cpp 的主 cpp 文件
主要内容:
#include<iostream>
#include<helloworld.h>
int main()
{
helloworld a;
a.getvalue();
}
但是在我 autoconf、automake、./configure 和 make 之后
它有一个错误:
helloworld/src/main.cpp:8: undefined reference to `helloworld::getvalue()'
我只想在main.cpp中使用helloworld.cpp的功能。我花了很多时间搜索和尝试错误。请帮忙。
添加了Makefiles.am
在父目录中,
我有两个文件 Makefile.am 和 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
在lib目录下有一个Makefile.am
INCDIR=../include
INCPATH=-I. -I$(INCDIR)
AM_CPPFLAGS=$(INCPATH)
lib_LTLIBRARIES=libhelloworld.la
libhelloworld_la_SOURCES=helloworld.cpp
在src目录下有一个Makefile.am
INCDIR=../include
INCPATH=-I. -I$(INCDIR)
AM_CPPFLAGS=$(INCPATH)
helloworld_LDADD=-L/lib/libhelloworld.la
bin_PROGRAMS=helloworld
helloworld_SOURCES=main.cpp
取出编译成功
a.getvalue();
helloworld_LDADD=-L/lib/libhelloworld.la
/lib/libhelloworld.la
这个从根目录搜索库而不是你的项目库/目录
尝试
./lib/libhelloworld.la
或
../lib/libhelloworld.la
或
lib/libhelloworld.la
这是 not 使用递归 make 的一个很好的演示案例,因为这根据库简化了可执行文件的声明。此外,使用单个 Makefile.am
有助于并行构建 (make -j3
)。
为了方便起见,我已经完成了示例并将其放在 github.com/ndim/cxx-automake-lib-and-main。
configure.ac
现在直接使用LT_INIT
,没有弃用的宏,只生成一个Makefile
,并生成一个helloworld-config.h
配置header来保持编译器清除所有 -D
定义的命令行:
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
top-level Makefile.am
现在是唯一的 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
然后 include/Makefile-files
处理我放入 include/helloworld/helloworld
的 header 文件,以帮助保持包含文件命名空间的清洁,并防止 make 对可执行文件感到困惑 helloworld
和 header 文件 helloworld
.
# -*- makefile-automake -*-
EXTRA_DIST += %reldir%/helloworld/helloworld
/* -*- c++ -*- */
#ifndef HELLOWORLD_HEADER
#define HELLOWORLD_HEADER
class helloworld {
public:
void getvalue();
};
#endif /* !defined(HELLOWORLD_HEADER) */
现在,lib/Makefile-files
将从库源文件 lib/helloworld.cpp
构建 libhelloworld.la
,我不得不为更改后的 header 名称进行一些调整:
# -*- 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() {
}
helloworld
程序在 src/Makefile-files
中定义,以便在必要时自动(重新)构建依赖项 libhelloworld.la
。源文件 src/main.cpp
已针对新 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();
}
如果您坚持使用递归 make,则需要在 src/Makefile.am
中添加一条特殊规则,以确保应用 lib/Makefile.am
重建库的规则(此处未测试,但在其他项目)。
这意味着正常的递归构建将构建 .
、include
、lib
、src
,然后再次构建 lib
。我强烈建议放弃递归 make 并使用我在其他答案中列出的 Makefile.am
解决方案。
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
我在 linux 中创建了一个名为 helloworld 的文件夹。 此文件夹内有子目录:
- 包括
- 库
- 源码
包括/ 在此目录中,我创建了一个名为 helloworld.h 的头文件 内容是:
class helloworld{
public:
void getvalue();
};
lib/ 在 lib 目录中,我创建了一个名为 helloworld.cpp 的 cpp 文件 内容主要是功能:
#include<iostream>
#include<helloworld.h>
using namespace std;
void helloworld::getvalue() {
}
src/ 在 src 目录中,我创建了一个名为 main.cpp 的主 cpp 文件 主要内容:
#include<iostream>
#include<helloworld.h>
int main()
{
helloworld a;
a.getvalue();
}
但是在我 autoconf、automake、./configure 和 make 之后 它有一个错误:
helloworld/src/main.cpp:8: undefined reference to `helloworld::getvalue()'
我只想在main.cpp中使用helloworld.cpp的功能。我花了很多时间搜索和尝试错误。请帮忙。
添加了Makefiles.am
在父目录中, 我有两个文件 Makefile.am 和 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
在lib目录下有一个Makefile.am
INCDIR=../include
INCPATH=-I. -I$(INCDIR)
AM_CPPFLAGS=$(INCPATH)
lib_LTLIBRARIES=libhelloworld.la
libhelloworld_la_SOURCES=helloworld.cpp
在src目录下有一个Makefile.am
INCDIR=../include
INCPATH=-I. -I$(INCDIR)
AM_CPPFLAGS=$(INCPATH)
helloworld_LDADD=-L/lib/libhelloworld.la
bin_PROGRAMS=helloworld
helloworld_SOURCES=main.cpp
取出编译成功
a.getvalue();
helloworld_LDADD=-L/lib/libhelloworld.la
/lib/libhelloworld.la
这个从根目录搜索库而不是你的项目库/目录
尝试
./lib/libhelloworld.la
或
../lib/libhelloworld.la
或
lib/libhelloworld.la
这是 not 使用递归 make 的一个很好的演示案例,因为这根据库简化了可执行文件的声明。此外,使用单个 Makefile.am
有助于并行构建 (make -j3
)。
为了方便起见,我已经完成了示例并将其放在 github.com/ndim/cxx-automake-lib-and-main。
configure.ac
现在直接使用LT_INIT
,没有弃用的宏,只生成一个Makefile
,并生成一个helloworld-config.h
配置header来保持编译器清除所有 -D
定义的命令行:
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
top-level Makefile.am
现在是唯一的 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
然后 include/Makefile-files
处理我放入 include/helloworld/helloworld
的 header 文件,以帮助保持包含文件命名空间的清洁,并防止 make 对可执行文件感到困惑 helloworld
和 header 文件 helloworld
.
# -*- makefile-automake -*-
EXTRA_DIST += %reldir%/helloworld/helloworld
/* -*- c++ -*- */
#ifndef HELLOWORLD_HEADER
#define HELLOWORLD_HEADER
class helloworld {
public:
void getvalue();
};
#endif /* !defined(HELLOWORLD_HEADER) */
现在,lib/Makefile-files
将从库源文件 lib/helloworld.cpp
构建 libhelloworld.la
,我不得不为更改后的 header 名称进行一些调整:
# -*- 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() {
}
helloworld
程序在 src/Makefile-files
中定义,以便在必要时自动(重新)构建依赖项 libhelloworld.la
。源文件 src/main.cpp
已针对新 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();
}
如果您坚持使用递归 make,则需要在 src/Makefile.am
中添加一条特殊规则,以确保应用 lib/Makefile.am
重建库的规则(此处未测试,但在其他项目)。
这意味着正常的递归构建将构建 .
、include
、lib
、src
,然后再次构建 lib
。我强烈建议放弃递归 make 并使用我在其他答案中列出的 Makefile.am
解决方案。
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