Skip to content
Browse files

use sourceCpp hooks to capture build output

  • Loading branch information...
1 parent e574571 commit 0d455358e9c2dd8b95a4d5a30691d229865c5ba4 @jjallaire jjallaire committed Nov 13, 2012
View
2 .gitignore
@@ -1,4 +1,4 @@
-build/
+/build/
build_*/
build-*/
qtcreator-build
View
1 src/cpp/session/CMakeLists.txt
@@ -74,6 +74,7 @@ set (SESSION_SOURCE_FILES
modules/SessionWorkspace.cpp
modules/build/SessionBuild.cpp
modules/build/SessionBuildErrors.cpp
+ modules/build/SessionSourceCpp.cpp
modules/tex/SessionCompilePdf.cpp
modules/tex/SessionCompilePdfSupervisor.cpp
modules/tex/SessionPdfLatex.cpp
View
10 src/cpp/session/SessionModuleContext.cpp
@@ -983,6 +983,11 @@ void consoleWriteOutput(const std::string& output)
// enque write output (same as session::rConsoleWrite)
ClientEvent event(client_events::kConsoleWriteOutput, output);
enqueClientEvent(event);
+
+ // fire event
+ module_context::events().onConsoleOutput(
+ module_context::ConsoleOutputNormal,
+ output);
}
void consoleWriteError(const std::string& message)
@@ -995,6 +1000,11 @@ void consoleWriteError(const std::string& message)
// enque write error (same as session::rConsoleWrite)
ClientEvent event(client_events::kConsoleWriteError, message);
enqueClientEvent(event);
+
+ // fire event
+ module_context::events().onConsoleOutput(
+ module_context::ConsoleOutputError,
+ message);
}
void showErrorMessage(const std::string& title, const std::string& message)
View
23 src/cpp/session/include/session/SessionModuleContext.hpp
@@ -188,6 +188,11 @@ core::Error registerRpcAsyncCoupleMethod(
_2));
}
+enum ConsoleOutputType
+{
+ ConsoleOutputNormal,
+ ConsoleOutputError
+};
enum ChangeSource
{
@@ -199,14 +204,16 @@ enum ChangeSource
// session events
struct Events : boost::noncopyable
{
- boost::signal<void ()> onClientInit;
- boost::signal<void ()> onBeforeExecute;
- boost::signal<void (ChangeSource)> onDetectChanges;
- boost::signal<void(bool)> onDeferredInit;
- boost::signal<void(bool)> onBackgroundProcessing;
- boost::signal<void(bool)> onShutdown;
- boost::signal<void ()> onSysSleep;
- boost::signal<void ()> onQuit;
+ boost::signal<void ()> onClientInit;
+ boost::signal<void ()> onBeforeExecute;
+ boost::signal<void (ConsoleOutputType, const std::string&)>
+ onConsoleOutput;
+ boost::signal<void (ChangeSource)> onDetectChanges;
+ boost::signal<void(bool)> onDeferredInit;
+ boost::signal<void(bool)> onBackgroundProcessing;
+ boost::signal<void(bool)> onShutdown;
+ boost::signal<void ()> onSysSleep;
+ boost::signal<void ()> onQuit;
};
Events& events();
View
37 src/cpp/session/modules/build/SessionBuild.cpp
@@ -46,6 +46,7 @@
#include <session/SessionModuleContext.hpp>
#include "SessionBuildErrors.hpp"
+#include "SessionSourceCpp.hpp"
using namespace core;
@@ -1303,27 +1304,6 @@ SEXP rs_canBuildCpp()
return r::sexp::create(module_context::canBuildCpp(), &rProtect);
}
-
-SEXP rs_sourceCppOnBuild(SEXP sFile, SEXP sFromCode, SEXP sShowOutput)
-{
- std::string file = r::sexp::asString(sFile);
- bool fromCode = r::sexp::asLogical(sFromCode);
- bool showOutput = r::sexp::asLogical(sShowOutput);
-
-
- r::sexp::Protect rProtect;
- return r::sexp::create(true, &rProtect);
-}
-
-SEXP rs_sourceCppOnBuildComplete(SEXP sSucceeded, SEXP sOutput)
-{
- bool succeeded = r::sexp::asLogical(sSucceeded);
- std::string output = sOutput != R_NilValue ? r::sexp::asString(sOutput) : "";
-
- return R_NilValue;
-}
-
-
} // anonymous namespace
@@ -1367,18 +1347,6 @@ Error initialize()
canBuildMethodDef.numArgs = 0;
r::routines::addCallMethod(canBuildMethodDef);
- R_CallMethodDef sourceCppOnBuildMethodDef ;
- sourceCppOnBuildMethodDef.name = "rs_sourceCppOnBuild" ;
- sourceCppOnBuildMethodDef.fun = (DL_FUNC)rs_sourceCppOnBuild ;
- sourceCppOnBuildMethodDef.numArgs = 3;
- r::routines::addCallMethod(sourceCppOnBuildMethodDef);
-
- R_CallMethodDef sourceCppOnBuildCompleteMethodDef ;
- sourceCppOnBuildCompleteMethodDef.name = "rs_sourceCppOnBuildComplete";
- sourceCppOnBuildCompleteMethodDef.fun = (DL_FUNC)rs_sourceCppOnBuildComplete;
- sourceCppOnBuildCompleteMethodDef.numArgs = 2;
- r::routines::addCallMethod(sourceCppOnBuildCompleteMethodDef);
-
// check for Rcpp attributes
SEXP functionSEXP = R_NilValue;
r::exec::RFunction func(".rs.getPackageFunction",
@@ -1399,7 +1367,8 @@ Error initialize()
(bind(registerRpcMethod, "start_build", startBuild))
(bind(registerRpcMethod, "terminate_build", terminateBuild))
(bind(registerRpcMethod, "devtools_load_all_path", devtoolsLoadAllPath))
- (bind(sourceModuleRFile, "SessionBuild.R"));
+ (bind(sourceModuleRFile, "SessionBuild.R"))
+ (bind(source_cpp::initialize));
return initBlock.execute();
}
View
166 src/cpp/session/modules/build/SessionSourceCpp.cpp
@@ -0,0 +1,166 @@
+/*
+ * SessionSourceCpp.cpp
+ *
+ * Copyright (C) 2009-12 by RStudio, Inc.
+ *
+ * This program is licensed to you under the terms of version 3 of the
+ * GNU Affero General Public License. This program is distributed WITHOUT
+ * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
+ * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
+ *
+ */
+
+#include "SessionSourceCpp.hpp"
+
+#include <boost/signal.hpp>
+
+#include <core/Error.hpp>
+#include <core/FilePath.hpp>
+#include <core/StringUtils.hpp>
+
+#include <r/RSexp.hpp>
+#include <r/RRoutines.hpp>
+
+#include <session/SessionModuleContext.hpp>
+
+using namespace core ;
+
+namespace session {
+namespace modules {
+namespace build {
+namespace source_cpp {
+
+namespace {
+
+class SourceCppContext : boost::noncopyable
+{
+private:
+ SourceCppContext() {}
+ friend SourceCppContext& sourceCppContext();
+
+public:
+ bool onBuild(const FilePath& sourceFile, bool fromCode, bool showOutput)
+ {
+ // always clear state before starting a new build
+ reset();
+
+ // capture source file
+ sourceFile_ = sourceFile;
+
+ // if this is from code then don't do anything
+ if (fromCode)
+ return true;
+
+ // capture all output that goes to the console
+ module_context::events().onConsoleOutput.connect(
+ boost::bind(&SourceCppContext::onConsoleOutput, this, _1, _2));
+
+ return true;
+ }
+
+ void onBuildComplete(bool succeeded, const std::string& output)
+ {
+ // defer handling of build complete so we make sure to get all of the
+ // stderr output from console std stream capture
+ module_context::scheduleIncrementalWork(
+ boost::posix_time::milliseconds(100),
+ boost::bind(&SourceCppContext::handleBuildComplete,
+ this, succeeded, output));
+ }
+
+private:
+
+ bool handleBuildComplete(bool succeeded, const std::string& output)
+ {
+ // collect all build output
+ std::string buildOutput = output + consoleOutputBuffer_;
+
+ // reset state
+ reset();
+
+ // one time only
+ return false;
+ }
+
+
+ void onConsoleOutput(module_context::ConsoleOutputType type,
+ const std::string& output)
+ {
+ consoleOutputBuffer_.append(output);
+ }
+
+ void reset()
+ {
+ sourceFile_ = FilePath();
+ consoleOutputBuffer_.clear();
+ module_context::events().onConsoleOutput.disconnect(
+ boost::bind(&SourceCppContext::onConsoleOutput, this, _1, _2));
+ }
+
+private:
+ FilePath sourceFile_;
+ std::string consoleOutputBuffer_;
+};
+
+SourceCppContext& sourceCppContext()
+{
+ static SourceCppContext instance;
+ return instance;
+}
+
+
+
+SEXP rs_sourceCppOnBuild(SEXP sFile, SEXP sFromCode, SEXP sShowOutput)
+{
+ std::string file = r::sexp::asString(sFile);
+ FilePath filePath(string_utils::systemToUtf8(file));
+ bool fromCode = r::sexp::asLogical(sFromCode);
+ bool showOutput = r::sexp::asLogical(sShowOutput);
+
+ bool doBuild = sourceCppContext().onBuild(filePath, fromCode, showOutput);
+
+ r::sexp::Protect rProtect;
+ return r::sexp::create(doBuild, &rProtect);
+}
+
+SEXP rs_sourceCppOnBuildComplete(SEXP sSucceeded, SEXP sOutput)
+{
+ bool succeeded = r::sexp::asLogical(sSucceeded);
+ std::string output = sOutput != R_NilValue ? r::sexp::asString(sOutput) : "";
+
+ sourceCppContext().onBuildComplete(succeeded, output);
+
+ return R_NilValue;
+}
+
+
+} // anonymous namespace
+
+
+Error initialize()
+{
+
+ R_CallMethodDef sourceCppOnBuildMethodDef ;
+ sourceCppOnBuildMethodDef.name = "rs_sourceCppOnBuild" ;
+ sourceCppOnBuildMethodDef.fun = (DL_FUNC)rs_sourceCppOnBuild ;
+ sourceCppOnBuildMethodDef.numArgs = 3;
+ r::routines::addCallMethod(sourceCppOnBuildMethodDef);
+
+ R_CallMethodDef sourceCppOnBuildCompleteMethodDef ;
+ sourceCppOnBuildCompleteMethodDef.name = "rs_sourceCppOnBuildComplete";
+ sourceCppOnBuildCompleteMethodDef.fun = (DL_FUNC)rs_sourceCppOnBuildComplete;
+ sourceCppOnBuildCompleteMethodDef.numArgs = 2;
+ r::routines::addCallMethod(sourceCppOnBuildCompleteMethodDef);
+
+
+
+
+
+ return Success();
+}
+
+} // namespace source_cpp
+} // namespace build
+} // namespace modules
+} // namespace session
View
34 src/cpp/session/modules/build/SessionSourceCpp.hpp
@@ -0,0 +1,34 @@
+/*
+ * SessionSourceCpp.hpp
+ *
+ * Copyright (C) 2009-12 by RStudio, Inc.
+ *
+ * This program is licensed to you under the terms of version 3 of the
+ * GNU Affero General Public License. This program is distributed WITHOUT
+ * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
+ * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
+ *
+ */
+
+#ifndef SESSION_BUILD_SOURCE_CPP_HPP
+#define SESSION_BUILD_SOURCE_CPP_HPP
+
+namespace core {
+ class Error;
+}
+
+namespace session {
+namespace modules {
+namespace build {
+namespace source_cpp {
+
+core::Error initialize();
+
+} // namespace source_cpp
+} // namespace build
+} // namespace modules
+} // namespace session
+
+#endif // SESSION_BUILD_SOURCE_CPP_HPP
+

0 comments on commit 0d45535

Please sign in to comment.
Something went wrong with that request. Please try again.