| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321 |
- /* depcheck.cpp - Dependency checker for NMake Makefiles
- * Copyright (c) 2024 Mika T. Lindqvist
- */
- #include <fstream>
- #include <iostream>
- #include <sstream>
- #include <string>
- #include <vector>
- int main(int argc, char* argv[]) {
- if (argc != 3) {
- printf("Usage: depcheck Makefile <top_directory>\n");
- return -1;
- }
- std::filebuf fb;
- if (fb.open (argv[1],std::ios::in)) {
- std::istream is(&fb);
- std::string makefile = argv[1];
- std::string l, tmp, tmp2;
- while (is) {
- std::getline(is, l);
- while (l.back() == '\\') {
- std::getline(is, tmp);
- l.replace(l.length() - 1, 1, tmp);
- }
- size_t pos = l.find("obj:");
- if (pos != std::string::npos) {
- std::string objfile = l.substr(0, pos+3);
- printf("File: %s\n", objfile.c_str());
- std::vector<std::string> files;
- std::stringstream ss(l.substr(pos+4));
- while(getline(ss, tmp, ' ')){
- if (tmp != "" && tmp != "/") {
- files.push_back(tmp);
- }
- }
- for (auto it = files.begin(); it != files.end(); ++it) {
- printf("Dependency: %s\n", (*it).c_str());
- }
- if (!files.empty()) {
- std::filebuf fb2;
- std::string src = files[0];
- size_t pos2 = src.find("$(TOP)");
- if (pos2 != std::string::npos) {
- src.replace(pos2, 6, argv[2]);
- }
- printf("Source: %s\n", src.c_str());
- if (fb2.open(src.c_str(),std::ios::in)) {
- std::istream is2(&fb2);
- std::vector<std::string> includes;
- while (is2) {
- std::getline(is2, l);
- pos = l.find("#");
- if (pos != std::string::npos) {
- pos2 = l.find("include");
- size_t pos3 = l.find("\"");
- if (pos2 != std::string::npos && pos3 != std::string::npos && pos2 > pos && pos3 > pos2) {
- tmp = l.substr(pos3 + 1);
- pos2 = tmp.find("\"");
- if (pos2 != std::string::npos) {
- tmp = tmp.substr(0, pos2);
- }
- pos2 = tmp.find("../");
- if (pos2 != std::string::npos) {
- tmp = tmp.substr(3);
- }
- printf("Line: %s\n", tmp.c_str());
- int found = 0;
- for (size_t i = 1; i < files.size(); i++) {
- pos3 = files[i].find("$(SUFFIX)");
- if (pos3 != std::string::npos) {
- tmp2 = files[i].substr(0, pos3).append(files[i].substr(pos3 + 9));
- printf("Comparing dependency \"%s\" and \"%s\"\n", tmp2.c_str(), tmp.c_str());
- if (tmp2 == tmp) {
- printf("Dependency %s OK\n", tmp.c_str());
- found = 1;
- includes.push_back(tmp);
- break;
- }
- printf("Comparing dependency \"%s\" and \"$(TOP)/%s\"\n", tmp2.c_str(), tmp.c_str());
- if (tmp2 == std::string("$(TOP)/").append(tmp)) {
- printf("Dependency %s OK\n", tmp.c_str());
- found = 1;
- includes.push_back(tmp);
- break;
- }
- tmp2 = files[i].substr(0, pos3).append("-ng").append(files[i].substr(pos3 + 9));
- printf("Comparing dependency \"%s\" and \"%s\"\n", tmp2.c_str(), tmp.c_str());
- if (tmp2 == tmp) {
- printf("Dependency %s OK\n", tmp.c_str());
- found = 1;
- includes.push_back(tmp);
- break;
- }
- printf("Comparing dependency \"%s\" and \"$(TOP)/%s\"\n", tmp2.c_str(), tmp.c_str());
- if (tmp2 == std::string("$(TOP)/").append(tmp)) {
- printf("Dependency %s OK\n", tmp.c_str());
- found = 1;
- includes.push_back(tmp);
- break;
- }
- } else {
- printf("Comparing dependency \"%s\" and \"%s\"\n", files[i].c_str(), tmp.c_str());
- if (files[i] == tmp) {
- printf("Dependency %s OK\n", tmp.c_str());
- found = 1;
- includes.push_back(tmp);
- break;
- }
- printf("Comparing dependency \"%s\" and \"$(TOP)/%s\"\n", files[i].c_str(), tmp.c_str());
- if (files[i] == std::string("$(TOP)/").append(tmp)) {
- printf("Dependency %s OK\n", tmp.c_str());
- found = 1;
- includes.push_back(tmp);
- break;
- }
- printf("Comparing dependency \"%s\" and \"$(TOP)/arch/%s\"\n", files[i].c_str(), tmp.c_str());
- if (files[i] == std::string("$(TOP)/arch/").append(tmp)) {
- printf("Dependency %s OK\n", tmp.c_str());
- found = 1;
- includes.push_back(tmp);
- break;
- }
- printf("Comparing dependency \"%s\" and \"$(TOP)/arch/generic/%s\"\n", files[i].c_str(), tmp.c_str());
- if (files[i] == std::string("$(TOP)/arch/generic/").append(tmp)) {
- printf("Dependency %s OK\n", tmp.c_str());
- found = 1;
- includes.push_back(tmp);
- break;
- }
- printf("Comparing dependency \"%s\" and \"$(TOP)/arch/arm/%s\"\n", files[i].c_str(), tmp.c_str());
- if (files[i] == std::string("$(TOP)/arch/arm/").append(tmp)) {
- printf("Dependency %s OK\n", tmp.c_str());
- found = 1;
- includes.push_back(tmp);
- break;
- }
- printf("Comparing dependency \"%s\" and \"$(TOP)/arch/x86/%s\"\n", files[i].c_str(), tmp.c_str());
- if (files[i] == std::string("$(TOP)/arch/x86/").append(tmp)) {
- printf("Dependency %s OK\n", tmp.c_str());
- found = 1;
- includes.push_back(tmp);
- break;
- }
- printf("Comparing dependency \"%s\" and \"$(TOP)/test/%s\"\n", files[i].c_str(), tmp.c_str());
- if (files[i] == std::string("$(TOP)/test/").append(tmp)) {
- printf("Dependency %s OK\n", tmp.c_str());
- found = 1;
- includes.push_back(tmp);
- break;
- }
- }
- }
- // Skip irrelevant dependencies
- if (tmp.substr(0, 9) == "arch/s390") found = 1;
- if (tmp == "zlib-ng.h" && std::find(includes.begin(), includes.end(), "zlib.h") != includes.end()) found = 1;
- if (found == 0) {
- printf("%s: Dependency %s missing for %s!\n", makefile.c_str(), tmp.c_str(), objfile.c_str());
- return -1;
- }
- }
- }
- }
- for (size_t i = 1; i < files.size(); i++) {
- int found = 0;
- tmp = files[i];
- printf("Dependency: %s\n", tmp.c_str());
- pos2 = tmp.find("$(TOP)");
- if (pos2 != std::string::npos) {
- tmp = tmp.substr(7);
- }
- for (size_t j = 0; j < includes.size(); j++) {
- pos2 = tmp.find("$(SUFFIX)");
- if (pos2 != std::string::npos) {
- std::string tmp1 = tmp.substr(0, pos2).append(tmp.substr(pos2 + 9));
- printf("[%zd/%zd] Comparing dependency \"%s\" and \"%s\"\n", j, includes.size(), tmp1.c_str(), includes[j].c_str());
- if (tmp1 == includes[j]) {
- printf("Dependency %s OK\n", files[i].c_str());
- found = 1;
- break;
- }
- printf("[%zd/%zd] Comparing dependency \"%s\" and \"arch/%s\"\n", j, includes.size(), tmp1.c_str(), includes[j].c_str());
- if (tmp1 == std::string("arch/").append(includes[j])) {
- printf("Dependency %s OK\n", files[i].c_str());
- found = 1;
- break;
- }
- printf("[%zd/%zd] Comparing dependency \"%s\" and \"arch/generic/%s\"\n", j, includes.size(), tmp1.c_str(), includes[j].c_str());
- if (tmp1 == std::string("arch/generic/").append(includes[j])) {
- printf("Dependency %s OK\n", files[i].c_str());
- found = 1;
- break;
- }
- printf("[%zd/%zd] Comparing dependency \"%s\" and \"arch/arm/%s\"\n", j, includes.size(), tmp1.c_str(), includes[j].c_str());
- if (tmp1 == std::string("arch/arm/").append(includes[j])) {
- printf("Dependency %s OK\n", files[i].c_str());
- found = 1;
- break;
- }
- printf("[%zd/%zd] Comparing dependency \"%s\" and \"arch/x86/%s\"\n", j, includes.size(), tmp1.c_str(), includes[j].c_str());
- if (tmp1 == std::string("arch/x86/").append(includes[j])) {
- printf("Dependency %s OK\n", files[i].c_str());
- found = 1;
- break;
- }
- printf("[%zd/%zd] Comparing dependency \"%s\" and \"test/%s\"\n", j, includes.size(), tmp1.c_str(), includes[j].c_str());
- if (tmp1 == std::string("test/").append(includes[j])) {
- printf("Dependency %s OK\n", files[i].c_str());
- found = 1;
- break;
- }
- tmp1 = tmp.substr(0, pos2).append("-ng").append(tmp.substr(pos2 + 9));
- printf("[%zd/%zd] Comparing dependency \"%s\" and \"%s\"\n", j, includes.size(), tmp1.c_str(), includes[j].c_str());
- if (tmp1 == includes[j]) {
- printf("Dependency %s OK\n", files[i].c_str());
- found = 1;
- break;
- }
- printf("[%zd/%zd] Comparing dependency \"%s\" and \"arch/%s\"\n", j, includes.size(), tmp1.c_str(), includes[j].c_str());
- if (tmp1 == std::string("arch/").append(includes[j])) {
- printf("Dependency %s OK\n", files[i].c_str());
- found = 1;
- break;
- }
- printf("[%zd/%zd] Comparing dependency \"%s\" and \"arch/generic/%s\"\n", j, includes.size(), tmp1.c_str(), includes[j].c_str());
- if (tmp1 == std::string("arch/generic/").append(includes[j])) {
- printf("Dependency %s OK\n", files[i].c_str());
- found = 1;
- break;
- }
- printf("[%zd/%zd] Comparing dependency \"%s\" and \"arch/arm/%s\"\n", j, includes.size(), tmp1.c_str(), includes[j].c_str());
- if (tmp1 == std::string("arch/arm/").append(includes[j])) {
- printf("Dependency %s OK\n", files[i].c_str());
- found = 1;
- break;
- }
- printf("[%zd/%zd] Comparing dependency \"%s\" and \"arch/x86/%s\"\n", j, includes.size(), tmp1.c_str(), includes[j].c_str());
- if (tmp1 == std::string("arch/x86/").append(includes[j])) {
- printf("Dependency %s OK\n", files[i].c_str());
- found = 1;
- break;
- }
- printf("[%zd/%zd] Comparing dependency \"%s\" and \"test/%s\"\n", j, includes.size(), tmp1.c_str(), includes[j].c_str());
- if (tmp1 == std::string("test/").append(includes[j])) {
- printf("Dependency %s OK\n", files[i].c_str());
- found = 1;
- break;
- }
- } else {
- printf("[%zd/%zd] Comparing dependency \"%s\" and \"%s\"\n", j, includes.size(), tmp.c_str(), includes[j].c_str());
- if (tmp == includes[j]) {
- printf("Dependency %s OK\n", files[i].c_str());
- found = 1;
- break;
- }
- printf("[%zd/%zd] Comparing dependency \"%s\" and \"arch/%s\"\n", j, includes.size(), tmp.c_str(), includes[j].c_str());
- if (tmp == std::string("arch/").append(includes[j])) {
- printf("Dependency %s OK\n", files[i].c_str());
- found = 1;
- break;
- }
- printf("[%zd/%zd] Comparing dependency \"%s\" and \"arch/generic/%s\"\n", j, includes.size(), tmp.c_str(), includes[j].c_str());
- if (tmp == std::string("arch/generic/").append(includes[j])) {
- printf("Dependency %s OK\n", files[i].c_str());
- found = 1;
- break;
- }
- printf("[%zd/%zd] Comparing dependency \"%s\" and \"arch/arm/%s\"\n", j, includes.size(), tmp.c_str(), includes[j].c_str());
- if (tmp == std::string("arch/arm/").append(includes[j])) {
- printf("Dependency %s OK\n", files[i].c_str());
- found = 1;
- break;
- }
- printf("[%zd/%zd] Comparing dependency \"%s\" and \"arch/x86/%s\"\n", j, includes.size(), tmp.c_str(), includes[j].c_str());
- if (tmp == std::string("arch/x86/").append(includes[j])) {
- printf("Dependency %s OK\n", files[i].c_str());
- found = 1;
- break;
- }
- printf("[%zd/%zd] Comparing dependency \"%s\" and \"test/%s\"\n", j, includes.size(), tmp.c_str(), includes[j].c_str());
- if (tmp == std::string("test/").append(includes[j])) {
- printf("Dependency %s OK\n", files[i].c_str());
- found = 1;
- break;
- }
- }
- }
- // Skip indirect dependencies
- if (tmp.find("arm_features.h") != std::string::npos
- && std::find(includes.begin(), includes.end(), "cpu_features.h") != includes.end()
- && (makefile.find(".arm") != std::string::npos
- || makefile.find(".a64") != std::string::npos)) found = 1;
- if (tmp.find("x86_features.h") != std::string::npos
- && std::find(includes.begin(), includes.end(), "cpu_features.h") != includes.end()
- && makefile.find(".msc") != std::string::npos) found = 1;
- //
- if (tmp.find("generic_functions.h") != std::string::npos
- && std::find(includes.begin(), includes.end(), "arch_functions.h") != includes.end()) found = 1;
- if (tmp.find("arm_functions.h") != std::string::npos
- && std::find(includes.begin(), includes.end(), "arch_functions.h") != includes.end()
- && (makefile.find(".arm") != std::string::npos
- || makefile.find(".a64") != std::string::npos)) found = 1;
- if (tmp.find("x86_functions.h") != std::string::npos
- && std::find(includes.begin(), includes.end(), "arch_functions.h") != includes.end()
- && makefile.find(".msc") != std::string::npos) found = 1;
- if (found == 0) {
- printf("%s: Dependency %s not needed for %s\n", makefile.c_str(), files[i].c_str(), objfile.c_str());
- return -1;
- }
- }
- fb2.close();
- }
- }
- }
- }
- fb.close();
- }
- return 0;
- }
|