链接到目录中所有文件的惯用方式(包括文件夹,src等...)

时间:2018-09-08 00:33:20

标签: c++ c compilation portaudio

我正在运行一个简单的PortAudio示例,将正弦波写入流中,并遇到一系列方法,问题从portaudio.h file not foundlinker command failed...Undefined symbols...referenced from:

这不一定是关于PortAudio的问题。

main.cpp
project
│
├── src
│   ├── source.cpp
│   └── *.cpp
└── include
    ├── source.h
    └── *.h

是否有一种常规的方式(可能是递归的)链接project中的所有文件,以确保source.cpp中定义的所有方法(以及相关的#include在{{1}中可用) }),而无需更改源或文件结构?

1 个答案:

答案 0 :(得分:0)

尽管可能不是最简单/最有效的方法,但最终还是编写了一个小脚本,但仍然可以达到结果。

#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <list>

/*
*   A C++ script to recursively link
*   all folders in a project as include search paths
*   and compile all source code against a main file.
*
*   Example:
*
*       link.cpp
*       main.cpp
*       project
*       │
*       ├── src
*       │   ├── source.cpp
*       │   └── *.cpp
*       └── include
*          ├── source.h
*          └── *.h
*   Usage:
*       g++ link.cpp -std=c++11 -o link
*       ./link main.cpp project -O2 -Wall -pedantic
*   Output:
*       Compiling ... g++ main.cpp  project/src/source.cpp -I project/include -I project/src -O2 -Wall -pedantic
*
*   /link paex_sine_c++.cpp portaudio -framework CoreAudio -framework CoreFoundation -framework AudioToolbox -framework CoreServices
*
*   
*/

std::list<std::string> source_list = {};
std::list<std::string> header_list = {};

int is_dir(const char *path)
{
    struct stat statbuf;
    if (stat(path, &statbuf) != 0)
        return 0;
    return S_ISDIR(statbuf.st_mode);
}

void run(std::string f, std::string pre[] = NULL, std::string post[] = NULL)
{
    if (pre == NULL && post == NULL)
    {   
        std::system(f.c_str());
    }   
    else if (f.length())
    {
        std::string call = pre[0] + f + post[0];
        std::system(call.c_str());
    } else {
        std::cout << "Error... no file was entered" << std::endl;
    }
}

void dirSearch(std::string p)
{
    FILE *fp;
    char path[100];

    std::string cd = "cd ";
    std::string ls = " && ls";
    std::string cmd = cd + p + ls;

    fp = popen(cmd.c_str(), "r");
    if (fp == NULL) {
        printf("Failed to run command\n");
        exit(1);
    }
    while (fgets(path, sizeof(path)-1, fp) != NULL) {

        std::string abs_path = p + "/" + path;

        // rm \n
        abs_path.pop_back();

        if ( is_dir(abs_path.c_str()) ) {
            header_list.push_back(abs_path);
            dirSearch(abs_path);
        }
        else {
            std::string SOURCE_FILE_EXT = ".c";

            if (abs_path.substr(abs_path.size() - SOURCE_FILE_EXT.size(), abs_path.size()) == SOURCE_FILE_EXT) {
                source_list.push_back(abs_path);
            }
        }
    }
    pclose(fp);
}

void compile(const char *f)
{
    std::string pre[1] = {"gcc "};
    std::string post[1] = {" && ./a.out"};
    run(f, pre, post);
}

int main(int argc, char **argv)
{
    dirSearch(argv[2]);

    std::string headers = "";
    std::string fsource = " ";
    std::string gcc_args = "";

    // add header path
    for (std::string l : header_list) {
        headers += " -I " + l;
    }
    // add source files
    for (std::string l : source_list) {
        fsource += " " + l;
    }
    // add in cmd args
    for (int i = 3; i < argc; i++){
        cmd_args += " ";
        cmd_args += argv[i];
    }

    std::string fmain = argv[1];
    std::string cmd = fmain + fsource.c_str() + headers.c_str() + cmd_args;

    std::cout << "Compiling ... gcc " << cmd.c_str() << std::endl;
    compile(cmd.c_str());
}