今天学习了一下Boost的文件遍历功能,同一时候发现GNU编译器有-MM选项。能够自己主动生成依赖关系,于是利用以上两点写了一个Makefile生成器。
能够生成一般的单个可运行文件的Makefile。使用的是Windows+Mingw+boost环境。假设使用Linux,仅仅需在程序中的两个System系统调用处和clean标签生成处将del 改成rm相关操作就好了。
如今更改成了Linux版本号。下载的版本号是Windows的。
以下是源码:
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 = " << endl;
make << "LIBS = ";
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 << ": $(Objs)" << endl;
make << "\t$(CC) $(Flags) $(Objs) -o " << target << " ${LIBS}" << 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 << "\trm -f ${Objs}" << endl;
make << "cleanbak:" << endl;
make << "\trm -f *~" << endl;
in.close();
std::system("rm -f .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。