Commit 033a687a authored by Peter Kuemmel's avatar Peter Kuemmel

Ninja: add wrapper for cl to extract dependencies

cmcldeps wraps cl and adds /showInclude before calling cl.
It parses the output of cl for used headers, drops system
headers and writes them to a GCC like dependency file.

cmcldeps uses ATM ninja code for process handling,
but could be ported later to SystemTools.

TODO: Why needs ninja multiple calls in the BuildDepends test?
parent 1d40729e
......@@ -251,3 +251,21 @@ IF(NOT EXISTS "${CMAKE_PLATFORM_ROOT_BIN}/CMakeCXXPlatform.cmake")
CONFIGURE_FILE(${CMAKE_ROOT}/Modules/Platform/Windows-cl.cmake.in
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeCXXPlatform.cmake IMMEDIATE)
ENDIF(NOT EXISTS "${CMAKE_PLATFORM_ROOT_BIN}/CMakeCXXPlatform.cmake")
IF(CMAKE_GENERATOR MATCHES "Ninja" AND CMAKE_C_COMPILER)
# TODO try_compile doesn't need cmcldeps, find a better solution
if(NOT EXISTS ${CMAKE_TRY_COMPILE_SOURCE_DIR}/../ShowIncludes)
SET(showdir ${CMAKE_BINARY_DIR}/CMakeFiles/ShowIncludes)
FILE(WRITE ${showdir}/foo.h "\n")
FILE(WRITE ${showdir}/main.c "#include \"foo.h\" \nint main(){}\n")
EXECUTE_PROCESS(COMMAND ${CMAKE_C_COMPILER} /nologo /showIncludes ${showdir}/main.c
WORKING_DIRECTORY ${showdir} OUTPUT_VARIABLE showOut)
STRING(REPLACE main.c "" showOut1 ${showOut})
STRING(REPLACE "/" "\\" header1 ${showdir}/foo.h)
STRING(TOLOWER ${header1} header2)
STRING(REPLACE ${header2} "" showOut2 ${showOut1})
STRING(REPLACE "\n" "" showOut3 ${showOut2})
SET(CMAKE_CL_SHOWINCLUDE_PREFIX ${showOut3})
ENDIF()
ENDIF()
......@@ -383,6 +383,10 @@ IF(CMAKE_ENABLE_NINJA)
cmNinjaUtilityTargetGenerator.h
)
ADD_DEFINITIONS(-DCMAKE_USE_NINJA)
IF(MSVC) # TODO WIN32
ADD_EXECUTABLE(cmcldeps cmcldeps.cxx)
INSTALL_TARGETS(/bin cmcldeps)
ENDIF()
ELSE()
MESSAGE(STATUS "Ninja generator disabled, enforce with -DCMAKE_ENABLE_NINJA=ON")
ENDIF()
......
......@@ -460,17 +460,28 @@ void cmGlobalNinjaGenerator
// check if mingw is used
const char* cc = mf->GetDefinition("CMAKE_C_COMPILER");
if(cc && std::string(cc).find("gcc.exe") != std::string::npos)
{
{
UsingMinGW = true;
std::string rc = cmSystemTools::FindProgram("windres");
if(rc.empty())
rc = "windres.exe";;
mf->AddDefinition("CMAKE_RC_COMPILER", rc.c_str());
}
else if (cc && std::string(cc).find("cl.exe") != std::string::npos)
{
const char* cmake = mf->GetDefinition("CMAKE_COMMAND");
std::string bindir = cmake ? cmake : "";
cmSystemTools::ReplaceString(bindir, "cmake.exe", "");
std::vector<std::string> locations;
locations.push_back(bindir);
std::string cldeps = cmSystemTools::FindProgram("cmcldeps", locations);
if(!cldeps.empty())
mf->AddDefinition("CMAKE_CMCLDEPS_EXECUTABLE", cldeps.c_str());
}
}
this->cmGlobalGenerator::EnableLanguage(language, mf, optional);
this->ResolveLanguageCompiler(*l, mf, optional);
}
}
}
bool cmGlobalNinjaGenerator::UsingMinGW = false;
......
......@@ -330,16 +330,20 @@ cmNinjaTargetGenerator
vars.Defines = "$DEFINES";
vars.TargetPDB = "$TARGET_PDB";
bool cldeps = false;
const char* cldeps = 0;
const char* showIncludePrefix = 0;
const char* cc = this->GetMakefile()->GetDefinition("CMAKE_C_COMPILER");
if(cc && std::string(cc).find("cl.exe") != std::string::npos)
cldeps = true;
{
cldeps = this->GetMakefile()->GetDefinition("CMAKE_CMCLDEPS_EXECUTABLE");
showIncludePrefix = this->GetMakefile()->GetDefinition("CMAKE_CL_SHOWINCLUDE_PREFIX");
}
std::string depfile;
std::string depfileFlagsName = "CMAKE_DEPFILE_FLAGS_" + language;
const char *depfileFlags =
this->GetMakefile()->GetDefinition(depfileFlagsName.c_str());
if (depfileFlags || cldeps) {
if (depfileFlags || (cldeps && showIncludePrefix)) {
std::string depfileFlagsStr = depfileFlags ? depfileFlags : "";
depfile = "$out.d";
cmSystemTools::ReplaceString(depfileFlagsStr, "<DEPFILE>",
......@@ -369,8 +373,11 @@ cmNinjaTargetGenerator
std::string cmdLine =
this->GetLocalGenerator()->BuildCommandLine(compileCmds);
if(cldeps)
cmdLine = "cldeps.exe $out.d $out " + cmdLine;
if(cldeps && showIncludePrefix)
{
std::string prefix = showIncludePrefix;
cmdLine = std::string(cldeps) + " $in $out.d $out " + "\"" + prefix + "\" " + cmdLine;
}
// Write the rule for compiling file of the given language.
std::ostringstream comment;
......
This diff is collapsed.
......@@ -28,6 +28,10 @@ function(help_xcode_depends)
endif(HELP_XCODE)
endfunction(help_xcode_depends)
if("${CMAKE_GENERATOR}" MATCHES "Ninja")
set(HELP_NINJA 1) # TODO Why is this needed?
endif()
# The Intel compiler causes the MSVC linker to crash during
# incremental linking, so avoid the /INCREMENTAL:YES flag.
if(WIN32 AND "${CMAKE_CXX_COMPILER_ID}" MATCHES "Intel")
......@@ -154,7 +158,7 @@ try_compile(RESULT
OUTPUT_VARIABLE OUTPUT)
# Xcode is in serious need of help here
if(HELP_XCODE)
if(HELP_XCODE OR HELP_NINJA)
try_compile(RESULT
${BuildDepends_BINARY_DIR}/Project
${BuildDepends_SOURCE_DIR}/Project
......@@ -165,7 +169,7 @@ if(HELP_XCODE)
${BuildDepends_SOURCE_DIR}/Project
testRebuild
OUTPUT_VARIABLE OUTPUT)
endif(HELP_XCODE)
endif()
message("Output from second build:\n${OUTPUT}")
if(NOT RESULT)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment