Идиоматический способ ссылки на ВСЕ файлы в каталоге (включая папку, src и т. Д.) - PullRequest
0 голосов
/ 08 сентября 2018

Я запускаю простой пример PortAudio для записи синусоидальной волны в поток, и у меня возникают проблемы в диапазоне от portaudio.h file not found до linker command failed...Undefined symbols...referenced from: со списком методов.

Это не обязательно вопрос PortAudio.

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

Существует ли обычный способ связать все файлы в project (возможно, рекурсивно), чтобы обеспечить доступность всех методов, определенных в source.cpp (и связанных #include в main.cpp), без изменения источника или структура файла?

1 Ответ

0 голосов
/ 29 октября 2018

Закончилось написание небольшого скрипта, хотя, возможно, это не самый простой / эффективный способ, он все же достигает результата.

#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());
}
...