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 27 static 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 40 std::string RealPath(const std::string &path) { 41 char file_abs_path[PATH_MAX]; 42 if (realpath(path.c_str(), file_abs_path) == nullptr) { 43 return ""; 44 } 45 return file_abs_path; 46 } 47 48 bool CollectExportedHeaderSet(const std::string &dir_name, 49 std::set<std::string> *exported_headers) { 50 std::error_code ec; 51 llvm::sys::fs::recursive_directory_iterator walker(dir_name, ec); 52 // Default construction - end of directory. 53 llvm::sys::fs::recursive_directory_iterator end; 54 llvm::sys::fs::file_status status; 55 for ( ; walker != end; walker.increment(ec)) { 56 if (ec) { 57 llvm::errs() << "Failed to walk dir : " << dir_name << "\n"; 58 return false; 59 } 60 61 const std::string &file_path = walker->path(); 62 63 llvm::StringRef file_name(llvm::sys::path::filename(file_path)); 64 // Ignore swap files and hidden files / dirs. Do not recurse into them too. 65 // We should also not look at source files. Many projects include source 66 // files in their exports. 67 if (ShouldSkipFile(file_name)) { 68 walker.no_push(); 69 continue; 70 } 71 72 if (walker->status(status)) { 73 llvm::errs() << "Failed to stat file : " << file_path << "\n"; 74 return false; 75 } 76 77 if ((status.type() != llvm::sys::fs::file_type::symlink_file) && 78 !llvm::sys::fs::is_regular_file(status)) { 79 // Ignore non regular files, except symlinks. 80 continue; 81 } 82 83 exported_headers->insert(RealPath(file_path)); 84 } 85 return true; 86 } 87 88 std::set<std::string> CollectAllExportedHeaders( 89 const std::vector<std::string> &exported_header_dirs) { 90 std::set<std::string> exported_headers; 91 for (auto &&dir : exported_header_dirs) { 92 if (!abi_util::CollectExportedHeaderSet(dir, &exported_headers)) { 93 llvm::errs() << "Couldn't collect exported headers\n"; 94 ::exit(1); 95 } 96 } 97 return exported_headers; 98 } 99 100 } // namespace abi_util 101