简体   繁体   English

Makefile和多文件C ++模板问题

[英]makefile and multiple file C++ template issue

I've got a C++ template class split into two files using #include directive as suggested in this link --> Templates spread across multiple files 我已经按照此链接中的建议使用#include指令将C ++模板类分为两个文件-> 模板分布在多个文件中

For both files I've used the standard naming *.h and *.cpp. 对于这两个文件,我都使用标准命名* .h和* .cpp。 In the makefile I've included the *.h one since - as I understand it - both files split in such way are in fact one from the compiler point of view. 在makefile中,我加入了* .h,因为-据我了解-从编译器的角度来看,以这种方式拆分的两个文件实际上都是其中一个。 I've set the same compilation options as in case of compiling a ususal *.cpp file. 我已经设置了与编译常用* .cpp文件相同的编译选项。

However, when I try to compile it through makefile i get the following error: 但是,当我尝试通过makefile对其进行编译时,出现以下错误:

Stos.o: file not recognized: File format not recognized
collect2: ld returned 1 exit status
make: *** [program] Error 1

I've read somewhere that it might be due to the fact that I compile *.h file. 我在某处读到它可能是由于我编译* .h文件所致。 I do not know what should I do instead. 我不知道该怎么办。

Thank you for your help. 谢谢您的帮助。

EDIT 编辑

I am posting the makefile itself to make matter more clear. 我将发布makefile本身,以使事情更加清楚。 Please, excuse me that the names are not in English, however in this case this shouldn't be a problem. 请原谅我的名字不是英语,但是在这种情况下这应该不是问题。 I've updated the error message so that it fits the makefile. 我已经更新了错误消息,使其适合Makefile。

Because of suggestions here, I've already changed names for template files from *.h and *.cpp mentioned above to *.hpp and *.tpp. 由于这里的建议,我已经将模板文件的名称从上面提到的* .h和* .cpp更改为* .hpp和* .tpp。

CC=g++
CFLAGS=-c -Wall -pedantic -W
COMP= $(CC) $(CFLAGS)

program: Graf.o wgraf.o wnazwe.o menu.o Stos.o TabDyn.o komunikaty.o main.o
    $(CC) Graf.o wgraf.o wnazwe.o menu.o Stos.o TabDyn.o komunikaty.o main.o -o program
Graf.o: graf_struktura/Graf.cpp graf_struktura/Graf.h lifo/TabDyn.hpp lifo/Stos.hpp
    $(COMP) graf_struktura/Graf.cpp -o $@
wgraf.o: wczytywanie_grafu/wczytaj_graf.cpp wczytywanie_grafu/wczytaj_graf.h    graf_struktura/Graf.h lifo/Stos.hpp
    $(COMP) wczytywanie_grafu/wczytaj_graf.cpp -o $@
wnazwe.o: wczytywanie_grafu/wczytaj_nazwe_pliku.cpp    wczytywanie_grafu/wczytaj_nazwe_pliku.h wczytywanie_grafu/komunikaty.cpp 
    $(COMP) wczytywanie_grafu/wczytaj_nazwe_pliku.cpp -o $@
komunikaty.o: wczytywanie_grafu/komunikaty.cpp
    $(COMP) wczytywanie_grafu/komunikaty.cpp
menu.o: menu/menu.cpp graf_struktura/Graf.h
    $(COMP) menu/menu.cpp
main.o: main.cpp wczytywanie_grafu/wczytaj_nazwe_pliku.h    wczytywanie_grafu/wczytaj_graf.h menu/menu.cpp graf_struktura/Graf.h
    $(COMP) main.cpp
#Here is the issue.
Stos.o: lifo/Stos.hpp lifo/Stos.tpp lifo/TabDyn.hpp
    $(COMP) lifo/Stos.hpp -o $@
TabDyn.o: lifo/TabDyn.hpp lifo/TabDyn.tpp
    $(COMP) lifo/TabDyn.hpp -o $@

Compiler actually creates "Stos.o" but fails to include it in "program" producing quoted error. 编译器实际上创建了“ Stos.o”,但未能将其包含在“程序”中,从而产生了引用的错误。

Hope that now my issue is more clear. 希望现在我的问题更加清楚。 Sorry if makefile is not elegant. 很抱歉,如果makefile不优雅。 I'm still a beginner at makefiles, please be understanding. 我仍然是makefiles的初学者,请谅解。

If your MyClass.h looks like 如果您的MyClass.h看起来像

#ifndef MYCLASS_H
#define MYCLASS_H
template<typename T>
  struct MyClass
  {
    void f();
  };
#include "MyClass.tcc"
#endif

And the MyClass.tcc file looks like 和MyClass.tcc文件看起来像

template<typename T>
  void
  MyClass::f(T)
  { }

Then code that uses the template, say in a file called main.cpp, looks like: 然后使用该模板的代码,例如在名为main.cpp的文件中,看起来像:

#include "MyClass.h"

int main()
{
  MyClass<int> m;
  m.f(1);
}

And the Makefile could look like: Makefile可能如下所示:

main: main.o
    $(CXX) $^ $(LDFLAGS) -o $@

main.o: main.cpp MyClass.h MyClass.tcc
    $(CXX) $(CXXFLAGS) $< -o $@

The makefile should not compile the template header, it compiles the main.cpp file into a .o, and lists the headers as dependencies. 生成文件不应编译模板头,它编译的main.cpp文件转换成以.o,并列出了标题为依赖关系。 If either of the headers or main.cpp changes then main.o will be recompiled. 如果头文件或main.cpp任何一个更改,那么main.o将被重新编译。 Don't compile the headers though. 但是不要编译头文件。

FWIW, in my own code I use .cc for source files, .h for headers and .tcc for inline definitions. FWIW,在我自己的代码中,我将.cc用于源文件,将.h用于标头,并将.tcc用于内联定义。 GCC knows that .tcc is a header file and will treat it correctly (as a header) if you say g++ foo.tcc , see http://gcc.gnu.org/onlinedocs/gcc/Overall-Options.html for the file extensions GCC recognises. GCC知道.tcc是头文件,如果您说g++ foo.tcc ,它将正确处理(作为头文件),有关文件,请参阅http://gcc.gnu.org/onlinedocs/gcc/Overall-Options.html 。 GCC识别的扩展。

NB rather than manually listing all the header dependencies you can use GCC to produce makefile fragments listing the dependencies, eg for main.cpp you would generate a main.d and in the makefile do include main.d ... that's beyond the scope of this answer though. 注意,您可以使用GCC生成列出依赖关系的makefile片段,而不是手动列出所有标头依赖关系,例如,对于main.cpp您将生成main.d并且在makefile中确实include main.d ...,这超出了这个答案虽然。

Include neither .h nor .cpp in your makefile. 在您的makefile文件中既不包含.h也不包含.cpp。 Files that use the template will include the .h (which will include the .cpp), and every translation unit will end up with (weak) symbols for all functions of the template without either of the files being in your Makefile. 使用模板的文件将包含.h(其中将包括.cpp),并且每个转换单元的模板所有功能都将以(弱)符号结尾,而您的Makefile中没有任何文件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM