Try to make C++ header path determination a bit more robust.

Generate C++ include paths at compile time, fallback to absolute path of compiler cling was built with, and finally relative/PATH invocation.

Previously if cling was built with wrapper to a compiler like ccache, then there was a
good chance the wrapper would be invoked to find C++ headers, meaning it would fail unless the user also had said wrapper.

This commit also:
  Changes LLVM_CXX macro to CLING_CXX_PATH.
  Fixes cling-compiledata.h not being updated after changes to
    cling-compiledata.h.in have occurred.

Signed-off-by: Vassil Vassilev <vvasilev@cern.ch>
This commit is contained in:
Frederich Munch 2016-08-11 06:12:20 -04:00 committed by sftnight
parent 6ae88ce8e9
commit b8b4becaf6
4 changed files with 215 additions and 26 deletions

View File

@ -139,7 +139,7 @@ $(call stripsrc,$(CLINGDIR)/%.o): $(CLINGDIR)/%.cpp $(LLVMDEP)
$(CLINGCOMPDH): FORCE $(LLVMDEP)
@mkdir -p $(dir $@)
@echo '#define LLVM_CXX "$(CXX) $(OPT) $(CLINGCXXFLAGSNOI)"' > $@_tmp
@echo '#define CLING_CXX_PATH "$(CXX) $(OPT) $(CLINGCXXFLAGSNOI)"' > $@_tmp
@diff -q $@_tmp $@ > /dev/null 2>&1 || mv $@_tmp $@
@rm -f $@_tmp

View File

@ -11,7 +11,6 @@
#include "ClingUtils.h"
#include "DeclCollector.h"
#include "cling-compiledata.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/TargetInfo.h"
@ -43,8 +42,9 @@
#include <memory>
#ifndef _MSC_VER
# include <unistd.h>
# define getcwd_func getcwd
#include "cling-compiledata.h"
#include <unistd.h>
#define getcwd_func getcwd
#endif
// FIXME: This code has been taken (copied from) llvm/tools/clang/lib/Driver/WindowsToolChain.cpp
@ -587,6 +587,29 @@ namespace {
}
}
static bool AddCxxPaths(llvm::StringRef PathStr, AdditionalArgList& Args) {
bool Success = true;
llvm::SmallVector<llvm::StringRef, 6> Paths;
for (std::pair<llvm::StringRef, llvm::StringRef> Split
= PathStr.split(':');
!Split.second.empty(); Split = PathStr.split(':')) {
if (!llvm::sys::fs::is_directory(Split.first)) {
Success = false;
break;
}
Paths.push_back(Split.first);
PathStr = Split.second;
}
// Add remaining part
if (Success && llvm::sys::fs::is_directory(PathStr)) {
for (llvm::StringRef Path : Paths)
Args.addArgument("-I", Path.str());
Args.addArgument("-I", PathStr.str());
return true;
}
return false;
}
#endif
///\brief Adds standard library -I used by whatever compiler is found in PATH.
@ -664,8 +687,21 @@ namespace {
}
#endif // _LIBCPP_VERSION
// first try the include directory cling was built with
#ifdef CLING_CXX_INCL
if (sArguments.empty())
ReadCompilerIncludePaths(LLVM_CXX, buffer, sArguments);
AddCxxPaths(CLING_CXX_INCL, sArguments);
#endif
// Then try the absolute path i.e.: '/usr/bin/g++'
#ifdef CLING_CXX_PATH
if (sArguments.empty())
ReadCompilerIncludePaths(CLING_CXX_PATH, buffer, sArguments);
#endif
// Finally try the relative path 'g++'
#ifdef CLING_CXX_RLTV
if (sArguments.empty())
ReadCompilerIncludePaths(CLING_CXX_RLTV, buffer, sArguments);
#endif
if (sArguments.empty()) {
// buffer is a copy of the query string that failed

View File

@ -108,27 +108,181 @@ endif()
#add_dependencies(clangDriver ClangAttrList ClangDiagnosticDriver
# ClangDriverOptions ClangCC1Options ClangCC1AsOptions)
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/cling-compiledata.h
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/cling-compiledata.h.in
${CMAKE_CURRENT_BINARY_DIR}/cling-compiledata.h)
if (UNIX)
add_file_dependencies(${CMAKE_CURRENT_SOURCE_DIR}/CIFactory.cpp ${CMAKE_CURRENT_BINARY_DIR}/cling-compiledata.h)
add_file_dependencies(${CMAKE_CURRENT_SOURCE_DIR}/Interpreter.cpp ${CMAKE_CURRENT_BINARY_DIR}/cling-compiledata.h)
# Remove all -I from CMAKE_CXX_FLAGS
string(REPLACE ";" " " __flags "${CMAKE_CXX_FLAGS}")
string(REGEX REPLACE "-I[^ ]+" "" CLING_COMPILER_FLAGS_NO_I "${__flags}")
# Remove all -I from CMAKE_CXX_FLAGS
string(REPLACE ";" " " __flags "${CMAKE_CXX_FLAGS}")
string(REGEX REPLACE "-I[^ ]+" "" CMAKE_CXX_FLAGS_NO_I "${__flags}")
option(CLING_CXX_PATH "Compiler cling will invoke for c++ headers." "")
option(CLING_CXX_HEADERS "Path cling will use for c++ headers." "")
# Remove absolute path from CMAKE_CXX_COMPILER
get_filename_component(_path ${CMAKE_CXX_COMPILER} PATH)
get_filename_component(_name ${CMAKE_CXX_COMPILER} NAME)
if("$ENV{PATH}" MATCHES ${_path})
set(CMAKE_CXX_COMPILER_RELATIVE ${_name})
else()
set(CMAKE_CXX_COMPILER_RELATIVE ${CMAKE_CXX_COMPILER})
endif()
function(stripNewLine strVal varName)
string(STRIP "${strVal}" strVal)
string(REGEX REPLACE "\\n$" "" strVal "${strVal}")
SET(${varName} ${strVal} PARENT_SCOPE)
endfunction()
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/cling-compiledata.h.in
"#define LLVM_CXX \"${CMAKE_CXX_COMPILER_RELATIVE} ${CMAKE_CXX_FLAGS_NO_I} ${CMAKE_CXX_FLAGS_${uppercase_CMAKE_BUILD_TYPE}}\"
"
)
if(NOT CLING_CXX_PATH)
# Remove absolute path from CMAKE_CXX_COMPILER
get_filename_component(_name ${CMAKE_CXX_COMPILER} NAME)
get_filename_component(_path ${CMAKE_CXX_COMPILER} PATH)
# This should probably be more general...but how?
if(_name STREQUAL "ccache" OR _name STREQUAL "distcc")
separate_arguments(_arg_list UNIX_COMMAND "${CMAKE_CXX_COMPILER_ARG1}")
if (_arg_list)
list(GET _arg_list 0 _name)
string(STRIP "${_name}" _name)
if (APPLE)
execute_process(COMMAND xcrun -f ${_name}
OUTPUT_VARIABLE CLING_CXX_FOUND
OUTPUT_STRIP_TRAILING_WHITESPACE)
stripNewLine("${CLING_CXX_FOUND}" CLING_CXX_FOUND)
else()
find_program(_cling_cxx_path "${_name}")
execute_process(COMMAND ${_cling_cxx_path} -xc++ -E -v /dev/null
OUTPUT_QUIET ERROR_VARIABLE _cling_cxx_path)
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
execute_process(
COMMAND echo ${_cling_cxx_path}
COMMAND grep "COLLECT_GCC="
OUTPUT_VARIABLE _cling_cxx_path)
string(REPLACE "COLLECT_GCC=" "" _cling_cxx_path "${_cling_cxx_path}")
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
execute_process(
COMMAND echo ${_cling_cxx_path}
COMMAND grep "/${_name}\" -cc1"
OUTPUT_VARIABLE _cling_clng_path)
if(NOT _cling_clng_path)
execute_process(
COMMAND echo ${_cling_cxx_path}
COMMAND grep "/clang\" -cc1"
OUTPUT_VARIABLE _cling_clng_path)
endif()
separate_arguments(_arg_list UNIX_COMMAND "${_cling_clng_path}")
if (_arg_list)
list(GET _arg_list 0 _cling_cxx_path)
endif()
endif()
stripNewLine("${_cling_cxx_path}" _cling_cxx_path)
set(CLING_CXX_FOUND "${_cling_cxx_path}")
endif()
if (NOT EXISTS "${CLING_CXX_FOUND}")
find_program(CLING_CXX_FOUND "${_name}")
endif()
else()
set(CLING_CXX_FOUND "")
set(_name "")
endif()
if (EXISTS ${CLING_CXX_FOUND})
set(CLING_CXX_PATH ${CLING_CXX_FOUND})
get_filename_component(_name ${CLING_CXX_PATH} NAME)
get_filename_component(_path ${CLING_CXX_PATH} PATH)
else()
set(CLING_CXX_PATH "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}")
if(_name)
set(CLING_CXX_RLTV "${_name}")
endif()
set(_path "__THISREALLYBETTERNOTBEINPATH_THANKS__")
endif()
else()
get_filename_component(_path ${CMAKE_CXX_COMPILER} PATH)
endif()
if("$ENV{PATH}" MATCHES ${_path})
set(CLING_CXX_RLTV ${_name})
elseif(NOT CLING_CXX_PATH)
set(CLING_CXX_PATH ${CMAKE_CXX_COMPILER})
endif()
endif()
if(NOT CLING_CXX_HEADERS)
if (CLING_CXX_PATH)
execute_process(COMMAND ${CLING_CXX_PATH} -xc++ -E -v /dev/null
OUTPUT_QUIET ERROR_VARIABLE CLING_CXX_HEADERS)
else()
execute_process(COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} -xc++ -E -v /dev/null
OUTPUT_QUIET ERROR_VARIABLE CLING_CXX_HEADERS)
endif()
execute_process(
COMMAND echo ${CLING_CXX_HEADERS}
COMMAND awk "/^#include </,/^End of search/{if (!/^#include </ && !/^End of search/){ print }}"
COMMAND grep -E "(c|g)\\+\\+"
OUTPUT_VARIABLE CLING_CXX_HEADERS)
stripNewLine("${CLING_CXX_HEADERS}" CLING_CXX_HEADERS)
endif()
if (NOT EXISTS ${CLING_CXX_HEADERS})
string(REPLACE "\n" ";" _cxx_inc_paths ${CLING_CXX_HEADERS})
foreach(_cxx_inc_path ${_cxx_inc_paths})
string(STRIP "${_cxx_inc_path}" _cxx_inc_path)
if (NOT EXISTS ${_cxx_inc_path})
set(_cxx_inc_join "")
break()
endif()
if(_cxx_inc_join)
set(_cxx_inc_join "${_cxx_inc_join}:${_cxx_inc_path}")
else()
set(_cxx_inc_join "${_cxx_inc_path}")
endif()
endforeach()
set(CLING_CXX_HEADERS "${_cxx_inc_join}")
if (NOT CLING_CXX_HEADERS)
MESSAGE(WARNING "Cannot determine location of C++ headers for runtime.")
endif()
endif()
MESSAGE(STATUS "Cling will look for C++ headers in '${CLING_CXX_HEADERS}' at runtime.")
if (CLING_CXX_PATH)
MESSAGE(STATUS "And if not found, will invoke: '${CLING_CXX_PATH}' for them.")
if (CLING_CXX_RLTV)
MESSAGE(STATUS "And then fallback to: '${CLING_CXX_RLTV}'")
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/cling-compiledata.h.in
"
#define CLING_CXX_INCL \"${CLING_CXX_HEADERS}\"
#define CLING_CXX_PATH \"${CLING_CXX_PATH} ${CMAKE_CXX_FLAGS_NO_I} ${CMAKE_CXX_FLAGS_${uppercase_CMAKE_BUILD_TYPE}}\"
#define CLING_CXX_RLTV \"${CLING_CXX_RLTV} ${CMAKE_CXX_FLAGS_NO_I} ${CMAKE_CXX_FLAGS_${uppercase_CMAKE_BUILD_TYPE}}\"
")
else()
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/cling-compiledata.h.in
"
#define CLING_CXX_INCL \"${CLING_CXX_HEADERS}\"
#define CLING_CXX_PATH \"${CLING_CXX_PATH} ${CMAKE_CXX_FLAGS_NO_I} ${CMAKE_CXX_FLAGS_${uppercase_CMAKE_BUILD_TYPE}}\"
")
endif()
else()
MESSAGE(STATUS "And if not found, will invoke: '${CLING_CXX_RLTV}' for them.")
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/cling-compiledata.h.in
"
#define CLING_CXX_INCL \"${CLING_CXX_HEADERS}\"
#define CLING_CXX_RLTV \"${CLING_CXX_RLTV} ${CMAKE_CXX_FLAGS_NO_I} ${CMAKE_CXX_FLAGS_${uppercase_CMAKE_BUILD_TYPE}}\"
")
endif()
# Make sure this goes last so so we can pick up any changes that occured
# Also means cling-compiledata.h.in should be edited never cling-compiledata.h
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/cling-compiledata.h
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${CMAKE_CURRENT_BINARY_DIR}/cling-compiledata.h.in
${CMAKE_CURRENT_BINARY_DIR}/cling-compiledata.h
MAIN_DEPENDENCY ${CMAKE_CURRENT_BINARY_DIR}/cling-compiledata.h.in
COMMENT "Updating cling-compiledata.h")
add_file_dependencies(${CMAKE_CURRENT_SOURCE_DIR}/CIFactory.cpp
${CMAKE_CURRENT_BINARY_DIR}/cling-compiledata.h)
add_file_dependencies(${CMAKE_CURRENT_SOURCE_DIR}/Interpreter.cpp
${CMAKE_CURRENT_BINARY_DIR}/cling-compiledata.h)
endif() # UNIX

View File

@ -10,7 +10,6 @@
#include "cling/Interpreter/Interpreter.h"
#include "ClingUtils.h"
#include "cling-compiledata.h"
#include "DynamicLookup.h"
#include "ExternalInterpreterSource.h"
#include "ForwardDeclPrinter.h"