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 重建库的规则(此处未测试,但在其他项目)。

这意味着正常的递归构建将构建 .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