Home | History | Annotate | Download | only in src
      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