Browse Source

Merge branch 'master' into net2

v0.7.4-release
Ryan Dahl 15 years ago
parent
commit
8c4561d2a0
  1. 6
      Makefile
  2. 2
      bin/node-waf
  3. 1
      deps/v8/SConstruct
  4. 16
      deps/v8/include/v8.h
  5. 23
      deps/v8/src/api.cc
  6. 5
      deps/v8/src/arm/codegen-arm.cc
  7. 2
      deps/v8/src/arm/codegen-arm.h
  8. 1
      deps/v8/src/arm/fast-codegen-arm.cc
  9. 1
      deps/v8/src/arm/full-codegen-arm.cc
  10. 1
      deps/v8/src/arm/jump-target-arm.cc
  11. 1
      deps/v8/src/arm/virtual-frame-arm.cc
  12. 14
      deps/v8/src/arm/virtual-frame-arm.h
  13. 4
      deps/v8/src/ast.h
  14. 3
      deps/v8/src/codegen-inl.h
  15. 1
      deps/v8/src/codegen.cc
  16. 1
      deps/v8/src/full-codegen.cc
  17. 27
      deps/v8/src/heap.cc
  18. 8
      deps/v8/src/heap.h
  19. 4
      deps/v8/src/ia32/codegen-ia32.cc
  20. 2
      deps/v8/src/ia32/codegen-ia32.h
  21. 1
      deps/v8/src/ia32/full-codegen-ia32.cc
  22. 1
      deps/v8/src/ia32/jump-target-ia32.cc
  23. 1
      deps/v8/src/ia32/register-allocator-ia32.cc
  24. 34
      deps/v8/src/ia32/stub-cache-ia32.cc
  25. 1
      deps/v8/src/ia32/virtual-frame-ia32.cc
  26. 16
      deps/v8/src/ia32/virtual-frame-ia32.h
  27. 14
      deps/v8/src/ic.cc
  28. 7
      deps/v8/src/jump-target-inl.h
  29. 3
      deps/v8/src/jump-target.cc
  30. 1
      deps/v8/src/register-allocator-inl.h
  31. 1
      deps/v8/src/register-allocator.cc
  32. 2
      deps/v8/src/version.cc
  33. 109
      deps/v8/src/virtual-frame-inl.h
  34. 68
      deps/v8/src/virtual-frame.cc
  35. 4
      deps/v8/src/x64/codegen-x64.cc
  36. 2
      deps/v8/src/x64/codegen-x64.h
  37. 1
      deps/v8/src/x64/fast-codegen-x64.cc
  38. 1
      deps/v8/src/x64/full-codegen-x64.cc
  39. 1
      deps/v8/src/x64/jump-target-x64.cc
  40. 1
      deps/v8/src/x64/register-allocator-x64.cc
  41. 1
      deps/v8/src/x64/virtual-frame-x64.cc
  42. 14
      deps/v8/src/x64/virtual-frame-x64.h
  43. 75
      deps/v8/test/cctest/test-api.cc
  44. 22
      deps/v8/test/cctest/test-thread-termination.cc
  45. 1
      deps/v8/tools/gyp/v8.gyp
  46. 4
      deps/v8/tools/visual_studio/v8_base.vcproj
  47. 4
      deps/v8/tools/visual_studio/v8_base_arm.vcproj
  48. 4
      deps/v8/tools/visual_studio/v8_base_x64.vcproj
  49. 22
      doc/api.txt
  50. 78
      lib/fs.js
  51. 32
      src/node.cc
  52. 2
      test/common.js
  53. 8
      test/simple/test-chdir.js
  54. 1
      test/simple/test-eio-race2.js
  55. 2
      test/simple/test-eio-race4.js
  56. 2
      test/simple/test-file-read-noexist.js
  57. 11
      test/simple/test-file-read-stream.js
  58. 22
      test/simple/test-file-write-stream.js
  59. 3
      test/simple/test-fs-chmod.js
  60. 3
      test/simple/test-fs-realpath.js
  61. 2
      test/simple/test-fs-stat.js
  62. 3
      test/simple/test-fs-symlink.js
  63. 3
      test/simple/test-fs-write.js
  64. 5
      test/simple/test-http-tls.js
  65. 3
      test/simple/test-ini.js
  66. 2
      test/simple/test-mkdir-rmdir.js
  67. 1
      test/simple/test-module-loading.js
  68. 2
      test/simple/test-readdir.js
  69. 1
      test/simple/test-stdio.js
  70. 1
      test/simple/test-stdout-flush.js
  71. 2
      test/simple/test-sync-fileread.js
  72. 8
      test/simple/test-umask.js
  73. 12
      tools/waf-light
  74. 21
      tools/wafadmin/3rdparty/boost.py
  75. 74
      tools/wafadmin/Build.py
  76. 33
      tools/wafadmin/Configure.py
  77. 6
      tools/wafadmin/Constants.py
  78. 13
      tools/wafadmin/Environment.py
  79. 25
      tools/wafadmin/Logs.py
  80. 45
      tools/wafadmin/Node.py
  81. 2
      tools/wafadmin/Options.py
  82. 28
      tools/wafadmin/Runner.py
  83. 28
      tools/wafadmin/Scripting.py
  84. 165
      tools/wafadmin/Task.py
  85. 27
      tools/wafadmin/TaskGen.py
  86. 2
      tools/wafadmin/Tools/ar.py
  87. 11
      tools/wafadmin/Tools/ccroot.py
  88. 17
      tools/wafadmin/Tools/compiler_cc.py
  89. 16
      tools/wafadmin/Tools/compiler_cxx.py
  90. 94
      tools/wafadmin/Tools/config_c.py
  91. 7
      tools/wafadmin/Tools/gas.py
  92. 29
      tools/wafadmin/Tools/gnome.py
  93. 5
      tools/wafadmin/Tools/intltool.py
  94. 11
      tools/wafadmin/Tools/javaw.py
  95. 2
      tools/wafadmin/Tools/lua.py
  96. 1
      tools/wafadmin/Tools/misc.py
  97. 186
      tools/wafadmin/Tools/msvc.py
  98. 72
      tools/wafadmin/Tools/perl.py
  99. 12
      tools/wafadmin/Tools/preproc.py
  100. 4
      tools/wafadmin/Tools/python.py

6
Makefile

@ -66,12 +66,12 @@ website-upload: doc
docclean: docclean:
@-rm -f doc/node.1 doc/api.xml doc/api.html doc/changelog.html @-rm -f doc/node.1 doc/api.xml doc/api.html doc/changelog.html
clean: docclean clean:
@$(WAF) clean @$(WAF) clean
@-find tools/ -name "*.pyc" -delete
distclean: docclean distclean: clean docclean
@-rm -rf build/ @-rm -rf build/
@-find tools/ -name "*.pyc" -delete
check: check:
@tools/waf-light check @tools/waf-light check

2
bin/node-waf

@ -12,6 +12,6 @@ t = join(w, 'Tools')
sys.path = [w, t] + sys.path sys.path = [w, t] + sys.path
import Scripting import Scripting
VERSION="1.5.10" VERSION="1.5.14"
Scripting.prepare(t, os.getcwd(), VERSION, wafdir) Scripting.prepare(t, os.getcwd(), VERSION, wafdir)
sys.exit(0) sys.exit(0)

1
deps/v8/SConstruct

