不确定如何创建MakeFIle
Unsure how to create a MakeFIle
我在为一个包含3个c++文件的项目创建makefile时遇到了问题。
在包含文件(tree.h、helperMethods.h和main.cpp)的目录中,我首先使用命令emacs makefile.make。然后,在emacs中,我将makefile写入如下:
all: tree.h helperMethods.h main.cpp
[tab]g++ -std=c++0x -o project3 tree.h helperMethods.h main.cpp
我已经手动验证了命令g++ -std=c++0x -o project3 tree.h helperMethods.h main.cpp确实编译了这三个文件,并生成了一个可执行文件。
在此之后,我保存makefile,退出emacs,并尝试运行它。
首先,我使用make,但这返回:
make: *** No targets specified and no makefile found. Stop.
然后我尝试使用make -f makefile。Make ,但这也不起作用,返回:
make: Nothing to be done for `all'.
在这一点上,我不确定为什么没有正确构造makefile。我没有很多制作文件的经验;我很确定我在makefile的主体中有正确的命令,但是当我写它时,我没有正确地设置它。
如果是相关的,这里有3个文件:
tree.h:
#ifndef tree_h
#define tree_h
#include <vector>
using namespace std;
template<class T>
class tree
{
public:
tree<T> * parent;
T element;
vector<tree<T> > nodes;
tree(const T& theElement)
{
element = theElement;
nodes = vector<tree<T> >();
}
tree()
{
nodes = vector<tree<T> >();
}
};
#endif
helperMethods.h
#ifndef helperMethods_h
#define helperMethods_h
#include "tree.h"
#include <tuple>
#include <string>
#include <iostream>
#include <vector>
using namespace std;
string printName(tuple<string, string, string> myTuple){
string ret = "";
if(std::get<0>(myTuple).length() > 0)
ret += get<0>(myTuple) + " ";
if(std::get<1>(myTuple).length() > 0 || std::get<2>(myTuple).length() > 0)
ret += "(";
if(std::get<1>(myTuple).length() > 0)
ret += get<1>(myTuple);
if(std::get<1>(myTuple).length() > 0 && std::get<2>(myTuple).length() > 0)
ret += ", ";
if(std::get<2>(myTuple).length() > 0)
ret += get<2>(myTuple);
if(std::get<1>(myTuple).length() > 0 || std::get<2>(myTuple).length() > 0)
ret += ")";
return ret;
}
bool tupleContain(tuple<string, string, string> myTuple, string myString){
return (std::get<0>(myTuple).compare(myString) == 0) || (std::get<1>(myTuple).compare(myString) == 0);
}
void findElement(tree<tuple<string, string, string> > myTree, string myString, bool* found, vector<int> *ret)
{
if(tupleContain(myTree.element, myString))
*found = true;
if(! * found)
{
for(int counter = 0; counter < (int)myTree.nodes.size(); counter ++)
{
if(!* found)
{
(*ret).push_back(counter);
findElement(myTree.nodes.at(counter), myString, found, ret);
if(!* found)
(*ret).pop_back();
}
}
}
}
void getLineage(tree<tuple<string, string, string> > myTree, string myString){
bool dummyForFound = false;
bool * found = & dummyForFound;
vector<int> lineage = vector<int>();
vector<int> * pointer = & lineage;
findElement(myTree, myString, found, &lineage);
if(lineage.size() == 0)
{
cout << "Species not present" << endl;
return;
}
vector<string> printString = vector<string>(lineage.size() + 1);
tree<tuple<string, string, string> > * currentNodePointer = & myTree;
for(int counter = 0; counter <= (int) lineage.size(); counter ++)
{
string currentLine = "";
for(int counter2 = 0; counter2 < 2*((int) lineage.size() - counter); counter2 ++)
currentLine += ">";
if(counter != lineage.size())
currentLine += " ";
tree<tuple<string, string, string> > currentNode = * currentNodePointer;
currentLine += printName(currentNode.element);
if(counter < (int) lineage.size())
{
int foo = lineage.at(counter);
tree<tuple<string, string, string> > currentNodeDummy = currentNode.nodes.at(foo);
*currentNodePointer = currentNodeDummy;
}
printString.at(counter) = currentLine;
}
for(int counter = 0; counter < (int) printString.size(); counter ++)
cout << printString.at(printString.size() - counter - 1) << endl;
cout << endl;
}
void getCommonLineage(tree<tuple<string, string, string> > myTree , string name1, string name2)
{
bool dummyForFound = false;
bool * found = & dummyForFound;
vector<int> lineage1 = vector<int>();
vector<int> * pointer1 = & lineage1;
vector<int> lineage2 = vector<int>();
vector<int> * pointer2 = & lineage2;
findElement(myTree, name1, found, pointer1);
* found = false;
findElement(myTree, name2, found, pointer2);
if(lineage2.size() == 0 || lineage1.size() == 0)
{
cout << "At least one species not present." << endl;
return;
}
bool stillSame = lineage1.at(0) == lineage2.at(0);
cout << "Level[0] Common Ancestor: ROOT (ROOT, ROOT)" << endl;
tree<tuple<string, string, string>> * lastSharedNode = & myTree;
int finalCounter = 0;
for(int counter = 0; counter < (int) min(lineage1.size(), lineage2.size()) && stillSame; counter ++)
{
tree<tuple<string, string, string> > dummyNode = * lastSharedNode;
tree<tuple<string, string, string> > currentNode = dummyNode.nodes.at(lineage1.at(counter));
*lastSharedNode = currentNode;
if(counter < (int) min(lineage1.size(), lineage2.size()) - 1 && lineage1.at(counter + 1) != lineage2.at(counter + 1))
stillSame = false;
tuple<string, string, string> currentElement = currentNode.element;
cout << "Level[" << counter + 1 << "] Commont Ancestor: " << printName(currentElement) << endl;
finalCounter ++;
}
cout << endl;
cout << "Ancestry unique to " << name1 << endl;
tree<tuple<string, string, string> > savedNode = *lastSharedNode;
tree<tuple<string, string, string> > * currentUnsharedNode = lastSharedNode;
for(int counter = finalCounter; counter < (int) lineage1.size(); counter ++)
{
tree<tuple<string, string, string> > dummyNode = * currentUnsharedNode;
tree<tuple<string, string, string> > currentNode = dummyNode.nodes.at(lineage1.at(counter));
tuple<string, string, string> currentElement = currentNode.element;
*currentUnsharedNode = currentNode;
cout << "Level[" << counter + 1 << "] ";
if(counter == lineage1.size() - 1)
cout << "Species of interest: ";
cout << printName(currentElement) << endl;
}
cout << endl;
currentUnsharedNode = &savedNode;
cout << "Ancestry unique to " << name2 << endl;
for(int counter = finalCounter; counter < (int) lineage2.size(); counter ++)
{
tree<tuple<string, string, string> > dummyNode = * currentUnsharedNode;
tree<tuple<string, string, string> > currentNode = dummyNode.nodes.at(lineage2.at(counter));
tuple<string, string, string> currentElement = currentNode.element;
*currentUnsharedNode = currentNode;
cout << "Level[" << counter + 1 << "] ";
if(counter == lineage2.size() - 1)
cout << "Species of interest: ";
cout << printName(currentElement) << endl;
}
cout << endl;
}
#endif
main.cpp
#include "rapidxml.h"
#include "tree.h"
#include "helperMethods.h"
#include <string>
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <vector>
#include <queue>
#include <tuple>
using namespace rapidxml;
int main(int argc, const char * arv[]){
tuple<string, string, string> human ("Human", "Homo sapiens", "Species");
tuple<string, string, string> apes ("Apes", "", "");
tuple<string, string, string> dogs ("Dogs", "", "");
tuple<string, string, string> root ("Root", "", "");
tuple<string, string, string> bears ("Bears", "", "");
tuple<string, string, string> cat ("Cat", "", "");
tuple<string, string, string> horse ("Horse", "", "");
tree<tuple<string, string, string> > myTree = tree<tuple<string, string, string>>(root);
tree<tuple<string, string, string> > b = tree<tuple<string, string, string>>(dogs);
tree<tuple<string, string, string> > c = tree<tuple<string, string, string>>(apes);
tree<tuple<string, string, string> > d = tree<tuple<string, string, string>>(bears);
tree<tuple<string, string, string> > e = tree<tuple<string, string, string>>(horse);
tree<tuple<string, string, string> > f = tree<tuple<string, string, string>>(human);
tree<tuple<string, string, string> > h = tree<tuple<string, string, string>>(cat);
d.nodes.push_back(f);
e.nodes.push_back(h);
b.nodes.push_back(d);
b.nodes.push_back(e);
myTree.nodes.push_back(b);
myTree.nodes.push_back(c);
cout << printName(myTree.nodes.at(0).element);
cout << "Welcome to my Tree of Life program!" << endl << endl;
int choice = 1;
while(choice == 1 || choice == 2) {
cout << "Please choose from the following options:" << endl;
cout << " 1.Get the lineage of a species" << endl;
cout << " 2.Get the commmon lineage of two species" << endl;
cout << " 3.Exit program" << endl << endl;
cin >> choice;
cout << endl;
if(choice == 1)
{
cout << "Please enter the name of the species of interest:" << endl;
string name;
cin >> name;
cout << endl;
getLineage(myTree, name);
}
if(choice == 2)
{
string name1, name2;
cout << "Please enter the name of the first species: " << endl;
cin >> name1;
cout << "Please enter the name of the second species: " << endl;
cin >> name2;
getCommonLineage(myTree, name1, name2);
}
}
return 0;
}
makefile通常被称为Makefile
(尽管makefile
也可以),没有任何扩展。如果您使用扩展名(不推荐),您必须告诉make
制作文件的名称。那既乏味又不必要。
第二,您不需要在编译命令行中放置头文件,也不应该这样做。在文件中使用#include
行来指定头文件。所以你的编译命令可能看起来像这样:
g++ -std=c++0x -o project3 main.cpp
现在,在这个命令中:
main.cpp
为源project3
是目标(即要创建的文件)
:
-
tree.h
和helperMethods.h
是编译工作所必需的;编译依赖于这个文件。(你知道这一点,但它们不会显示在命令行中,所以它不明显。)此外,如果它们改变了,你必须重新编译你的文件。
makefile解释了如何从源生成目标,并列出了目标的依赖项。(从技术上讲,make并不区分源和依赖;它认为它们都是先决条件。)
对于上面的命令,整个make recipe可能看起来像这样:
project3: main.cpp tree.h helperMethods.h
g++ -std=c++0x -o project3 main.cpp
通常,我们不使用main.cpp
;相反,我们将项目3的主文件称为project3.cpp
,就像目标(输出)文件是project3
一样。实际上,如果您这样做了,并且您没有任何其他依赖项(头文件),您可以键入:
make project3
根本没有makefile , make
会显示命令:
g++ -o project3 project3.cpp
在这种情况下,该命令将是错误的,因为它没有指定正确的c++标准。但它通常是有效的,这是一个很好的理由来命名您的目标和源具有相同的基本名称。
还有一件事:您的文件tree.h
是一个仅限头文件的库,这很好。但helperMethods.h
只是假装是一个头文件。这确实是一个完整的实现。你应该解决这个问题。
另外,把using namespace std
放在头文件中真的是一个坏主意。头文件应该在所有需要它的地方显式地使用std::
命名空间前缀。通常不建议在任何地方使用using namespace std
,但它在头文件中尤其糟糕,因为它会无声地污染任何包含头文件的默认名称空间。这可能导致非常模糊的bug,或者编译错误。
学校作业,嗯?对于你自己正在做的事情来说,project3
似乎是一个可怕的任意名称。
您不需要在makefile处理中包含.h文件,因为严格地说,它们不需要单独编译。你的makefile需要一个规则来构建main。然后是一个从main.o中构建可执行文件的规则。头文件应该作为main的依赖项添加。因此,如果它们中的任何一个改变,make
将知道从那里重建。
基本上,它需要看起来像这样:
# http://stackoverflow.com/questions/15458126/unsure-how-to-create-a-makefile
all: project3
clean:
-rm main.o project3
project3: main.o
g++ -std=c++0x -o project3 main.o
main.o: main.cpp tree.h helperMethods.h
g++ -std=c++0x -c main.cpp
其他人可能会为此目的生成一个完全不同但同样有效的makefile。这个过程有一定的自由度。
您在这里拥有的是构建整个东西的规则(请记住,如果没有提供目标,则自动选择makefile中的第一个),清理任何中间文件的规则,从目标文件构建可执行文件的规则,以及从源文件构建目标文件的规则。这种方法不能很好地扩展;对于更大、更复杂的makefile来说,手工管理所有的依赖关系是很不愉快的,但在这个非常简单的例子中,这很好。
- Makefile 创建两个库 - 一个依赖于另一个
- 通过构建配置创建makefile
- 您可以使用 makefile 从 .o 对象文件创建 C++ 文件吗?
- C MakeFile项目如何使用相同的Basename加上后缀和相同扩展名创建文件列表
- 如何在makefile中添加.c,.cc和.so文件以创建另一个.so
- 如何转换一个普通的makefile以创建可以在另一台计算机上使用的静态可执行文件
- 在Eclipse(Ubuntu)创建C Makefile项目时,如何生成.bin(可执行文件)
- 创建文件中断-ddebug标志在C 的makefile中
- 正在创建将.o存储到目录中的makefile c++
- makefile:未创建可执行文件
- C Gnu makefile我无法用ar创建静态库
- 如何创建一个只有主文件和模板头(C++)的makefile
- 如何使用 makefile 在 c++ 中创建静态/动态库
- GNU MAKE - 从我自己的 Makefile 创建 getoptpp 库或建议 c++ 的命令行选项库
- 如何(从字面上)创建一个makefile(用于linux中的c)
- 用多个cpp文件为vc++创建makefile
- 没有为opencv_contrib创建makefile
- 如何为现有项目创建Makefile
- 为c++程序创建makefile,以便与c++一起运行
- 不确定如何创建MakeFIle