diff --git a/src/node/binding.gyp b/src/node/binding.gyp
index 10afaf696271f120ce1ef2fb10e80a36ee3d72e8..7ef3bdf4bdedaf150aaa75d8ef0b4f290d3d877d 100644
--- a/src/node/binding.gyp
+++ b/src/node/binding.gyp
@@ -1,9 +1,4 @@
 {
-  "variables" : {
-    'no_install': "<!(echo $GRPC_NO_INSTALL)",
-    'grpc_root': "<!(echo $GRPC_ROOT)",
-    'grpc_lib_subdir': "<!(echo $GRPC_LIB_SUBDIR)"
-    },
   "targets" : [
     {
       'include_dirs': [
@@ -24,7 +19,9 @@
       'link_settings': {
         'libraries': [
           '-lrt',
-          '-lpthread'
+          '-lpthread',
+          '-lgrpc',
+          '-lgpr'
         ],
       },
       "target_name": "grpc",
@@ -38,27 +35,6 @@
         "ext/server.cc",
         "ext/server_credentials.cc",
         "ext/timeval.cc"
-      ],
-      'conditions' : [
-        ['no_install=="yes"', {
-          'include_dirs': [
-            "<(grpc_root)/include"
-          ],
-          'link_settings': {
-            'libraries': [
-              '<(grpc_root)/<(grpc_lib_subdir)/libgrpc.a',
-              '<(grpc_root)/<(grpc_lib_subdir)/libgpr.a'
-            ]
-          }
-        }],
-        ['no_install!="yes"', {
-            'link_settings': {
-              'libraries': [
-                '-lgrpc',
-                '-lgpr'
-              ]
-            }
-          }]
       ]
     }
   ]
diff --git a/tools/run_tests/build_node.sh b/tools/run_tests/build_node.sh
index c3e88c565d276cac7f804d545f215a417541e443..c85ecf1b2595c6fc594539400a383690c76bd08f 100755
--- a/tools/run_tests/build_node.sh
+++ b/tools/run_tests/build_node.sh
@@ -36,12 +36,8 @@ CONFIG=${CONFIG:-opt}
 # change to grpc repo root
 cd $(dirname $0)/../..
 
-# tells npm install to look for files in that directory
-export GRPC_ROOT=`pwd`
-# tells npm install the subdirectory with library files
-export GRPC_LIB_SUBDIR=libs/$CONFIG
-# tells npm install not to use default locations
-export GRPC_NO_INSTALL=yes
+export CXXFLAGS=-I`pwd`/include
+export LDFLAGS=-L`pwd`/libs/$CONFIG
 
 cd src/node
 
diff --git a/tools/run_tests/jobset.py b/tools/run_tests/jobset.py
index ad65da535b42bccf7ff642b61b092b27ecf808d4..26caf031c3a5f8b5d6a71371e58e270734824f88 100755
--- a/tools/run_tests/jobset.py
+++ b/tools/run_tests/jobset.py
@@ -136,7 +136,7 @@ def which(filename):
 class JobSpec(object):
   """Specifies what to run for a job."""
 
-  def __init__(self, cmdline, shortname=None, environ={}, hash_targets=[]):
+  def __init__(self, cmdline, shortname=None, environ=None, hash_targets=None):
     """
     Arguments:
       cmdline: a list of arguments to pass as the command line
@@ -144,6 +144,10 @@ class JobSpec(object):
       hash_targets: which files to include in the hash representing the jobs version
                     (or empty, indicating the job should not be hashed)
     """
+    if environ is None:
+      environ = {}
+    if hash_targets is None:
+      hash_targets = []
     self.cmdline = cmdline
     self.environ = environ
     self.shortname = cmdline[0] if shortname is None else shortname
diff --git a/tools/run_tests/run_node.sh b/tools/run_tests/run_node.sh
index ccf1b9d6f54918d9dd713f95ee1c516a5884a9d8..3a82c04a8ef2f961fbd831ddbff42536f082ffd0 100755
--- a/tools/run_tests/run_node.sh
+++ b/tools/run_tests/run_node.sh
@@ -30,9 +30,13 @@
 
 set -ex
 
+CONFIG=${CONFIG:-opt}
+
 # change to grpc repo root
 cd $(dirname $0)/../..
 
 root=`pwd`
 
+export LD_LIBRARY_PATH=$root/libs/$CONFIG
+
 $root/src/node/node_modules/mocha/bin/mocha $root/src/node/test
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index 9d45693cd4acb5dcf635362886e1637e9b3365f6..0f4544a5c6c48efe433f515a329309ceced58745 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -51,11 +51,14 @@ os.chdir(ROOT)
 # SimpleConfig: just compile with CONFIG=config, and run the binary to test
 class SimpleConfig(object):
 
-  def __init__(self, config, environ={}):
+  def __init__(self, config, environ=None):
+    if environ is None:
+      environ = {}
     self.build_config = config
     self.maxjobs = 2 * multiprocessing.cpu_count()
     self.allow_hashing = (config != 'gcov')
     self.environ = environ
+    self.environ['CONFIG'] = config
 
   def job_spec(self, cmdline, hash_targets):
     """Construct a jobset.JobSpec for a test under this config
@@ -78,7 +81,9 @@ class SimpleConfig(object):
 # ValgrindConfig: compile with some CONFIG=config, but use valgrind to run
 class ValgrindConfig(object):
 
-  def __init__(self, config, tool, args=[]):
+  def __init__(self, config, tool, args=None):
+    if args is None:
+      args = []
     self.build_config = config
     self.tool = tool
     self.args = args
@@ -115,6 +120,12 @@ class CLanguage(object):
   def build_steps(self):
     return []
 
+  def supports_multi_config(self):
+    return True
+
+  def __str__(self):
+    return self.make_target
+
 
 class NodeLanguage(object):
 
@@ -127,6 +138,12 @@ class NodeLanguage(object):
   def build_steps(self):
     return [['tools/run_tests/build_node.sh']]
 
+  def supports_multi_config(self):
+    return False
+
+  def __str__(self):
+    return 'node'
+
 
 class PhpLanguage(object):
 
@@ -139,6 +156,12 @@ class PhpLanguage(object):
   def build_steps(self):
     return [['tools/run_tests/build_php.sh']]
 
+  def supports_multi_config(self):
+    return False
+
+  def __str__(self):
+    return 'php'
+
 
 class PythonLanguage(object):
 
@@ -156,6 +179,12 @@ class PythonLanguage(object):
   def build_steps(self):
     return [['tools/run_tests/build_python.sh']]
 
+  def supports_multi_config(self):
+    return False
+
+  def __str__(self):
+    return 'python'
+
 class RubyLanguage(object):
 
   def test_specs(self, config, travis):
@@ -167,6 +196,12 @@ class RubyLanguage(object):
   def build_steps(self):
     return [['tools/run_tests/build_ruby.sh']]
 
+  def supports_multi_config(self):
+    return False
+
+  def __str__(self):
+    return 'ruby'
+
 class CSharpLanguage(object):
 
   def test_specs(self, config, travis):
@@ -178,6 +213,12 @@ class CSharpLanguage(object):
   def build_steps(self):
     return [['tools/run_tests/build_csharp.sh']]
 
+  def supports_multi_config(self):
+    return False
+
+  def __str__(self):
+    return 'csharp'
+
 # different configurations we can run under
 _CONFIGS = {
     'dbg': SimpleConfig('dbg'),
@@ -242,6 +283,13 @@ build_configs = set(cfg.build_config for cfg in run_configs)
 
 make_targets = []
 languages = set(_LANGUAGES[l] for l in args.language)
+
+if len(build_configs) > 1:
+  for language in languages:
+    if not language.supports_multi_config():
+      print language, 'does not support multiple build configurations'
+      sys.exit(1)
+
 build_steps = [jobset.JobSpec(['make',
                                '-j', '%d' % (multiprocessing.cpu_count() + 1),
                                'EXTRA_DEFINES=GRPC_TEST_SLOWDOWN_MACHINE_FACTOR=%f' % args.slowdown,
@@ -249,7 +297,8 @@ build_steps = [jobset.JobSpec(['make',
                                    itertools.chain.from_iterable(
                                        l.make_targets() for l in languages))))
                for cfg in build_configs] + list(set(
-                   jobset.JobSpec(cmdline)
+                   jobset.JobSpec(cmdline, environ={'CONFIG': cfg})
+                   for cfg in build_configs
                    for l in languages
                    for cmdline in l.build_steps()))
 one_run = set(