1 // Copyright (C) 2017 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include <header_abi_util.h> 16 17 #include <llvm/Support/raw_ostream.h> 18 #include <llvm/Support/FileSystem.h> 19 #include <llvm/Support/Path.h> 20 21 #include <set> 22 #include <string> 23 #include <vector> 24 25 namespace abi_util { 26 ShouldSkipFile(llvm::StringRef & file_name)27static bool ShouldSkipFile(llvm::StringRef &file_name) { 28 // Ignore swap files and hidden files / dirs. Do not recurse into them too. 29 // We should also not look at source files. Many projects include source 30 // files in their exports. 31 if (file_name.empty() || file_name.startswith(".") || 32 file_name.endswith(".swp") || file_name.endswith(".swo") || 33 file_name.endswith("#") || file_name.endswith(".cpp") || 34 file_name.endswith(".cc") || file_name.endswith(".c")) { 35 return true; 36 } 37 return false; 38 } 39 CollectExportedHeaderSet(const std::string & dir_name,std::set<std::string> * exported_headers)40bool CollectExportedHeaderSet(const std::string &dir_name, 41 std::set<std::string> *exported_headers) { 42 std::error_code ec; 43 llvm::sys::fs::recursive_directory_iterator walker(dir_name, ec); 44 // Default construction - end of directory. 45 llvm::sys::fs::recursive_directory_iterator end; 46 llvm::sys::fs::file_status status; 47 for ( ; walker != end; walker.increment(ec)) { 48 if (ec) { 49 llvm::errs() << "Failed to walk dir : " << dir_name << "\n"; 50 return false; 51 } 52 53 const std::string &file_path = walker->path(); 54 55 llvm::StringRef file_name(llvm::sys::path::filename(file_path)); 56 // Ignore swap files and hidden files / dirs. Do not recurse into them too. 57 // We should also not look at source files. Many projects include source 58 // files in their exports. 59 if (ShouldSkipFile(file_name)) { 60 walker.no_push(); 61 continue; 62 } 63 64 if (walker->status(status)) { 65 llvm::errs() << "Failed to stat file : " << file_path << "\n"; 66 return false; 67 } 68 69 if (!llvm::sys::fs::is_regular_file(status)) { 70 // Ignore non regular files. eg: soft links. 71 continue; 72 } 73 74 llvm::SmallString<128> abs_path(file_path); 75 if (llvm::sys::fs::make_absolute(abs_path)) { 76 llvm::errs() << "Failed to get absolute path for : " << file_name << "\n"; 77 return false; 78 } 79 exported_headers->insert(abs_path.str()); 80 } 81 return true; 82 } 83 CollectAllExportedHeaders(const std::vector<std::string> & exported_header_dirs)84std::set<std::string> CollectAllExportedHeaders( 85 const std::vector<std::string> &exported_header_dirs) { 86 std::set<std::string> exported_headers; 87 for (auto &&dir : exported_header_dirs) { 88 if (!abi_util::CollectExportedHeaderSet(dir, &exported_headers)) { 89 llvm::errs() << "Couldn't collect exported headers\n"; 90 ::exit(1); 91 } 92 } 93 return exported_headers; 94 } 95 96 } // namespace abi_util 97