1 // Copyright (C) 2018 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 "fixed_argv.h" 16 #include "omp_header_data.h" 17 18 #include <llvm/ADT/SmallString.h> 19 #include <llvm/Support/FileSystem.h> 20 #include <llvm/Support/Path.h> 21 22 #include <fstream> 23 #include <string> 24 #include <system_error> 25 26 #include <stdlib.h> 27 28 static std::string openmp_include_dir; 29 30 static void RemoveOpenMPIncludeDir() { 31 if (openmp_include_dir.empty()) { 32 return; 33 } 34 35 // Remove the <omp.h> header file. 36 llvm::SmallString<64> path; 37 llvm::sys::path::append(path, openmp_include_dir, "omp.h"); 38 llvm::sys::fs::remove(llvm::Twine(path)); 39 40 // Remove the directory. 41 llvm::sys::fs::remove(llvm::Twine(openmp_include_dir)); 42 } 43 44 static std::error_code WriteFile(const char *path, const char *data, 45 size_t size) { 46 std::fstream output(path, std::ios_base::out | std::ios_base::trunc); 47 if (!output) { 48 return std::make_error_code(std::io_errc::stream); 49 } 50 51 output.write(data, size); 52 if (!output) { 53 return std::make_error_code(std::io_errc::stream); 54 } 55 56 return std::error_code(); 57 } 58 59 static std::error_code CreateOpenMPIncludeDir() { 60 llvm::SmallString<64> path; 61 62 // Create a temporary directory for include fixes. 63 std::error_code error_code = 64 llvm::sys::fs::createUniqueDirectory("header-abi-dump-include", path); 65 if (error_code) { 66 return error_code; 67 } 68 69 openmp_include_dir = path.str(); 70 71 // Register a directory cleanup callback. 72 ::atexit(RemoveOpenMPIncludeDir); 73 74 // Create <omp.h> and write the content. 75 llvm::sys::path::append(path, "omp.h"); 76 return WriteFile(path.c_str(), OMP_HEADER_DATA, sizeof(OMP_HEADER_DATA) - 1); 77 } 78 79 static void SetupOpenMPIncludeDir(FixedArgv &fixed_argv) { 80 // FIXME: clang-3289846 does not have <omp.h>. This workaround copies omp.h 81 // from LLVM 5.0+ and adds `-isystem` to header search paths. 82 if (fixed_argv.IsLastArgEqualFirstOption("-fopenmp", "-fno-openmp")) { 83 std::error_code ec = CreateOpenMPIncludeDir(); 84 if (!ec) { 85 fixed_argv.PushForwardArgs("-isystem", openmp_include_dir.c_str()); 86 } 87 } 88 } 89 90 static FixedArgvRegistry X(SetupOpenMPIncludeDir); 91