Makefile生成器,使用C++和Boost实现

今天学习了一下Boost的文件遍历功能,同时发现GNU编译器有-MM选项,可以自动生成依赖关系,于是利用以上两点写了一个Makefile生成器。可以生成一般的单个可执行文件的Makefile,使用的是Windows+Mingw+boost环境。如果使用Linux,只需在程序中的两个System系统调用处和clean标签生成处将del 改成rm相关操作就好了。

下面是源代码:

makemake.cpp:

#include <iostream>
#include <fstream>
#include <cstdlib>
#include <vector>
#include <string>
#include <exception>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/program_options.hpp>

using namespace std;
namespace po = boost::program_options;
using namespace boost::filesystem;
using namespace boost;

void getFiles(vector<string>& src);

const string head = string(
"######################################################################\n")+
"# This makefile is generated by makemake.                            #\n"+
"# By Eric Brown.                                                     #\n"+
"# 2014/10/27                                                         #\n"+
"######################################################################\n";

int main(int argc, char* argv[])
{
	vector<string> src;
	string compiler = "g++";
	string target = "a";
	vector<string> objs;
	bool debug = false;

	try
	{
		po::options_description desc("---Help---");
		desc.add_options()
			("help,h", "print this message.")
			("gcc,c", "use gcc compiler. Program uses g++ default.")
			("debug,g", "use debug option(-g) in makefile.")
			("out,o", po::value<string>(), "the target file name.");
		po::positional_options_description p;
		p.add("out", -1);
		po::variables_map vm;
		po::store(po::command_line_parser(argc, argv).options(desc).
				positional(p).run(), vm);
		po::notify(vm);

		if (vm.count("help"))
		{
			cout << desc << endl;
			return 0;
		}
		if (vm.count("gcc"))
			compiler = "gcc";
		if (vm.count("out"))
			target = vm["out"].as<string>();
		if (vm.count("debug"))
			debug = true;
	} catch(std::exception& e) {
		cout << e.what() << endl;
		return 1;
	}

	getFiles(src);

	ofstream make;
	make.open("Makefile", ios_base::out);
	
	make << head << endl;
	make << "CC = " << compiler << endl;
	make << "Flags = ";
	if (debug)
		make << "-g";

	make << endl;

	make << "src = ";
	for (int i = 0; i < src.size(); ++i)
	{
		make << src[i] << ' ';
		std::system(string(compiler + " -MM \"" + src[i] + "\" >> .temp~").c_str());
	}

	make << "\nObjs = ";
	for (int i = 0; i < src.size(); ++i)
	{
		if (ends_with(src[i], ".cpp"))
			objs.push_back(replace_last_copy(src[i], ".cpp", ".o"));
		if (ends_with(src[i], ".c"))
			objs.push_back(replace_last_copy(src[i], ".c", ".o"));
		make << objs[i] << ' ';
	}
	make << endl;

	make << '\n' << target << ".exe: $(Objs)" << endl;
	make << "\t$(CC) $(Flags) $(Objs) -o " << target << ".exe" << endl;
	make << "$(Objs): $<" << endl;
	make << "\t$(CC) $(Flags) $< -c\n" << endl;

	ifstream in(".temp~");
	string line;
	while(getline(in, line))
		make << line << endl;
	make << endl;

	make << "clean:" << endl;
	make << "\tdel *.o" << endl;
	make << "cleanbak:" << endl;
	make << "\tdel *~" << endl;
	in.close();

	std::system("del .temp~");

	make.close();

	return 0;
}

void getFiles(vector<string>& src)
{
	path p = current_path();
	directory_iterator beg(p);
	directory_iterator end;
	for (; beg != end; beg++)
	{
		string name = beg->path().filename().string();
		if (ends_with(name, ".cpp") ||
			ends_with(name, ".c"))
			src.push_back(name);
	}
}
可执行程序可以在这里下载:http://download.csdn.net/detail/pdcxs007/8090981。


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。