c++ 程序 (.cpp) 如何与 header(.h) 和 libtool (.la) 一起工作?

Posted

技术标签:

【中文标题】c++ 程序 (.cpp) 如何与 header(.h) 和 libtool (.la) 一起工作?【英文标题】:How a c++ program (.cpp) work with header(.h) and libtool (.la)? 【发布时间】:2020-02-13 10:13:21 【问题描述】:

我在 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

配置.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 一个库还是只是另一个 .cpp 你想用 main.cpp 编译? 如果你有库是动态的还是静态的? 因为这是一个关于 autoconf/automake 的问题(而不是 C++ 本身),也许你应该添加你的 autoconf/automake 脚本。 【参考方案1】:
helloworld_LDADD=-L/lib/libhelloworld.la


/lib/libhelloworld.la  

这个从根目录搜索的 lib 不是你的项目 lib/ 目录

试试

./lib/libhelloworld.la

../lib/libhelloworld.la

lib/libhelloworld.la

【讨论】:

也不工作。我试图将所有文件一起移动到目录中。同样的问题。 @Jemttinhwa 没关系。你添加了你的makefile。我改变了答案。 ../lib/libhelloworld.la => 没有制定目标的规则 '../lib/libhelloworld.la' ...... lib/libhelloworld.la => 没有制定规则目标'lib/libhelloworld.la' ...... ./lib/libhelloworld.la => 没有规则来制作目标'lib/libhelloworld.la' ...... @Jemttinhwa 您的项目生成的 libhelloworld.la 的位置是什么? hmm.. 它现在在 /helloworld/lib/.libs/libhelloworld.la【参考方案2】:

这是 not 使用递归 make 的一个很好的演示案例,因为这简化了依赖于库的可执行文件的声明。此外,使用单个 Makefile.am 有助于并行构建 (make -j3)。

为了您的方便,我已经完成了示例并将其放在github.com/ndim/cxx-automake-lib-and-main。

configure.ac 现在直接使用 LT_INIT 而没有弃用的宏,只生成一个 Makefile,并生成一个 helloworld-config.h 配置头,以保持编译器命令行与所有 -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

***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 的头文件,以帮助保持包含文件命名空间干净,并防止make 对可执行文件helloworld 和头文件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,我必须针对更改后的标头名称进行一些调整:

# -*- 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 已适应新的标题名称/位置。

# -*- 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();

【讨论】:

【参考方案3】:

如果您坚持使用递归 make,则需要在 src/Makefile.am 中添加一个特殊规则,以确保应用 lib/Makefile.am 重建库的规则(此处未经测试,但在其他项目中使用)。

现在这意味着正常的递归构建将构建.includelibsrc,然后再次构建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

【讨论】:

以上是关于c++ 程序 (.cpp) 如何与 header(.h) 和 libtool (.la) 一起工作?的主要内容,如果未能解决你的问题,请参考以下文章

解析 C++ 源代码并将 in-header 内联方法移动到 .cpp 源文件的工具? [关闭]

程序missing function header是啥意思

如何正确链接/包含 c++ 库

将 C++ 与 Python 连接

c++中后缀名.c 与.cpp的区别

在 C 或 C++ 中包含标头的正确方法