@ -267,6 +267,7 @@ V8_EXTRA_FLAGS = {
'gcc': { 'gcc': {
'all': { 'all': {
'WARNINGFLAGS': ['-Wall', 'WARNINGFLAGS': ['-Wall',
'-Werror',
'-W', '-W',
'-Wno-unused-parameter', '-Wno-unused-parameter',
'-Wnon-virtual-dtor'] '-Wnon-virtual-dtor']

16
deps/v8/include/v8.h

@ -2441,6 +2441,16 @@ class V8EXPORT V8 {
*/ */
static void TerminateExecution(); static void TerminateExecution();
/**
* Is V8 terminating JavaScript execution.
*
* Returns true if JavaScript execution is currently terminating
* because of a call to TerminateExecution. In that case there are
* still JavaScript frames on the stack and the termination
* exception is still active.
*/
static bool IsExecutionTerminating();
/** /**
* Releases any resources used by v8 and stops any utility threads * Releases any resources used by v8 and stops any utility threads
* that may be running. Note that disposing v8 is permanent, it * that may be running. Note that disposing v8 is permanent, it
@ -2473,6 +2483,12 @@ class V8EXPORT V8 {
*/ */
static void LowMemoryNotification(); static void LowMemoryNotification();
/**
* Optional notification that a context has been disposed. V8 uses
* these notifications to guide the garbage collection heuristic.
*/
static void ContextDisposedNotification();
private: private:
V8(); V8();

23
deps/v8/src/api.cc

@ -438,7 +438,6 @@ bool V8::IsGlobalWeak(i::Object** obj) {
void V8::DisposeGlobal(i::Object** obj) { void V8::DisposeGlobal(i::Object** obj) {
LOG_API("DisposeGlobal"); LOG_API("DisposeGlobal");
if (!i::V8::IsRunning()) return; if (!i::V8::IsRunning()) return;
if ((*obj)->IsGlobalContext()) i::Heap::NotifyContextDisposed();
i::GlobalHandles::Destroy(obj); i::GlobalHandles::Destroy(obj);
} }
@ -2821,6 +2820,12 @@ void v8::V8::LowMemoryNotification() {
} }
void v8::V8::ContextDisposedNotification() {
if (!i::V8::IsRunning()) return;
i::Heap::NotifyContextDisposed();
}
const char* v8::V8::GetVersion() { const char* v8::V8::GetVersion() {
static v8::internal::EmbeddedVector<char, 128> buffer; static v8::internal::EmbeddedVector<char, 128> buffer;
v8::internal::Version::GetString(buffer); v8::internal::Version::GetString(buffer);
@ -2852,13 +2857,6 @@ Persistent<Context> v8::Context::New(
i::Handle<i::Context> env; i::Handle<i::Context> env;
{ {
ENTER_V8; ENTER_V8;
#if defined(ANDROID)
// On mobile device, full GC is expensive, leave it to the system to
// decide when should make a full GC.
#else
// Give the heap a chance to cleanup if we've disposed contexts.
i::Heap::CollectAllGarbageIfContextDisposed();
#endif
v8::Handle<ObjectTemplate> proxy_template = global_template; v8::Handle<ObjectTemplate> proxy_template = global_template;
i::Handle<i::FunctionTemplateInfo> proxy_constructor; i::Handle<i::FunctionTemplateInfo> proxy_constructor;
i::Handle<i::FunctionTemplateInfo> global_constructor; i::Handle<i::FunctionTemplateInfo> global_constructor;
@ -3561,6 +3559,15 @@ void V8::TerminateExecution() {
} }
bool V8::IsExecutionTerminating() {
if (!i::V8::IsRunning()) return false;
if (i::Top::has_scheduled_exception()) {
return i::Top::scheduled_exception() == i::Heap::termination_exception();
}
return false;
}
String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) { String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) {
EnsureInitialized("v8::String::Utf8Value::Utf8Value()"); EnsureInitialized("v8::String::Utf8Value::Utf8Value()");
if (obj.IsEmpty()) { if (obj.IsEmpty()) {

5
deps/v8/src/arm/codegen-arm.cc

@ -35,7 +35,7 @@
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
#include "runtime.h" #include "runtime.h"
#include "scopes.h" #include "scopes.h"
#include "virtual-frame-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
@ -133,9 +133,6 @@ CodeGenerator::CodeGenerator(MacroAssembler* masm)
} }
Scope* CodeGenerator::scope() { return info_->function()->scope(); }
// Calling conventions: // Calling conventions:
// fp: caller's frame pointer // fp: caller's frame pointer
// sp: stack pointer // sp: stack pointer

2
deps/v8/src/arm/codegen-arm.h

@ -203,7 +203,7 @@ class CodeGenerator: public AstVisitor {
// Accessors // Accessors
inline bool is_eval(); inline bool is_eval();
Scope* scope(); inline Scope* scope();
// Generating deferred code. // Generating deferred code.
void ProcessDeferred(); void ProcessDeferred();

1
deps/v8/src/arm/fast-codegen-arm.cc

@ -29,6 +29,7 @@
#include "codegen-inl.h" #include "codegen-inl.h"
#include "fast-codegen.h" #include "fast-codegen.h"
#include "scopes.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

1
deps/v8/src/arm/full-codegen-arm.cc

@ -32,6 +32,7 @@
#include "debug.h" #include "debug.h"
#include "full-codegen.h" #include "full-codegen.h"
#include "parser.h" #include "parser.h"
#include "scopes.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

1
deps/v8/src/arm/jump-target-arm.cc

@ -30,6 +30,7 @@
#include "codegen-inl.h" #include "codegen-inl.h"
#include "jump-target-inl.h" #include "jump-target-inl.h"
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
#include "virtual-frame-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

1
deps/v8/src/arm/virtual-frame-arm.cc

@ -30,6 +30,7 @@
#include "codegen-inl.h" #include "codegen-inl.h"
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
#include "scopes.h" #include "scopes.h"
#include "virtual-frame-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

14
deps/v8/src/arm/virtual-frame-arm.h

@ -62,7 +62,7 @@ class VirtualFrame : public ZoneObject {
VirtualFrame(); VirtualFrame();
// Construct a virtual frame as a clone of an existing one. // Construct a virtual frame as a clone of an existing one.
explicit VirtualFrame(VirtualFrame* original); explicit inline VirtualFrame(VirtualFrame* original);
CodeGenerator* cgen() { return CodeGeneratorScope::Current(); } CodeGenerator* cgen() { return CodeGeneratorScope::Current(); }
MacroAssembler* masm() { return cgen()->masm(); } MacroAssembler* masm() { return cgen()->masm(); }
@ -344,9 +344,9 @@ class VirtualFrame : public ZoneObject {
void EmitPushMultiple(int count, int src_regs); void EmitPushMultiple(int count, int src_regs);
// Push an element on the virtual frame. // Push an element on the virtual frame.
void Push(Register reg, NumberInfo::Type info = NumberInfo::kUnknown); inline void Push(Register reg, NumberInfo::Type info = NumberInfo::kUnknown);
void Push(Handle<Object> value); inline void Push(Handle<Object> value);
void Push(Smi* value) { Push(Handle<Object>(value)); } inline void Push(Smi* value);
// Pushing a result invalidates it (its contents become owned by the frame). // Pushing a result invalidates it (its contents become owned by the frame).
void Push(Result* result) { void Push(Result* result) {
@ -362,7 +362,7 @@ class VirtualFrame : public ZoneObject {
// Nip removes zero or more elements from immediately below the top // Nip removes zero or more elements from immediately below the top
// of the frame, leaving the previous top-of-frame value on top of // of the frame, leaving the previous top-of-frame value on top of
// the frame. Nip(k) is equivalent to x = Pop(), Drop(k), Push(x). // the frame. Nip(k) is equivalent to x = Pop(), Drop(k), Push(x).
void Nip(int num_dropped); inline void Nip(int num_dropped);
private: private:
static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset; static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset;
@ -457,7 +457,7 @@ class VirtualFrame : public ZoneObject {
// Push a copy of a frame slot (typically a local or parameter) on top of // Push a copy of a frame slot (typically a local or parameter) on top of
// the frame. // the frame.
void PushFrameSlotAt(int index); inline void PushFrameSlotAt(int index);
// Push a the value of a frame slot (typically a local or parameter) on // Push a the value of a frame slot (typically a local or parameter) on
// top of the frame and invalidate the slot. // top of the frame and invalidate the slot.
@ -500,7 +500,7 @@ class VirtualFrame : public ZoneObject {
// Register counts are correctly updated. // Register counts are correctly updated.
int InvalidateFrameSlotAt(int index); int InvalidateFrameSlotAt(int index);
bool Equals(VirtualFrame* other); inline bool Equals(VirtualFrame* other);
// Classes that need raw access to the elements_ array. // Classes that need raw access to the elements_ array.
friend class DeferredCode; friend class DeferredCode;

4
deps/v8/src/ast.h

@ -931,10 +931,6 @@ class VariableProxy: public Expression {
return var()->is_global() || var()->rewrite()->IsLeaf(); return var()->is_global() || var()->rewrite()->IsLeaf();
} }
// Reading from a mutable variable is a side effect, but 'this' is
// immutable.
virtual bool IsTrivial() { return is_this(); }
bool IsVariable(Handle<String> n) { bool IsVariable(Handle<String> n) {
return !is_this() && name().is_identical_to(n); return !is_this() && name().is_identical_to(n);
} }

3
deps/v8/src/codegen-inl.h

@ -50,8 +50,11 @@ namespace v8 {
namespace internal { namespace internal {
Handle<Script> CodeGenerator::script() { return info_->script(); } Handle<Script> CodeGenerator::script() { return info_->script(); }
bool CodeGenerator::is_eval() { return info_->is_eval(); } bool CodeGenerator::is_eval() { return info_->is_eval(); }
Scope* CodeGenerator::scope() { return info_->function()->scope(); }
} } // namespace v8::internal } } // namespace v8::internal
#endif // V8_CODEGEN_INL_H_ #endif // V8_CODEGEN_INL_H_

1
deps/v8/src/codegen.cc

@ -39,6 +39,7 @@
#include "runtime.h" #include "runtime.h"
#include "scopeinfo.h" #include "scopeinfo.h"
#include "stub-cache.h" #include "stub-cache.h"
#include "virtual-frame-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

1
deps/v8/src/full-codegen.cc

@ -30,6 +30,7 @@
#include "codegen-inl.h" #include "codegen-inl.h"
#include "compiler.h" #include "compiler.h"
#include "full-codegen.h" #include "full-codegen.h"
#include "scopes.h"
#include "stub-cache.h" #include "stub-cache.h"
#include "debug.h" #include "debug.h"
#include "liveedit.h" #include "liveedit.h"

27
deps/v8/src/heap.cc

@ -115,7 +115,7 @@ int Heap::gc_count_ = 0;
int Heap::always_allocate_scope_depth_ = 0; int Heap::always_allocate_scope_depth_ = 0;
int Heap::linear_allocation_scope_depth_ = 0; int Heap::linear_allocation_scope_depth_ = 0;
bool Heap::context_disposed_pending_ = false; int Heap::contexts_disposed_ = 0;
#ifdef DEBUG #ifdef DEBUG
bool Heap::allocation_allowed_ = true; bool Heap::allocation_allowed_ = true;
@ -371,21 +371,8 @@ void Heap::CollectAllGarbage(bool force_compaction) {
} }
void Heap::CollectAllGarbageIfContextDisposed() {
// If the garbage collector interface is exposed through the global
// gc() function, we avoid being clever about forcing GCs when
// contexts are disposed and leave it to the embedder to make
// informed decisions about when to force a collection.
if (!FLAG_expose_gc && context_disposed_pending_) {
HistogramTimerScope scope(&Counters::gc_context);
CollectAllGarbage(false);
}
context_disposed_pending_ = false;
}
void Heap::NotifyContextDisposed() { void Heap::NotifyContextDisposed() {
context_disposed_pending_ = true; contexts_disposed_++;
} }
@ -620,7 +607,8 @@ void Heap::MarkCompact(GCTracer* tracer) {
Shrink(); Shrink();
Counters::objs_since_last_full.Set(0); Counters::objs_since_last_full.Set(0);
context_disposed_pending_ = false;
contexts_disposed_ = 0;
} }
@ -3072,6 +3060,13 @@ bool Heap::IdleNotification() {
static int number_idle_notifications = 0; static int number_idle_notifications = 0;
static int last_gc_count = gc_count_; static int last_gc_count = gc_count_;
if (!FLAG_expose_gc && (contexts_disposed_ > 0)) {
HistogramTimerScope scope(&Counters::gc_context);
CollectAllGarbage(false);
ASSERT(contexts_disposed_ == 0);
return false;
}
bool finished = false; bool finished = false;
if (last_gc_count == gc_count_) { if (last_gc_count == gc_count_) {

8
deps/v8/src/heap.h

@ -632,10 +632,6 @@ class Heap : public AllStatic {
// parameter is true. // parameter is true.
static void CollectAllGarbage(bool force_compaction); static void CollectAllGarbage(bool force_compaction);
// Performs a full garbage collection if a context has been disposed
// since the last time the check was performed.
static void CollectAllGarbageIfContextDisposed();
// Notify the heap that a context has been disposed. // Notify the heap that a context has been disposed.
static void NotifyContextDisposed(); static void NotifyContextDisposed();
@ -908,7 +904,9 @@ class Heap : public AllStatic {
static int always_allocate_scope_depth_; static int always_allocate_scope_depth_;
static int linear_allocation_scope_depth_; static int linear_allocation_scope_depth_;
static bool context_disposed_pending_;
// For keeping track of context disposals.
static int contexts_disposed_;
#if defined(V8_TARGET_ARCH_X64) #if defined(V8_TARGET_ARCH_X64)
static const int kMaxObjectSizeInNewSpace = 512*KB; static const int kMaxObjectSizeInNewSpace = 512*KB;

4
deps/v8/src/ia32/codegen-ia32.cc

@ -39,6 +39,7 @@
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
#include "runtime.h" #include "runtime.h"
#include "scopes.h" #include "scopes.h"
#include "virtual-frame-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
@ -116,9 +117,6 @@ CodeGenerator::CodeGenerator(MacroAssembler* masm)
} }
Scope* CodeGenerator::scope() { return info_->function()->scope(); }
// Calling conventions: // Calling conventions:
// ebp: caller's frame pointer // ebp: caller's frame pointer
// esp: stack pointer // esp: stack pointer

2
deps/v8/src/ia32/codegen-ia32.h

@ -343,7 +343,7 @@ class CodeGenerator: public AstVisitor {
// Accessors // Accessors
inline bool is_eval(); inline bool is_eval();
Scope* scope(); inline Scope* scope();
// Generating deferred code. // Generating deferred code.
void ProcessDeferred(); void ProcessDeferred();

1
deps/v8/src/ia32/full-codegen-ia32.cc

@ -32,6 +32,7 @@
#include "debug.h" #include "debug.h"
#include "full-codegen.h" #include "full-codegen.h"
#include "parser.h" #include "parser.h"
#include "scopes.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

1
deps/v8/src/ia32/jump-target-ia32.cc

@ -30,6 +30,7 @@
#include "codegen-inl.h" #include "codegen-inl.h"
#include "jump-target-inl.h" #include "jump-target-inl.h"
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
#include "virtual-frame-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

1
deps/v8/src/ia32/register-allocator-ia32.cc

@ -29,6 +29,7 @@
#include "codegen-inl.h" #include "codegen-inl.h"
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
#include "virtual-frame-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

34
deps/v8/src/ia32/stub-cache-ia32.cc

@ -479,17 +479,14 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
// Holds information about possible function call optimizations. // Holds information about possible function call optimizations.
class CallOptimization BASE_EMBEDDED { class CallOptimization BASE_EMBEDDED {
public: public:
explicit CallOptimization(LookupResult* lookup) explicit CallOptimization(LookupResult* lookup) {
: constant_function_(NULL), if (!lookup->IsProperty() || !lookup->IsCacheable() ||
is_simple_api_call_(false), lookup->type() != CONSTANT_FUNCTION) {
expected_receiver_type_(NULL), Initialize(NULL);
api_call_info_(NULL) { } else {
if (!lookup->IsProperty() || !lookup->IsCacheable()) return; // We only optimize constant function calls.
Initialize(lookup->GetConstantFunction());
// We only optimize constant function calls. }
if (lookup->type() != CONSTANT_FUNCTION) return;
Initialize(lookup->GetConstantFunction());
} }
explicit CallOptimization(JSFunction* function) { explicit CallOptimization(JSFunction* function) {
@ -537,11 +534,14 @@ class CallOptimization BASE_EMBEDDED {
private: private:
void Initialize(JSFunction* function) { void Initialize(JSFunction* function) {
if (!function->is_compiled()) return; constant_function_ = NULL;
constant_function_ = function;
is_simple_api_call_ = false; is_simple_api_call_ = false;
expected_receiver_type_ = NULL;
api_call_info_ = NULL;
if (function == NULL || !function->is_compiled()) return;
constant_function_ = function;
AnalyzePossibleApiFunction(function); AnalyzePossibleApiFunction(function);
} }
@ -1223,7 +1223,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
// -- ... // -- ...
// -- esp[(argc + 1) * 4] : receiver // -- esp[(argc + 1) * 4] : receiver
// ----------------------------------- // -----------------------------------
Label miss; Label miss_in_smi_check;
// Get the receiver from the stack. // Get the receiver from the stack.
const int argc = arguments().immediate(); const int argc = arguments().immediate();
@ -1232,7 +1232,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
// Check that the receiver isn't a smi. // Check that the receiver isn't a smi.
if (check != NUMBER_CHECK) { if (check != NUMBER_CHECK) {
__ test(edx, Immediate(kSmiTagMask)); __ test(edx, Immediate(kSmiTagMask));
__ j(zero, &miss, not_taken); __ j(zero, &miss_in_smi_check, not_taken);
} }
// Make sure that it's okay not to patch the on stack receiver // Make sure that it's okay not to patch the on stack receiver
@ -1241,6 +1241,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
CallOptimization optimization(function); CallOptimization optimization(function);
int depth = kInvalidProtoDepth; int depth = kInvalidProtoDepth;
Label miss;
switch (check) { switch (check) {
case RECEIVER_MAP_CHECK: case RECEIVER_MAP_CHECK:
@ -1359,6 +1360,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
if (depth != kInvalidProtoDepth) { if (depth != kInvalidProtoDepth) {
FreeSpaceForFastApiCall(masm(), eax); FreeSpaceForFastApiCall(masm(), eax);
} }
__ bind(&miss_in_smi_check);
Handle<Code> ic = ComputeCallMiss(arguments().immediate()); Handle<Code> ic = ComputeCallMiss(arguments().immediate());
__ jmp(ic, RelocInfo::CODE_TARGET); __ jmp(ic, RelocInfo::CODE_TARGET);

1
deps/v8/src/ia32/virtual-frame-ia32.cc

@ -30,6 +30,7 @@
#include "codegen-inl.h" #include "codegen-inl.h"
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
#include "scopes.h" #include "scopes.h"
#include "virtual-frame-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

16
deps/v8/src/ia32/virtual-frame-ia32.h

@ -76,7 +76,7 @@ class VirtualFrame: public ZoneObject {
VirtualFrame(); VirtualFrame();
// Construct a virtual frame as a clone of an existing one. // Construct a virtual frame as a clone of an existing one.
explicit VirtualFrame(VirtualFrame* original); explicit inline VirtualFrame(VirtualFrame* original);
CodeGenerator* cgen() { return CodeGeneratorScope::Current(); } CodeGenerator* cgen() { return CodeGeneratorScope::Current(); }
@ -395,11 +395,9 @@ class VirtualFrame: public ZoneObject {
NumberInfo::Type info = NumberInfo::kUnknown); NumberInfo::Type info = NumberInfo::kUnknown);
// Push an element on the virtual frame. // Push an element on the virtual frame.
void Push(Register reg, NumberInfo::Type info = NumberInfo::kUnknown); inline void Push(Register reg, NumberInfo::Type info = NumberInfo::kUnknown);
void Push(Handle<Object> value); inline void Push(Handle<Object> value);
void Push(Smi* value) { inline void Push(Smi* value);
Push(Handle<Object> (value));
}
// Pushing a result invalidates it (its contents become owned by the // Pushing a result invalidates it (its contents become owned by the
// frame). // frame).
@ -422,7 +420,7 @@ class VirtualFrame: public ZoneObject {
// Nip removes zero or more elements from immediately below the top // Nip removes zero or more elements from immediately below the top
// of the frame, leaving the previous top-of-frame value on top of // of the frame, leaving the previous top-of-frame value on top of
// the frame. Nip(k) is equivalent to x = Pop(), Drop(k), Push(x). // the frame. Nip(k) is equivalent to x = Pop(), Drop(k), Push(x).
void Nip(int num_dropped); inline void Nip(int num_dropped);
private: private:
static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset; static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset;
@ -530,7 +528,7 @@ class VirtualFrame: public ZoneObject {
// Push a copy of a frame slot (typically a local or parameter) on top of // Push a copy of a frame slot (typically a local or parameter) on top of
// the frame. // the frame.
void PushFrameSlotAt(int index); inline void PushFrameSlotAt(int index);
// Push a the value of a frame slot (typically a local or parameter) on // Push a the value of a frame slot (typically a local or parameter) on
// top of the frame and invalidate the slot. // top of the frame and invalidate the slot.
@ -581,7 +579,7 @@ class VirtualFrame: public ZoneObject {
// (via PrepareForCall). // (via PrepareForCall).
Result RawCallCodeObject(Handle<Code> code, RelocInfo::Mode rmode); Result RawCallCodeObject(Handle<Code> code, RelocInfo::Mode rmode);
bool Equals(VirtualFrame* other); inline bool Equals(VirtualFrame* other);
// Classes that need raw access to the elements_ array. // Classes that need raw access to the elements_ array.
friend class DeferredCode; friend class DeferredCode;

14
deps/v8/src/ic.cc

@ -1049,20 +1049,6 @@ Object* StoreIC::Store(State state,
return *value; return *value;
} }
// Use specialized code for setting the length of arrays.
if (receiver->IsJSArray()
&& name->Equals(Heap::length_symbol())
&& receiver->AllowsSetElementsLength()) {
#ifdef DEBUG
if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n");
#endif
Code* target = Builtins::builtin(Builtins::StoreIC_ArrayLength);
set_target(target);
StubCache::Set(*name, HeapObject::cast(*object)->map(), target);
return receiver->SetProperty(*name, *value, NONE);
}
// Lookup the property locally in the receiver. // Lookup the property locally in the receiver.
if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) { if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) {
LookupResult lookup; LookupResult lookup;

7
deps/v8/src/jump-target-inl.h

@ -28,6 +28,8 @@
#ifndef V8_JUMP_TARGET_INL_H_ #ifndef V8_JUMP_TARGET_INL_H_
#define V8_JUMP_TARGET_INL_H_ #define V8_JUMP_TARGET_INL_H_
#include "virtual-frame-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
@ -36,14 +38,15 @@ CodeGenerator* JumpTarget::cgen() {
} }
void JumpTarget::InitializeEntryElement(int index, FrameElement* target) { void JumpTarget::InitializeEntryElement(int index, FrameElement* target) {
entry_frame_->elements_[index].clear_copied(); FrameElement* element = &entry_frame_->elements_[index];
element->clear_copied();
if (target->is_register()) { if (target->is_register()) {
entry_frame_->set_register_location(target->reg(), index); entry_frame_->set_register_location(target->reg(), index);
} else if (target->is_copy()) { } else if (target->is_copy()) {
entry_frame_->elements_[target->index()].set_copied(); entry_frame_->elements_[target->index()].set_copied();
} }
if (direction_ == BIDIRECTIONAL && !target->is_copy()) { if (direction_ == BIDIRECTIONAL && !target->is_copy()) {
entry_frame_->elements_[index].set_number_info(NumberInfo::kUnknown); element->set_number_info(NumberInfo::kUnknown);
} }
} }

3
deps/v8/src/jump-target.cc

@ -100,9 +100,8 @@ void JumpTarget::ComputeEntryFrame() {
// change our decision about undetermined or invalid elements. // change our decision about undetermined or invalid elements.
if (element == NULL || !element->is_valid()) break; if (element == NULL || !element->is_valid()) break;
element = element->Combine(&reaching_frames_[j]->elements_[i]);
FrameElement* other = &reaching_frames_[j]->elements_[i]; FrameElement* other = &reaching_frames_[j]->elements_[i];
element = element->Combine(other);
if (element != NULL && !element->is_copy()) { if (element != NULL && !element->is_copy()) {
ASSERT(other != NULL); ASSERT(other != NULL);
// We overwrite the number information of one of the incoming frames. // We overwrite the number information of one of the incoming frames.

1
deps/v8/src/register-allocator-inl.h

@ -30,7 +30,6 @@
#include "codegen.h" #include "codegen.h"
#include "register-allocator.h" #include "register-allocator.h"
#include "virtual-frame.h"
#if V8_TARGET_ARCH_IA32 #if V8_TARGET_ARCH_IA32
#include "ia32/register-allocator-ia32-inl.h" #include "ia32/register-allocator-ia32-inl.h"

1
deps/v8/src/register-allocator.cc

@ -29,6 +29,7 @@
#include "codegen-inl.h" #include "codegen-inl.h"
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
#include "virtual-frame-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

2
deps/v8/src/version.cc

@ -35,7 +35,7 @@
#define MAJOR_VERSION 2 #define MAJOR_VERSION 2
#define MINOR_VERSION 1 #define MINOR_VERSION 1
#define BUILD_NUMBER 2 #define BUILD_NUMBER 2
#define PATCH_LEVEL 0 #define PATCH_LEVEL 6
#define CANDIDATE_VERSION false #define CANDIDATE_VERSION false
// Define SONAME to have the SCons build the put a specific SONAME into the // Define SONAME to have the SCons build the put a specific SONAME into the

109
deps/v8/src/virtual-frame-inl.h

@ -0,0 +1,109 @@
// Copyright 2008 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef V8_VIRTUAL_FRAME_INL_H_
#define V8_VIRTUAL_FRAME_INL_H_
#include "virtual-frame.h"
namespace v8 {
namespace internal {
// When cloned, a frame is a deep copy of the original.
VirtualFrame::VirtualFrame(VirtualFrame* original)
: elements_(original->element_count()),
stack_pointer_(original->stack_pointer_) {
elements_.AddAll(original->elements_);
// Copy register locations from original.
memcpy(&register_locations_,
original->register_locations_,
sizeof(register_locations_));
}
void VirtualFrame::PushFrameSlotAt(int index) {
elements_.Add(CopyElementAt(index));
}
void VirtualFrame::Push(Register reg, NumberInfo::Type info) {
if (is_used(reg)) {
int index = register_location(reg);
FrameElement element = CopyElementAt(index, info);
elements_.Add(element);
} else {
Use(reg, element_count());
FrameElement element =
FrameElement::RegisterElement(reg, FrameElement::NOT_SYNCED, info);
elements_.Add(element);
}
}
void VirtualFrame::Push(Handle<Object> value) {
FrameElement element =
FrameElement::ConstantElement(value, FrameElement::NOT_SYNCED);
elements_.Add(element);
}
void VirtualFrame::Push(Smi* value) {
Push(Handle<Object> (value));
}
void VirtualFrame::Nip(int num_dropped) {
ASSERT(num_dropped >= 0);
if (num_dropped == 0) return;
Result tos = Pop();
if (num_dropped > 1) {
Drop(num_dropped - 1);
}
SetElementAt(0, &tos);
}
bool VirtualFrame::Equals(VirtualFrame* other) {
#ifdef DEBUG
for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
if (register_location(i) != other->register_location(i)) {
return false;
}
}
if (element_count() != other->element_count()) return false;
#endif
if (stack_pointer_ != other->stack_pointer_) return false;
for (int i = 0; i < element_count(); i++) {
if (!elements_[i].Equals(other->elements_[i])) return false;
}
return true;
}
} } // namespace v8::internal
#endif // V8_VIRTUAL_FRAME_INL_H_

68
deps/v8/src/virtual-frame.cc

@ -29,6 +29,7 @@
#include "codegen-inl.h" #include "codegen-inl.h"
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
#include "virtual-frame-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
@ -36,18 +37,6 @@ namespace internal {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// VirtualFrame implementation. // VirtualFrame implementation.
// When cloned, a frame is a deep copy of the original.
VirtualFrame::VirtualFrame(VirtualFrame* original)
: elements_(original->element_count()),
stack_pointer_(original->stack_pointer_) {
elements_.AddAll(original->elements_);
// Copy register locations from original.
memcpy(&register_locations_,
original->register_locations_,
sizeof(register_locations_));
}
// Create a duplicate of an existing valid frame element. // Create a duplicate of an existing valid frame element.
// We can pass an optional number type information that will override the // We can pass an optional number type information that will override the
// existing information about the backing element. The new information must // existing information about the backing element. The new information must
@ -338,61 +327,6 @@ void VirtualFrame::SetElementAt(int index, Result* value) {
} }
void VirtualFrame::PushFrameSlotAt(int index) {
elements_.Add(CopyElementAt(index));
}
void VirtualFrame::Push(Register reg, NumberInfo::Type info) {
if (is_used(reg)) {
int index = register_location(reg);
FrameElement element = CopyElementAt(index, info);
elements_.Add(element);
} else {
Use(reg, element_count());
FrameElement element =
FrameElement::RegisterElement(reg, FrameElement::NOT_SYNCED, info);
elements_.Add(element);
}
}
void VirtualFrame::Push(Handle<Object> value) {
FrameElement element =
FrameElement::ConstantElement(value, FrameElement::NOT_SYNCED);
elements_.Add(element);
}
void VirtualFrame::Nip(int num_dropped) {
ASSERT(num_dropped >= 0);
if (num_dropped == 0) return;
Result tos = Pop();
if (num_dropped > 1) {
Drop(num_dropped - 1);
}
SetElementAt(0, &tos);
}
bool VirtualFrame::Equals(VirtualFrame* other) {
#ifdef DEBUG
for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
if (register_location(i) != other->register_location(i)) {
return false;
}
}
if (element_count() != other->element_count()) return false;
#endif
if (stack_pointer_ != other->stack_pointer_) return false;
for (int i = 0; i < element_count(); i++) {
if (!elements_[i].Equals(other->elements_[i])) return false;
}
return true;
}
// Specialization of List::ResizeAdd to non-inlined version for FrameElements. // Specialization of List::ResizeAdd to non-inlined version for FrameElements.
// The function ResizeAdd becomes a real function, whose implementation is the // The function ResizeAdd becomes a real function, whose implementation is the
// inlined ResizeAddInternal. // inlined ResizeAddInternal.

4
deps/v8/src/x64/codegen-x64.cc

@ -36,6 +36,7 @@
#include "regexp-macro-assembler.h" #include "regexp-macro-assembler.h"
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
#include "scopes.h" #include "scopes.h"
#include "virtual-frame-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
@ -259,9 +260,6 @@ CodeGenerator::CodeGenerator(MacroAssembler* masm)
} }
Scope* CodeGenerator::scope() { return info_->function()->scope(); }
void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
// Call the runtime to declare the globals. The inevitable call // Call the runtime to declare the globals. The inevitable call
// will sync frame elements to memory anyway, so we do it eagerly to // will sync frame elements to memory anyway, so we do it eagerly to

2
deps/v8/src/x64/codegen-x64.h

@ -343,7 +343,7 @@ class CodeGenerator: public AstVisitor {
// Accessors // Accessors
inline bool is_eval(); inline bool is_eval();
Scope* scope(); inline Scope* scope();
// Generating deferred code. // Generating deferred code.
void ProcessDeferred(); void ProcessDeferred();

1
deps/v8/src/x64/fast-codegen-x64.cc

@ -29,6 +29,7 @@
#include "codegen-inl.h" #include "codegen-inl.h"
#include "fast-codegen.h" #include "fast-codegen.h"
#include "scopes.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

1
deps/v8/src/x64/full-codegen-x64.cc

@ -32,6 +32,7 @@
#include "debug.h" #include "debug.h"
#include "full-codegen.h" #include "full-codegen.h"
#include "parser.h" #include "parser.h"
#include "scopes.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

1
deps/v8/src/x64/jump-target-x64.cc

@ -30,6 +30,7 @@
#include "codegen-inl.h" #include "codegen-inl.h"
#include "jump-target-inl.h" #include "jump-target-inl.h"
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
#include "virtual-frame-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

1
deps/v8/src/x64/register-allocator-x64.cc

@ -29,6 +29,7 @@
#include "codegen-inl.h" #include "codegen-inl.h"
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
#include "virtual-frame-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

1
deps/v8/src/x64/virtual-frame-x64.cc

@ -30,6 +30,7 @@
#include "codegen-inl.h" #include "codegen-inl.h"
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
#include "scopes.h" #include "scopes.h"
#include "virtual-frame-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

14
deps/v8/src/x64/virtual-frame-x64.h

@ -76,7 +76,7 @@ class VirtualFrame : public ZoneObject {
VirtualFrame(); VirtualFrame();
// Construct a virtual frame as a clone of an existing one. // Construct a virtual frame as a clone of an existing one.
explicit VirtualFrame(VirtualFrame* original); explicit inline VirtualFrame(VirtualFrame* original);
CodeGenerator* cgen() { return CodeGeneratorScope::Current(); } CodeGenerator* cgen() { return CodeGeneratorScope::Current(); }
MacroAssembler* masm() { return cgen()->masm(); } MacroAssembler* masm() { return cgen()->masm(); }
@ -395,9 +395,9 @@ class VirtualFrame : public ZoneObject {
void EmitPush(Handle<Object> value); void EmitPush(Handle<Object> value);
// Push an element on the virtual frame. // Push an element on the virtual frame.
void Push(Register reg, NumberInfo::Type info = NumberInfo::kUnknown); inline void Push(Register reg, NumberInfo::Type info = NumberInfo::kUnknown);
void Push(Handle<Object> value); inline void Push(Handle<Object> value);
void Push(Smi* value) { Push(Handle<Object>(value)); } inline void Push(Smi* value);
// Pushing a result invalidates it (its contents become owned by the // Pushing a result invalidates it (its contents become owned by the
// frame). // frame).
@ -414,7 +414,7 @@ class VirtualFrame : public ZoneObject {
// Nip removes zero or more elements from immediately below the top // Nip removes zero or more elements from immediately below the top
// of the frame, leaving the previous top-of-frame value on top of // of the frame, leaving the previous top-of-frame value on top of
// the frame. Nip(k) is equivalent to x = Pop(), Drop(k), Push(x). // the frame. Nip(k) is equivalent to x = Pop(), Drop(k), Push(x).
void Nip(int num_dropped); inline void Nip(int num_dropped);
private: private:
static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset; static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset;
@ -506,7 +506,7 @@ class VirtualFrame : public ZoneObject {
// Push a copy of a frame slot (typically a local or parameter) on top of // Push a copy of a frame slot (typically a local or parameter) on top of
// the frame. // the frame.
void PushFrameSlotAt(int index); inline void PushFrameSlotAt(int index);
// Push a the value of a frame slot (typically a local or parameter) on // Push a the value of a frame slot (typically a local or parameter) on
// top of the frame and invalidate the slot. // top of the frame and invalidate the slot.
@ -557,7 +557,7 @@ class VirtualFrame : public ZoneObject {
// (via PrepareForCall). // (via PrepareForCall).
Result RawCallCodeObject(Handle<Code> code, RelocInfo::Mode rmode); Result RawCallCodeObject(Handle<Code> code, RelocInfo::Mode rmode);
bool Equals(VirtualFrame* other); inline bool Equals(VirtualFrame* other);
// Classes that need raw access to the elements_ array. // Classes that need raw access to the elements_ array.
friend class DeferredCode; friend class DeferredCode;

75
deps/v8/test/cctest/test-api.cc

@ -6433,6 +6433,45 @@ THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
CHECK_GE(interceptor_call_count, 50); CHECK_GE(interceptor_call_count, 50);
} }
THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
int interceptor_call_count = 0;
v8::HandleScope scope;
v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
v8::Handle<v8::FunctionTemplate> method_templ =
v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
v8_str("method_data"),
v8::Signature::New(fun_templ));
v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
proto_templ->Set(v8_str("method"), method_templ);
v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
NULL, NULL, NULL, NULL,
v8::External::Wrap(&interceptor_call_count));
LocalContext context;
v8::Handle<v8::Function> fun = fun_templ->GetFunction();
GenerateSomeGarbage();
context->Global()->Set(v8_str("o"), fun->NewInstance());
v8::TryCatch try_catch;
v8::Handle<Value> value = CompileRun(
"o.foo = 17;"
"var receiver = {};"
"receiver.__proto__ = o;"
"var result = 0;"
"var saved_result = 0;"
"for (var i = 0; i < 100; i++) {"
" result = receiver.method(41);"
" if (i == 50) {"
" saved_result = result;"
" receiver = 333;"
" }"
"}");
CHECK(try_catch.HasCaught());
CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
try_catch.Exception()->ToString());
CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
CHECK_GE(interceptor_call_count, 50);
}
THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) { THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
int interceptor_call_count = 0; int interceptor_call_count = 0;
v8::HandleScope scope; v8::HandleScope scope;
@ -6521,7 +6560,7 @@ THREADED_TEST(CallICFastApi_SimpleSignature) {
CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value()); CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
} }
THREADED_TEST(CallICFastApi_SimpleSignature_Miss) { THREADED_TEST(CallICFastApi_SimpleSignature_Miss1) {
v8::HandleScope scope; v8::HandleScope scope;
v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(); v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
v8::Handle<v8::FunctionTemplate> method_templ = v8::Handle<v8::FunctionTemplate> method_templ =
@ -6552,6 +6591,40 @@ THREADED_TEST(CallICFastApi_SimpleSignature_Miss) {
CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value()); CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
} }
THREADED_TEST(CallICFastApi_SimpleSignature_Miss2) {
v8::HandleScope scope;
v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
v8::Handle<v8::FunctionTemplate> method_templ =
v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
v8_str("method_data"),
v8::Signature::New(fun_templ));
v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
proto_templ->Set(v8_str("method"), method_templ);
v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
LocalContext context;
v8::Handle<v8::Function> fun = fun_templ->GetFunction();
GenerateSomeGarbage();
context->Global()->Set(v8_str("o"), fun->NewInstance());
v8::TryCatch try_catch;
v8::Handle<Value> value = CompileRun(
"o.foo = 17;"
"var receiver = {};"
"receiver.__proto__ = o;"
"var result = 0;"
"var saved_result = 0;"
"for (var i = 0; i < 100; i++) {"
" result = receiver.method(41);"
" if (i == 50) {"
" saved_result = result;"
" receiver = 333;"
" }"
"}");
CHECK(try_catch.HasCaught());
CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
try_catch.Exception()->ToString());
CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
}
static int interceptor_call_count = 0; static int interceptor_call_count = 0;

22
deps/v8/test/cctest/test-thread-termination.cc

@ -40,6 +40,7 @@ v8::Handle<v8::Value> Signal(const v8::Arguments& args) {
v8::Handle<v8::Value> TerminateCurrentThread(const v8::Arguments& args) { v8::Handle<v8::Value> TerminateCurrentThread(const v8::Arguments& args) {
CHECK(!v8::V8::IsExecutionTerminating());
v8::V8::TerminateExecution(); v8::V8::TerminateExecution();
return v8::Undefined(); return v8::Undefined();
} }
@ -52,15 +53,19 @@ v8::Handle<v8::Value> Fail(const v8::Arguments& args) {
v8::Handle<v8::Value> Loop(const v8::Arguments& args) { v8::Handle<v8::Value> Loop(const v8::Arguments& args) {
CHECK(!v8::V8::IsExecutionTerminating());
v8::Handle<v8::String> source = v8::Handle<v8::String> source =
v8::String::New("try { doloop(); fail(); } catch(e) { fail(); }"); v8::String::New("try { doloop(); fail(); } catch(e) { fail(); }");
v8::Script::Compile(source)->Run(); v8::Handle<v8::Value> result = v8::Script::Compile(source)->Run();
CHECK(result.IsEmpty());
CHECK(v8::V8::IsExecutionTerminating());
return v8::Undefined(); return v8::Undefined();
} }
v8::Handle<v8::Value> DoLoop(const v8::Arguments& args) { v8::Handle<v8::Value> DoLoop(const v8::Arguments& args) {
v8::TryCatch try_catch; v8::TryCatch try_catch;
CHECK(!v8::V8::IsExecutionTerminating());
v8::Script::Compile(v8::String::New("function f() {" v8::Script::Compile(v8::String::New("function f() {"
" var term = true;" " var term = true;"
" try {" " try {"
@ -78,12 +83,14 @@ v8::Handle<v8::Value> DoLoop(const v8::Arguments& args) {
CHECK(try_catch.Exception()->IsNull()); CHECK(try_catch.Exception()->IsNull());
CHECK(try_catch.Message().IsEmpty()); CHECK(try_catch.Message().IsEmpty());
CHECK(!try_catch.CanContinue()); CHECK(!try_catch.CanContinue());
CHECK(v8::V8::IsExecutionTerminating());
return v8::Undefined(); return v8::Undefined();
} }
v8::Handle<v8::Value> DoLoopNoCall(const v8::Arguments& args) { v8::Handle<v8::Value> DoLoopNoCall(const v8::Arguments& args) {
v8::TryCatch try_catch; v8::TryCatch try_catch;
CHECK(!v8::V8::IsExecutionTerminating());
v8::Script::Compile(v8::String::New("var term = true;" v8::Script::Compile(v8::String::New("var term = true;"
"while(true) {" "while(true) {"
" if (term) terminate();" " if (term) terminate();"
@ -93,6 +100,7 @@ v8::Handle<v8::Value> DoLoopNoCall(const v8::Arguments& args) {
CHECK(try_catch.Exception()->IsNull()); CHECK(try_catch.Exception()->IsNull());
CHECK(try_catch.Message().IsEmpty()); CHECK(try_catch.Message().IsEmpty());
CHECK(!try_catch.CanContinue()); CHECK(!try_catch.CanContinue());
CHECK(v8::V8::IsExecutionTerminating());
return v8::Undefined(); return v8::Undefined();
} }
@ -118,11 +126,13 @@ TEST(TerminateOnlyV8ThreadFromThreadItself) {
CreateGlobalTemplate(TerminateCurrentThread, DoLoop); CreateGlobalTemplate(TerminateCurrentThread, DoLoop);
v8::Persistent<v8::Context> context = v8::Context::New(NULL, global); v8::Persistent<v8::Context> context = v8::Context::New(NULL, global);
v8::Context::Scope context_scope(context); v8::Context::Scope context_scope(context);
CHECK(!v8::V8::IsExecutionTerminating());
// Run a loop that will be infinite if thread termination does not work. // Run a loop that will be infinite if thread termination does not work.
v8::Handle<v8::String> source = v8::Handle<v8::String> source =
v8::String::New("try { loop(); fail(); } catch(e) { fail(); }"); v8::String::New("try { loop(); fail(); } catch(e) { fail(); }");
v8::Script::Compile(source)->Run(); v8::Script::Compile(source)->Run();
// Test that we can run the code again after thread termination. // Test that we can run the code again after thread termination.
CHECK(!v8::V8::IsExecutionTerminating());
v8::Script::Compile(source)->Run(); v8::Script::Compile(source)->Run();
context.Dispose(); context.Dispose();
} }
@ -136,10 +146,12 @@ TEST(TerminateOnlyV8ThreadFromThreadItselfNoLoop) {
CreateGlobalTemplate(TerminateCurrentThread, DoLoopNoCall); CreateGlobalTemplate(TerminateCurrentThread, DoLoopNoCall);
v8::Persistent<v8::Context> context = v8::Context::New(NULL, global); v8::Persistent<v8::Context> context = v8::Context::New(NULL, global);
v8::Context::Scope context_scope(context); v8::Context::Scope context_scope(context);
CHECK(!v8::V8::IsExecutionTerminating());
// Run a loop that will be infinite if thread termination does not work. // Run a loop that will be infinite if thread termination does not work.
v8::Handle<v8::String> source = v8::Handle<v8::String> source =
v8::String::New("try { loop(); fail(); } catch(e) { fail(); }"); v8::String::New("try { loop(); fail(); } catch(e) { fail(); }");
v8::Script::Compile(source)->Run(); v8::Script::Compile(source)->Run();
CHECK(!v8::V8::IsExecutionTerminating());
// Test that we can run the code again after thread termination. // Test that we can run the code again after thread termination.
v8::Script::Compile(source)->Run(); v8::Script::Compile(source)->Run();
context.Dispose(); context.Dispose();
@ -149,6 +161,7 @@ TEST(TerminateOnlyV8ThreadFromThreadItselfNoLoop) {
class TerminatorThread : public v8::internal::Thread { class TerminatorThread : public v8::internal::Thread {
void Run() { void Run() {
semaphore->Wait(); semaphore->Wait();
CHECK(!v8::V8::IsExecutionTerminating());
v8::V8::TerminateExecution(); v8::V8::TerminateExecution();
} }
}; };
@ -165,6 +178,7 @@ TEST(TerminateOnlyV8ThreadFromOtherThread) {
v8::Handle<v8::ObjectTemplate> global = CreateGlobalTemplate(Signal, DoLoop); v8::Handle<v8::ObjectTemplate> global = CreateGlobalTemplate(Signal, DoLoop);
v8::Persistent<v8::Context> context = v8::Context::New(NULL, global); v8::Persistent<v8::Context> context = v8::Context::New(NULL, global);
v8::Context::Scope context_scope(context); v8::Context::Scope context_scope(context);
CHECK(!v8::V8::IsExecutionTerminating());
// Run a loop that will be infinite if thread termination does not work. // Run a loop that will be infinite if thread termination does not work.
v8::Handle<v8::String> source = v8::Handle<v8::String> source =
v8::String::New("try { loop(); fail(); } catch(e) { fail(); }"); v8::String::New("try { loop(); fail(); } catch(e) { fail(); }");
@ -187,6 +201,7 @@ class LoopingThread : public v8::internal::Thread {
CreateGlobalTemplate(Signal, DoLoop); CreateGlobalTemplate(Signal, DoLoop);
v8::Persistent<v8::Context> context = v8::Context::New(NULL, global); v8::Persistent<v8::Context> context = v8::Context::New(NULL, global);
v8::Context::Scope context_scope(context); v8::Context::Scope context_scope(context);
CHECK(!v8::V8::IsExecutionTerminating());
// Run a loop that will be infinite if thread termination does not work. // Run a loop that will be infinite if thread termination does not work.
v8::Handle<v8::String> source = v8::Handle<v8::String> source =
v8::String::New("try { loop(); fail(); } catch(e) { fail(); }"); v8::String::New("try { loop(); fail(); } catch(e) { fail(); }");
@ -235,6 +250,7 @@ int call_count = 0;
v8::Handle<v8::Value> TerminateOrReturnObject(const v8::Arguments& args) { v8::Handle<v8::Value> TerminateOrReturnObject(const v8::Arguments& args) {
if (++call_count == 10) { if (++call_count == 10) {
CHECK(!v8::V8::IsExecutionTerminating());
v8::V8::TerminateExecution(); v8::V8::TerminateExecution();
return v8::Undefined(); return v8::Undefined();
} }
@ -246,6 +262,7 @@ v8::Handle<v8::Value> TerminateOrReturnObject(const v8::Arguments& args) {
v8::Handle<v8::Value> LoopGetProperty(const v8::Arguments& args) { v8::Handle<v8::Value> LoopGetProperty(const v8::Arguments& args) {
v8::TryCatch try_catch; v8::TryCatch try_catch;
CHECK(!v8::V8::IsExecutionTerminating());
v8::Script::Compile(v8::String::New("function f() {" v8::Script::Compile(v8::String::New("function f() {"
" try {" " try {"
" while(true) {" " while(true) {"
@ -261,6 +278,7 @@ v8::Handle<v8::Value> LoopGetProperty(const v8::Arguments& args) {
CHECK(try_catch.Exception()->IsNull()); CHECK(try_catch.Exception()->IsNull());
CHECK(try_catch.Message().IsEmpty()); CHECK(try_catch.Message().IsEmpty());
CHECK(!try_catch.CanContinue()); CHECK(!try_catch.CanContinue());
CHECK(v8::V8::IsExecutionTerminating());
return v8::Undefined(); return v8::Undefined();
} }
@ -278,12 +296,14 @@ TEST(TerminateLoadICException) {
v8::Persistent<v8::Context> context = v8::Context::New(NULL, global); v8::Persistent<v8::Context> context = v8::Context::New(NULL, global);
v8::Context::Scope context_scope(context); v8::Context::Scope context_scope(context);
CHECK(!v8::V8::IsExecutionTerminating());
// Run a loop that will be infinite if thread termination does not work. // Run a loop that will be infinite if thread termination does not work.
v8::Handle<v8::String> source = v8::Handle<v8::String> source =
v8::String::New("try { loop(); fail(); } catch(e) { fail(); }"); v8::String::New("try { loop(); fail(); } catch(e) { fail(); }");
call_count = 0; call_count = 0;
v8::Script::Compile(source)->Run(); v8::Script::Compile(source)->Run();
// Test that we can run the code again after thread termination. // Test that we can run the code again after thread termination.
CHECK(!v8::V8::IsExecutionTerminating());
call_count = 0; call_count = 0;
v8::Script::Compile(source)->Run(); v8::Script::Compile(source)->Run();
context.Dispose(); context.Dispose();

1
deps/v8/tools/gyp/v8.gyp

@ -391,6 +391,7 @@
'../../src/variables.h', '../../src/variables.h',
'../../src/version.cc', '../../src/version.cc',
'../../src/version.h', '../../src/version.h',
'../../src/virtual-frame-inl.h',
'../../src/virtual-frame.h', '../../src/virtual-frame.h',
'../../src/virtual-frame.cc', '../../src/virtual-frame.cc',
'../../src/zone-inl.h', '../../src/zone-inl.h',

4
deps/v8/tools/visual_studio/v8_base.vcproj

@ -936,6 +936,10 @@
RelativePath="..\..\src\version.h" RelativePath="..\..\src\version.h"
> >
</File> </File>
<File
RelativePath="..\..\src\virtual-frame-inl.h"
>
</File>
<File <File
RelativePath="..\..\src\virtual-frame.h" RelativePath="..\..\src\virtual-frame.h"
> >

4
deps/v8/tools/visual_studio/v8_base_arm.vcproj

@ -948,6 +948,10 @@
RelativePath="..\..\src\version.h" RelativePath="..\..\src\version.h"
> >
</File> </File>
<File
RelativePath="..\..\src\virtual-frame-inl.h"
>
</File>
<File <File
RelativePath="..\..\src\virtual-frame.h" RelativePath="..\..\src\virtual-frame.h"
> >

4
deps/v8/tools/visual_studio/v8_base_x64.vcproj

@ -937,6 +937,10 @@
RelativePath="..\..\src\version.h" RelativePath="..\..\src\version.h"
> >
</File> </File>
<File
RelativePath="..\..\src\virtual-frame-inl.h"
>
</File>
<File <File
RelativePath="..\..\src\virtual-frame.h" RelativePath="..\..\src\virtual-frame.h"
> >

22
doc/api.txt

@ -143,10 +143,11 @@ Gets/sets the group identity of the process. (See setgid(2).)
+process.chdir(directory)+:: +process.chdir(directory)+::
Changes the current working directory of the process. Changes the current working directory of the process.
+process.umask(mask)+ :: +process.umask([mask])+ ::
Sets the process's file mode creation mask. Child processes inherit the mask Sets or read the process's file mode creation mask. Child processes inherit
from the parent process. the mask from the parent process.
- returns the old mask. - returns the old mask if +mask+ argument is given, otherwise returns
the current mask.
+process.kill(pid, signal="SIGTERM")+ :: +process.kill(pid, signal="SIGTERM")+ ::
Send a signal to a process. +pid+ is the process id and +signal+ is the Send a signal to a process. +pid+ is the process id and +signal+ is the
@ -822,7 +823,7 @@ until the stream is resumed.
+readStream.resume()+ :: +readStream.resume()+ ::
Resumes the stream. Together with +pause()+ this useful to throttle reading. Resumes the stream. Together with +pause()+ this useful to throttle reading.
+readStream.forceClose()+ :: +readStream.forceClose([callback])+ ::
Allows to close the stream before the +"end"+ is reached. No more events other Allows to close the stream before the +"end"+ is reached. No more events other
than +"close"+ will be fired after this method has been called. than +"close"+ will be fired after this method has been called.
@ -844,7 +845,7 @@ Returns a new FileWriteStream object.
+options+ is an object with the following defaults: +options+ is an object with the following defaults:
+ +
---------------------------------------- ----------------------------------------
{ "flags": "r" { "flags": "w"
, "encoding": "binary" , "encoding": "binary"
, "mode": 0666 , "mode": 0666
} }
@ -854,15 +855,18 @@ Returns a new FileWriteStream object.
A boolean that is +true+ by default, but turns +false+ after an +"error"+ A boolean that is +true+ by default, but turns +false+ after an +"error"+
occured or +close()+ / +forceClose()+ was called. occured or +close()+ / +forceClose()+ was called.
+writeStream.write(data)+ :: +writeStream.write(data, [callback])+ ::
Returns +true+ if the data was flushed to the kernel, and +false+ if it was Returns +true+ if the data was flushed to the kernel, and +false+ if it was
queued up for being written later. A +"drain"+ will fire after all queued data queued up for being written later. A +"drain"+ will fire after all queued data
has been written. has been written.
+
You can also specify +callback+ to be notified when the data from this write
has been flushed. The first param is +err+, the second is +bytesWritten+.
+writeStream.close()+ :: +writeStream.close([callback])+ ::
Closes the stream right after all queued +write()+ calls have finished. Closes the stream right after all queued +write()+ calls have finished.
+writeStream.forceClose()+ :: +writeStream.forceClose([callback])+ ::
Allows to close the stream regardless of its current state. Allows to close the stream regardless of its current state.
== HTTP == HTTP

78
lib/fs.js

@ -1,6 +1,7 @@
var var
sys = require('sys'), sys = require('sys'),
events = require('events'); events = require('events'),
fs = require('fs');
exports.Stats = process.Stats; exports.Stats = process.Stats;
@ -495,16 +496,31 @@ var FileReadStream = exports.FileReadStream = function(path, options) {
read(); read();
}); });
this.forceClose = function() { this.forceClose = function(cb) {
this.readable = false; this.readable = false;
fs.close(this.fd, function(err) {
if (err) {
self.emit('error', err);
return;
}
self.emit('close'); function close() {
}); fs.close(self.fd, function(err) {
if (err) {
if (cb) {
cb(err);
}
self.emit('error', err);
return;
}
if (cb) {
cb(null);
}
self.emit('close');
});
}
if (this.fd) {
close();
} else {
this.addListener('open', close);
}
}; };
this.pause = function() { this.pause = function() {
@ -546,7 +562,7 @@ var FileWriteStream = exports.FileWriteStream = function(path, options) {
queue = [], queue = [],
busy = false; busy = false;
queue.push([fs.open, this.path, this.flags, this.mode]); queue.push([fs.open, this.path, this.flags, this.mode, undefined]);
function flush() { function flush() {
if (busy) { if (busy) {
@ -560,29 +576,40 @@ var FileWriteStream = exports.FileWriteStream = function(path, options) {
busy = true; busy = true;
var method = args.shift(); var
method = args.shift(),
cb = args.pop();
args.push(function(err) { args.push(function(err) {
busy = false; busy = false;
if (err) { if (err) {
self.writeable = false; self.writeable = false;
if (cb) {
cb(err);
}
self.emit('error', err); self.emit('error', err);
return; return;
} }
// save reference for file pointer
if (method === fs.open) {
self.fd = arguments[1];
self.emit('open', self.fd);
}
// stop flushing after close // stop flushing after close
if (method === fs.close) { if (method === fs.close) {
if (cb) {
cb(null);
}
self.emit('close'); self.emit('close');
return; return;
} }
// save reference for file pointer
if (method === fs.open) {
self.fd = arguments[1];
self.emit('open', self.fd);
} else if (cb) {
// write callback
cb(null, arguments[1]);
}
flush(); flush();
}); });
@ -594,30 +621,37 @@ var FileWriteStream = exports.FileWriteStream = function(path, options) {
method.apply(null, args); method.apply(null, args);
}; };
this.write = function(data) { this.write = function(data, cb) {
if (!this.writeable) { if (!this.writeable) {
throw new Error('stream not writeable'); throw new Error('stream not writeable');
} }
queue.push([fs.write, data, undefined, this.encoding]); queue.push([fs.write, data, undefined, this.encoding, cb]);
flush(); flush();
return false; return false;
}; };
this.close = function() { this.close = function(cb) {
this.writeable = false; this.writeable = false;
queue.push([fs.close,]); queue.push([fs.close, cb]);
flush(); flush();
}; };
this.forceClose = function() { this.forceClose = function(cb) {
this.writeable = false; this.writeable = false;
fs.close(self.fd, function(err) { fs.close(self.fd, function(err) {
if (err) { if (err) {
if (cb) {
cb(err);
}
self.emit('error', err); self.emit('error', err);
return; return;
} }
if (cb) {
cb(null);
}
self.emit('close'); self.emit('close');
}); });
}; };

32
src/node.cc

@ -475,14 +475,18 @@ static Handle<Value> Cwd(const Arguments& args) {
static Handle<Value> Umask(const Arguments& args){ static Handle<Value> Umask(const Arguments& args){
HandleScope scope; HandleScope scope;
unsigned int old;
if(args.Length() < 1 || !args[0]->IsInt32()) { if(args.Length() < 1) {
old = umask(0);
umask((mode_t)old);
}
else if(!args[0]->IsInt32()) {
return ThrowException(Exception::TypeError( return ThrowException(Exception::TypeError(
String::New("argument must be an integer."))); String::New("argument must be an integer.")));
} }
unsigned int mask = args[0]->Uint32Value(); else {
unsigned int old = umask((mode_t)mask); old = umask((mode_t)args[0]->Uint32Value());
}
return scope.Close(Uint32::New(old)); return scope.Close(Uint32::New(old));
} }
@ -1191,13 +1195,21 @@ static void ParseDebugOpt(const char* arg) {
static void PrintHelp() { static void PrintHelp() {
printf("Usage: node [options] script.js [arguments] \n" printf("Usage: node [options] script.js [arguments] \n"
"Options:\n"
" -v, --version print node's version\n" " -v, --version print node's version\n"
" --debug[=port] enable remote debugging via given TCP port\n" " --debug[=port] enable remote debugging via given TCP port\n"
" without stopping the execution\n" " without stopping the execution\n"
" --debug-brk[=port] as above, but break in script.js and\n" " --debug-brk[=port] as above, but break in script.js and\n"
" wait for remote debugger to connect\n" " wait for remote debugger to connect\n"
" --cflags print pre-processor and compiler flags\n" " --v8-options print v8 command line options\n"
" --v8-options print v8 command line options\n\n" " --vars print various compiled-in variables\n"
"\n"
"Enviromental variables:\n"
"NODE_PATH ':'-separated list of directories\n"
" prefixed to the module search path,\n"
" require.paths.\n"
"NODE_DEBUG Print additional debugging output.\n"
"\n"
"Documentation can be found at http://nodejs.org/api.html" "Documentation can be found at http://nodejs.org/api.html"
" or with 'man node'\n"); " or with 'man node'\n");
} }
@ -1214,8 +1226,10 @@ static void ParseArgs(int *argc, char **argv) {
} else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) { } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {
printf("%s\n", NODE_VERSION); printf("%s\n", NODE_VERSION);
exit(0); exit(0);
} else if (strcmp(arg, "--cflags") == 0) { } else if (strcmp(arg, "--vars") == 0) {
printf("%s\n", NODE_CFLAGS); printf("NODE_PREFIX: %s\n", NODE_PREFIX);
printf("NODE_LIBRARIES_PREFIX: %s/%s\n", NODE_PREFIX, "lib/node/libraries");
printf("NODE_CFLAGS: %s\n", NODE_CFLAGS);
exit(0); exit(0);
} else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) { } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
PrintHelp(); PrintHelp();

2
test/common.js

@ -12,5 +12,3 @@ var sys = require("sys");
process.mixin(exports, sys); process.mixin(exports, sys);
exports.assert = require('assert'); exports.assert = require('assert');
exports.fs = require("fs");
exports.path = path;

8
test/simple/test-chdir.js

@ -1,9 +1,7 @@
process.mixin(require("../common")); process.mixin(require("../common"));
var dirname = path.dirname(__filename); assert.equal(true, process.cwd() !== __dirname);
assert.equal(true, process.cwd() !== dirname); process.chdir(__dirname);
process.chdir(dirname); assert.equal(true, process.cwd() === __dirname);
assert.equal(true, process.cwd() === dirname);

1
test/simple/test-eio-race2.js

@ -1,4 +1,5 @@
process.mixin(require("../common")); process.mixin(require("../common"));
var path = require('path');
var testTxt = path.join(fixturesDir, "x.txt"); var testTxt = path.join(fixturesDir, "x.txt");
var fs = require('fs'); var fs = require('fs');

2
test/simple/test-eio-race4.js

@ -1,5 +1,5 @@
process.mixin(require("../common")); process.mixin(require("../common"));
var fs = require('fs');
var N = 100; var N = 100;
var j = 0; var j = 0;

2
test/simple/test-file-read-noexist.js

@ -1,4 +1,6 @@
process.mixin(require("../common")); process.mixin(require("../common"));
var path = require('path');
var fs = require('fs');
var got_error = false; var got_error = false;
var filename = path.join(fixturesDir, "does_not_exist.txt"); var filename = path.join(fixturesDir, "does_not_exist.txt");

11
test/simple/test-file-read-stream.js

@ -1,13 +1,16 @@
process.mixin(require('../common')); process.mixin(require('../common'));
var var
path = require('path'),
fs = require('fs'),
fn = path.join(fixturesDir, 'multipart.js'), fn = path.join(fixturesDir, 'multipart.js'),
file = fs.createReadStream(fn), file = fs.createReadStream(fn),
callbacks = { callbacks = {
open: -1, open: -1,
end: -1, end: -1,
close: -1 close: -1,
forceClose: -1
}, },
paused = false, paused = false,
@ -47,6 +50,12 @@ file
assert.equal(fs.readFileSync(fn), fileContent); assert.equal(fs.readFileSync(fn), fileContent);
}); });
var file2 = fs.createReadStream(fn);
file2.forceClose(function(err) {
assert.ok(!err);
callbacks.forceClose++;
});
process.addListener('exit', function() { process.addListener('exit', function() {
for (var k in callbacks) { for (var k in callbacks) {
assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]); assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]);

22
test/simple/test-file-write-stream.js

@ -1,15 +1,19 @@
process.mixin(require('../common')); process.mixin(require('../common'));
var var
path = require('path'),
fs = require('fs'),
fn = path.join(fixturesDir, "write.txt"), fn = path.join(fixturesDir, "write.txt"),
file = fs.createWriteStream(fn), file = fs.createWriteStream(fn),
EXPECTED = '0123456789', EXPECTED = '012345678910',
callbacks = { callbacks = {
open: -1, open: -1,
drain: -2, drain: -2,
close: -1 close: -1,
closeCb: -1,
write: -11,
}; };
file file
@ -27,7 +31,10 @@ file
file.write(EXPECTED); file.write(EXPECTED);
} else if (callbacks.drain == 0) { } else if (callbacks.drain == 0) {
assert.equal(EXPECTED+EXPECTED, fs.readFileSync(fn)); assert.equal(EXPECTED+EXPECTED, fs.readFileSync(fn));
file.close(); file.close(function(err) {
assert.ok(!err);
callbacks.closeCb++;
});
} }
}) })
.addListener('close', function() { .addListener('close', function() {
@ -39,8 +46,13 @@ file
fs.unlinkSync(fn); fs.unlinkSync(fn);
}); });
for (var i = 0; i < 10; i++) { for (var i = 0; i < 11; i++) {
assert.strictEqual(false, file.write(i)); (function(i) {
assert.strictEqual(false, file.write(i, function(err, bytesWritten) {
callbacks.write++;
assert.equal(new String(i).length, bytesWritten);
}));
})(i);
} }
process.addListener('exit', function() { process.addListener('exit', function() {

3
test/simple/test-fs-chmod.js

@ -1,5 +1,6 @@
process.mixin(require("../common")); process.mixin(require("../common"));
var path = require('path');
var fs = require('fs');
var got_error = false; var got_error = false;
var success_count = 0; var success_count = 0;

3
test/simple/test-fs-realpath.js

@ -1,5 +1,6 @@
process.mixin(require("../common")); process.mixin(require("../common"));
var fs = require('fs');
var path = require('path');
var async_completed = 0, async_expected = 0, unlink = []; var async_completed = 0, async_expected = 0, unlink = [];
function asynctest(testBlock, args, callback, assertBlock) { function asynctest(testBlock, args, callback, assertBlock) {

2
test/simple/test-fs-stat.js

@ -1,5 +1,5 @@
process.mixin(require("../common")); process.mixin(require("../common"));
var fs = require('fs');
var got_error = false; var got_error = false;
var success_count = 0; var success_count = 0;

3
test/simple/test-fs-symlink.js

@ -1,5 +1,6 @@
process.mixin(require("../common")); process.mixin(require("../common"));
var path = require('path');
var fs = require('fs');
var completed = 0; var completed = 0;
// test creating and reading symbolic link // test creating and reading symbolic link

3
test/simple/test-fs-write.js

@ -1,5 +1,6 @@
process.mixin(require("../common")); process.mixin(require("../common"));
var path = require('path');
var fs = require('fs');
var fn = path.join(fixturesDir, "write.txt"); var fn = path.join(fixturesDir, "write.txt");
var expected = "hello"; var expected = "hello";
var found; var found;

5
test/simple/test-http-tls.js

@ -1,6 +1,7 @@
process.mixin(require("../common")); process.mixin(require("../common"));
http = require("http"); var http = require("http");
url = require("url"); var url = require("url");
var fs = require('fs');
HOST = "localhost"; HOST = "localhost";

3
test/simple/test-ini.js

@ -1,5 +1,6 @@
process.mixin(require("../common")); process.mixin(require("../common"));
require("fs"); var path = require('path');
var fs = require("fs");
parse = require("ini").parse; parse = require("ini").parse;
debug("load fixtures/fixture.ini"); debug("load fixtures/fixture.ini");

2
test/simple/test-mkdir-rmdir.js

@ -1,4 +1,6 @@
process.mixin(require("../common")); process.mixin(require("../common"));
var path = require('path');
var fs = require('fs');
var dirname = path.dirname(__filename); var dirname = path.dirname(__filename);
var fixtures = path.join(dirname, "../fixtures"); var fixtures = path.join(dirname, "../fixtures");

1
test/simple/test-module-loading.js

@ -1,4 +1,5 @@
process.mixin(require("../common")); process.mixin(require("../common"));
var path = require('path');
debug("load test-module-loading.js"); debug("load test-module-loading.js");

2
test/simple/test-readdir.js

@ -1,4 +1,6 @@
process.mixin(require("../common")); process.mixin(require("../common"));
var path = require('path');
var fs = require('fs');
var got_error = false, var got_error = false,
readdirDir = path.join(fixturesDir, "readdir") readdirDir = path.join(fixturesDir, "readdir")

1
test/simple/test-stdio.js

@ -1,4 +1,5 @@
process.mixin(require("../common")); process.mixin(require("../common"));
var path = require('path');
var sub = path.join(fixturesDir, 'echo.js'); var sub = path.join(fixturesDir, 'echo.js');

1
test/simple/test-stdout-flush.js

@ -1,4 +1,5 @@
process.mixin(require("../common")); process.mixin(require("../common"));
var path = require('path');
var sub = path.join(fixturesDir, 'print-chars.js'); var sub = path.join(fixturesDir, 'print-chars.js');

2
test/simple/test-sync-fileread.js

@ -1,4 +1,6 @@
process.mixin(require('../common')); process.mixin(require('../common'));
var path = require('path');
var fs = require('fs');
var fixture = path.join(__dirname, "../fixtures/x.txt"); var fixture = path.join(__dirname, "../fixtures/x.txt");

8
test/simple/test-umask.js

@ -3,4 +3,10 @@ process.mixin(require("../common"));
var mask = 0664; var mask = 0664;
var old = process.umask(mask); var old = process.umask(mask);
assert.equal(true, mask === process.umask(old)); assert.equal(mask, process.umask(old));
// confirm reading the umask does not modify it.
// 1. If the test fails, this call will succeed, but the mask will be set to 0
assert.equal(old, process.umask());
// 2. If the test fails, process.umask() will return 0
assert.equal(old, process.umask());

12
tools/waf-light

@ -1,6 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python
# encoding: utf-8 # encoding: ISO8859-1
# Thomas Nagy, 2005-2009 # Thomas Nagy, 2005-2010
""" """
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@ -37,7 +37,7 @@ if 'PSYCOWAF' in os.environ:
try:import psyco;psyco.full() try:import psyco;psyco.full()
except:pass except:pass
VERSION="1.5.10" VERSION="1.5.14"
REVISION="x" REVISION="x"
INSTALL="x" INSTALL="x"
C1='x' C1='x'
@ -149,7 +149,7 @@ t = join(w, 'Tools')
f = join(w, '3rdparty') f = join(w, '3rdparty')
sys.path = [w, t, f] + sys.path sys.path = [w, t, f] + sys.path
import Scripting if __name__ == '__main__':
Scripting.prepare(t, cwd, VERSION, wafdir) import Scripting
sys.exit(0) Scripting.prepare(t, cwd, VERSION, wafdir)

21
tools/wafadmin/3rdparty/boost.py

@ -17,7 +17,7 @@
# conf.check_boost(lib='signals filesystem', static='onlystatic', score_version=(-1000, 1000), tag_minscore=1000) # conf.check_boost(lib='signals filesystem', static='onlystatic', score_version=(-1000, 1000), tag_minscore=1000)
# #
#def build(bld): #def build(bld):
# bld.new_task_gen(source='main.c', target='bar', uselib="BOOST BOOST_SYSTEM") # bld(source='main.c', target='bar', uselib="BOOST BOOST_SYSTEM")
# #
#ISSUES: #ISSUES:
# * find_includes should be called only once! # * find_includes should be called only once!
@ -28,7 +28,7 @@
## * the rest of the code has not really been tried ## * the rest of the code has not really been tried
# * make certain a demo is provided (in demos/adv for example) # * make certain a demo is provided (in demos/adv for example)
# TODO: boost.py will be removed in waf 1.6 # TODO: bad and underdocumented code -> boost.py will be removed in waf 1.6 to be rewritten later
import os.path, glob, types, re, sys import os.path, glob, types, re, sys
import Configure, config_c, Options, Utils, Logs import Configure, config_c, Options, Utils, Logs
@ -52,6 +52,7 @@ is_versiontag = re.compile('^\d+_\d+_?\d*$')
is_threadingtag = re.compile('^mt$') is_threadingtag = re.compile('^mt$')
is_abitag = re.compile('^[sgydpn]+$') is_abitag = re.compile('^[sgydpn]+$')
is_toolsettag = re.compile('^(acc|borland|como|cw|dmc|darwin|gcc|hp_cxx|intel|kylix|vc|mgw|qcc|sun|vacpp)\d*$') is_toolsettag = re.compile('^(acc|borland|como|cw|dmc|darwin|gcc|hp_cxx|intel|kylix|vc|mgw|qcc|sun|vacpp)\d*$')
is_pythontag=re.compile('^py[0-9]{2}$')
def set_options(opt): def set_options(opt):
opt.add_option('--boost-includes', type='string', default='', dest='boostincludes', help='path to the boost directory where the includes are e.g. /usr/local/include/boost-1_35') opt.add_option('--boost-includes', type='string', default='', dest='boostincludes', help='path to the boost directory where the includes are e.g. /usr/local/include/boost-1_35')
@ -74,8 +75,8 @@ def version_string(version):
def libfiles(lib, pattern, lib_paths): def libfiles(lib, pattern, lib_paths):
result = [] result = []
for lib_path in lib_paths: for lib_path in lib_paths:
libname = pattern % ('boost_' + lib + '*') libname = pattern % ('boost_%s[!_]*' % lib)
result += glob.glob(lib_path + '/' + libname) result += glob.glob(os.path.join(lib_path, libname))
return result return result
@conf @conf
@ -99,9 +100,10 @@ def tags_score(tags, kw):
score = 0 score = 0
needed_tags = { needed_tags = {
'threading': kw['tag_threading'], 'threading': kw['tag_threading'],
'abi': kw['tag_abi'], 'abi': kw['tag_abi'],
'toolset': kw['tag_toolset'], 'toolset': kw['tag_toolset'],
'version': kw['tag_version'] 'version': kw['tag_version'],
'python': kw['tag_python']
} }
if kw['tag_toolset'] is None: if kw['tag_toolset'] is None:
@ -120,6 +122,7 @@ def tags_score(tags, kw):
if is_threadingtag.match(tag): found_tags['threading'] = tag if is_threadingtag.match(tag): found_tags['threading'] = tag
if is_abitag.match(tag): found_tags['abi'] = tag if is_abitag.match(tag): found_tags['abi'] = tag
if is_toolsettag.match(tag): found_tags['toolset'] = tag if is_toolsettag.match(tag): found_tags['toolset'] = tag
if is_pythontag.match(tag): found_tags['python'] = tag
for tagname in needed_tags.iterkeys(): for tagname in needed_tags.iterkeys():
if needed_tags[tagname] is not None and tagname in found_tags: if needed_tags[tagname] is not None and tagname in found_tags:
@ -148,8 +151,12 @@ def validate_boost(self, kw):
set_default(kw, x, None) set_default(kw, x, None)
set_default(kw, 'tag_abi', '^[^d]*$') set_default(kw, 'tag_abi', '^[^d]*$')
set_default(kw, 'python', str(sys.version_info[0]) + str(sys.version_info[1]) )
set_default(kw, 'tag_python', '^py' + kw['python'] + '$')
set_default(kw, 'score_threading', (10, -10)) set_default(kw, 'score_threading', (10, -10))
set_default(kw, 'score_abi', (10, -10)) set_default(kw, 'score_abi', (10, -10))
set_default(kw, 'score_python', (10,-10))
set_default(kw, 'score_toolset', (1, -1)) set_default(kw, 'score_toolset', (1, -1))
set_default(kw, 'score_version', (100, -100)) set_default(kw, 'score_version', (100, -100))

74
tools/wafadmin/Build.py

@ -33,11 +33,14 @@ class BuildError(Utils.WafError):
Utils.WafError.__init__(self, self.format_error()) Utils.WafError.__init__(self, self.format_error())
def format_error(self): def format_error(self):
lst = ['Build failed'] lst = ['Build failed:']
for tsk in self.tasks: for tsk in self.tasks:
txt = tsk.format_error() txt = tsk.format_error()
if txt: lst.append(txt) if txt: lst.append(txt)
return '\n'.join(lst) sep = ' '
if len(lst) > 2:
sep = '\n'
return sep.join(lst)
def group_method(fun): def group_method(fun):
""" """
@ -62,7 +65,8 @@ def group_method(fun):
m = k[0].task_manager m = k[0].task_manager
if not m.groups: m.add_group() if not m.groups: m.add_group()
m.groups[m.current_group].post_funs.append((fun, k, kw)) m.groups[m.current_group].post_funs.append((fun, k, kw))
kw['cwd'] = k[0].path if not 'cwd' in kw:
kw['cwd'] = k[0].path
else: else:
fun(*k, **kw) fun(*k, **kw)
return f return f
@ -269,7 +273,7 @@ class BuildContext(Utils.Context):
self.generator.start() self.generator.start()
except KeyboardInterrupt: except KeyboardInterrupt:
dw() dw()
if self.generator.consumers: if Runner.TaskConsumer.consumers:
self.save() self.save()
raise raise
except Exception: except Exception:
@ -278,7 +282,7 @@ class BuildContext(Utils.Context):
raise raise
else: else:
dw() dw()
if self.generator.consumers: if Runner.TaskConsumer.consumers:
self.save() self.save()
if self.generator.error: if self.generator.error:
@ -316,6 +320,9 @@ class BuildContext(Utils.Context):
except OSError: pass except OSError: pass
def new_task_gen(self, *k, **kw): def new_task_gen(self, *k, **kw):
if self.task_gen_cache_names:
self.task_gen_cache_names = {}
kw['bld'] = self kw['bld'] = self
if len(k) == 0: if len(k) == 0:
ret = TaskGen.task_gen(*k, **kw) ret = TaskGen.task_gen(*k, **kw)
@ -328,6 +335,13 @@ class BuildContext(Utils.Context):
ret = cls(*k, **kw) ret = cls(*k, **kw)
return ret return ret
def __call__(self, *k, **kw):
if self.task_gen_cache_names:
self.task_gen_cache_names = {}
kw['bld'] = self
return TaskGen.task_gen(*k, **kw)
def load_envs(self): def load_envs(self):
try: try:
lst = Utils.listdir(self.cachedir) lst = Utils.listdir(self.cachedir)
@ -384,7 +398,7 @@ class BuildContext(Utils.Context):
lstvariants.append(env.variant()) lstvariants.append(env.variant())
self.lst_variants = lstvariants self.lst_variants = lstvariants
debug('build: list of variants is %r' % lstvariants) debug('build: list of variants is %r', lstvariants)
for name in lstvariants+[0]: for name in lstvariants+[0]:
for v in 'node_sigs cache_node_abspath'.split(): for v in 'node_sigs cache_node_abspath'.split():
@ -418,7 +432,7 @@ class BuildContext(Utils.Context):
if not self.srcnode: if not self.srcnode:
self.srcnode = self.root.ensure_dir_node_from_path(srcdir) self.srcnode = self.root.ensure_dir_node_from_path(srcdir)
debug('build: srcnode is %s and srcdir %s' % (self.srcnode.name, srcdir)) debug('build: srcnode is %s and srcdir %s', self.srcnode.name, srcdir)
self.path = self.srcnode self.path = self.srcnode
@ -498,24 +512,30 @@ class BuildContext(Utils.Context):
lst.reverse() lst.reverse()
# list the files in the build dirs # list the files in the build dirs
# remove the existing timestamps if the build files are removed try:
for variant in self.lst_variants: for variant in self.lst_variants:
sub_path = os.path.join(self.bldnode.abspath(), variant , *lst) sub_path = os.path.join(self.bldnode.abspath(), variant , *lst)
try:
self.listdir_bld(src_dir_node, sub_path, variant) self.listdir_bld(src_dir_node, sub_path, variant)
except OSError: except OSError:
#debug('build: osError on ' + sub_path)
# listdir failed, remove all sigs of nodes # listdir failed, remove the build node signatures for all variants
# TODO more things to remove? for node in src_dir_node.childs.values():
dict = self.node_sigs[variant] if node.id & 3 != Node.BUILD:
for node in src_dir_node.childs.values(): continue
if node.id in dict:
for dct in self.node_sigs:
if node.id in dct:
dict.__delitem__(node.id) dict.__delitem__(node.id)
# avoid deleting the build dir node # the policy is to avoid removing nodes representing directories
if node.id != self.bldnode.id: src_dir_node.childs.__delitem__(node.name)
src_dir_node.childs.__delitem__(node.name)
os.makedirs(sub_path) for variant in self.lst_variants:
sub_path = os.path.join(self.bldnode.abspath(), variant , *lst)
try:
os.makedirs(sub_path)
except OSError:
pass
# ======================================= # # ======================================= #
def listdir_src(self, parent_node): def listdir_src(self, parent_node):
@ -599,7 +619,7 @@ class BuildContext(Utils.Context):
lst = [str(env[a]) for a in vars_lst] lst = [str(env[a]) for a in vars_lst]
ret = Utils.h_list(lst) ret = Utils.h_list(lst)
debug("envhash: %r %r" % (ret, lst)) debug('envhash: %r %r', ret, lst)
# next time # next time
self.cache_sig_vars[idx] = ret self.cache_sig_vars[idx] = ret
@ -769,6 +789,7 @@ class BuildContext(Utils.Context):
Logs.warn('could not remove %s (error code %r)' % (e.filename, e.errno)) Logs.warn('could not remove %s (error code %r)' % (e.filename, e.errno))
return True return True
red = re.compile(r"^([A-Za-z]:)?[/\\\\]*")
def get_install_path(self, path, env=None): def get_install_path(self, path, env=None):
"installation path prefixed by the destdir, the variables like in '${PREFIX}/bin' are substituted" "installation path prefixed by the destdir, the variables like in '${PREFIX}/bin' are substituted"
if not env: env = self.env if not env: env = self.env
@ -776,7 +797,7 @@ class BuildContext(Utils.Context):
path = path.replace('/', os.sep) path = path.replace('/', os.sep)
destpath = Utils.subst_vars(path, env) destpath = Utils.subst_vars(path, env)
if destdir: if destdir:
destpath = os.path.join(destdir, destpath.lstrip(os.sep)) destpath = os.path.join(destdir, self.red.sub('', destpath))
return destpath return destpath
def install_files(self, path, files, env=None, chmod=O644, relative_trick=False, cwd=None): def install_files(self, path, files, env=None, chmod=O644, relative_trick=False, cwd=None):
@ -891,10 +912,11 @@ class BuildContext(Utils.Context):
link = True link = True
elif os.readlink(tgt) != src: elif os.readlink(tgt) != src:
link = True link = True
if link:
try: os.remove(tgt) try: os.remove(tgt)
except OSError: pass except OSError: pass
if link:
info('* symlink %s (-> %s)' % (tgt, src)) info('* symlink %s (-> %s)' % (tgt, src))
os.symlink(src, tgt) os.symlink(src, tgt)
return 0 return 0
@ -909,7 +931,7 @@ class BuildContext(Utils.Context):
def exec_command(self, cmd, **kw): def exec_command(self, cmd, **kw):
# 'runner' zone is printed out for waf -v, see wafadmin/Options.py # 'runner' zone is printed out for waf -v, see wafadmin/Options.py
debug('runner: system command -> %s' % cmd) debug('runner: system command -> %s', cmd)
if self.log: if self.log:
self.log.write('%s\n' % cmd) self.log.write('%s\n' % cmd)
kw['log'] = self.log kw['log'] = self.log

33
tools/wafadmin/Configure.py

@ -157,6 +157,7 @@ class ConfigurationContext(Utils.Context):
for tool in tools: for tool in tools:
tool = tool.replace('++', 'xx') tool = tool.replace('++', 'xx')
if tool == 'java': tool = 'javaw' if tool == 'java': tool = 'javaw'
if tool.lower() == 'unittest': tool = 'unittestw'
# avoid loading the same tool more than once with the same functions # avoid loading the same tool more than once with the same functions
# used by composite projects # used by composite projects
@ -166,10 +167,14 @@ class ConfigurationContext(Utils.Context):
self.tool_cache.append(mag) self.tool_cache.append(mag)
module = Utils.load_tool(tool, tooldir) module = Utils.load_tool(tool, tooldir)
func = getattr(module, 'detect', None)
if func: if funs:
if type(func) is type(find_file): func(self) self.eval_rules(funs)
else: self.eval_rules(funs or func) else:
func = getattr(module, 'detect', None)
if func:
if type(func) is type(find_file): func(self)
else: self.eval_rules(func)
self.tools.append({'tool':tool, 'tooldir':tooldir, 'funs':funs}) self.tools.append({'tool':tool, 'tooldir':tooldir, 'funs':funs})
@ -232,17 +237,20 @@ class ConfigurationContext(Utils.Context):
def check_message_1(self, sr): def check_message_1(self, sr):
self.line_just = max(self.line_just, len(sr)) self.line_just = max(self.line_just, len(sr))
self.log.write(sr + '\n\n') for x in ('\n', self.line_just * '-', '\n', sr, '\n'):
self.log.write(x)
Utils.pprint('NORMAL', "%s :" % sr.ljust(self.line_just), sep='') Utils.pprint('NORMAL', "%s :" % sr.ljust(self.line_just), sep='')
def check_message_2(self, sr, color='GREEN'): def check_message_2(self, sr, color='GREEN'):
self.log.write(sr)
self.log.write('\n')
Utils.pprint(color, sr) Utils.pprint(color, sr)
def check_message(self, th, msg, state, option=''): def check_message(self, th, msg, state, option=''):
sr = 'Checking for %s %s' % (th, msg) sr = 'Checking for %s %s' % (th, msg)
self.check_message_1(sr) self.check_message_1(sr)
p = self.check_message_2 p = self.check_message_2
if state: p('ok ' + option) if state: p('ok ' + str(option))
else: p('not found', 'YELLOW') else: p('not found', 'YELLOW')
# FIXME remove in waf 1.6 # FIXME remove in waf 1.6
@ -268,10 +276,15 @@ class ConfigurationContext(Utils.Context):
ret = find_program_impl(self.env, x, path_list, var, environ=self.environ) ret = find_program_impl(self.env, x, path_list, var, environ=self.environ)
if ret: break if ret: break
self.check_message('program', ','.join(filename), ret, ret) self.check_message_1('Check for program %s' % ' or '.join(filename))
self.log.write('find program=%r paths=%r var=%r -> %r\n\n' % (filename, path_list, var, ret)) self.log.write(' find program=%r paths=%r var=%r\n -> %r\n' % (filename, path_list, var, ret))
if not ret and mandatory: if ret:
self.fatal('The program %r could not be found' % filename) Utils.pprint('GREEN', str(ret))
else:
Utils.pprint('YELLOW', 'not found')
if mandatory:
self.fatal('The program %r is required' % filename)
if var: if var:
self.env[var] = ret self.env[var] = ret
return ret return ret

6
tools/wafadmin/Constants.py

@ -9,9 +9,9 @@ maintainer: the version number is updated from the top-level wscript file
""" """
# do not touch these three lines, they are updated automatically # do not touch these three lines, they are updated automatically
HEXVERSION = 0x105010 HEXVERSION = 0x105014
WAFVERSION="1.5.10" WAFVERSION="1.5.14"
WAFREVISION = "6794M" WAFREVISION = "7363M"
ABI = 7 ABI = 7
# permissions # permissions

13
tools/wafadmin/Environment.py

@ -53,9 +53,14 @@ class Environment(object):
def __setitem__(self, key, value): def __setitem__(self, key, value):
self.table[key] = value self.table[key] = value
def __delitem__(self, key, value): def __delitem__(self, key):
del self.table[key] del self.table[key]
def pop(self, key, *args):
if len(args):
return self.table.pop(key, *args)
return self.table.pop(key)
def set_variant(self, name): def set_variant(self, name):
self.table[VARIANT] = name self.table[VARIANT] = name
@ -173,7 +178,7 @@ class Environment(object):
for m in re_imp.finditer(code): for m in re_imp.finditer(code):
g = m.group g = m.group
tbl[g(2)] = eval(g(3)) tbl[g(2)] = eval(g(3))
Logs.debug('env: %s' % str(self.table)) Logs.debug('env: %s', self.table)
def get_destdir(self): def get_destdir(self):
"return the destdir, useful for installing" "return the destdir, useful for installing"
@ -197,9 +202,9 @@ class Environment(object):
else: else:
self[name] = value self[name] = value
def __detattr__(self, name): def __delattr__(self, name):
if name in self.__slots__: if name in self.__slots__:
object.__detattr__(self, name) object.__delattr__(self, name)
else: else:
del self[name] del self[name]

25
tools/wafadmin/Logs.py

@ -23,12 +23,13 @@ colors_lst = {
'cursor_off' :'\x1b[?25l', 'cursor_off' :'\x1b[?25l',
} }
got_tty = not os.environ.get('TERM', 'dumb') in ['dumb', 'emacs'] got_tty = False
if got_tty: term = os.environ.get('TERM', 'dumb')
if not term in ['dumb', 'emacs']:
try: try:
got_tty = sys.stderr.isatty() got_tty = sys.stderr.isatty() or (sys.platform == 'win32' and term in ['xterm', 'msys'])
except AttributeError: except AttributeError:
got_tty = False pass
import Utils import Utils
@ -93,17 +94,17 @@ class formatter(logging.Formatter):
return rec.c1+rec.msg+rec.c2 return rec.c1+rec.msg+rec.c2
return logging.Formatter.format(self, rec) return logging.Formatter.format(self, rec)
def debug(msg): def debug(*k, **kw):
if verbose: if verbose:
# FIXME why does it eat the newlines???? k = list(k)
msg = msg.replace('\n', ' ') k[0] = k[0].replace('\n', ' ')
logging.debug(msg) logging.debug(*k, **kw)
def error(msg): def error(*k, **kw):
logging.error(msg) logging.error(*k, **kw)
if verbose > 1: if verbose > 1:
if isinstance(msg, Utils.WafError): if isinstance(k[0], Utils.WafError):
st = msg.stack st = k[0].stack
else: else:
st = traceback.extract_stack() st = traceback.extract_stack()
if st: if st:

45
tools/wafadmin/Node.py

@ -30,8 +30,8 @@ ${TGT[0].abspath(env)} -> /path/to/dir/to/file.ext
""" """
import os, sys, fnmatch, re import os, sys, fnmatch, re, stat
import Utils import Utils, Constants
UNDEFINED = 0 UNDEFINED = 0
DIR = 1 DIR = 1
@ -256,7 +256,6 @@ class Node(object):
return None return None
return current return current
# FIXME: remove in waf 1.6 ?
def ensure_dir_node_from_path(self, lst): def ensure_dir_node_from_path(self, lst):
"used very rarely, force the construction of a branch of node instance for representing folders" "used very rarely, force the construction of a branch of node instance for representing folders"
@ -278,7 +277,6 @@ class Node(object):
current = self.__class__(name, prev, DIR) current = self.__class__(name, prev, DIR)
return current return current
# FIXME: remove in waf 1.6
def exclusive_build_node(self, path): def exclusive_build_node(self, path):
""" """
create a hierarchy in the build dir (no source folders) for ill-behaving compilers create a hierarchy in the build dir (no source folders) for ill-behaving compilers
@ -495,7 +493,7 @@ class Node(object):
return self.name[k:] return self.name[k:]
def find_iter_impl(self, src=True, bld=True, dir=True, accept_name=None, is_prune=None, maxdepth=25): def find_iter_impl(self, src=True, bld=True, dir=True, accept_name=None, is_prune=None, maxdepth=25):
"find nodes in the filesystem hierarchy, try to instanciate the nodes passively" """find nodes in the filesystem hierarchy, try to instanciate the nodes passively; same gotcha as ant_glob"""
bld_ctx = self.__class__.bld bld_ctx = self.__class__.bld
bld_ctx.rescan(self) bld_ctx.rescan(self)
for name in bld_ctx.cache_dir_contents[self.id]: for name in bld_ctx.cache_dir_contents[self.id]:
@ -534,7 +532,7 @@ class Node(object):
raise StopIteration raise StopIteration
def find_iter(self, in_pat=['*'], ex_pat=exclude_pats, prune_pat=prune_pats, src=True, bld=True, dir=False, maxdepth=25, flat=False): def find_iter(self, in_pat=['*'], ex_pat=exclude_pats, prune_pat=prune_pats, src=True, bld=True, dir=False, maxdepth=25, flat=False):
"find nodes recursively, this returns everything but folders by default" """find nodes recursively, this returns everything but folders by default; same gotcha as ant_glob"""
if not (src or bld or dir): if not (src or bld or dir):
raise StopIteration raise StopIteration
@ -568,9 +566,12 @@ class Node(object):
return ret return ret
def ant_glob(self, *k, **kw): def ant_glob(self, *k, **kw):
"""
known gotcha: will enumerate the files, but only if the folder exists in the source directory
"""
src=kw.get('src', 1) src=kw.get('src', 1)
bld=kw.get('bld', 1) bld=kw.get('bld', 0)
dir=kw.get('dir', 0) dir=kw.get('dir', 0)
excl = kw.get('excl', exclude_regs) excl = kw.get('excl', exclude_regs)
incl = k and k[0] or kw.get('incl', '**') incl = k and k[0] or kw.get('incl', '**')
@ -655,6 +656,36 @@ class Node(object):
return ret return ret
def update_build_dir(self, env=None):
if not env:
for env in bld.all_envs:
self.update_build_dir(env)
return
path = self.abspath(env)
lst = Utils.listdir(path)
try:
self.__class__.bld.cache_dir_contents[self.id].update(lst)
except KeyError:
self.__class__.bld.cache_dir_contents[self.id] = set(lst)
self.__class__.bld.cache_scanned_folders[self.id] = True
for k in lst:
npath = path + os.sep + k
st = os.stat(npath)
if stat.S_ISREG(st[stat.ST_MODE]):
ick = self.find_or_declare(k)
if not (ick.id in self.__class__.bld.node_sigs[env.variant()]):
self.__class__.bld.node_sigs[env.variant()][ick.id] = Constants.SIG_NIL
elif stat.S_ISDIR(st[stat.ST_MODE]):
child = self.find_dir(k)
if not child:
child = self.ensure_dir_node_from_path(k)
child.update_build_dir(env)
class Nodu(Node): class Nodu(Node):
pass pass

2
tools/wafadmin/Options.py

@ -260,6 +260,8 @@ class Handler(Utils.Context):
for tool in tools: for tool in tools:
tool = tool.replace('++', 'xx') tool = tool.replace('++', 'xx')
if tool == 'java': tool = 'javaw'
if tool.lower() == 'unittest': tool = 'unittestw'
module = Utils.load_tool(tool, path) module = Utils.load_tool(tool, path)
try: try:
fun = module.set_options fun = module.set_options

28
tools/wafadmin/Runner.py

@ -24,10 +24,12 @@ def run(*args, **kwargs):
threading.Thread.run = run threading.Thread.run = run
class TaskConsumer(threading.Thread): class TaskConsumer(threading.Thread):
def __init__(self, m): ready = Queue(0)
consumers = []
def __init__(self):
threading.Thread.__init__(self) threading.Thread.__init__(self)
self.setDaemon(1) self.setDaemon(1)
self.master = m
self.start() self.start()
def run(self): def run(self):
@ -37,9 +39,9 @@ class TaskConsumer(threading.Thread):
pass pass
def loop(self): def loop(self):
m = self.master
while 1: while 1:
tsk = m.ready.get() tsk = TaskConsumer.ready.get()
m = tsk.master
if m.stop: if m.stop:
m.out.put(tsk) m.out.put(tsk)
continue continue
@ -98,16 +100,13 @@ class Parallel(object):
# tasks that are awaiting for another task to complete # tasks that are awaiting for another task to complete
self.frozen = [] self.frozen = []
# tasks waiting to be run by the consumers # tasks returned by the consumers
self.ready = Queue(0)
self.out = Queue(0) self.out = Queue(0)
self.count = 0 # tasks not in the producer area self.count = 0 # tasks not in the producer area
self.processed = 1 # progress indicator self.processed = 1 # progress indicator
self.consumers = None # the consumer threads, created lazily
self.stop = False # error condition to stop the build self.stop = False # error condition to stop the build
self.error = False # error flag self.error = False # error flag
@ -162,6 +161,12 @@ class Parallel(object):
def start(self): def start(self):
"execute the tasks" "execute the tasks"
if TaskConsumer.consumers:
# the worker pool is usually loaded lazily (see below)
# in case it is re-used with a different value of numjobs:
while len(TaskConsumer.consumers) < self.numjobs:
TaskConsumer.consumers.append(TaskConsumer())
while not self.stop: while not self.stop:
self.refill_task_list() self.refill_task_list()
@ -202,12 +207,13 @@ class Parallel(object):
# run me: put the task in ready queue # run me: put the task in ready queue
tsk.position = (self.processed, self.total) tsk.position = (self.processed, self.total)
self.count += 1 self.count += 1
self.ready.put(tsk) tsk.master = self
TaskConsumer.ready.put(tsk)
self.processed += 1 self.processed += 1
# create the consumer threads only if there is something to consume # create the consumer threads only if there is something to consume
if not self.consumers: if not TaskConsumer.consumers:
self.consumers = [TaskConsumer(self) for i in xrange(self.numjobs)] TaskConsumer.consumers = [TaskConsumer() for i in xrange(self.numjobs)]
# self.count represents the tasks that have been made available to the consumer threads # self.count represents the tasks that have been made available to the consumer threads
# collect all the tasks after an error else the message may be incomplete # collect all the tasks after an error else the message may be incomplete

28
tools/wafadmin/Scripting.py

@ -201,19 +201,20 @@ def configure(conf):
src = getattr(Options.options, SRCDIR, None) src = getattr(Options.options, SRCDIR, None)
if not src: src = getattr(Utils.g_module, SRCDIR, None) if not src: src = getattr(Utils.g_module, SRCDIR, None)
if not src: src = getattr(Utils.g_module, 'top', None)
if not src: if not src:
src = '.' src = '.'
incomplete_src = 1 incomplete_src = 1
src = os.path.abspath(src) src = os.path.abspath(src)
bld = getattr(Options.options, BLDDIR, None) bld = getattr(Options.options, BLDDIR, None)
if not bld: if not bld: bld = getattr(Utils.g_module, BLDDIR, None)
bld = getattr(Utils.g_module, BLDDIR, None) if not bld: bld = getattr(Utils.g_module, 'out', None)
if bld == '.':
raise Utils.WafError('Setting blddir="." may cause distclean problems')
if not bld: if not bld:
bld = 'build' bld = 'build'
incomplete_bld = 1 incomplete_bld = 1
if bld == '.':
raise Utils.WafError('Setting blddir="." may cause distclean problems')
bld = os.path.abspath(bld) bld = os.path.abspath(bld)
try: os.makedirs(bld) try: os.makedirs(bld)
@ -418,7 +419,7 @@ def dont_dist(name, src, build_dir):
if (name.startswith(',,') if (name.startswith(',,')
or name.startswith('++') or name.startswith('++')
or name.startswith('.waf-1.') or name.startswith('.waf')
or (src == '.' and name == Options.lockfile) or (src == '.' and name == Options.lockfile)
or name in excludes or name in excludes
or name == build_dir or name == build_dir
@ -451,6 +452,7 @@ def copytree(src, dst, build_dir):
# TODO in waf 1.6, change this method if "srcdir == blddir" is allowed # TODO in waf 1.6, change this method if "srcdir == blddir" is allowed
def distclean(ctx=None): def distclean(ctx=None):
'''removes the build directory''' '''removes the build directory'''
global commands
lst = os.listdir('.') lst = os.listdir('.')
for f in lst: for f in lst:
if f == Options.lockfile: if f == Options.lockfile:
@ -475,7 +477,7 @@ def distclean(ctx=None):
Logs.warn('file %r cannot be removed' % f) Logs.warn('file %r cannot be removed' % f)
# remove the local waf cache # remove the local waf cache
if f.startswith('.waf-'): if not commands and f.startswith('.waf'):
shutil.rmtree(f, ignore_errors=True) shutil.rmtree(f, ignore_errors=True)
# FIXME waf 1.6 a unique ctx parameter, and remove the optional appname and version # FIXME waf 1.6 a unique ctx parameter, and remove the optional appname and version
@ -488,7 +490,10 @@ def dist(appname='', version=''):
if not version: version = getattr(Utils.g_module, VERSION, '1.0') if not version: version = getattr(Utils.g_module, VERSION, '1.0')
tmp_folder = appname + '-' + version tmp_folder = appname + '-' + version
arch_name = tmp_folder+'.tar.'+g_gz if g_gz in ['gz', 'bz2']:
arch_name = tmp_folder + '.tar.' + g_gz
else:
arch_name = tmp_folder + '.' + 'zip'
# remove the previous dir # remove the previous dir
try: try:
@ -516,9 +521,12 @@ def dist(appname='', version=''):
# go back to the root directory # go back to the root directory
os.chdir(back) os.chdir(back)
tar = tarfile.open(arch_name, 'w:' + g_gz) if g_gz in ['gz', 'bz2']:
tar.add(tmp_folder) tar = tarfile.open(arch_name, 'w:' + g_gz)
tar.close() tar.add(tmp_folder)
tar.close()
else:
Utils.zip_folder(tmp_folder, arch_name, tmp_folder)
try: from hashlib import sha1 as sha try: from hashlib import sha1 as sha
except ImportError: from sha import sha except ImportError: from sha import sha

165
tools/wafadmin/Task.py

@ -42,7 +42,7 @@ The role of the Task Manager is to give the tasks in order (groups of task that
""" """
import os, shutil, sys, re, random, datetime import os, shutil, sys, re, random, datetime, tempfile
from Utils import md5 from Utils import md5
import Build, Runner, Utils, Node, Logs, Options import Build, Runner, Utils, Node, Logs, Options
from Logs import debug, warn, error from Logs import debug, warn, error
@ -346,6 +346,7 @@ class store_task_type(type):
if name.endswith('_task'): if name.endswith('_task'):
name = name.replace('_task', '') name = name.replace('_task', '')
if name != 'TaskBase':
TaskBase.classes[name] = cls TaskBase.classes[name] = cls
class TaskBase(object): class TaskBase(object):
@ -502,9 +503,9 @@ class Task(TaskBase):
* persistence: do not re-execute tasks that have already run * persistence: do not re-execute tasks that have already run
* caching: same files can be saved and retrieved from a cache directory * caching: same files can be saved and retrieved from a cache directory
* dependencies: * dependencies:
implicit, like .c files depending on .h files implicit, like .c files depending on .h files
explicit, like the input nodes or the dep_nodes explicit, like the input nodes or the dep_nodes
environment variables, like the CXXFLAGS in self.env environment variables, like the CXXFLAGS in self.env
""" """
vars = [] vars = []
def __init__(self, env, **kw): def __init__(self, env, **kw):
@ -612,18 +613,14 @@ class Task(TaskBase):
bld = self.generator.bld bld = self.generator.bld
# first compute the signature # first compute the signature
try: new_sig = self.signature()
new_sig = self.signature()
except KeyError:
debug("task: something is wrong, computing the task %r signature failed" % self)
return RUN_ME
# compare the signature to a signature computed previously # compare the signature to a signature computed previously
key = self.unique_id() key = self.unique_id()
try: try:
prev_sig = bld.task_sigs[key][0] prev_sig = bld.task_sigs[key][0]
except KeyError: except KeyError:
debug("task: task %r must run as it was never run before or the task code changed" % self) debug("task: task %r must run as it was never run before or the task code changed", self)
return RUN_ME return RUN_ME
# compare the signatures of the outputs # compare the signatures of the outputs
@ -633,7 +630,7 @@ class Task(TaskBase):
if bld.node_sigs[variant][node.id] != new_sig: if bld.node_sigs[variant][node.id] != new_sig:
return RUN_ME return RUN_ME
except KeyError: except KeyError:
debug("task: task %r must run as the output nodes do not exist" % self) debug("task: task %r must run as the output nodes do not exist", self)
return RUN_ME return RUN_ME
# debug if asked to # debug if asked to
@ -648,8 +645,8 @@ class Task(TaskBase):
bld = self.generator.bld bld = self.generator.bld
env = self.env env = self.env
sig = self.signature() sig = self.signature()
ssig = sig.encode('hex')
cnt = 0
variant = env.variant() variant = env.variant()
for node in self.outputs: for node in self.outputs:
# check if the node exists .. # check if the node exists ..
@ -662,35 +659,78 @@ class Task(TaskBase):
# important, store the signature for the next run # important, store the signature for the next run
bld.node_sigs[variant][node.id] = sig bld.node_sigs[variant][node.id] = sig
bld.task_sigs[self.unique_id()] = self.cache_sig
# We could re-create the signature of the task with the signature of the outputs # file caching, if possible
# in practice, this means hashing the output files # try to avoid data corruption as much as possible
# this is unnecessary if not Options.cache_global or Options.options.nocache or not self.outputs:
if Options.cache_global: return None
ssig = sig.encode('hex')
dest = os.path.join(Options.cache_global, '%s_%d_%s' % (ssig, cnt, node.name))
try: shutil.copy2(node.abspath(env), dest)
except IOError: warn('Could not write the file to the cache')
cnt += 1
bld.task_sigs[self.unique_id()] = self.cache_sig if getattr(self, 'cached', None):
return None
dname = os.path.join(Options.cache_global, ssig)
tmpdir = tempfile.mkdtemp(prefix=Options.cache_global)
try:
shutil.rmtree(dname)
except:
pass
try:
for node in self.outputs:
variant = node.variant(env)
dest = os.path.join(tmpdir, node.name)
shutil.copy2(node.abspath(env), dest)
except (OSError, IOError):
try:
shutil.rmtree(tmpdir)
except:
pass
else:
try:
os.rename(tmpdir, dname)
except OSError:
try:
shutil.rmtree(tmpdir)
except:
pass
else:
try:
os.chmod(dname, O755)
except:
pass
def can_retrieve_cache(self): def can_retrieve_cache(self):
"""Retrieve build nodes from the cache - the file time stamps are updated """
for cleaning the least used files from the cache dir - be careful when overridding""" Retrieve build nodes from the cache
if not Options.cache_global: return None update the file timestamps to help cleaning the least used entries from the cache
if Options.options.nocache: return None additionally, set an attribute 'cached' to avoid re-creating the same cache files
if not self.outputs: return None
suppose there are files in cache/dir1/file1 and cache/dir2/file2
first, read the timestamp of dir1
then try to copy the files
then look at the timestamp again, if it has changed, the data may have been corrupt (cache update by another process)
should an exception occur, ignore the data
"""
if not Options.cache_global or Options.options.nocache or not self.outputs:
return None
env = self.env env = self.env
sig = self.signature() sig = self.signature()
ssig = sig.encode('hex')
# first try to access the cache folder for the task
dname = os.path.join(Options.cache_global, ssig)
try:
t1 = os.stat(dname).st_mtime
except OSError:
return None
cnt = 0
for node in self.outputs: for node in self.outputs:
variant = node.variant(env) variant = node.variant(env)
ssig = sig.encode('hex') orig = os.path.join(dname, node.name)
orig = os.path.join(Options.cache_global, '%s_%d_%s' % (ssig, cnt, node.name))
try: try:
shutil.copy2(orig, node.abspath(env)) shutil.copy2(orig, node.abspath(env))
# mark the cache file as used recently (modified) # mark the cache file as used recently (modified)
@ -698,13 +738,21 @@ class Task(TaskBase):
except (OSError, IOError): except (OSError, IOError):
debug('task: failed retrieving file') debug('task: failed retrieving file')
return None return None
else:
cnt += 1 # is it the same folder?
try:
t2 = os.stat(dname).st_mtime
except OSError:
return None
if t1 != t2:
return None
for node in self.outputs: for node in self.outputs:
self.generator.bld.node_sigs[variant][node.id] = sig self.generator.bld.node_sigs[variant][node.id] = sig
self.generator.bld.printout('restoring from cache %r\n' % node.bldpath(env)) self.generator.bld.printout('restoring from cache %r\n' % node.bldpath(env))
self.cached = True
return 1 return 1
def debug_why(self, old_sigs): def debug_why(self, old_sigs):
@ -714,12 +762,12 @@ class Task(TaskBase):
def v(x): def v(x):
return x.encode('hex') return x.encode('hex')
debug("Task %r" % self) debug("Task %r", self)
msgs = ['Task must run', '* Source file or manual dependency', '* Implicit dependency', '* Environment variable'] msgs = ['Task must run', '* Source file or manual dependency', '* Implicit dependency', '* Environment variable']
tmp = 'task: -> %s: %s %s' tmp = 'task: -> %s: %s %s'
for x in xrange(len(msgs)): for x in xrange(len(msgs)):
if (new_sigs[x] != old_sigs[x]): if (new_sigs[x] != old_sigs[x]):
debug(tmp % (msgs[x], v(old_sigs[x]), v(new_sigs[x]))) debug(tmp, msgs[x], v(old_sigs[x]), v(new_sigs[x]))
def sig_explicit_deps(self): def sig_explicit_deps(self):
bld = self.generator.bld bld = self.generator.bld
@ -731,7 +779,10 @@ class Task(TaskBase):
bld.rescan(x.parent) bld.rescan(x.parent)
variant = x.variant(self.env) variant = x.variant(self.env)
m.update(bld.node_sigs[variant][x.id]) try:
m.update(bld.node_sigs[variant][x.id])
except KeyError:
raise Utils.WafError('Missing node signature for %r (required by %r)' % (x, self))
# manual dependencies, they can slow down the builds # manual dependencies, they can slow down the builds
if bld.deps_man: if bld.deps_man:
@ -748,8 +799,8 @@ class Task(TaskBase):
variant = v.variant(self.env) variant = v.variant(self.env)
try: try:
v = bld.node_sigs[variant][v.id] v = bld.node_sigs[variant][v.id]
except KeyError: # make it fatal? except KeyError:
v = '' raise Utils.WafError('Missing node signature for %r (required by %r)' % (v, self))
elif hasattr(v, '__call__'): elif hasattr(v, '__call__'):
v = v() # dependency is a function, call it v = v() # dependency is a function, call it
m.update(v) m.update(v)
@ -805,14 +856,21 @@ class Task(TaskBase):
# no previous run or the signature of the dependencies has changed, rescan the dependencies # no previous run or the signature of the dependencies has changed, rescan the dependencies
(nodes, names) = self.scan() (nodes, names) = self.scan()
if Logs.verbose: if Logs.verbose:
debug('deps: scanner for %s returned %s %s' % (str(self), str(nodes), str(names))) debug('deps: scanner for %s returned %s %s', str(self), str(nodes), str(names))
# store the dependencies in the cache # store the dependencies in the cache
bld.node_deps[key] = nodes bld.node_deps[key] = nodes
bld.raw_deps[key] = names bld.raw_deps[key] = names
# recompute the signature and return it # recompute the signature and return it
sig = self.compute_sig_implicit_deps() try:
sig = self.compute_sig_implicit_deps()
except KeyError:
try:
nodes = bld.node_deps.get(self.unique_id(), [])
except:
nodes = '?'
raise Utils.WafError('Missing node signature for %r (for implicit dependencies %r)' % (nodes, self))
return sig return sig
@ -855,7 +913,7 @@ def compile_fun_shell(name, line):
The reserved keywords TGT and SRC represent the task input and output nodes The reserved keywords TGT and SRC represent the task input and output nodes
quick test: quick test:
bld.new_task_gen(source='wscript', rule='echo "foo\\${SRC[0].name}\\bar"') bld(source='wscript', rule='echo "foo\\${SRC[0].name}\\bar"')
""" """
extr = [] extr = []
@ -886,7 +944,7 @@ def compile_fun_shell(name, line):
c = COMPILE_TEMPLATE_SHELL % (line, parm) c = COMPILE_TEMPLATE_SHELL % (line, parm)
debug('action: %s' % c) debug('action: %s', c)
return (funex(c), dvars) return (funex(c), dvars)
def compile_fun_noshell(name, line): def compile_fun_noshell(name, line):
@ -924,7 +982,7 @@ def compile_fun_noshell(name, line):
app("lst.extend(%r)" % params[-1].split()) app("lst.extend(%r)" % params[-1].split())
fun = COMPILE_TEMPLATE_NOSHELL % "\n\t".join(buf) fun = COMPILE_TEMPLATE_NOSHELL % "\n\t".join(buf)
debug('action: %s' % fun) debug('action: %s', fun)
return (funex(fun), dvars) return (funex(fun), dvars)
def compile_fun(name, line, shell=None): def compile_fun(name, line, shell=None):
@ -992,10 +1050,29 @@ def update_outputs(cls):
def post_run(self): def post_run(self):
old_post_run(self) old_post_run(self)
bld = self.outputs[0].__class__.bld bld = self.outputs[0].__class__.bld
bld.node_sigs[self.env.variant()][self.outputs[0].id] = \ for output in self.outputs:
Utils.h_file(self.outputs[0].abspath(self.env)) bld.node_sigs[self.env.variant()][output.id] = Utils.h_file(output.abspath(self.env))
cls.post_run = post_run cls.post_run = post_run
old_runnable_status = cls.runnable_status
def runnable_status(self):
status = old_runnable_status(self)
if status != RUN_ME:
return status
try:
bld = self.outputs[0].__class__.bld
new_sig = self.signature()
prev_sig = bld.task_sigs[self.unique_id()][0]
if prev_sig == new_sig:
return SKIP_ME
except KeyError:
pass
except IndexError:
pass
return RUN_ME
cls.runnable_status = runnable_status
def extract_outputs(tasks): def extract_outputs(tasks):
"""file_deps: Infer additional dependencies from task input and output nodes """file_deps: Infer additional dependencies from task input and output nodes
""" """

27
tools/wafadmin/TaskGen.py

@ -196,13 +196,13 @@ class task_gen(object):
self.meths = out self.meths = out
# then we run the methods in order # then we run the methods in order
debug('task_gen: posting %s %d' % (self, id(self))) debug('task_gen: posting %s %d', self, id(self))
for x in out: for x in out:
try: try:
v = getattr(self, x) v = getattr(self, x)
except AttributeError: except AttributeError:
raise Utils.WafError("tried to retrieve %s which is not a valid method" % x) raise Utils.WafError("tried to retrieve %s which is not a valid method" % x)
debug('task_gen: -> %s (%d)' % (x, id(self))) debug('task_gen: -> %s (%d)', x, id(self))
v() v()
def post(self): def post(self):
@ -217,7 +217,7 @@ class task_gen(object):
#error("OBJECT ALREADY POSTED" + str( self)) #error("OBJECT ALREADY POSTED" + str( self))
return return
self.apply() self.apply()
debug('task_gen: posted %s' % self.name) debug('task_gen: posted %s', self.name)
self.posted = True self.posted = True
def get_hook(self, ext): def get_hook(self, ext):
@ -342,7 +342,7 @@ def declare_order(*k):
if not f1 in task_gen.prec[f2]: if not f1 in task_gen.prec[f2]:
task_gen.prec[f2].append(f1) task_gen.prec[f2].append(f1)
def declare_chain(name='', action='', ext_in='', ext_out='', reentrant=1, color='BLUE', def declare_chain(name='', action='', ext_in='', ext_out='', reentrant=True, color='BLUE',
install=0, before=[], after=[], decider=None, rule=None, scan=None): install=0, before=[], after=[], decider=None, rule=None, scan=None):
""" """
see Tools/flex.py for an example see Tools/flex.py for an example
@ -363,7 +363,7 @@ def declare_chain(name='', action='', ext_in='', ext_out='', reentrant=1, color=
def x_file(self, node): def x_file(self, node):
if decider: if decider:
ext = decider(self, node) ext = decider(self, node)
elif isinstance(ext_out, str): else:
ext = ext_out ext = ext_out
if isinstance(ext, str): if isinstance(ext, str):
@ -373,7 +373,7 @@ def declare_chain(name='', action='', ext_in='', ext_out='', reentrant=1, color=
elif isinstance(ext, list): elif isinstance(ext, list):
out_source = [node.change_ext(x) for x in ext] out_source = [node.change_ext(x) for x in ext]
if reentrant: if reentrant:
for i in xrange(reentrant): for i in xrange((reentrant is True) and len(out_source) or reentrant):
self.allnodes.append(out_source[i]) self.allnodes.append(out_source[i])
else: else:
# XXX: useless: it will fail on Utils.to_list above... # XXX: useless: it will fail on Utils.to_list above...
@ -405,6 +405,7 @@ Intelligent compilers binding aspect-oriented programming and parallelization, w
""" """
def taskgen(func): def taskgen(func):
setattr(task_gen, func.__name__, func) setattr(task_gen, func.__name__, func)
return func
def feature(*k): def feature(*k):
def deco(func): def deco(func):
@ -502,6 +503,8 @@ def exec_rule(self):
# create the task class # create the task class
name = getattr(self, 'name', None) or self.target or self.rule name = getattr(self, 'name', None) or self.target or self.rule
if not isinstance(name, str):
name = str(self.idx)
cls = Task.task_type_from_func(name, func, vars) cls = Task.task_type_from_func(name, func, vars)
# now create one instance # now create one instance
@ -524,9 +527,6 @@ def exec_rule(self):
raise Utils.WafError('input file %r could not be found (%r)' % (x, self.path.abspath())) raise Utils.WafError('input file %r could not be found (%r)' % (x, self.path.abspath()))
tsk.inputs.append(y) tsk.inputs.append(y)
if getattr(self, 'always', None):
Task.always_run(cls)
if getattr(self, 'scan', None): if getattr(self, 'scan', None):
cls.scan = self.scan cls.scan = self.scan
@ -539,7 +539,10 @@ def exec_rule(self):
if getattr(self, 'on_results', None): if getattr(self, 'on_results', None):
Task.update_outputs(cls) Task.update_outputs(cls)
for x in ['after', 'before']: if getattr(self, 'always', None):
Task.always_run(cls)
for x in ['after', 'before', 'ext_in', 'ext_out']:
setattr(cls, x, getattr(self, x, [])) setattr(cls, x, getattr(self, x, []))
feature('*')(exec_rule) feature('*')(exec_rule)
before('apply_core')(exec_rule) before('apply_core')(exec_rule)
@ -552,8 +555,8 @@ def sequence_order(self):
there is also an awesome trick for executing the method in last position there is also an awesome trick for executing the method in last position
to use: to use:
bld.new_task_gen(features='javac seq') bld(features='javac seq')
bld.new_task_gen(features='jar seq') bld(features='jar seq')
to start a new sequence, set the attribute seq_start, for example: to start a new sequence, set the attribute seq_start, for example:
obj.seq_start = True obj.seq_start = True

2
tools/wafadmin/Tools/ar.py

@ -10,7 +10,7 @@ import Task, Utils
from Configure import conftest from Configure import conftest
ar_str = '${AR} ${ARFLAGS} ${AR_TGT_F}${TGT} ${AR_SRC_F}${SRC}' ar_str = '${AR} ${ARFLAGS} ${AR_TGT_F}${TGT} ${AR_SRC_F}${SRC}'
cls = Task.simple_task_type('static_link', ar_str, color='YELLOW', ext_in='.o', shell=False) cls = Task.simple_task_type('static_link', ar_str, color='YELLOW', ext_in='.o', ext_out='.bin', shell=False)
cls.maxjobs = 1 cls.maxjobs = 1
cls.install = Utils.nada cls.install = Utils.nada

11
tools/wafadmin/Tools/ccroot.py

@ -132,7 +132,7 @@ def scan(self):
node = self.inputs[0] node = self.inputs[0]
(nodes, names) = preproc.get_deps(node, self.env, nodepaths = self.env['INC_PATHS']) (nodes, names) = preproc.get_deps(node, self.env, nodepaths = self.env['INC_PATHS'])
if Logs.verbose: if Logs.verbose:
debug('deps: deps for %s: %r; unresolved %r' % (str(node), nodes, names)) debug('deps: deps for %s: %r; unresolved %r', str(node), nodes, names)
return (nodes, names) return (nodes, names)
all_nodes = [] all_nodes = []
@ -141,7 +141,7 @@ def scan(self):
for node in self.inputs: for node in self.inputs:
(nodes, names) = preproc.get_deps(node, self.env, nodepaths = self.env['INC_PATHS']) (nodes, names) = preproc.get_deps(node, self.env, nodepaths = self.env['INC_PATHS'])
if Logs.verbose: if Logs.verbose:
debug('deps: deps for %s: %r; unresolved %r' % (str(node), nodes, names)) debug('deps: deps for %s: %r; unresolved %r', str(node), nodes, names)
for x in nodes: for x in nodes:
if id(x) in seen: continue if id(x) in seen: continue
seen.add(id(x)) seen.add(id(x))
@ -209,7 +209,7 @@ def default_cc(self):
@feature('cprogram', 'dprogram', 'cstaticlib', 'dstaticlib', 'cshlib', 'dshlib') @feature('cprogram', 'dprogram', 'cstaticlib', 'dstaticlib', 'cshlib', 'dshlib')
def apply_verif(self): def apply_verif(self):
"""no particular order, used for diagnostic""" """no particular order, used for diagnostic"""
if not (self.source or getattr(self, 'add_objects', None)): if not (self.source or getattr(self, 'add_objects', None) or getattr(self, 'uselib_local', None)):
raise Utils.WafError('no source files specified for %s' % self) raise Utils.WafError('no source files specified for %s' % self)
if not self.target: if not self.target:
raise Utils.WafError('no target for %s' % self) raise Utils.WafError('no target for %s' % self)
@ -329,10 +329,13 @@ def apply_link(self):
self.link_task = tsk self.link_task = tsk
@feature('cc', 'cxx') @feature('cc', 'cxx')
@after('apply_link', 'init_cc', 'init_cxx') @after('apply_link', 'init_cc', 'init_cxx', 'apply_core')
def apply_lib_vars(self): def apply_lib_vars(self):
"""after apply_link because of 'link_task' """after apply_link because of 'link_task'
after default_cc because of the attribute 'uselib'""" after default_cc because of the attribute 'uselib'"""
# after 'apply_core' in case if 'cc' if there is no link
env = self.env env = self.env
# 1. the case of the libs defined in the project (visit ancestors first) # 1. the case of the libs defined in the project (visit ancestors first)

17
tools/wafadmin/Tools/compiler_cc.py

@ -11,7 +11,7 @@ c_compiler = {
'win32': ['msvc', 'gcc'], 'win32': ['msvc', 'gcc'],
'cygwin': ['gcc'], 'cygwin': ['gcc'],
'darwin': ['gcc'], 'darwin': ['gcc'],
'aix5': ['gcc'], 'aix': ['xlc', 'gcc'],
'linux': ['gcc', 'icc', 'suncc'], 'linux': ['gcc', 'icc', 'suncc'],
'sunos': ['gcc', 'suncc'], 'sunos': ['gcc', 'suncc'],
'irix': ['gcc'], 'irix': ['gcc'],
@ -33,17 +33,24 @@ def detect(conf):
""" """
try: test_for_compiler = Options.options.check_c_compiler try: test_for_compiler = Options.options.check_c_compiler
except AttributeError: conf.fatal("Add set_options(opt): opt.tool_options('compiler_cc')") except AttributeError: conf.fatal("Add set_options(opt): opt.tool_options('compiler_cc')")
orig = conf.env
for compiler in test_for_compiler.split(): for compiler in test_for_compiler.split():
conf.env = orig.copy()
try: try:
conf.check_tool(compiler) conf.check_tool(compiler)
except Configure.ConfigurationError, e: except Configure.ConfigurationError, e:
debug('compiler_cc: %r' % e) debug('compiler_cc: %r' % e)
else: else:
if conf.env['CC']: if conf.env['CC']:
orig.table = conf.env.get_merged_dict()
conf.env = orig
conf.check_message(compiler, '', True) conf.check_message(compiler, '', True)
conf.env['COMPILER_CC'] = compiler conf.env['COMPILER_CC'] = compiler
break break
conf.check_message(compiler, '', False) conf.check_message(compiler, '', False)
break
else:
conf.fatal('could not configure a c compiler!')
def set_options(opt): def set_options(opt):
build_platform = Utils.unversioned_sys_platform() build_platform = Utils.unversioned_sys_platform()
@ -57,11 +64,3 @@ def set_options(opt):
for c_compiler in test_for_compiler.split(): for c_compiler in test_for_compiler.split():
opt.tool_options('%s' % c_compiler, option_group=cc_compiler_opts) opt.tool_options('%s' % c_compiler, option_group=cc_compiler_opts)
"""opt.add_option('-d', '--debug-level',
action = 'store',
default = ccroot.DEBUG_LEVELS.RELEASE,
help = "Specify the debug level, does nothing if CFLAGS is set in the environment. [Allowed Values: '%s']" % "', '".join(ccroot.DEBUG_LEVELS.ALL),
choices = ccroot.DEBUG_LEVELS.ALL,
dest = 'debug_level')"""

16
tools/wafadmin/Tools/compiler_cxx.py

@ -11,7 +11,7 @@ cxx_compiler = {
'win32': ['msvc', 'g++'], 'win32': ['msvc', 'g++'],
'cygwin': ['g++'], 'cygwin': ['g++'],
'darwin': ['g++'], 'darwin': ['g++'],
'aix': ['g++'], 'aix': ['xlc++', 'g++'],
'linux': ['g++', 'icpc', 'sunc++'], 'linux': ['g++', 'icpc', 'sunc++'],
'sunos': ['g++', 'sunc++'], 'sunos': ['g++', 'sunc++'],
'irix': ['g++'], 'irix': ['g++'],
@ -28,17 +28,24 @@ def __list_possible_compiler(platform):
def detect(conf): def detect(conf):
try: test_for_compiler = Options.options.check_cxx_compiler try: test_for_compiler = Options.options.check_cxx_compiler
except AttributeError: raise Configure.ConfigurationError("Add set_options(opt): opt.tool_options('compiler_cxx')") except AttributeError: raise Configure.ConfigurationError("Add set_options(opt): opt.tool_options('compiler_cxx')")
orig = conf.env
for compiler in test_for_compiler.split(): for compiler in test_for_compiler.split():
try: try:
conf.env = orig.copy()
conf.check_tool(compiler) conf.check_tool(compiler)
except Configure.ConfigurationError, e: except Configure.ConfigurationError, e:
debug('compiler_cxx: %r' % e) debug('compiler_cxx: %r' % e)
else: else:
if conf.env['CXX']: if conf.env['CXX']:
orig.table = conf.env.get_merged_dict()
conf.env = orig
conf.check_message(compiler, '', True) conf.check_message(compiler, '', True)
conf.env['COMPILER_CXX'] = compiler conf.env['COMPILER_CXX'] = compiler
break break
conf.check_message(compiler, '', False) conf.check_message(compiler, '', False)
break
else:
conf.fatal('could not configure a cxx compiler!')
def set_options(opt): def set_options(opt):
build_platform = Utils.unversioned_sys_platform() build_platform = Utils.unversioned_sys_platform()
@ -52,10 +59,3 @@ def set_options(opt):
for cxx_compiler in test_for_compiler.split(): for cxx_compiler in test_for_compiler.split():
opt.tool_options('%s' % cxx_compiler, option_group=cxx_compiler_opts) opt.tool_options('%s' % cxx_compiler, option_group=cxx_compiler_opts)
"""opt.add_option('-d', '--debug-level',
action = 'store',
default = ccroot.DEBUG_LEVELS.RELEASE,
help = "Specify the debug level, does nothing if CXXFLAGS is set in the environment. [Allowed Values: '%s']" % "', '".join(ccroot.DEBUG_LEVELS.ALL),
choices = ccroot.DEBUG_LEVELS.ALL,
dest = 'debug_level')"""

94
tools/wafadmin/Tools/config_c.py

@ -100,6 +100,11 @@ def validate_cfg(self, kw):
if 'modversion' in kw: if 'modversion' in kw:
return return
if 'variables' in kw:
if not 'msg' in kw:
kw['msg'] = 'Checking for %s variables' % kw['package']
return
# checking for the version of a module, for the moment, one thing at a time # checking for the version of a module, for the moment, one thing at a time
for x in cfg_ver.keys(): for x in cfg_ver.keys():
y = x.replace('-', '_') y = x.replace('-', '_')
@ -112,7 +117,7 @@ def validate_cfg(self, kw):
return return
if not 'msg' in kw: if not 'msg' in kw:
kw['msg'] = 'Checking for %s' % kw['package'] kw['msg'] = 'Checking for %s' % (kw['package'] or kw['path'])
if not 'okmsg' in kw: if not 'okmsg' in kw:
kw['okmsg'] = 'ok' kw['okmsg'] = 'ok'
if not 'errmsg' in kw: if not 'errmsg' in kw:
@ -121,22 +126,31 @@ def validate_cfg(self, kw):
@conf @conf
def cmd_and_log(self, cmd, kw): def cmd_and_log(self, cmd, kw):
Logs.debug('runner: %s\n' % cmd) Logs.debug('runner: %s\n' % cmd)
if self.log: self.log.write('%s\n' % cmd) if self.log:
self.log.write('%s\n' % cmd)
try: try:
p = Utils.pproc.Popen(cmd, stdout=Utils.pproc.PIPE, shell=True) p = Utils.pproc.Popen(cmd, stdout=Utils.pproc.PIPE, stderr=Utils.pproc.PIPE, shell=True)
output = p.communicate()[0] (out, err) = p.communicate()
except OSError: except OSError, e:
self.fatal('fail') self.log.write('error %r' % e)
self.fatal(str(e))
out = str(out)
err = str(err)
if self.log:
self.log.write(out)
self.log.write(err)
if p.returncode: if p.returncode:
if not kw.get('errmsg', ''): if not kw.get('errmsg', ''):
if kw.get('mandatory', False): if kw.get('mandatory', False):
kw['errmsg'] = output.strip() kw['errmsg'] = out.strip()
else: else:
kw['errmsg'] = 'fail' kw['errmsg'] = 'fail'
self.fatal('fail') self.fatal('fail')
return output return out
@conf @conf
def exec_cfg(self, kw): def exec_cfg(self, kw):
@ -165,6 +179,18 @@ def exec_cfg(self, kw):
self.define('%s_VERSION' % Utils.quote_define_name(kw.get('uselib_store', kw['modversion'])), version) self.define('%s_VERSION' % Utils.quote_define_name(kw.get('uselib_store', kw['modversion'])), version)
return version return version
# retrieving variables of a module
if 'variables' in kw:
env = kw.get('env', self.env)
uselib = kw.get('uselib_store', kw['package'].upper())
vars = Utils.to_list(kw['variables'])
for v in vars:
val = self.cmd_and_log('%s --variable=%s %s' % (kw['path'], v, kw['package']), kw).strip()
env.append_unique('%s_%s' % (uselib, v), val)
if not 'okmsg' in kw:
kw['okmsg'] = 'ok'
return
lst = [kw['path']] lst = [kw['path']]
for key, val in kw.get('define_variable', {}).iteritems(): for key, val in kw.get('define_variable', {}).iteritems():
lst.append('--define-variable=%s=%s' % (key, val)) lst.append('--define-variable=%s=%s' % (key, val))
@ -184,6 +210,12 @@ def exec_cfg(self, kw):
@conf @conf
def check_cfg(self, *k, **kw): def check_cfg(self, *k, **kw):
"""
for pkg-config mostly, but also all the -config tools
conf.check_cfg(path='mpicc', args='--showme:compile --showme:link', package='', uselib_store='OPEN_MPI')
conf.check_cfg(package='dbus-1', variables='system_bus_default_address session_bus_services_dir')
"""
self.validate_cfg(kw) self.validate_cfg(kw)
if 'msg' in kw: if 'msg' in kw:
self.check_message_1(kw['msg']) self.check_message_1(kw['msg'])
@ -213,7 +245,7 @@ def check_cfg(self, *k, **kw):
# env: an optional environment (modified -> provide a copy) # env: an optional environment (modified -> provide a copy)
# compiler: cc or cxx - it tries to guess what is best # compiler: cc or cxx - it tries to guess what is best
# type: program, shlib, staticlib, objects # type: cprogram, cshlib, cstaticlib
# code: a c code to execute # code: a c code to execute
# uselib_store: where to add the variables # uselib_store: where to add the variables
# uselib: parameters to use for building # uselib: parameters to use for building
@ -364,23 +396,26 @@ def validate_c(self, kw):
def post_check(self, *k, **kw): def post_check(self, *k, **kw):
"set the variables after a test was run successfully" "set the variables after a test was run successfully"
is_success = 0 is_success = False
if kw['execute']: if kw['execute']:
if kw['success']: if kw['success']:
is_success = kw['success'] is_success = True
else: else:
is_success = (kw['success'] == 0) is_success = (kw['success'] == 0)
def define_or_stuff():
nm = kw['define_name']
if kw['execute'] and kw.get('define_ret', None) and isinstance(is_success, str):
self.define(kw['define_name'], is_success, quote=kw.get('quote', 1))
else:
self.define_cond(kw['define_name'], is_success)
if 'define_name' in kw: if 'define_name' in kw:
if 'header_name' in kw or 'function_name' in kw or 'type_name' in kw or 'fragment' in kw: if 'header_name' in kw or 'function_name' in kw or 'type_name' in kw or 'fragment' in kw:
define_or_stuff() if kw['execute']:
key = kw['success']
if isinstance(key, str):
if key:
self.define(kw['define_name'], key, quote=kw.get('quote', 1))
else:
self.define_cond(kw['define_name'], True)
else:
self.define_cond(kw['define_name'], False)
else:
self.define_cond(kw['define_name'], is_success)
if is_success and 'uselib_store' in kw: if is_success and 'uselib_store' in kw:
import cc, cxx import cc, cxx
@ -478,7 +513,7 @@ def run_c_code(self, *k, **kw):
bld.rescan(bld.srcnode) bld.rescan(bld.srcnode)
o = bld.new_task_gen(features=[kw['compile_mode'], kw['type']], source=test_f_name, target='testprog') o = bld(features=[kw['compile_mode'], kw['type']], source=test_f_name, target='testprog')
for k, v in kw.iteritems(): for k, v in kw.iteritems():
setattr(o, k, v) setattr(o, k, v)
@ -507,11 +542,18 @@ def run_c_code(self, *k, **kw):
# if we need to run the program, try to get its result # if we need to run the program, try to get its result
if kw['execute']: if kw['execute']:
args = Utils.to_list(kw.get('exec_args', [])) args = Utils.to_list(kw.get('exec_args', []))
try: proc = Utils.pproc.Popen([lastprog], *args, stdout=Utils.pproc.PIPE, stderr=Utils.pproc.PIPE)
data = Utils.cmd_output([lastprog] + args).strip() (out, err) = proc.communicate()
except ValueError, e: w = self.log.write
w(str(out))
w('\n')
w(str(err))
w('\n')
w('returncode %r' % proc.returncode)
w('\n')
if proc.returncode:
self.fatal(Utils.ex_stack()) self.fatal(Utils.ex_stack())
ret = data ret = out
return ret return ret
@ -540,7 +582,7 @@ def define(self, define, value, quote=1):
# the user forgot to tell if the value is quoted or not # the user forgot to tell if the value is quoted or not
if isinstance(value, str): if isinstance(value, str):
if quote: if quote:
tbl[define] = '"%s"' % str(value) tbl[define] = '"%s"' % repr('"'+value)[2:-1].replace('"', '\\"')
else: else:
tbl[define] = value tbl[define] = value
elif isinstance(value, int): elif isinstance(value, int):
@ -643,8 +685,6 @@ def get_config_header(self):
config_header.append('#define %s' % key) config_header.append('#define %s' % key)
elif value is UNDEFINED: elif value is UNDEFINED:
config_header.append('/* #undef %s */' % key) config_header.append('/* #undef %s */' % key)
elif isinstance(value, str):
config_header.append('#define %s %s' % (key, repr(value)[1:-1]))
else: else:
config_header.append('#define %s %s' % (key, value)) config_header.append('#define %s %s' % (key, value))
return "\n".join(config_header) return "\n".join(config_header)

7
tools/wafadmin/Tools/gas.py

@ -23,14 +23,13 @@ def asm_hook(self, node):
self.compiled_tasks.append(task) self.compiled_tasks.append(task)
self.meths.append('asm_incflags') self.meths.append('asm_incflags')
@taskgen
@after('apply_obj_vars_cc') @after('apply_obj_vars_cc')
@after('apply_obj_vars_cxx') @after('apply_obj_vars_cxx')
@before('apply_link') @before('apply_link')
def asm_incflags(self): def asm_incflags(self):
if self.env['ASINCFLAGS']: self.env['_ASINCFLAGS'] = self.env['ASINCFLAGS'] self.env.append_value('_ASINCFLAGS', self.env.ASINCFLAGS)
if 'cxx' in self.features: self.env['_ASINCFLAGS'] = self.env['_CXXINCFLAGS'] var = ('cxx' in self.features) and 'CXX' or 'CC'
else: self.env['_ASINCFLAGS'] = self.env['_CCINCFLAGS'] self.env.append_value('_ASINCFLAGS', self.env['_%sINCFLAGS' % var])
def detect(conf): def detect(conf):
conf.find_program(['gas', 'as'], var='AS') conf.find_program(['gas', 'as'], var='AS')

29
tools/wafadmin/Tools/gnome.py

@ -66,13 +66,18 @@ def apply_gnome_doc(self):
self.env['APPNAME'] = self.doc_module self.env['APPNAME'] = self.doc_module
lst = self.to_list(self.doc_linguas) lst = self.to_list(self.doc_linguas)
bld = self.bld bld = self.bld
lst.append('C')
for x in lst: for x in lst:
tsk = self.create_task('xml2po') if not x == 'C':
node = self.path.find_resource(x+'/'+x+'.po') tsk = self.create_task('xml2po')
src = self.path.find_resource('C/%s.xml' % self.doc_module) node = self.path.find_resource(x+'/'+x+'.po')
out = self.path.find_or_declare('%s/%s.xml' % (x, self.doc_module)) src = self.path.find_resource('C/%s.xml' % self.doc_module)
tsk.set_inputs([node, src]) out = self.path.find_or_declare('%s/%s.xml' % (x, self.doc_module))
tsk.set_outputs(out) tsk.set_inputs([node, src])
tsk.set_outputs(out)
else:
out = self.path.find_resource('%s/%s.xml' % (x, self.doc_module))
tsk2 = self.create_task('xsltproc2po') tsk2 = self.create_task('xsltproc2po')
out2 = self.path.find_or_declare('%s/%s-%s.omf' % (x, self.doc_module, x)) out2 = self.path.find_or_declare('%s/%s-%s.omf' % (x, self.doc_module, x))
@ -83,8 +88,8 @@ def apply_gnome_doc(self):
tsk2.run_after.append(tsk) tsk2.run_after.append(tsk)
if bld.is_install: if bld.is_install:
path = self.install_path + 'gnome/help/%s/%s' % (self.doc_module, x) path = self.install_path + '/gnome/help/%s/%s' % (self.doc_module, x)
bld.install_files(self.install_path + 'omf', out2, env=self.env) bld.install_files(self.install_path + '/omf', out2, env=self.env)
for y in self.to_list(self.doc_figures): for y in self.to_list(self.doc_figures):
try: try:
os.stat(self.path.abspath() + '/' + x + '/' + y) os.stat(self.path.abspath() + '/' + x + '/' + y)
@ -92,6 +97,12 @@ def apply_gnome_doc(self):
except: except:
bld.install_as(path + '/' + y, self.path.abspath() + '/C/' + y) bld.install_as(path + '/' + y, self.path.abspath() + '/C/' + y)
bld.install_as(path + '/%s.xml' % self.doc_module, out.abspath(self.env)) bld.install_as(path + '/%s.xml' % self.doc_module, out.abspath(self.env))
if x == 'C':
xmls = self.to_list(self.doc_includes)
xmls.append(self.doc_entities)
for z in xmls:
out = self.path.find_resource('%s/%s' % (x, z))
bld.install_as(path + '/%s' % z, out.abspath(self.env))
# OBSOLETE # OBSOLETE
class xml_to_taskgen(TaskGen.task_gen): class xml_to_taskgen(TaskGen.task_gen):
@ -180,7 +191,7 @@ Task.simple_task_type('xml2po', '${XML2PO} ${XML2POFLAGS} ${SRC} > ${TGT}', colo
xslt_magic = """${XSLTPROC2PO} -o ${TGT[0].abspath(env)} \ xslt_magic = """${XSLTPROC2PO} -o ${TGT[0].abspath(env)} \
--stringparam db2omf.basename ${APPNAME} \ --stringparam db2omf.basename ${APPNAME} \
--stringparam db2omf.format docbook \ --stringparam db2omf.format docbook \
--stringparam db2omf.lang C \ --stringparam db2omf.lang ${TGT[0].abspath(env)[:-4].split('-')[-1]} \
--stringparam db2omf.dtd '-//OASIS//DTD DocBook XML V4.3//EN' \ --stringparam db2omf.dtd '-//OASIS//DTD DocBook XML V4.3//EN' \
--stringparam db2omf.omf_dir ${PREFIX}/share/omf \ --stringparam db2omf.omf_dir ${PREFIX}/share/omf \
--stringparam db2omf.help_dir ${PREFIX}/share/gnome/help \ --stringparam db2omf.help_dir ${PREFIX}/share/gnome/help \

5
tools/wafadmin/Tools/intltool.py

@ -12,11 +12,10 @@ from Logs import error
""" """
Usage: Usage:
bld.new_task_gen(features='intltool_in', source='a.po b.po', podir='po', cache='.intlcache', flags='') bld(features='intltool_in', source='a.po b.po', podir='po', cache='.intlcache', flags='')
""" """
class intltool_in_taskgen(TaskGen.task_gen): class intltool_in_taskgen(TaskGen.task_gen):
"""deprecated""" """deprecated"""
def __init__(self, *k, **kw): def __init__(self, *k, **kw):

11
tools/wafadmin/Tools/javaw.py

@ -123,16 +123,15 @@ def apply_java(self):
tsk.env.append_value('JAVACFLAGS', ['-sourcepath', names]) tsk.env.append_value('JAVACFLAGS', ['-sourcepath', names])
if self.jarname: if self.jarname:
tsk = self.create_task('jar_create') jtsk = self.create_task('jar_create', bld_nodes, self.path.find_or_declare(self.jarname))
tsk.set_inputs(bld_nodes) jtsk.set_run_after(tsk)
tsk.set_outputs(self.path.find_or_declare(self.jarname))
if not self.env['JAROPTS']: if not self.env.JAROPTS:
if self.jaropts: if self.jaropts:
self.env['JAROPTS'] = self.jaropts self.env.JAROPTS = self.jaropts
else: else:
dirs = '.' dirs = '.'
self.env['JAROPTS'] = ['-C', ''.join(self.env['OUTDIR']), dirs] self.env.JAROPTS = ['-C', ''.join(self.env['OUTDIR']), dirs]
Task.simple_task_type('jar_create', '${JAR} ${JARCREATE} ${TGT} ${JAROPTS}', color='GREEN') Task.simple_task_type('jar_create', '${JAR} ${JARCREATE} ${TGT} ${JAROPTS}', color='GREEN')
cls = Task.simple_task_type('javac', '${JAVAC} -classpath ${CLASSPATH} -d ${OUTDIR} ${JAVACFLAGS} ${SRC}') cls = Task.simple_task_type('javac', '${JAVAC} -classpath ${CLASSPATH} -d ${OUTDIR} ${JAVACFLAGS} ${SRC}')

2
tools/wafadmin/Tools/lua.py

@ -12,7 +12,7 @@ TaskGen.declare_chain(
rule = '${LUAC} -s -o ${TGT} ${SRC}', rule = '${LUAC} -s -o ${TGT} ${SRC}',
ext_in = '.lua', ext_in = '.lua',
ext_out = '.luac', ext_out = '.luac',
reentrant = 0, reentrant = False,
install = 'LUADIR', # env variable install = 'LUADIR', # env variable
) )

1
tools/wafadmin/Tools/misc.py

@ -72,6 +72,7 @@ def apply_copy(self):
tsk = self.create_task('copy', node, newnode) tsk = self.create_task('copy', node, newnode)
tsk.fun = self.fun tsk.fun = self.fun
tsk.chmod = self.chmod tsk.chmod = self.chmod
tsk.install_path = self.install_path
if not tsk.env: if not tsk.env:
tsk.debug() tsk.debug()

186
tools/wafadmin/Tools/msvc.py

@ -80,15 +80,15 @@ def setup_msvc(conf, versions):
for target in platforms: for target in platforms:
try: try:
arch,(p1,p2,p3) = targets[target] arch,(p1,p2,p3) = targets[target]
compiler,version = version.split() compiler,revision = version.split()
return compiler,p1,p2,p3 return compiler,revision,p1,p2,p3
except KeyError: continue except KeyError: continue
except KeyError: continue except KeyError: continue
conf.fatal('msvc: Impossible to find a valid architecture for building (in setup_msvc)') conf.fatal('msvc: Impossible to find a valid architecture for building (in setup_msvc)')
@conf @conf
def get_msvc_version(conf, compiler, version, target, vcvars): def get_msvc_version(conf, compiler, version, target, vcvars):
debug('msvc: get_msvc_version: ' + compiler + ' ' + version + ' ' + target + ' ...') debug('msvc: get_msvc_version: %r %r %r', compiler, version, target)
batfile = os.path.join(conf.blddir, 'waf-print-msvc.bat') batfile = os.path.join(conf.blddir, 'waf-print-msvc.bat')
f = open(batfile, 'w') f = open(batfile, 'w')
f.write("""@echo off f.write("""@echo off
@ -107,7 +107,7 @@ echo LIB=%%LIB%%
if lines[0].find(x) != -1: if lines[0].find(x) != -1:
break break
else: else:
debug('msvc: get_msvc_version: %r %r %r -> not found' % (compiler, version, target)) debug('msvc: get_msvc_version: %r %r %r -> not found', compiler, version, target)
conf.fatal('msvc: Impossible to find a valid architecture for building (in get_msvc_version)') conf.fatal('msvc: Impossible to find a valid architecture for building (in get_msvc_version)')
for line in lines[1:]: for line in lines[1:]:
@ -136,11 +136,11 @@ echo LIB=%%LIB%%
if p.returncode != 0: if p.returncode != 0:
raise Exception('return code: %r: %r' % (p.returncode, err)) raise Exception('return code: %r: %r' % (p.returncode, err))
except Exception, e: except Exception, e:
debug('msvc: get_msvc_version: %r %r %r -> failure' % (compiler, version, target)) debug('msvc: get_msvc_version: %r %r %r -> failure', compiler, version, target)
debug(str(e)) debug(str(e))
conf.fatal('msvc: cannot run the compiler (in get_msvc_version)') conf.fatal('msvc: cannot run the compiler (in get_msvc_version)')
else: else:
debug('msvc: get_msvc_version: %r %r %r -> OK' % (compiler, version, target)) debug('msvc: get_msvc_version: %r %r %r -> OK', compiler, version, target)
return (MSVC_PATH, MSVC_INCDIR, MSVC_LIBDIR) return (MSVC_PATH, MSVC_INCDIR, MSVC_LIBDIR)
@ -297,12 +297,13 @@ def gather_icl_versions(conf, versions):
@conf @conf
def get_msvc_versions(conf): def get_msvc_versions(conf):
if not conf.env['MSVC_INSTALLED_VERSIONS']: if not conf.env.MSVC_INSTALLED_VERSIONS:
conf.env['MSVC_INSTALLED_VERSIONS'] = [] lst = []
conf.gather_msvc_versions(conf.env['MSVC_INSTALLED_VERSIONS']) conf.gather_msvc_versions(lst)
conf.gather_wsdk_versions(conf.env['MSVC_INSTALLED_VERSIONS']) conf.gather_wsdk_versions(lst)
conf.gather_icl_versions(conf.env['MSVC_INSTALLED_VERSIONS']) conf.gather_icl_versions(lst)
return conf.env['MSVC_INSTALLED_VERSIONS'] conf.env.MSVC_INSTALLED_VERSIONS = lst
return conf.env.MSVC_INSTALLED_VERSIONS
@conf @conf
def print_all_msvc_detected(conf): def print_all_msvc_detected(conf):
@ -401,7 +402,7 @@ def libname_msvc(self, libname, is_static=False, mandatory=False):
for path in _libpaths: for path in _libpaths:
for libn in libnames: for libn in libnames:
if os.path.exists(os.path.join(path, libn)): if os.path.exists(os.path.join(path, libn)):
debug('msvc: lib found: %s' % os.path.join(path,libn)) debug('msvc: lib found: %s', os.path.join(path,libn))
return re.sub('\.lib$', '',libn) return re.sub('\.lib$', '',libn)
#if no lib can be found, just return the libname as msvc expects it #if no lib can be found, just return the libname as msvc expects it
@ -449,7 +450,7 @@ link_add_flags
@conftest @conftest
def autodetect(conf): def autodetect(conf):
v = conf.env v = conf.env
compiler, path, includes, libdirs = detect_msvc(conf) compiler, version, path, includes, libdirs = detect_msvc(conf)
v['PATH'] = path v['PATH'] = path
v['CPPPATH'] = includes v['CPPPATH'] = includes
v['LIBPATH'] = libdirs v['LIBPATH'] = libdirs
@ -475,19 +476,16 @@ def find_msvc(conf):
v = conf.env v = conf.env
compiler, path, includes, libdirs = detect_msvc(conf) compiler, version, path, includes, libdirs = detect_msvc(conf)
v['PATH'] = path
v['CPPPATH'] = includes
v['LIBPATH'] = libdirs
compiler_name, linker_name, lib_name = _get_prog_names(conf, compiler) compiler_name, linker_name, lib_name = _get_prog_names(conf, compiler)
has_msvc_manifest = (compiler == 'msvc' and float(version) >= 8) or (compiler == 'wsdk' and float(version) >= 6) or (compiler == 'intel' and float(version) >= 11)
# compiler # compiler
cxx = None cxx = None
if v['CXX']: cxx = v['CXX'] if v.CXX: cxx = v.CXX
elif 'CXX' in conf.environ: cxx = conf.environ['CXX'] elif 'CXX' in conf.environ: cxx = conf.environ['CXX']
if not cxx: cxx = conf.find_program(compiler_name, var='CXX', path_list=path) if not cxx: cxx = conf.find_program(compiler_name, var='CXX', path_list=path, mandatory=True)
if not cxx: conf.fatal('%s was not found (compiler)' % compiler_name)
cxx = conf.cmd_to_list(cxx) cxx = conf.cmd_to_list(cxx)
# before setting anything, check if the compiler is really msvc # before setting anything, check if the compiler is really msvc
@ -496,43 +494,50 @@ def find_msvc(conf):
if not Utils.cmd_output([cxx, '/nologo', '/?'], silent=True, env=env): if not Utils.cmd_output([cxx, '/nologo', '/?'], silent=True, env=env):
conf.fatal('the msvc compiler could not be identified') conf.fatal('the msvc compiler could not be identified')
# c/c++ compiler link = v.LINK_CXX
v['CC'] = v['CXX'] = cxx if not link:
v['CC_NAME'] = v['CXX_NAME'] = 'msvc' link = conf.find_program(linker_name, path_list=path, mandatory=True)
ar = v.AR
if not ar:
ar = conf.find_program(lib_name, path_list=path, mandatory=True)
# environment flags # manifest tool. Not required for VS 2003 and below. Must have for VS 2005 and later
try: v.prepend_value('CPPPATH', conf.environ['INCLUDE']) mt = v.MT
except KeyError: pass if has_msvc_manifest:
try: v.prepend_value('LIBPATH', conf.environ['LIB']) mt = conf.find_program('MT', path_list=path, mandatory=True)
except KeyError: pass
# linker # no more possibility of failure means the data state will be consistent
if not v['LINK_CXX']: # we may store the data safely now
link = conf.find_program(linker_name, path_list=path)
if link: v['LINK_CXX'] = link
else: conf.fatal('%s was not found (linker)' % linker_name)
v['LINK'] = link
if not v['LINK_CC']: v['LINK_CC'] = v['LINK_CXX'] v.MSVC_MANIFEST = has_msvc_manifest
v.PATH = path
v.CPPPATH = includes
v.LIBPATH = libdirs
# staticlib linker # c/c++ compiler
if not v['AR']: v.CC = v.CXX = cxx
stliblink = conf.find_program(lib_name, path_list=path) v.CC_NAME = v.CXX_NAME = 'msvc'
if not stliblink: return
v['AR'] = stliblink v.LINK = v.LINK_CXX = link
v['ARFLAGS'] = ['/NOLOGO'] if not v.LINK_CC:
v.LINK_CC = v.LINK_CXX
v.AR = ar
v.MT = mt
v.MTFLAGS = v.ARFLAGS = ['/NOLOGO']
# manifest tool. Not required for VS 2003 and below. Must have for VS 2005 and later
manifesttool = conf.find_program('MT', path_list=path)
if manifesttool:
v['MT'] = manifesttool
v['MTFLAGS'] = ['/NOLOGO']
conf.check_tool('winres') conf.check_tool('winres')
if not conf.env['WINRC']: if not conf.env.WINRC:
warn('Resource compiler not found. Compiling resource file is disabled') warn('Resource compiler not found. Compiling resource file is disabled')
# environment flags
try: v.prepend_value('CPPPATH', conf.environ['INCLUDE'])
except KeyError: pass
try: v.prepend_value('LIBPATH', conf.environ['LIB'])
except KeyError: pass
@conftest @conftest
def msvc_common_flags(conf): def msvc_common_flags(conf):
v = conf.env v = conf.env
@ -702,52 +707,47 @@ def apply_manifest(self):
"""Special linker for MSVC with support for embedding manifests into DLL's """Special linker for MSVC with support for embedding manifests into DLL's
and executables compiled by Visual Studio 2005 or probably later. Without and executables compiled by Visual Studio 2005 or probably later. Without
the manifest file, the binaries are unusable. the manifest file, the binaries are unusable.
See: http://msdn2.microsoft.com/en-us/library/ms235542(VS.80).aspx See: http://msdn2.microsoft.com/en-us/library/ms235542(VS.80).aspx"""
Problems with this tool: it is always called whether MSVC creates manifests or not."""
if self.env.CC_NAME != 'msvc':
return
tsk = self.create_task('msvc_manifest') if self.env.CC_NAME == 'msvc' and self.env.MSVC_MANIFEST:
tsk.set_inputs(self.link_task.outputs[0]) out_node = self.link_task.outputs[0]
man_node = out_node.parent.find_or_declare(out_node.name + '.manifest')
self.link_task.outputs.append(man_node)
self.link_task.do_manifest = True
def exec_mf(self): def exec_mf(self):
env = self.env env = self.env
outfile = self.inputs[0].bldpath(env) mtool = env['MT']
manifest = outfile + '.manifest' if not mtool:
if os.path.exists(manifest): return 0
debug('msvc: manifesttool')
mtool = env['MT'] self.do_manifest = False
if not mtool:
return 0 outfile = self.outputs[0].bldpath(env)
manifest = self.outputs[-1].bldpath(env)
mode = ''
# embedding mode. Different for EXE's and DLL's. # embedding mode. Different for EXE's and DLL's.
# see: http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx # see: http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx
if 'cprogram' in self.generator.features: mode = ''
mode = '1' if 'cprogram' in self.generator.features:
elif 'cshlib' in self.generator.features: mode = '1'
mode = '2' elif 'cshlib' in self.generator.features:
mode = '2'
debug('msvc: embedding manifest')
#flags = ' '.join(env['MTFLAGS'] or []) debug('msvc: embedding manifest')
#flags = ' '.join(env['MTFLAGS'] or [])
lst = []
lst.extend(Utils.to_list(env['MT'])) lst = []
lst.extend(Utils.to_list(env['MTFLAGS'])) lst.extend(Utils.to_list(env['MT']))
lst.extend(Utils.to_list("-manifest")) lst.extend(Utils.to_list(env['MTFLAGS']))
lst.extend(Utils.to_list(manifest)) lst.extend(Utils.to_list("-manifest"))
lst.extend(Utils.to_list("-outputresource:%s;%s" % (outfile, mode))) lst.extend(Utils.to_list(manifest))
lst.extend(Utils.to_list("-outputresource:%s;%s" % (outfile, mode)))
#cmd='%s %s -manifest "%s" -outputresource:"%s";#%s' % (mtool, flags,
# manifest, outfile, mode) #cmd='%s %s -manifest "%s" -outputresource:"%s";#%s' % (mtool, flags,
lst = [lst] # manifest, outfile, mode)
ret = self.exec_command(*lst) lst = [lst]
return self.exec_command(*lst)
return ret
cls = Task.task_type_from_func('msvc_manifest', vars=['MT', 'MTFLAGS'], color='BLUE', func=exec_mf, ext_in='.bin')
cls.quiet = 1
########## stupid evil command modification: concatenate the tokens /Fx, /doc, and /x: with the next token ########## stupid evil command modification: concatenate the tokens /Fx, /doc, and /x: with the next token
@ -769,7 +769,11 @@ def exec_command_msvc(self, *k, **kw):
env.update(PATH = ';'.join(self.env['PATH'])) env.update(PATH = ';'.join(self.env['PATH']))
kw['env'] = env kw['env'] = env
return self.generator.bld.exec_command(*k, **kw) ret = self.generator.bld.exec_command(*k, **kw)
if ret: return ret
if getattr(self, 'do_manifest', None):
ret = exec_mf(self)
return ret
for k in 'cc cxx winrc cc_link cxx_link static_link qxx'.split(): for k in 'cc cxx winrc cc_link cxx_link static_link qxx'.split():
cls = Task.TaskBase.classes.get(k, None) cls = Task.TaskBase.classes.get(k, None)

72
tools/wafadmin/Tools/perl.py

@ -36,31 +36,29 @@ def check_perl_version(conf, minver=None):
Perl binary can be overridden by --with-perl-binary config variable Perl binary can be overridden by --with-perl-binary config variable
""" """
res = True
if not getattr(Options.options, 'perlbinary', None): if getattr(Options.options, 'perlbinary', None):
perl = conf.find_program("perl", var="PERL") conf.env.PERL = Options.options.perlbinary
if not perl:
return False
else: else:
perl = Options.options.perlbinary conf.find_program('perl', var='PERL', mandatory=True)
conf.env['PERL'] = perl
try:
version = Utils.cmd_output(perl + " -e'printf \"%vd\", $^V'") version = Utils.cmd_output([conf.env.PERL, '-e', 'printf "%vd",$^V'])
if not version: except:
res = False conf.fatal('could not determine the perl version')
version = "Unknown"
elif not minver is None: conf.env.PERL_VERSION = version
ver = tuple(map(int, version.split("."))) cver = ''
if minver:
try:
ver = tuple(map(int, version.split('.')))
except:
conf.fatal('unsupported perl version %r' % version)
if ver < minver: if ver < minver:
res = False conf.fatal('perl is too old')
if minver is None: cver = '.'.join(map(str,minver))
cver = "" conf.check_message('perl', cver, True, version)
else:
cver = ".".join(map(str,minver))
conf.check_message("perl", cver, res, version)
return res
@conf @conf
def check_perl_module(conf, module): def check_perl_module(conf, module):
@ -85,31 +83,25 @@ def check_perl_ext_devel(conf):
Sets different xxx_PERLEXT variables in the environment. Sets different xxx_PERLEXT variables in the environment.
Also sets the ARCHDIR_PERL variable useful as installation path, Also sets the ARCHDIR_PERL variable useful as installation path,
which can be overridden by --with-perl-archdir option. which can be overridden by --with-perl-archdir
""" """
if not conf.env['PERL']: if not conf.env.PERL:
return False conf.fatal('perl detection is required first')
perl = conf.env['PERL']
def read_out(cmd): def read_out(cmd):
return Utils.to_list(Utils.cmd_output(perl + cmd)) return Utils.to_list(Utils.cmd_output([conf.env.PERL, '-MConfig', '-e', cmd]))
conf.env["LINKFLAGS_PERLEXT"] = read_out(" -MConfig -e'print $Config{lddlflags}'")
conf.env["CPPPATH_PERLEXT"] = read_out(" -MConfig -e'print \"$Config{archlib}/CORE\"'")
conf.env["CCFLAGS_PERLEXT"] = read_out(" -MConfig -e'print \"$Config{ccflags} $Config{cccdlflags}\"'")
conf.env["XSUBPP"] = read_out(" -MConfig -e'print \"$Config{privlib}/ExtUtils/xsubpp$Config{exe_ext}\"'") conf.env.LINKFLAGS_PERLEXT = read_out('print $Config{lddlflags}')
conf.env["EXTUTILS_TYPEMAP"] = read_out(" -MConfig -e'print \"$Config{privlib}/ExtUtils/typemap\"'") conf.env.CPPPATH_PERLEXT = read_out('print "$Config{archlib}/CORE"')
conf.env.CCFLAGS_PERLEXT = read_out('print "$Config{ccflags} $Config{cccdlflags}"')
conf.env.XSUBPP = read_out('print "$Config{privlib}/ExtUtils/xsubpp$Config{exe_ext}"')
conf.env.EXTUTILS_TYPEMAP = read_out('print "$Config{privlib}/ExtUtils/typemap"')
conf.env.perlext_PATTERN = '%s.' + read_out('print $Config{dlext}')[0]
if not getattr(Options.options, 'perlarchdir', None): if getattr(Options.options, 'perlarchdir', None):
conf.env["ARCHDIR_PERL"] = Utils.cmd_output(perl + " -MConfig -e'print $Config{sitearch}'") conf.env.ARCHDIR_PERL = Options.options.perlarchdir
else: else:
conf.env["ARCHDIR_PERL"] = getattr(Options.options, 'perlarchdir') conf.env.ARCHDIR_PERL = read_out('print $Config{sitearch}')[0]
conf.env['perlext_PATTERN'] = '%s.' + Utils.cmd_output(perl + " -MConfig -e'print $Config{dlext}'")
return True
def set_options(opt): def set_options(opt):
opt.add_option("--with-perl-binary", type="string", dest="perlbinary", help = 'Specify alternate perl binary', default=None) opt.add_option("--with-perl-binary", type="string", dest="perlbinary", help = 'Specify alternate perl binary', default=None)

12
tools/wafadmin/Tools/preproc.py

@ -638,7 +638,7 @@ class c_parser(object):
self.count_files += 1 self.count_files += 1
if self.count_files > 30000: raise PreprocError("recursion limit exceeded") if self.count_files > 30000: raise PreprocError("recursion limit exceeded")
pc = self.parse_cache pc = self.parse_cache
debug('preproc: reading file %r' % filepath) debug('preproc: reading file %r', filepath)
try: try:
lns = pc[filepath] lns = pc[filepath]
except KeyError: except KeyError:
@ -660,7 +660,7 @@ class c_parser(object):
traceback.print_exc() traceback.print_exc()
def start(self, node, env): def start(self, node, env):
debug('preproc: scanning %s (in %s)' % (node.name, node.parent.name)) debug('preproc: scanning %s (in %s)', node.name, node.parent.name)
self.env = env self.env = env
variant = node.variant(env) variant = node.variant(env)
@ -684,11 +684,11 @@ class c_parser(object):
self.process_line(kind, line) self.process_line(kind, line)
except Exception, e: except Exception, e:
if Logs.verbose: if Logs.verbose:
debug('preproc: line parsing failed (%s): %s %s' % (e, line, Utils.ex_stack())) debug('preproc: line parsing failed (%s): %s %s', e, line, Utils.ex_stack())
def process_line(self, token, line): def process_line(self, token, line):
ve = Logs.verbose ve = Logs.verbose
if ve: debug('preproc: line is %s - %s state is %s' % (token, line, self.state)) if ve: debug('preproc: line is %s - %s state is %s', token, line, self.state)
state = self.state state = self.state
# make certain we define the state if we are about to enter in an if block # make certain we define the state if we are about to enter in an if block
@ -718,7 +718,7 @@ class c_parser(object):
(kind, inc) = extract_include(line, self.defs) (kind, inc) = extract_include(line, self.defs)
if inc in self.ban_includes: return if inc in self.ban_includes: return
if token == 'import': self.ban_includes.append(inc) if token == 'import': self.ban_includes.append(inc)
if ve: debug('preproc: include found %s (%s) ' % (inc, kind)) if ve: debug('preproc: include found %s (%s) ', inc, kind)
if kind == '"' or not strict_quotes: if kind == '"' or not strict_quotes:
self.tryfind(inc) self.tryfind(inc)
elif token == 'elif': elif token == 'elif':
@ -734,7 +734,7 @@ class c_parser(object):
m = re_mac.search(line) m = re_mac.search(line)
if m: if m:
name = m.group(0) name = m.group(0)
if ve: debug('preproc: define %s %s' % (name, line)) if ve: debug('preproc: define %s %s', name, line)
self.defs[name] = line self.defs[name] = line
else: else:
raise PreprocError("invalid define line %s" % line) raise PreprocError("invalid define line %s" % line)

4
tools/wafadmin/Tools/python.py

@ -360,10 +360,10 @@ def check_python_version(conf, minver=None):
conf.check_message_custom('Python version', '', pyver_full) conf.check_message_custom('Python version', '', pyver_full)
else: else:
minver_str = '.'.join(map(str, minver)) minver_str = '.'.join(map(str, minver))
conf.check_message('Python version', ">= %s" % (minver_str,), result, option=pyver_full) conf.check_message('Python version', ">= %s" % minver_str, result, option=pyver_full)
if not result: if not result:
conf.fatal('The python version is too old (%r)' % minver) conf.fatal('The python version is too old (%r)' % pyver_full)
@conf @conf
def check_python_module(conf, module_name): def check_python_module(conf, module_name):

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save