Как программа на С ++ (. cpp) работает с заголовком (.h) и libtool (.la)? - PullRequest
0 голосов
/ 13 февраля 2020

Я создал папку в linux с именем helloworld. Внутри этой папки есть подкаталог:

  • include
  • lib
  • sr c

include / В этом каталоге я создал заголовочный файл с именем helloworld.h. Содержимое:

class helloworld{
public:

       void getvalue();

};

lib / В каталоге lib Я создал файл cpp с именем helloworld. Содержимое cpp в основном функции:

#include<iostream>
#include<helloworld.h>
using namespace std;

void helloworld::getvalue() {

}

src / В каталоге sr c у меня есть создайте основной cpp файл с именем main. cpp содержимое является основным:

#include<iostream>
#include<helloworld.h>

int main()
{
helloworld a;
a.getvalue();
}

, но после того, как я автоматически выполню автонастройку, automake, ./configure, и когда make, у него появляется ошибка:

helloworld/src/main.cpp:8: undefined reference to `helloworld::getvalue()'

Все, что я хочу, это использовать helloworld. Функции cpp в main. cpp. Я потратил много времени на поиски и попытки и ошибки. Пожалуйста помоги.

Добавлен Makefiles.am

в родительский каталог, у меня есть два файла Makefile.am и configure.a c:

Makefile.am

AUTOMAKE_OPTIONS = foreign
SUBDIRS=src lib

configure.a c

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

В каталоге sr c есть один файл 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();

Ответы [ 3 ]

1 голос
/ 19 февраля 2020

Это хороший демонстрационный пример для , а не , использующего рекурсивное 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 будет строить libhelloworld.la из исходного файла библиотеки lib/helloworld.cpp, который мне пришлось немного адаптировать для измененного имени заголовка:

# -*- 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();
}
1 голос
/ 13 февраля 2020
helloworld_LDADD=-L/lib/libhelloworld.la


/lib/libhelloworld.la  

эта библиотека поиска из root каталога, а не вашего проекта lib / directory

Попробуйте

./lib/libhelloworld.la

или

../lib/libhelloworld.la

или

lib/libhelloworld.la
0 голосов
/ 19 февраля 2020

Если вы настаиваете на использовании рекурсивного make, вам нужно добавить специальное правило к src/Makefile.am, чтобы убедиться, что применяются правила lib/Makefile.am для перестройки библиотеки (здесь не проверено, но используется в других проектах).

Теперь это означает, что обычная рекурсивная сборка будет строить ., include, lib, src, а затем lib снова. Я бы настоятельно рекомендовал отказаться от рекурсивного изготовления и использовать одно решение 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
...