无法将 c++ 项目完全编译和链接为静态库

Posted

技术标签:

【中文标题】无法将 c++ 项目完全编译和链接为静态库【英文标题】:Cannot totally compile and link cpp project as a static library 【发布时间】:2016-09-07 15:20:28 【问题描述】:

我已遵循此link 并调整了其步骤以使其适用于我的项目。

我的目标是创建一个libfile.a 以作为静态库分发。项目树如下:

project
   |
   +-src
      +- <some cpp and hpp files>
      |
      + containers
             |
             +- <other cpp and hpp files>

我轻松创建了configure.ac 文件和Makefile.ams。树结构是这样改变的:

project
   |
   +- configure.ac
   +- Makefile.am
   +-src
      +- <some cpp and hpp files>
      + Makefile.am
      |
      + containers
             |
             +- <other cpp and hpp files>

现在,我去的时候:(*)

aclocal; autoreconf --install; autoconf; ./configure
make

src 中包含的所有.*pp files 生成.o files,但是当它开始在src/containers 中生成这些目标时它会失败。所以Makefile 没有正确生成。我究竟做错了什么?有人可以帮我吗?

PS 这里涉及到文件:

# --- configure.ac ---

AC_PREREQ([2.68])
AC_INIT([filea], [1.0], [dev@host.net])
AM_INIT_AUTOMAKE([filea], [1.0])
AC_CONFIG_SRCDIR([src/HashFunctions.cpp])
AC_CONFIG_HEADERS([config.h])

AC_PROG_CXX
AC_PROG_RANLIB

AC_CHECK_HEADERS([stddef.h stdint.h string.h])
AC_HEADER_STDBOOL

AC_C_INLINE
AC_TYPE_SIZE_T
AC_TYPE_UINT16_T
AC_TYPE_UINT32_T
AC_TYPE_UINT8_T

AC_FUNC_MALLOC
AC_FUNC_MKTIME
AC_CHECK_FUNCS([memset])

AC_OUTPUT([Makefile src/Makefile])

# --- Makefile.am ---

AUTOMAKE_OPTIONS = foreign
SUBDIRS = src


# --- src/Makefile.am ---

lib_LIBRARIES = libfile.a
libfile_a_SOURCES = \
    ConfigLib.hpp \
    ConfigLib.cpp \
    HashFunctions.cpp \
    HashFunctions.hpp \
    Logger.hpp \
    Logger.cpp \
    Queue.hpp

libfile_a_SOURCES += \
    containers/SafeContainer.cpp \
    containers/SafeInterger.cpp \
    containers/SafeMap.cpp

编辑 1 根据Brett Hale 的建议,标有(*) 的命令已替换为以下命令:

autoreconf -fvi

输出:

autoreconf: Entering directory `.'
autoreconf: configure.ac: not using Gettext
autoreconf: running: aclocal --force 
autoreconf: configure.ac: tracing
autoreconf: configure.ac: not using Libtool
autoreconf: running: /usr/bin/autoconf --force
autoreconf: running: /usr/bin/autoheader --force
autoreconf: running: automake --add-missing --copy --force-missing
autoreconf: Leaving directory `.'

搭配时:

./configure
make

仍然没有找到在子目录中生成目标的规则。

EDIT 2 我切换到非递归方法(感谢Karel Zak's blog),最后我可以makemy lib。

【问题讨论】:

您可以尝试使用:autoreconf -fvi 代替 aclocal; ....; 命令吗? 我可以建议调查 SCons、CMake 和其他构建系统 - 甚至是普通的 make - 任何东西,但可怕的是 autoconf/@987654348 @... @JesperJuhl - 是的,cmake 最初是出于纯粹的意图......只是发现这是一个 hard 问题,并且在没有 20 年经验的情况下有效地重新发明了***与 bash / m4 不同,自动工具 - 以及其他地方都没有使用的语法。 @BrettHale 感谢您的回答。请查看问题中的 EDIT 1; @JesperJuhl Ty 回答。我更喜欢对 autoconf / automake 进行更多调查,希望不久或稍后在一些帮助下,我会弄清楚它是如何完成的。 【参考方案1】:

按照典型的recursive approach,我仍然不知道我做错了什么;但是,最后我完成了这项工作,切换到 non-recursive approach(正如我在 EDIT 2 中所写)。 Karel Zak 博客上的This article 对我帮助很大!

# -- new configure.ac file --
AC_PREREQ([2.68])
AC_INIT([filea], [1.0], [dev@host.net])
AM_INIT_AUTOMAKE([filea], [1.0])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_SRCDIR([src/HashFunctions.cpp])

AM_INIT_AUTOMAKE([filea], [1.0])
LT_INIT

AC_CANONICAL_HOST
AC_PROG_LIBTOOL
AC_PROG_GREP
AC_PROG_EGREP
AC_PROG_CXX
 ...
AC_HEADER_STDBOOL
AC_C_INLINE
AC_TYPE_PID_T
AC_TYPE_SIZE_T
AC_TYPE_SSIZE_T
AC_TYPE_UINT8_T
AC_TYPE_UINT16_T
AC_TYPE_UINT32_T

AC_FUNC_ERROR_AT_LINE
AC_FUNC_FORK
AC_FUNC_MALLOC
AC_FUNC_MKTIME
AC_CHECK_FUNCS([memset socket])

AC_OUTPUT([Makefile]) # the makefile is only one!
                      # In the subdirectory I have created few
                      # Makemodule.am included in the "main makefile.am"

# --- makefile.am ---
AUTOMAKE_OPTIONS = foreign
lib_LIBRARIES = filea.a

libfilea_a_SOURCES =
include src/Makemodule.am
include src/containers/Makemodule.am # now filea_a_SOURCES is a
                                     # "global variable"
# -- src/Makemodule.am
libfilea_a_SOURCES += \
    src/ConfigLib.hpp \
    src/ConfigLib.cpp \
    src/HashFunctions.cpp \
    src/HashFunctions.hpp \
    src/Logger.hpp \
    src/Logger.cpp \
    src/Queue.hpp

# -- src/containers/Makemodule.am
libfile_a_SOURCES += \
    src/containers/SafeContainer.cpp \
    src/containers/SafeInterger.cpp \
    src/containers/SafeMap.cpp

请注意,现在即使Makemodule.am 文件被放置在目录树中的不同级别,只要在其中一个模块中键入文件名,它之前都必须有其相对路径。此路径相对于Makefile 位置。

【讨论】:

以上是关于无法将 c++ 项目完全编译和链接为静态库的主要内容,如果未能解决你的问题,请参考以下文章

将 C 库与 Haskell 库静态链接

gdbserver 找不到静态库课程

如何使用 C++ 静态库编译 C# 应用程序?

将 ruby​​ 库静态链接到 C++ 应用程序

使用 Visual Studio 2010 将 libexif 编译为静态库 - 然后从 Visual C++ 项目链接

为啥我无法链接到使用动态并行和可分离编译的 CUDA 静态库?