summaryrefslogtreecommitdiffstats
path: root/CMake.pdf
Commit message (Expand)AuthorAgeFilesLines
* ENH:New pdf for CMakeWill Schroeder2002-04-261-0/+0
* ENH:Support v1.2Will Schroeder2002-01-151-0/+0
* ENH:Docs for version 1.2Will Schroeder2002-01-151-0/+0
* updated from rtfWill Schroeder2001-12-051-0/+0
* ENH:Updated documentationWill Schroeder2001-09-181-0/+0
* ENH: update pdf to rtfBill Hoffman2001-08-091-0/+0
* Re-adding doc files. They were accidentally removed due to a symlink from th...Brad King2001-08-061-0/+0
* Removing Web directory from CMake. It is moving to a separate, parallel CVS ...Brad King2001-08-061-0/+0
* updated docsWill Schroeder2001-06-071-0/+0
* BUG: Removing old CMake.pdf and adding the gzipped version, CMake.pdf.gz beca...Brad King2001-05-101-1366/+0
* ENH:Added pdf fileWill Schroeder2001-02-161-0/+1366
sion 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef NINJA_SUBPROCESS_H_ +#define NINJA_SUBPROCESS_H_ + +#include +#include +#include +using namespace std; + +#ifdef _WIN32 +#include +#else +#include +#endif + +//#include "exit_status.h" +enum ExitStatus { + ExitSuccess, + ExitFailure, + ExitInterrupted +}; + +/// Subprocess wraps a single async subprocess. It is entirely +/// passive: it expects the caller to notify it when its fds are ready +/// for reading, as well as call Finish() to reap the child once done() +/// is true. +struct Subprocess { + ~Subprocess(); + + /// Returns ExitSuccess on successful process exit, ExitInterrupted if + /// the process was interrupted, ExitFailure if it otherwise failed. + ExitStatus Finish(); + + bool Done() const; + + const string& GetOutput() const; + + private: + Subprocess(); + bool Start(struct SubprocessSet* set, const string& command); + void OnPipeReady(); + + string buf_; + +#ifdef _WIN32 + /// Set up pipe_ as the parent-side pipe of the subprocess; return the + /// other end of the pipe, usable in the child process. + HANDLE SetupPipe(HANDLE ioport); + + HANDLE child_; + HANDLE pipe_; + OVERLAPPED overlapped_; + char overlapped_buf_[4 << 10]; + bool is_reading_; +#else + int fd_; + pid_t pid_; +#endif + + friend struct SubprocessSet; +}; + +/// SubprocessSet runs a ppoll/pselect() loop around a set of Subprocesses. +/// DoWork() waits for any state change in subprocesses; finished_ +/// is a queue of subprocesses as they finish. +struct SubprocessSet { + SubprocessSet(); + ~SubprocessSet(); + + Subprocess* Add(const string& command); + bool DoWork(); + Subprocess* NextFinished(); + void Clear(); + + vector running_; + queue finished_; + +#ifdef _WIN32 + static BOOL WINAPI NotifyInterrupted(DWORD dwCtrlType); + static HANDLE ioport_; +#else + static void SetInterruptedFlag(int signum); + static bool interrupted_; + + struct sigaction old_act_; + sigset_t old_mask_; +#endif +}; + +#endif // NINJA_SUBPROCESS_H_ + + +/* + ninja's util functions +*/ + + +static void Fatal(const char* msg, ...) { + va_list ap; + fprintf(stderr, "ninja: FATAL: "); + va_start(ap, msg); + vfprintf(stderr, msg, ap); + va_end(ap); + fprintf(stderr, "\n"); +#ifdef _WIN32 + // On Windows, some tools may inject extra threads. + // exit() may block on locks held by those threads, so forcibly exit. + fflush(stderr); + fflush(stdout); + ExitProcess(1); +#else + exit(1); +#endif +} + + +#ifdef _WIN32 +string GetLastErrorString() { + DWORD err = GetLastError(); + + char* msg_buf; + FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + err, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (char*)&msg_buf, + 0, + NULL); + string msg = msg_buf; + LocalFree(msg_buf); + return msg; +} +#endif + +#define snprintf _snprintf + + +/* + ninja's subprocess-win32.cc +*/ + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//#include "subprocess.h" + +#include + +#include + +//#include "util.h" + +namespace { + +void Win32Fatal(const char* function) { + Fatal("%s: %s", function, GetLastErrorString().c_str()); +} + +} // anonymous namespace + +Subprocess::Subprocess() : child_(NULL) , overlapped_(), is_reading_(false) { +} + +Subprocess::~Subprocess() { + if (pipe_) { + if (!CloseHandle(pipe_)) + Win32Fatal("CloseHandle"); + } + // Reap child if forgotten. + if (child_) + Finish(); +} + +HANDLE Subprocess::SetupPipe(HANDLE ioport) { + char pipe_name[100]; + snprintf(pipe_name, sizeof(pipe_name), + "\\\\.\\pipe\\ninja_pid%u_sp%p", GetCurrentProcessId(), this); + + pipe_ = ::CreateNamedPipeA(pipe_name, + PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, + PIPE_TYPE_BYTE, + PIPE_UNLIMITED_INSTANCES, + 0, 0, INFINITE, NULL); + if (pipe_ == INVALID_HANDLE_VALUE) + Win32Fatal("CreateNamedPipe"); + + if (!CreateIoCompletionPort(pipe_, ioport, (ULONG_PTR)this, 0)) + Win32Fatal("CreateIoCompletionPort"); + + memset(&overlapped_, 0, sizeof(overlapped_)); + if (!ConnectNamedPipe(pipe_, &overlapped_) && + GetLastError() != ERROR_IO_PENDING) { + Win32Fatal("ConnectNamedPipe"); + } + + // Get the write end of the pipe as a handle inheritable across processes. + HANDLE output_write_handle = CreateFile(pipe_name, GENERIC_WRITE, 0, + NULL, OPEN_EXISTING, 0, NULL); + HANDLE output_write_child; + if (!DuplicateHandle(GetCurrentProcess(), output_write_handle, + GetCurrentProcess(), &output_write_child, + 0, TRUE, DUPLICATE_SAME_ACCESS)) { + Win32Fatal("DuplicateHandle"); + } + CloseHandle(output_write_handle); + + return output_write_child; +} + +bool Subprocess::Start(SubprocessSet* set, const string& command) { + HANDLE child_pipe = SetupPipe(set->ioport_); + + SECURITY_ATTRIBUTES security_attributes; + memset(&security_attributes, 0, sizeof(SECURITY_ATTRIBUTES)); + security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES); + security_attributes.bInheritHandle = TRUE; + // Must be inheritable so subprocesses can dup to children. + HANDLE nul = CreateFile("NUL", GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + &security_attributes, OPEN_EXISTING, 0, NULL); + if (nul == INVALID_HANDLE_VALUE) + Fatal("couldn't open nul"); + + STARTUPINFOA startup_info; + memset(&startup_info, 0, sizeof(startup_info)); + startup_info.cb = sizeof(STARTUPINFO); + startup_info.dwFlags = STARTF_USESTDHANDLES; + startup_info.hStdInput = nul; + startup_info.hStdOutput = child_pipe; + startup_info.hStdError = child_pipe; + + PROCESS_INFORMATION process_info; + memset(&process_info, 0, sizeof(process_info)); + + // Do not prepend 'cmd /c' on Windows, this breaks command + // lines greater than 8,191 chars. + if (!CreateProcessA(NULL, (char*)command.c_str(), NULL, NULL, + /* inherit handles */ TRUE, CREATE_NEW_PROCESS_GROUP, + NULL, NULL, + &startup_info, &process_info)) { + DWORD error = GetLastError(); + if (error == ERROR_FILE_NOT_FOUND) { // file (program) not found error is treated as a normal build action failure + if (child_pipe) + CloseHandle(child_pipe); + CloseHandle(pipe_); + CloseHandle(nul); + pipe_ = NULL; + // child_ is already NULL; + buf_ = "CreateProcess failed: The system cannot find the file specified.\n"; + return true; + } else { + Win32Fatal("CreateProcess"); // pass all other errors to Win32Fatal + } + } + + // Close pipe channel only used by the child. + if (child_pipe) + CloseHandle(child_pipe); + CloseHandle(nul); + + CloseHandle(process_info.hThread); + child_ = process_info.hProcess; + + return true; +} + +void Subprocess::OnPipeReady() { + DWORD bytes; + if (!GetOverlappedResult(pipe_, &overlapped_, &bytes, TRUE)) { + if (GetLastError() == ERROR_BROKEN_PIPE) { + CloseHandle(pipe_); + pipe_ = NULL; + return; + } + Win32Fatal("GetOverlappedResult"); + } + + if (is_reading_ && bytes) + buf_.append(overlapped_buf_, bytes); + + memset(&overlapped_, 0, sizeof(overlapped_)); + is_reading_ = true; + if (!::ReadFile(pipe_, overlapped_buf_, sizeof(overlapped_buf_), + &bytes, &overlapped_)) { + if (GetLastError() == ERROR_BROKEN_PIPE) { + CloseHandle(pipe_); + pipe_ = NULL; + return; + } + if (GetLastError() != ERROR_IO_PENDING) + Win32Fatal("ReadFile"); + } + + // Even if we read any bytes in the readfile call, we'll enter this + // function again later and get them at that point. +} + +ExitStatus Subprocess::Finish() { + if (!child_) + return ExitFailure; + + // TODO: add error handling for all of these. + WaitForSingleObject(child_, INFINITE); + + DWORD exit_code = 0; + GetExitCodeProcess(child_, &exit_code); + + CloseHandle(child_); + child_ = NULL; + + return exit_code == 0 ? ExitSuccess : + exit_code == CONTROL_C_EXIT ? ExitInterrupted : + ExitFailure; +} + +bool Subprocess::Done() const { + return pipe_ == NULL; +} + +const string& Subprocess::GetOutput() const { + return buf_; +} + +HANDLE SubprocessSet::ioport_; + +SubprocessSet::SubprocessSet() { + ioport_ = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1); + if (!ioport_) + Win32Fatal("CreateIoCompletionPort"); + if (!SetConsoleCtrlHandler(NotifyInterrupted, TRUE)) + Win32Fatal("SetConsoleCtrlHandler"); +} + +SubprocessSet::~SubprocessSet() { + Clear(); + + SetConsoleCtrlHandler(NotifyInterrupted, FALSE); + CloseHandle(ioport_); +} + +BOOL WINAPI SubprocessSet::NotifyInterrupted(DWORD dwCtrlType) { + if (dwCtrlType == CTRL_C_EVENT || dwCtrlType == CTRL_BREAK_EVENT) { + if (!PostQueuedCompletionStatus(ioport_, 0, 0, NULL)) + Win32Fatal("PostQueuedCompletionStatus"); + return TRUE; + } + + return FALSE; +} + +Subprocess *SubprocessSet::Add(const string& command) { + Subprocess *subprocess = new Subprocess; + if (!subprocess->Start(this, command)) { + delete subprocess; + return 0; + } + if (subprocess->child_) + running_.push_back(subprocess); + else + finished_.push(subprocess); + return subprocess; +} + +bool SubprocessSet::DoWork() { + DWORD bytes_read; + Subprocess* subproc; + OVERLAPPED* overlapped; + + if (!GetQueuedCompletionStatus(ioport_, &bytes_read, (PULONG_PTR)&subproc, + &overlapped, INFINITE)) { + if (GetLastError() != ERROR_BROKEN_PIPE) + Win32Fatal("GetQueuedCompletionStatus"); + } + + if (!subproc) // A NULL subproc indicates that we were interrupted and is + // delivered by NotifyInterrupted above. + return true; + + subproc->OnPipeReady(); + + if (subproc->Done()) { + vector::iterator end = + std::remove(running_.begin(), running_.end(), subproc); + if (running_.end() != end) { + finished_.push(subproc); + running_.resize(end - running_.begin()); + } + } + + return false; +} + +Subprocess* SubprocessSet::NextFinished() { + if (finished_.empty()) + return NULL; + Subprocess* subproc = finished_.front(); + finished_.pop(); + return subproc; +} + +void SubprocessSet::Clear() { + for (vector::iterator i = running_.begin(); + i != running_.end(); ++i) { + if ((*i)->child_) + if (!GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, GetProcessId((*i)->child_))) + Win32Fatal("GenerateConsoleCtrlEvent"); + } + for (vector::iterator i = running_.begin(); + i != running_.end(); ++i) + delete *i; + running_.clear(); +} + + +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +// Wrapper around cl that adds /showIncludes to command line, and uses that to +// generate .d files that match the style from gcc -MD. +// +// /showIncludes is equivalent to -MD, not -MMD, that is, system headers are +// included. + + +#include +#include +//#include "subprocess.h" +//#include "util.h" + +// We don't want any wildcard expansion. +// See http://msdn.microsoft.com/en-us/library/zay8tzh6(v=vs.85).aspx +void _setargv() {} + + +static void usage(const char* msg) { + Fatal("%s\n\nusage:\n" + " cldeps " + " " + " " + " " + " " + " " + "\n", msg); +} + +static string trimLeadingSpace(const string& cmdline) { + int i = 0; + for (; cmdline[i] == ' '; ++i) + ; + return cmdline.substr(i); +} + +static void doEscape(string& str, const string& search, const string& repl) { + string::size_type pos = 0; + while ((pos = str.find(search, pos)) != string::npos) { + str.replace(pos, search.size(), repl); + pos += repl.size(); + } +} + +// Strips one argument from the cmdline and returns it. "surrounding quotes" +// are removed from the argument if there were any. +static string getArg(string& cmdline) { + string ret; + bool in_quoted = false; + unsigned int i = 0; + + cmdline = trimLeadingSpace(cmdline); + + for (;; ++i) { + if (i >= cmdline.size()) + usage("Couldn't parse arguments."); + if (!in_quoted && cmdline[i] == ' ') + break; + if (cmdline[i] == '"') + in_quoted = !in_quoted; + } + + ret = cmdline.substr(0, i); + if (ret[0] == '"' && ret[i - 1] == '"') + ret = ret.substr(1, ret.size() - 2); + cmdline = cmdline.substr(i); + return ret; +} + +static void parseCommandLine(LPTSTR wincmdline, + string& srcfile, string& dfile, string& objfile, string& prefix, string& clpath, string& rest) { + string cmdline(wincmdline); + /* self */ getArg(cmdline); + srcfile = getArg(cmdline); + std::string::size_type pos = srcfile.rfind("\\"); + if (pos != string::npos) { + srcfile = srcfile.substr(pos + 1); + } else { + srcfile = ""; + } + dfile = getArg(cmdline); + objfile = getArg(cmdline); + prefix = getArg(cmdline); + clpath = getArg(cmdline); + rest = trimLeadingSpace(cmdline); +} + +static void outputDepFile(const string& dfile, const string& objfile, + vector& incs) { + + // strip duplicates + sort(incs.begin(), incs.end()); + incs.erase(unique(incs.begin(), incs.end()), incs.end()); + + FILE* out = fopen(dfile.c_str(), "wb"); + + // FIXME should this be fatal or not? delete obj? delete d? + if (!out) + return; + + fprintf(out, "%s: \\\n", objfile.c_str()); + for (vector::iterator i(incs.begin()); i != incs.end(); ++i) { + string tmp = *i; + doEscape(tmp, "\\", "\\\\"); + doEscape(tmp, " ", "\\ "); + //doEscape(tmp, "(", "("); // TODO ninja cant read ( and ) + //doEscape(tmp, ")", ")"); + fprintf(out, "%s \\\n", tmp.c_str()); + } + + fprintf(out, "\n"); + fclose(out); +} + + +bool startsWith(const std::string& str, const std::string& what) { + return str.compare(0, what.size(), what) == 0; +} + +bool contains(const std::string& str, const std::string& what) { + return str.find(what) != std::string::npos; +} + +int main() { + + // Use the Win32 api instead of argc/argv so we can avoid interpreting the + // rest of command line after the .d and .obj. Custom parsing seemed + // preferable to the ugliness you get into in trying to re-escape quotes for + // subprocesses, so by avoiding argc/argv, the subprocess is called with + // the same command line verbatim. + + string srcfile, dfile, objfile, prefix, clpath, rest; + parseCommandLine(GetCommandLine(), srcfile, dfile, objfile, prefix, clpath, rest); + + //fprintf(stderr, "D: %s\n", dfile.c_str()); + //fprintf(stderr, "OBJ: %s\n", objfile.c_str()); + //fprintf(stderr, "CL: %s\n", clpath.c_str()); + //fprintf(stderr, "REST: %s\n", rest.c_str()); + + SubprocessSet subprocs; + Subprocess* subproc = subprocs.Add(clpath + " /showIncludes " + rest); + if(!subproc) + return 2; + + while ((subproc = subprocs.NextFinished()) == NULL) { + subprocs.DoWork(); + } + + bool success = subproc->Finish() == ExitSuccess; + string output = subproc->GetOutput(); + + delete subproc; + + // process the include directives and output everything else + stringstream ss(output); + string line; + vector includes; + bool isFirstLine = true; // cl prints always first the source filename + std::string sysHeadersCamel = "Program Files (x86)\\Microsoft "; + std::string sysHeadersLower = "program files (x86)\\microsoft "; + while (getline(ss, line)) { + if (startsWith(line, prefix)) { + if (!contains(line, sysHeadersCamel) && !contains(line, sysHeadersLower)) { + string inc = trimLeadingSpace(line.substr(prefix.size()).c_str()); + if (inc[inc.size() - 1] == '\r') // blech, stupid \r\n + inc = inc.substr(0, inc.size() - 1); + includes.push_back(inc); + } + } else { + if (!isFirstLine || !startsWith(line, srcfile)) { + fprintf(stdout, "%s\n", line.c_str()); + } else { + isFirstLine = false; + } + } + } + + if (!success) + return 3; + + // don't update .d until/unless we succeed compilation + outputDepFile(dfile, objfile, includes); + + return 0; +} diff --git a/Tests/BuildDepends/CMakeLists.txt b/Tests/BuildDepends/CMakeLists.txt index aa32d67..5e36d11 100644 --- a/Tests/BuildDepends/CMakeLists.txt +++ b/Tests/BuildDepends/CMakeLists.txt @@ -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) -- cgit v0.12 From 941afa571c9f45c52bb935bad1c3b83fe415372e Mon Sep 17 00:00:00 2001 From: Peter Kuemmel Date: Fri, 8 Jun 2012 22:01:57 +0200 Subject: Ninja: allow spaces in source path And make /showIncude prefix visible for all build rules --- Modules/CMakeCCompiler.cmake.in | 5 +++++ Modules/CMakeCXXCompiler.cmake.in | 5 +++++ Modules/CMakeClDeps.cmake | 14 ++++++++++++++ Modules/CMakeDetermineCCompiler.cmake | 4 +--- Modules/CMakeDetermineCXXCompiler.cmake | 1 + Modules/Platform/Windows-cl.cmake | 18 ------------------ Source/cmGlobalNinjaGenerator.cxx | 14 +------------- Source/cmNinjaTargetGenerator.cxx | 27 ++++++++++----------------- 8 files changed, 37 insertions(+), 51 deletions(-) create mode 100644 Modules/CMakeClDeps.cmake diff --git a/Modules/CMakeCCompiler.cmake.in b/Modules/CMakeCCompiler.cmake.in index b14cf34..7a17e18 100644 --- a/Modules/CMakeCCompiler.cmake.in +++ b/Modules/CMakeCCompiler.cmake.in @@ -48,3 +48,8 @@ SET(CMAKE_C_HAS_ISYSROOT "@CMAKE_C_HAS_ISYSROOT@") SET(CMAKE_C_IMPLICIT_LINK_LIBRARIES "@CMAKE_C_IMPLICIT_LINK_LIBRARIES@") SET(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "@CMAKE_C_IMPLICIT_LINK_DIRECTORIES@") + +IF(MSVC_CXX_ARCHITECTURE_ID) + SET(CMAKE_CMCLDEPS_EXECUTABLE "@CMAKE_CMCLDEPS_EXECUTABLE@") + SET(CMAKE_CL_SHOWINCLUDE_PREFIX "@CMAKE_CL_SHOWINCLUDE_PREFIX@") +ENDIF() diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in index bc3bc2e..49a54d0 100644 --- a/Modules/CMakeCXXCompiler.cmake.in +++ b/Modules/CMakeCXXCompiler.cmake.in @@ -49,3 +49,8 @@ SET(CMAKE_CXX_HAS_ISYSROOT "@CMAKE_CXX_HAS_ISYSROOT@") SET(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "@CMAKE_CXX_IMPLICIT_LINK_LIBRARIES@") SET(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "@CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES@") + +IF(MSVC_CXX_ARCHITECTURE_ID) + SET(CMAKE_CMCLDEPS_EXECUTABLE "@CMAKE_CMCLDEPS_EXECUTABLE@") + SET(CMAKE_CL_SHOWINCLUDE_PREFIX "@CMAKE_CL_SHOWINCLUDE_PREFIX@") +ENDIF() diff --git a/Modules/CMakeClDeps.cmake b/Modules/CMakeClDeps.cmake new file mode 100644 index 0000000..435a6c5 --- /dev/null +++ b/Modules/CMakeClDeps.cmake @@ -0,0 +1,14 @@ +IF(MSVC_C_ARCHITECTURE_ID AND CMAKE_GENERATOR MATCHES "Ninja" AND CMAKE_C_COMPILER) + FIND_PROGRAM(CMAKE_CMCLDEPS_EXECUTABLE NAMES cmcldeps.exe) + 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} CACHE STRING "cl.exe's /showInclides prefix" FORCE) +ENDIF() diff --git a/Modules/CMakeDetermineCCompiler.cmake b/Modules/CMakeDetermineCCompiler.cmake index e2e268f..53f558e 100644 --- a/Modules/CMakeDetermineCCompiler.cmake +++ b/Modules/CMakeDetermineCCompiler.cmake @@ -165,9 +165,7 @@ ENDIF (CMAKE_CROSSCOMPILING AND "${CMAKE_C_COMPILER_ID}" MATCHES "GNU" AND NOT _CMAKE_TOOLCHAIN_PREFIX) - - - +INCLUDE(${CMAKE_ROOT}/Modules/CMakeClDeps.cmake) INCLUDE(CMakeFindBinUtils) IF(MSVC_C_ARCHITECTURE_ID) SET(SET_MSVC_C_ARCHITECTURE_ID diff --git a/Modules/CMakeDetermineCXXCompiler.cmake b/Modules/CMakeDetermineCXXCompiler.cmake index 8298369..7f8f3ec 100644 --- a/Modules/CMakeDetermineCXXCompiler.cmake +++ b/Modules/CMakeDetermineCXXCompiler.cmake @@ -173,6 +173,7 @@ ENDIF (CMAKE_CROSSCOMPILING AND "${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU" AND NOT _CMAKE_TOOLCHAIN_PREFIX) +INCLUDE(${CMAKE_ROOT}/Modules/CMakeClDeps.cmake) INCLUDE(CMakeFindBinUtils) IF(MSVC_CXX_ARCHITECTURE_ID) SET(SET_MSVC_CXX_ARCHITECTURE_ID diff --git a/Modules/Platform/Windows-cl.cmake b/Modules/Platform/Windows-cl.cmake index eed4e52..be6abb6 100644 --- a/Modules/Platform/Windows-cl.cmake +++ b/Modules/Platform/Windows-cl.cmake @@ -251,21 +251,3 @@ 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() diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 9a2597b..648855c 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -458,8 +458,7 @@ void cmGlobalNinjaGenerator else if(*l == "RC") { // check if mingw is used - const char* cc = mf->GetDefinition("CMAKE_C_COMPILER"); - if(cc && std::string(cc).find("gcc.exe") != std::string::npos) + if(mf->IsOn("CMAKE_COMPILER_IS_MINGW")) { UsingMinGW = true; std::string rc = cmSystemTools::FindProgram("windres"); @@ -467,17 +466,6 @@ void cmGlobalNinjaGenerator 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 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); diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 6518727..75b3929 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -330,20 +330,14 @@ cmNinjaTargetGenerator vars.Defines = "$DEFINES"; vars.TargetPDB = "$TARGET_PDB"; - 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 = this->GetMakefile()->GetDefinition("CMAKE_CMCLDEPS_EXECUTABLE"); - showIncludePrefix = this->GetMakefile()->GetDefinition("CMAKE_CL_SHOWINCLUDE_PREFIX"); - } + cmMakefile* mf = this->GetMakefile(); + const char* clDepsBinary = mf->GetDefinition("CMAKE_CMCLDEPS_EXECUTABLE"); + const char* clShowPrefix = mf->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 && showIncludePrefix)) { + const char *depfileFlags = mf->GetDefinition(depfileFlagsName.c_str()); + if (depfileFlags || (clDepsBinary && clShowPrefix)) { std::string depfileFlagsStr = depfileFlags ? depfileFlags : ""; depfile = "$out.d"; cmSystemTools::ReplaceString(depfileFlagsStr, "", @@ -351,7 +345,7 @@ cmNinjaTargetGenerator cmSystemTools::ReplaceString(depfileFlagsStr, "", "$out"); cmSystemTools::ReplaceString(depfileFlagsStr, "", - this->GetMakefile()->GetDefinition("CMAKE_C_COMPILER")); + mf->GetDefinition("CMAKE_C_COMPILER")); flags += " " + depfileFlagsStr; } vars.Flags = flags.c_str(); @@ -361,8 +355,7 @@ cmNinjaTargetGenerator std::string compileCmdVar = "CMAKE_"; compileCmdVar += language; compileCmdVar += "_COMPILE_OBJECT"; - std::string compileCmd = - this->GetMakefile()->GetRequiredDefinition(compileCmdVar.c_str()); + std::string compileCmd = mf->GetRequiredDefinition(compileCmdVar.c_str()); std::vector compileCmds; cmSystemTools::ExpandListArgument(compileCmd, compileCmds); @@ -373,10 +366,10 @@ cmNinjaTargetGenerator std::string cmdLine = this->GetLocalGenerator()->BuildCommandLine(compileCmds); - if(cldeps && showIncludePrefix) + if(clDepsBinary && clShowPrefix) { - std::string prefix = showIncludePrefix; - cmdLine = std::string(cldeps) + " $in $out.d $out " + "\"" + prefix + "\" " + cmdLine; + std::string prefix = clShowPrefix; + cmdLine = "\"" + std::string(clDepsBinary) + "\" $in $out.d $out \"" + prefix + "\" " + cmdLine; } // Write the rule for compiling file of the given language. -- cgit v0.12 From 0412e5c9330606b29ef61199b44e99daf5f28097 Mon Sep 17 00:00:00 2001 From: Peter Kuemmel Date: Sat, 9 Jun 2012 09:06:01 +0200 Subject: Ninja: assume cmcldeps in the same dir as cmake --- Modules/CMakeClDeps.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/CMakeClDeps.cmake b/Modules/CMakeClDeps.cmake index 435a6c5..9fac729 100644 --- a/Modules/CMakeClDeps.cmake +++ b/Modules/CMakeClDeps.cmake @@ -1,5 +1,5 @@ IF(MSVC_C_ARCHITECTURE_ID AND CMAKE_GENERATOR MATCHES "Ninja" AND CMAKE_C_COMPILER) - FIND_PROGRAM(CMAKE_CMCLDEPS_EXECUTABLE NAMES cmcldeps.exe) + STRING(REPLACE "cmake.exe" "cmcldeps.exe" CMAKE_CMCLDEPS_EXECUTABLE ${CMAKE_COMMAND}) SET(showdir ${CMAKE_BINARY_DIR}/CMakeFiles/ShowIncludes) FILE(WRITE ${showdir}/foo.h "\n") FILE(WRITE ${showdir}/main.c "#include \"foo.h\" \nint main(){}\n") -- cgit v0.12 From 64c5752d938457be411e3a9d781d4441e6634743 Mon Sep 17 00:00:00 2001 From: Peter Kuemmel Date: Sat, 9 Jun 2012 10:43:23 +0200 Subject: Ninja: add copyright and description --- Modules/CMakeClDeps.cmake | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Modules/CMakeClDeps.cmake b/Modules/CMakeClDeps.cmake index 9fac729..1d3e986 100644 --- a/Modules/CMakeClDeps.cmake +++ b/Modules/CMakeClDeps.cmake @@ -1,3 +1,22 @@ +#============================================================================= +# Copyright 2012 Kitware, Inc. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= + +# +# When using Ninja cl.exe is wrapped by cmcldeps to extract the included +# headers for dependency tracking. +# +# cmcldeps path is set, and cmcldeps needs to know the localized string +# in front of each include path, so it can remove it. +# + IF(MSVC_C_ARCHITECTURE_ID AND CMAKE_GENERATOR MATCHES "Ninja" AND CMAKE_C_COMPILER) STRING(REPLACE "cmake.exe" "cmcldeps.exe" CMAKE_CMCLDEPS_EXECUTABLE ${CMAKE_COMMAND}) SET(showdir ${CMAKE_BINARY_DIR}/CMakeFiles/ShowIncludes) -- cgit v0.12 From 8b27a94f2879b3ea1c00e1e0e4bef7cc77fd2cb6 Mon Sep 17 00:00:00 2001 From: Peter Kuemmel Date: Sat, 9 Jun 2012 11:36:53 +0200 Subject: Ninja: don't set cmcldeps vars to empty string when they are not defined --- Modules/CMakeCCompiler.cmake.in | 6 ++---- Modules/CMakeCXXCompiler.cmake.in | 6 ++---- Modules/CMakeClDeps.cmake | 5 +++-- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/Modules/CMakeCCompiler.cmake.in b/Modules/CMakeCCompiler.cmake.in index 7a17e18..ded8cf6 100644 --- a/Modules/CMakeCCompiler.cmake.in +++ b/Modules/CMakeCCompiler.cmake.in @@ -49,7 +49,5 @@ SET(CMAKE_C_HAS_ISYSROOT "@CMAKE_C_HAS_ISYSROOT@") SET(CMAKE_C_IMPLICIT_LINK_LIBRARIES "@CMAKE_C_IMPLICIT_LINK_LIBRARIES@") SET(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "@CMAKE_C_IMPLICIT_LINK_DIRECTORIES@") -IF(MSVC_CXX_ARCHITECTURE_ID) - SET(CMAKE_CMCLDEPS_EXECUTABLE "@CMAKE_CMCLDEPS_EXECUTABLE@") - SET(CMAKE_CL_SHOWINCLUDE_PREFIX "@CMAKE_CL_SHOWINCLUDE_PREFIX@") -ENDIF() +@SET_CMAKE_CMCLDEPS_EXECUTABLE@ +@SET_CMAKE_CL_SHOWINCLUDE_PREFIX@ diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in index 49a54d0..5b6376a 100644 --- a/Modules/CMakeCXXCompiler.cmake.in +++ b/Modules/CMakeCXXCompiler.cmake.in @@ -50,7 +50,5 @@ SET(CMAKE_CXX_HAS_ISYSROOT "@CMAKE_CXX_HAS_ISYSROOT@") SET(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "@CMAKE_CXX_IMPLICIT_LINK_LIBRARIES@") SET(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "@CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES@") -IF(MSVC_CXX_ARCHITECTURE_ID) - SET(CMAKE_CMCLDEPS_EXECUTABLE "@CMAKE_CMCLDEPS_EXECUTABLE@") - SET(CMAKE_CL_SHOWINCLUDE_PREFIX "@CMAKE_CL_SHOWINCLUDE_PREFIX@") -ENDIF() +@SET_CMAKE_CMCLDEPS_EXECUTABLE@ +@SET_CMAKE_CL_SHOWINCLUDE_PREFIX@ diff --git a/Modules/CMakeClDeps.cmake b/Modules/CMakeClDeps.cmake index 1d3e986..9c49169 100644 --- a/Modules/CMakeClDeps.cmake +++ b/Modules/CMakeClDeps.cmake @@ -17,7 +17,7 @@ # in front of each include path, so it can remove it. # -IF(MSVC_C_ARCHITECTURE_ID AND CMAKE_GENERATOR MATCHES "Ninja" AND CMAKE_C_COMPILER) +IF(MSVC_C_ARCHITECTURE_ID AND CMAKE_GENERATOR MATCHES "Ninja" AND CMAKE_C_COMPILER AND CMAKE_COMMAND) STRING(REPLACE "cmake.exe" "cmcldeps.exe" CMAKE_CMCLDEPS_EXECUTABLE ${CMAKE_COMMAND}) SET(showdir ${CMAKE_BINARY_DIR}/CMakeFiles/ShowIncludes) FILE(WRITE ${showdir}/foo.h "\n") @@ -29,5 +29,6 @@ IF(MSVC_C_ARCHITECTURE_ID AND CMAKE_GENERATOR MATCHES "Ninja" AND CMAKE_C_COMPIL STRING(TOLOWER ${header1} header2) STRING(REPLACE ${header2} "" showOut2 ${showOut1}) STRING(REPLACE "\n" "" showOut3 ${showOut2}) - SET(CMAKE_CL_SHOWINCLUDE_PREFIX ${showOut3} CACHE STRING "cl.exe's /showInclides prefix" FORCE) + SET(SET_CMAKE_CMCLDEPS_EXECUTABLE "SET(CMAKE_CMCLDEPS_EXECUTABLE \"${CMAKE_CMCLDEPS_EXECUTABLE}\")") + SET(SET_CMAKE_CL_SHOWINCLUDE_PREFIX "SET(CMAKE_CL_SHOWINCLUDE_PREFIX \"${showOut3}\")") ENDIF() -- cgit v0.12 From 7553a3799a188594ee0bda46b18095479e3ee54b Mon Sep 17 00:00:00 2001 From: Peter Kuemmel Date: Sat, 9 Jun 2012 12:38:12 +0200 Subject: Ninja: fix ModuleNoticies test --- Modules/CMakeClDeps.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Modules/CMakeClDeps.cmake b/Modules/CMakeClDeps.cmake index 9c49169..6815e2b 100644 --- a/Modules/CMakeClDeps.cmake +++ b/Modules/CMakeClDeps.cmake @@ -1,3 +1,4 @@ + #============================================================================= # Copyright 2012 Kitware, Inc. # @@ -8,6 +9,8 @@ # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) # # When using Ninja cl.exe is wrapped by cmcldeps to extract the included -- cgit v0.12 From db607dea8dbb0d16e75e5ae1e764002e4ce8e605 Mon Sep 17 00:00:00 2001 From: Peter Kuemmel Date: Sat, 9 Jun 2012 13:52:20 +0200 Subject: Ninja: don't use cmcldeps for try_compile --- Source/cmNinjaTargetGenerator.cxx | 16 ++++++++++++++-- Source/cmcldeps.cxx | 12 ++++++++---- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 75b3929..40fdc8b 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -331,13 +331,25 @@ cmNinjaTargetGenerator vars.TargetPDB = "$TARGET_PDB"; cmMakefile* mf = this->GetMakefile(); + bool useClDeps = false; const char* clDepsBinary = mf->GetDefinition("CMAKE_CMCLDEPS_EXECUTABLE"); const char* clShowPrefix = mf->GetDefinition("CMAKE_CL_SHOWINCLUDE_PREFIX"); + const char* projectName = mf->GetProjectName(); + if (clDepsBinary && clShowPrefix) + { + useClDeps = true; + if (projectName && std::string(projectName) == "CMAKE_TRY_COMPILE") + { + // don't wrap for try_compile, TODO but why doesn't it work with cmcldeps? + useClDeps = false; + } + } + std::string depfile; std::string depfileFlagsName = "CMAKE_DEPFILE_FLAGS_" + language; const char *depfileFlags = mf->GetDefinition(depfileFlagsName.c_str()); - if (depfileFlags || (clDepsBinary && clShowPrefix)) { + if (depfileFlags || useClDeps) { std::string depfileFlagsStr = depfileFlags ? depfileFlags : ""; depfile = "$out.d"; cmSystemTools::ReplaceString(depfileFlagsStr, "", @@ -366,7 +378,7 @@ cmNinjaTargetGenerator std::string cmdLine = this->GetLocalGenerator()->BuildCommandLine(compileCmds); - if(clDepsBinary && clShowPrefix) + if(useClDeps) { std::string prefix = clShowPrefix; cmdLine = "\"" + std::string(clDepsBinary) + "\" $in $out.d $out \"" + prefix + "\" " + cmdLine; diff --git a/Source/cmcldeps.cxx b/Source/cmcldeps.cxx index 48f2cfd..d6cafc5 100644 --- a/Source/cmcldeps.cxx +++ b/Source/cmcldeps.cxx @@ -52,6 +52,8 @@ struct Subprocess { const string& GetOutput() const; + int ExitCode() const { return exit_code_; } + private: Subprocess(); bool Start(struct SubprocessSet* set, const string& command); @@ -69,6 +71,7 @@ struct Subprocess { OVERLAPPED overlapped_; char overlapped_buf_[4 << 10]; bool is_reading_; + int exit_code_; #else int fd_; pid_t pid_; @@ -189,7 +192,7 @@ void Win32Fatal(const char* function) { } // anonymous namespace -Subprocess::Subprocess() : child_(NULL) , overlapped_(), is_reading_(false) { +Subprocess::Subprocess() : child_(NULL) , overlapped_(), is_reading_(false), exit_code_(1) { } Subprocess::~Subprocess() { @@ -338,7 +341,7 @@ ExitStatus Subprocess::Finish() { CloseHandle(child_); child_ = NULL; - + exit_code_ = exit_code; return exit_code == 0 ? ExitSuccess : exit_code == CONTROL_C_EXIT ? ExitInterrupted : ExitFailure; @@ -606,8 +609,9 @@ int main() { } bool success = subproc->Finish() == ExitSuccess; - string output = subproc->GetOutput(); + int exit_code = subproc->ExitCode(); + string output = subproc->GetOutput(); delete subproc; // process the include directives and output everything else @@ -635,7 +639,7 @@ int main() { } if (!success) - return 3; + return exit_code; // don't update .d until/unless we succeed compilation outputDepFile(dfile, objfile, includes); -- cgit v0.12 From 1a38a5d65fa33f8ff06104b23f9bd38110387ddc Mon Sep 17 00:00:00 2001 From: Peter Kuemmel Date: Sun, 10 Jun 2012 15:22:01 +0200 Subject: Ninja: allow spaces in cldeps's .d file --- Source/cmcldeps.cxx | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/Source/cmcldeps.cxx b/Source/cmcldeps.cxx index d6cafc5..0b9a2fc 100644 --- a/Source/cmcldeps.cxx +++ b/Source/cmcldeps.cxx @@ -517,7 +517,7 @@ static string getArg(string& cmdline) { if (i >= cmdline.size()) usage("Couldn't parse arguments."); if (!in_quoted && cmdline[i] == ' ') - break; + break; // "a b" "x y" if (cmdline[i] == '"') in_quoted = !in_quoted; } @@ -560,9 +560,12 @@ static void outputDepFile(const string& dfile, const string& objfile, if (!out) return; - fprintf(out, "%s: \\\n", objfile.c_str()); + string tmp = objfile; + doEscape(tmp, " ", "\\ "); + fprintf(out, "%s: \\\n", tmp.c_str()); + for (vector::iterator i(incs.begin()); i != incs.end(); ++i) { - string tmp = *i; + tmp = *i; doEscape(tmp, "\\", "\\\\"); doEscape(tmp, " ", "\\ "); //doEscape(tmp, "(", "("); // TODO ninja cant read ( and ) @@ -594,10 +597,14 @@ int main() { string srcfile, dfile, objfile, prefix, clpath, rest; parseCommandLine(GetCommandLine(), srcfile, dfile, objfile, prefix, clpath, rest); - //fprintf(stderr, "D: %s\n", dfile.c_str()); - //fprintf(stderr, "OBJ: %s\n", objfile.c_str()); - //fprintf(stderr, "CL: %s\n", clpath.c_str()); - //fprintf(stderr, "REST: %s\n", rest.c_str()); +#if 0 + fprintf(stderr, "\n\ncmcldebug:\n"); + fprintf(stderr, ".d : %s\n", dfile.c_str()); + fprintf(stderr, "OBJ : %s\n", objfile.c_str()); + fprintf(stderr, "CL : %s\n", clpath.c_str()); + fprintf(stderr, "REST: %s\n", rest.c_str()); + fprintf(stderr, "\n\n"); +#endif SubprocessSet subprocs; Subprocess* subproc = subprocs.Add(clpath + " /showIncludes " + rest); -- cgit v0.12 From 343ff7a72e7c08f3a63dde25bd1f06c8c3854f56 Mon Sep 17 00:00:00 2001 From: Peter Kuemmel Date: Sun, 10 Jun 2012 15:31:06 +0200 Subject: Ninja: fix line length --- Source/cmcldeps.cxx | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/Source/cmcldeps.cxx b/Source/cmcldeps.cxx index 0b9a2fc..9aa94d3 100644 --- a/Source/cmcldeps.cxx +++ b/Source/cmcldeps.cxx @@ -192,7 +192,8 @@ void Win32Fatal(const char* function) { } // anonymous namespace -Subprocess::Subprocess() : child_(NULL) , overlapped_(), is_reading_(false), exit_code_(1) { +Subprocess::Subprocess() : child_(NULL) , overlapped_(), is_reading_(false), + exit_code_(1) { } Subprocess::~Subprocess() { @@ -273,14 +274,17 @@ bool Subprocess::Start(SubprocessSet* set, const string& command) { NULL, NULL, &startup_info, &process_info)) { DWORD error = GetLastError(); - if (error == ERROR_FILE_NOT_FOUND) { // file (program) not found error is treated as a normal build action failure + if (error == ERROR_FILE_NOT_FOUND) { + // file (program) not found error is treated + // as a normal build action failure if (child_pipe) CloseHandle(child_pipe); CloseHandle(pipe_); CloseHandle(nul); pipe_ = NULL; // child_ is already NULL; - buf_ = "CreateProcess failed: The system cannot find the file specified.\n"; + buf_ = + "CreateProcess failed: The system cannot find the file specified.\n"; return true; } else { Win32Fatal("CreateProcess"); // pass all other errors to Win32Fatal @@ -436,7 +440,8 @@ void SubprocessSet::Clear() { for (vector::iterator i = running_.begin(); i != running_.end(); ++i) { if ((*i)->child_) - if (!GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, GetProcessId((*i)->child_))) + if (!GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, + GetProcessId((*i)->child_))) Win32Fatal("GenerateConsoleCtrlEvent"); } for (vector::iterator i = running_.begin(); @@ -530,7 +535,12 @@ static string getArg(string& cmdline) { } static void parseCommandLine(LPTSTR wincmdline, - string& srcfile, string& dfile, string& objfile, string& prefix, string& clpath, string& rest) { + string& srcfile, + string& dfile, + string& objfile, + string& prefix, + string& clpath, + string& rest) { string cmdline(wincmdline); /* self */ getArg(cmdline); srcfile = getArg(cmdline); @@ -595,7 +605,8 @@ int main() { // the same command line verbatim. string srcfile, dfile, objfile, prefix, clpath, rest; - parseCommandLine(GetCommandLine(), srcfile, dfile, objfile, prefix, clpath, rest); + parseCommandLine(GetCommandLine(), srcfile, dfile, objfile, + prefix, clpath, rest); #if 0 fprintf(stderr, "\n\ncmcldebug:\n"); @@ -630,7 +641,8 @@ int main() { std::string sysHeadersLower = "program files (x86)\\microsoft "; while (getline(ss, line)) { if (startsWith(line, prefix)) { - if (!contains(line, sysHeadersCamel) && !contains(line, sysHeadersLower)) { + if (!contains(line, sysHeadersCamel) + && !contains(line, sysHeadersLower)) { string inc = trimLeadingSpace(line.substr(prefix.size()).c_str()); if (inc[inc.size() - 1] == '\r') // blech, stupid \r\n inc = inc.substr(0, inc.size() - 1); -- cgit v0.12 From ba8d0db217399dede6d897c928b4dbf52e7e141b Mon Sep 17 00:00:00 2001 From: Peter Kuemmel Date: Sun, 10 Jun 2012 20:20:29 +0200 Subject: Ninja: don't pollute the rules file with useless comments --- Source/cmGlobalNinjaGenerator.cxx | 20 +++++++++++++++++++- Source/cmGlobalNinjaGenerator.h | 10 ++++++++++ Source/cmLocalNinjaGenerator.cxx | 2 ++ Source/cmNinjaNormalTargetGenerator.cxx | 5 ++--- Source/cmNinjaTargetGenerator.cxx | 3 ++- 5 files changed, 35 insertions(+), 5 deletions(-) diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 648855c..4773c37 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -43,12 +43,13 @@ void cmGlobalNinjaGenerator::WriteComment(std::ostream& os, std::string replace = comment; std::string::size_type lpos = 0; std::string::size_type rpos; + os << "\n#############################################\n"; while((rpos = replace.find('\n', lpos)) != std::string::npos) { os << "# " << replace.substr(lpos, rpos - lpos) << "\n"; lpos = rpos + 1; } - os << "# " << replace.substr(lpos) << "\n"; + os << "# " << replace.substr(lpos) << "\n\n"; } static bool IsIdentChar(char c) @@ -318,6 +319,8 @@ void cmGlobalNinjaGenerator::WriteRule(std::ostream& os, cmGlobalNinjaGenerator::Indent(os, 1); os << "generator = 1\n"; } + + os << "\n"; } void cmGlobalNinjaGenerator::WriteVariable(std::ostream& os, @@ -374,12 +377,21 @@ cmGlobalNinjaGenerator::cmGlobalNinjaGenerator() , CompileCommandsStream(0) , Rules() , AllDependencies() + , CommentStream(0) { // // Ninja is not ported to non-Unix OS yet. // this->ForceUnixPaths = true; this->FindMakeProgramFile = "CMakeNinjaFindMake.cmake"; + this->ClearCommentStream(); +} + +void cmGlobalNinjaGenerator::ClearCommentStream() +{ + delete CommentStream; + CommentStream = new cmsys_ios::stringstream(std::ios::out); } + //---------------------------------------------------------------------------- // Virtual public methods. @@ -537,7 +549,13 @@ void cmGlobalNinjaGenerator::AddRule(const std::string& name, { // Do not add the same rule twice. if (this->HasRule(name)) + { + this->ClearCommentStream(); return; + } + + *this->RulesFileStream << this->GetCommentStream().str(); + this->ClearCommentStream(); this->Rules.insert(name); cmGlobalNinjaGenerator::WriteRule(*this->RulesFileStream, diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index 0c740e8..b2c2aa8 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -16,6 +16,8 @@ # include "cmGlobalGenerator.h" # include "cmNinjaTypes.h" +//#define NINJA_GEN_VERBOSE_FILES + class cmLocalGenerator; class cmGeneratedFileStream; class cmGeneratorTarget; @@ -215,6 +217,11 @@ public: cmGeneratedFileStream* GetRulesFileStream() const { return this->RulesFileStream; } + void ClearCommentStream(); + cmsys_ios::stringstream& GetCommentStream() const + { return *this->CommentStream; } + + void AddCXXCompileCommand(const std::string &commandLine, const std::string &sourceFile); @@ -346,6 +353,9 @@ private: static cmLocalGenerator* LocalGenerator; static bool UsingMinGW; + + cmsys_ios::stringstream* CommentStream; + }; #endif // ! cmGlobalNinjaGenerator_h diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index a0141cf..5d193cd 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -46,7 +46,9 @@ void cmLocalNinjaGenerator::Generate() this->SetConfigName(); this->WriteProcessedMakefile(this->GetBuildFileStream()); +#ifdef NINJA_GEN_VERBOSE_FILES this->WriteProcessedMakefile(this->GetRulesFileStream()); +#endif this->WriteBuildFileTop(); diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index ddf96eb..e377706 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -96,13 +96,11 @@ void cmNinjaNormalTargetGenerator::Generate() #endif this->WriteLinkStatement(); } - - this->GetBuildFileStream() << "\n"; - this->GetRulesFileStream() << "\n"; } void cmNinjaNormalTargetGenerator::WriteLanguagesRules() { +#ifdef NINJA_GEN_VERBOSE_FILES cmGlobalNinjaGenerator::WriteDivider(this->GetRulesFileStream()); this->GetRulesFileStream() << "# Rules for each languages for " @@ -110,6 +108,7 @@ void cmNinjaNormalTargetGenerator::WriteLanguagesRules() << " target " << this->GetTargetName() << "\n\n"; +#endif std::set languages; this->GetTarget()->GetLanguages(languages); diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 40fdc8b..f66d1d3 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -309,10 +309,11 @@ void cmNinjaTargetGenerator ::WriteLanguageRules(const std::string& language) { +#ifdef NINJA_GEN_VERBOSE_FILES this->GetRulesFileStream() << "# Rules for language " << language << "\n\n"; +#endif this->WriteCompileRule(language); - this->GetRulesFileStream() << "\n"; } void -- cgit v0.12 From 4db9dd89df2cc21747c65383b197efb9ca5cba4d Mon Sep 17 00:00:00 2001 From: Peter Kuemmel Date: Sun, 10 Jun 2012 21:27:25 +0200 Subject: Ninja: use slahes in .d files --- Source/cmcldeps.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/cmcldeps.cxx b/Source/cmcldeps.cxx index 9aa94d3..ac1c49a7 100644 --- a/Source/cmcldeps.cxx +++ b/Source/cmcldeps.cxx @@ -576,7 +576,7 @@ static void outputDepFile(const string& dfile, const string& objfile, for (vector::iterator i(incs.begin()); i != incs.end(); ++i) { tmp = *i; - doEscape(tmp, "\\", "\\\\"); + doEscape(tmp, "\\", "/"); doEscape(tmp, " ", "\\ "); //doEscape(tmp, "(", "("); // TODO ninja cant read ( and ) //doEscape(tmp, ")", ")"); -- cgit v0.12 From c54ef23c16cfa40c8016643d0a6471539f04fabe Mon Sep 17 00:00:00 2001 From: Peter Kuemmel Date: Tue, 12 Jun 2012 00:51:08 +0200 Subject: Line Length: <79 --- Source/cmNinjaTargetGenerator.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index f66d1d3..02af738 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -341,7 +341,8 @@ cmNinjaTargetGenerator useClDeps = true; if (projectName && std::string(projectName) == "CMAKE_TRY_COMPILE") { - // don't wrap for try_compile, TODO but why doesn't it work with cmcldeps? + // don't wrap for try_compile, + // TODO but why doesn't it work with cmcldeps? useClDeps = false; } } @@ -382,7 +383,8 @@ cmNinjaTargetGenerator if(useClDeps) { std::string prefix = clShowPrefix; - cmdLine = "\"" + std::string(clDepsBinary) + "\" $in $out.d $out \"" + prefix + "\" " + cmdLine; + cmdLine = "\"" + std::string(clDepsBinary) + "\" $in $out.d $out \"" + + prefix + "\" " + cmdLine; } // Write the rule for compiling file of the given language. -- cgit v0.12 From 7b91c3dfac88b2d01a8bac71e800032fcd03ec54 Mon Sep 17 00:00:00 2001 From: Peter Kuemmel Date: Tue, 12 Jun 2012 00:51:27 +0200 Subject: Millenium update: 79 * (16/9)/(4/3) = 105 --- Utilities/KWStyle/CMake.kws.xml.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Utilities/KWStyle/CMake.kws.xml.in b/Utilities/KWStyle/CMake.kws.xml.in index c2b4429..faa6a73 100644 --- a/Utilities/KWStyle/CMake.kws.xml.in +++ b/Utilities/KWStyle/CMake.kws.xml.in @@ -1,6 +1,6 @@ -79 +105