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

今天学习了一下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(  
"######################################################################
")+  
"# This makefile is generated by makemake.                            #
"+  
"# By Eric Brown.                                                     #
"+  
"# 2014/10/27                                                         #
"+  
"######################################################################
";  

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 << "
Objs = ";  
    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 << '
' << target << ": $(Objs)" << endl;  
    make << "	$(CC) $(Flags) $(Objs) -o " << target << " ${LIBS}" << endl;  
    make << "$(Objs): $<" << endl;
    make << "	$(CC) $(Flags) $< -c
" << endl;  

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

    make << "clean:" << endl;  
    make << "	rm -f ${Objs}" << endl;  
    make << "cleanbak:" << endl;  
    make << "	rm -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。