【问题标题】:Using identical source files for multiple libraries with GNU Autotools使用 GNU Autotools 为多个库使用相同的源文件
【发布时间】:2014-05-26 12:19:14
【问题描述】:

我正在开发一个使用 GNU Autotools 进行构建的 C/C++ 项目。我的目录结构如下:

..
adapter/
    libraryA/
        include/
        src/
        ..
    libraryB/
        include/
        src/
        ..            
    ..
src/
    Log.cpp
    ..

除了libraryAlibraryB,我还有一个顶层库,称为libraryMain,它们都使用来自src 的相同Log.cpp。如果我使用传递给configure--disable-dependency-tracking 选项构建外源代码(另请参阅我的帖子here),libtool 抱怨

libtool: 链接: `Log.lo' 不是一个有效的 libtool 对象

在链接libraryMain 时,因为src 在构建libraryAlibraryB 时生成了Log.lo,然后libraryMain 引用了libraryB。如果我从src 中手动删除Log.lo 并重建libraryMain,一切正常,因为libraryMainbuild/src 中生成了自己的Log.lo

为了让事情更清楚,我的Makefile.am for libraryMain(位于src)如下所示:

..
libcomana_@COMANA_API_VERSION@_la_SOURCES = \
    .. \
    Log.cpp
..

libraryAMakefile.am(位于adapter/libraryA/src)是

..
libraryA_la_SOURCES = \
    .. \
    $(top_srcdir)/src/Log.cpp
..

我已经明白问题是由于adapter 中的库没有将它们生成的.lo 文件放在他们自己的目录中,而是直接放在项目根目录中的src 目录下。我实际上会假设没有 libtool 对象被放置在源代码树中,而是在构建树中,就像 libraryMain 所做的那样。作为第一个解决方法,我在adapter/libraryA/srcadapter/libraryB/src 中创建了指向src/Log.cpp 的符号链接,但我认为这可能不是很优雅。我真的希望我已经把自己说得够清楚了。我真的很感谢任何关于这个问题的 cmets。

【问题讨论】:

    标签: autotools


    【解决方案1】:

    好的,我想我的问题可能有点不清楚。最后,我通过省略--disable-dependency-tracking 选项并更改我的Makefile.ams 以不包括任何以$(srcdir)$(top_srcdir) 为前缀的源来规避问题,因为这似乎使automake 混淆,至少在构建时外源(另见我的帖子herethis 错误报告)。虽然我不知道这是否是正确的地方,但我决定建立一个小例子,它可以正常工作并避免我在问题中描述的问题。

    我的目录结构如下:

    autogen.sh
    configure.ac
    Makefile.am
    adapter
        Makefile.am
        adapterA
            Makefile.am
            include
                foo.h
            src
                foo.cpp
                Makefile.am                
        adapterB
            Makefile.am
            include
                foo.h
            src
                foo.cpp
                Makefile.am
    debug
    include
        hello.h
    m4
    src
        hello.cpp
        helloconf.sh.in
        Makefile.am
    

    文件包含以下代码:

    autogen.sh:

    #!/bin/sh
    
    # GNU autotools toolchain
    libtoolize --automake
    aclocal
    autoheader
    automake --add-missing --force-missing --gnu
    autoconf
    

    configure.ac:

    dnl Process this file with autoconf to produce a configure script.
    
    dnl Project name and version
    AC_INIT([hello], [0.1])
    
    dnl Library version information
    AC_SUBST([HELLO_API_VERSION], [0.1])
    AC_SUBST([HELLO_SO_VERSION], [0:0:0])
    
    dnl Create a separate header with C preprocessor `#define` statements
    AC_CONFIG_HEADERS([config.h])
    
    dnl Look for auxiliary scripts in the current directory
    AC_CONFIG_AUX_DIR([.])
    
    dnl Automake initialization
    dnl -Wall Show warnings
    dnl -Wall Treat warnings as errors
    dnl subdir-objects Place generated object files (.o) into the same as 
    dnl                directory their source files, in order to avoid 
    dnl                collisions when non-recursive make is used
    AM_INIT_AUTOMAKE([-Wall subdir-objects])
    m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
    
    dnl Libtool settings
    LT_INIT([disable-static])
    AC_CONFIG_MACRO_DIR([m4])
    
    dnl Doxygen
    dnl DX_HTML_FEATURE(ON)
    dnl DX_PDF_FEATURE(OFF)
    dnl DX_INIT_DOXYGEN([$PACKAGE_NAME], [Doxyfile], [doc])
    
    dnl Checks for programs
    AC_PROG_CXX([g++])
    AC_PROG_INSTALL
    AC_PROG_LN_S
    AM_PROG_LIBTOOL
    
    dnl Use the C++ compiler for the following checks
    AC_LANG([C++])
    
    dnl Checks for libraries
    
    dnl Checks for header files
    AC_HEADER_STDC
    AC_CHECK_HEADER(iostream)
    
    dnl Checks for typedefs, structures, and compiler characteristics
    AC_TYPE_SIZE_T
    
    dnl Checks for library functions
    
    dnl Compiler and linker flags
    AC_SUBST([AM_CXXFLAGS], [-Wall]) # C++
    AC_SUBST([AM_LDFLAGS], [-Wall]) # ld (Linker)
    
    dnl Libraries
    AC_SUBST([LIBS])
    
    AC_CONFIG_FILES(
        Makefile
        adapter/Makefile
        adapter/adapterA/Makefile
        adapter/adapterA/src/Makefile
        adapter/adapterB/Makefile
        adapter/adapterB/src/Makefile
        src/Makefile
        src/helloconf.sh
    )
    
    AC_OUTPUT
    

    Makefile.am:

    # Process this file with automake to produce Makefile.in
    
    # Independent executable script for inclusion in the distribution archive
    dist_noinst_SCRIPTS = autogen.sh
    
    # Look for additional autoconf macros in the m4 subdirectory
    ACLOCAL_AMFLAGS = \
        -I m4 \
        @ACLOCAL_FLAGS@
    
    # Subdirectories
    SUBDIRS = \
        adapter \
        src 
    
    # Entire directories copied recursively into the distribution
    EXTRA_DIST = 
    
    # Delete anything except for files required to run `./configure && make`
    MAINTAINERCLEANFILES = 
    
    # Delete anything which should not be part of the distribution
    DISTCLEANFILES = 
    

    adapter/Makefile.am:

    # Process this file with automake to produce Makefile.in
    
    SUBDIRS = \
        adapterA \
        adapterB
    

    adapter/adapterA/Makefile.am:

    # Process this file with automake to produce Makefile.in
    
    SUBDIRS = src
    

    adapter/adapterA/include/foo.h:

    #ifndef FOO_H_
    #define FOO_H_
    
    void foo();
    
    #endif
    

    adapter/adapterA/src/foo.cpp:

    #include <iostream>
    
    #include "foo.h"
    
    void foo()
    {
        std::cout << "Hello, foo from adapterA" << std::endl;
    }
    

    adapter/adapterA/src/Makefile.am:

    # Process this file with automake to produce Makefile.in
    
    # Adapter .so version
    ADAPTER_SO_VERSION = 0:0:0
    
    AM_CXXFLAGS = \
        -I$(top_srcdir)/include \
        -I$(srcdir)/../include \
        @AM_CXXFLAGS@
    
    # Library name
    lib_LTLIBRARIES = libadapter-@HELLO_API_VERSION@.la
    
    # Sources
    libadapter_@HELLO_API_VERSION@_la_SOURCES = \
        ../../../src/hello.cpp \
        foo.cpp
    
    # Linker flags    
    libadapter_@HELLO_API_VERSION@_la_LDFLAGS = \
        -version-info $(ADAPTER_SO_VERSION)
    
    # Include directory and headers
    libadapter_@HELLO_API_VERSION@_la_includedir = \
        $(exec_prefix)/include/adapter/adapterA
    libadapter_@HELLO_API_VERSION@_la_include_HEADERS = \
        ../include/foo.h
    
    # Library install directory
    libdir = $(exec_prefix)/lib/adapter/adapterA
    

    adapter/adapterB/Makefile.amadapter/adapterB/include/foo.h 与它们的 A 等效项相同。

    adapter/adapterB/src/foo.cpp:

    #include <iostream>
    
    #include "foo.h"
    
    void foo()
    {
        std::cout << "Hello, foo from adapterB" << std::endl;
    }
    

    adapter/adapterB/src/Makefile.am:

    # Process this file with automake to produce Makefile.in
    
    # Adapter .so version
    ADAPTER_SO_VERSION = 0:0:0
    
    AM_CXXFLAGS = \
        -I$(top_srcdir)/include \
        -I$(srcdir)/../include \
        @AM_CXXFLAGS@
    
    # Library name
    lib_LTLIBRARIES = libadapter-@HELLO_API_VERSION@.la
    
    # Sources
    libadapter_@HELLO_API_VERSION@_la_SOURCES = \
        ../../../src/hello.cpp \
        foo.cpp
    
    # Linker flags    
    libadapter_@HELLO_API_VERSION@_la_LDFLAGS = \
        -version-info $(ADAPTER_SO_VERSION)
    
    # Include directory and headers
    libadapter_@HELLO_API_VERSION@_la_includedir = \
        $(exec_prefix)/include/adapter/adapterB
    libadapter_@HELLO_API_VERSION@_la_include_HEADERS = \
        ../include/foo.h
    
    # Library install directory
    libdir = $(exec_prefix)/lib/adapter/adapterB
    

    include/hello.h:

    #ifndef HELLO_H_
    #define HELLO_H_
    
    void hello();
    
    #endif
    

    src/hello.cpp:

    #include <iostream>
    
    #include "hello.h"
    
    void hello()
    {
        std::cout << "Hello, world!" << std::endl;
    }
    

    src/helloconf.sh.in:

    #!/bin/bash
    
    echo @prefix@
    

    src/Makefile.am:

    # Process this file with automake to produce Makefile.in
    
    # Look for additional autoconf macros in the m4 subdirectory
    ACLOCAL_AMFLAGS = \
        -I m4 \
        @ACLOCAL_FLAGS@
    
    # Compiler flags
    AM_CXXFLAGS = \
        -I$(top_srcdir)/include \
        @AM_CXXFLAGS@
    
    # Library name
    lib_LTLIBRARIES = libhello-@HELLO_API_VERSION@.la
    
    # Sources
    libhello_@HELLO_API_VERSION@_la_SOURCES = \
        hello.cpp
    
    # Libraries
    libhello_@HELLO_API_VERSION@_la_LDFLAGS = \
        -version-info $(HELLO_SO_VERSION)
    libhello_@HELLO_API_VERSION@_la_LIBADD = @LTLIBOBJS@
    
    # Include directory and headers
    libhello_@HELLO_API_VERSION@_la_includedir = $(includedir)
    
    libhello_@HELLO_API_VERSION@_la_include_HEADERS = \
        $(top_srcdir)/include/hello.h
    
    # Data
    helloconf_DATA = helloconf.sh
    helloconfdir = $(exec_prefix)/bin
    EXTRA_DIST = $(helloconf_DATA)
    

    P.S.:我知道上传存档可能会更好,但我想将所有内容保存在一个地方。

    【讨论】:

      猜你喜欢
      • 2021-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-10
      • 1970-01-01
      相关资源
      最近更新 更多