summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--SConscript (renamed from src/SConscript)111
-rw-r--r--SConscript.env (renamed from src/SConscript.env)25
-rw-r--r--SConstruct26
-rw-r--r--build/compile_commands.py197
-rw-r--r--build/depends.py1192
-rw-r--r--build/features.py155
-rw-r--r--build/mixxx.py7
-rw-r--r--build/windows/__init__.py0
-rw-r--r--build/windows/signtool.py29
-rw-r--r--lib/benchmark/SConscript4
-rw-r--r--lib/gmock-1.7.0/SConscript5
-rw-r--r--lib/gtest-1.7.0/SConscript4
-rw-r--r--lib/soundtouch/SConscript27
-rw-r--r--lib/vamp/SConscript23
-rw-r--r--res/controllers/Behringer CMD MM1.midi.xml117
-rw-r--r--res/controllers/Behringer-CMD-MM1-scripts.js1038
-rw-r--r--res/controllers/DJ TechTools MIDI Fighter Twister.midi.xml313
-rw-r--r--res/controllers/DJ TechTools-MIDI Fighter Twister-scripts.js85
-rw-r--r--res/skins/Deere/style.qss67
-rw-r--r--res/skins/Deere/tool_bar.xml2
-rw-r--r--res/skins/LateNight/button_1state.xml4
-rw-r--r--res/skins/LateNight/button_2state_nohover.xml42
-rw-r--r--res/skins/LateNight/button_hotcue.xml14
-rw-r--r--res/skins/LateNight/deck_row_1_keyVinylFx.xml92
-rw-r--r--res/skins/LateNight/deck_row_4_overviewSpinny.xml147
-rw-r--r--res/skins/LateNight/deck_row_5_transportLoopJump.xml363
-rw-r--r--res/skins/LateNight/fx_unit_parameters_visible.xml16
-rw-r--r--res/skins/LateNight/fx_units_12.xml48
-rw-r--r--res/skins/LateNight/fx_units_34.xml48
-rw-r--r--res/skins/LateNight/mixer.xml26
-rw-r--r--res/skins/LateNight/mixer_channel_4decks.xml26
-rw-r--r--res/skins/LateNight/mixer_channel_left.xml25
-rw-r--r--res/skins/LateNight/mixer_channel_right.xml25
-rw-r--r--res/skins/LateNight/preview_deck.xml2
-rw-r--r--res/skins/LateNight/rate_controls.xml157
-rw-r--r--res/skins/LateNight/sampler.xml2
-rw-r--r--res/skins/LateNight/skin.xml4
-rw-r--r--res/skins/LateNight/style.qss33
-rw-r--r--res/skins/LateNight/style/mixxx_logo.pngbin6963 -> 0 bytes
-rw-r--r--res/skins/LateNight/style/mixxx_logo.svg (renamed from res/skins/LateNight/style/logo_LateNight_160x40.svg)0
-rw-r--r--res/skins/LateNight/style/mixxx_logo_toolbar.pngbin2243 -> 0 bytes
-rw-r--r--res/skins/LateNight/toolbar.xml2
-rw-r--r--res/skins/LateNight/waveform.xml3
-rw-r--r--res/skins/Shade/style.qss59
-rw-r--r--res/skins/Tango/style.qss53
-rw-r--r--res/skins/Tango/waveform.xml3
-rw-r--r--src/control/controlmodel.h2
-rw-r--r--src/controllers/controllerdebug.h16
-rw-r--r--src/controllers/hid/hidcontroller.h2
-rw-r--r--src/controllers/midi/midicontroller.cpp15
-rw-r--r--src/controllers/midi/midicontrollerpresetfilehandler.cpp47
-rw-r--r--src/controllers/midi/portmidicontroller.h2
-rw-r--r--src/encoder/encodermp3.cpp6
-rw-r--r--src/encoder/encodermp3.h2
-rw-r--r--src/engine/enginechannel.h3
-rw-r--r--src/library/basesqltablemodel.cpp1
-rw-r--r--src/library/browse/browsetablemodel.h2
-rw-r--r--src/library/dlgcoverartfullsize.cpp65
-rw-r--r--src/mixxx.cpp8
-rw-r--r--src/soundio/soundmanagerutil.cpp2
-rw-r--r--src/sources/soundsourceflac.h2
-rw-r--r--src/sources/soundsourcemp3.h2
-rw-r--r--src/sources/soundsourceoggvorbis.h2
-rw-r--r--src/sources/soundsourceopus.h2
-rw-r--r--src/sources/soundsourcesndfile.h2
-rw-r--r--src/util/battery/batterymac.cpp1
-rw-r--r--src/util/statmodel.h2
-rw-r--r--src/waveform/sharedglcontext.cpp6
-rw-r--r--src/widget/controlwidgetconnection.h4
-rw-r--r--src/widget/wnumberrate.h2
71 files changed, 2606 insertions, 2214 deletions
diff --git a/.gitignore b/.gitignore
index 3fc5557322..3a3e97fdb9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -59,3 +59,4 @@ lib/*/lib/*.lib
lib/qtscript-bytearray/*.cc
*.vscode
+compile_commands.json \ No newline at end of file
diff --git a/src/SConscript b/SConscript
index 3a538db5d8..1754889cc5 100644
--- a/src/SConscript
+++ b/SConscript
@@ -35,23 +35,23 @@ flags = build.flags
# both mixxx and mixxx-test.
mixxx_lib = env.StaticLibrary('libmixxx',
[source for source in sources
- if str(source) != 'main.cpp'])
+ if str(source) != 'src/main.cpp'])
# mixxx.qrc must not be bundled into libmixxx.a since the linker will not link
# it into the resulting binary unless it is on the link command-line explicitly
# (it has no link-time symbols that are needed by anything in Mixxx).
-mixxx_qrc = env.StaticObject(env.Qrc5('qrc_mixxx', '#res/mixxx.qrc'))
+mixxx_qrc = env.StaticObject(env.Qrc5('res/mixxx.cc', 'res/mixxx.qrc'))
# libmixxx.a needs to precede all other libraries so that symbols it requires
# end up in the linker's list of unresolved symbols before other libraries are
# searched for symbols.
env.Prepend(LIBS=mixxx_lib)
-mixxx_main = env.StaticObject('main.cpp')
+mixxx_main = env.StaticObject('src/main.cpp')
#Tell SCons to build Mixxx
#=========================
if build.platform_is_windows:
dist_dir = 'dist%s' % build.bitwidth
# Populate the stuff that changes in the .rc file
- fo = open(File('#src/mixxx.rc.include').abspath, "w")
+ fo = open(File('src/mixxx.rc.include').abspath, "w")
str_list = []
str_list.append('#define VER_FILEVERSION ')
@@ -79,7 +79,7 @@ if build.platform_is_windows:
fo.write(''.join(str_list))
fo.close()
- mixxx_rc = env.RES('#src/mixxx.rc')
+ mixxx_rc = env.RES('src/mixxx.rc')
mixxx_bin = env.Program('mixxx',
[mixxx_main, mixxx_qrc, mixxx_rc],
LINKCOM = [env['LINKCOM'], 'mt.exe -nologo -manifest ${TARGET}.manifest -outputresource:$TARGET;1'])
@@ -104,25 +104,25 @@ else:
test_bin = None
def define_test_targets(default=False):
global test_bin
- test_files = Glob('test/*.cpp', strings=True)
+ test_files = Glob('src/test/*.cpp', strings=True)
test_env = env.Clone()
- test_env.Append(CPPPATH="#lib/gtest-1.7.0/include")
- test_env.Append(CPPPATH="#lib/gmock-1.7.0/include")
- test_env.Append(CPPPATH="#lib/benchmark/include")
- test_files = [test_env.StaticObject(filename)
- if filename !='main.cpp' else filename
- for filename in test_files]
- test_sources = test_files
- test_env.Append(LIBPATH="#lib/gtest-1.7.0/lib")
+ test_env.Append(CPPPATH="lib/gtest-1.7.0/include")
+ test_env.Append(LIBPATH="lib/gtest-1.7.0")
test_env.Append(LIBS=['gtest'])
- test_env.Append(LIBPATH="#lib/gmock-1.7.0/lib")
+ test_env.Append(CPPPATH="lib/gmock-1.7.0/include")
+ test_env.Append(LIBPATH="lib/gmock-1.7.0")
test_env.Append(LIBS=['gmock'])
- test_env.Append(LIBPATH="#lib/benchmark/lib")
+ test_env.Append(CPPPATH="lib/benchmark/include")
+ test_env.Append(LIBPATH="lib/benchmark")
test_env.Append(LIBS=['benchmark'])
+ test_files = [test_env.StaticObject(filename)
+ if filename !='src/test/main.cpp' else filename
+ for filename in test_files]
+
if build.platform_is_windows:
# For SHGetValueA in Google's benchmark library.
test_env.Append(LIBS=['Shlwapi'])
@@ -138,10 +138,10 @@ def define_test_targets(default=False):
# Currently both executables are built with /subsystem:windows
# and the console is attached manually
test_bin = test_env.Program(
- 'mixxx-test', [test_sources, mixxx_qrc, mixxx_rc],
+ 'mixxx-test', [test_files, mixxx_qrc, mixxx_rc],
LINKCOM = [env['LINKCOM'], 'mt.exe -nologo -manifest ${TARGET}.manifest -outputresource:$TARGET;1'])
else:
- test_bin = test_env.Program('mixxx-test', [test_sources, mixxx_qrc])
+ test_bin = test_env.Program('mixxx-test', [test_files, mixxx_qrc])
if not build.platform_is_windows:
copy_test_bin = Command("../mixxx-test", test_bin, Copy("$TARGET", "$SOURCE"))
@@ -533,16 +533,29 @@ if build.platform_is_windows:
#env.Alias('mixxx', icon)
env.Alias('mixxx', binary)
+ binaries_to_codesign = [binary, dlls, vamp_plugins]
+
# imageformats DLL
if imgfmtdll_files:
imageformats_dll = env.Install(os.path.join(base_dist_dir, "imageformats"), imgfmtdll_files)
+ binaries_to_codesign.append(imageformats_dll)
env.Alias('mixxx', imageformats_dll)
# QSQLite DLL
if sqldll_files:
sql_dlls = env.Install(os.path.join(base_dist_dir, "sqldrivers"), sqldll_files)
+ binaries_to_codesign.append(sql_dlls)
env.Alias('mixxx', sql_dlls)
+ if 'sign' in COMMAND_LINE_TARGETS:
+ codesign_subject_name = SCons.ARGUMENTS.get('windows_codesign_subject_name', '')
+ if not codesign_subject_name:
+ raise Exception('Code-signing was requested but windows_codesign_subject_name was not provided.')
+ codesign = env.SignTool(
+ 'Mixxx_signtool',
+ binaries_to_codesign,
+ SUBJECT_NAME=codesign_subject_name)
+ env.Alias('sign', codesign)
def BuildRelease(target, source, env):
print("==== Mixxx Post-Build Checks ====")
@@ -560,8 +573,8 @@ def BuildRelease(target, source, env):
package_version = construct_version(build, mixxx_version, branch_name,
vcs_revision)
arch = "x64" if build.machine_is_64bit else "x86"
- exe_name = '%s-%s-%s.msi' % (package_name, package_version, arch)
- print(exe_name)
+ msi_name = '%s-%s-%s.msi' % (package_name, package_version, arch)
+ print(msi_name)
print("Top line of README, check version:")
if build.platform_is_windows:
os.system('for /l %l in (1,1,1) do @for /f "tokens=1,2* delims=:" %a in (\'findstr /n /r "^" README ^| findstr /r "^%l:"\') do @echo %b')
@@ -572,6 +585,7 @@ def BuildRelease(target, source, env):
os.system('for /l %l in (1,1,2) do @for /f "tokens=1,2* delims=:" %a in (\'findstr /n /r "^" LICENSE ^| findstr /r "^%l:"\') do @echo %b')
else:
os.system('head -n 2 LICENSE')
+
#if (raw_input("Go ahead and build installer (yes/[no])? ") == "yes"):
if True:
# TODO(XXX): Installing a runtime isn't specific to MSVS?
@@ -715,7 +729,7 @@ def BuildRelease(target, source, env):
command = '"%(wix)s\\light.exe" -cc .\ -nologo -sw1076 -spdb -ext WixUIExtension -cultures:%(deflang)s -loc build\wix\Localization\mixxx_%(deflang)s.wxl -out %(package_name)s build\wix\*.wixobj build\wix\subdirs\*.wixobj' % \
{'wix': wix_path,
'deflang': defaultLanguage,
- 'package_name': 'part.' + exe_name}
+ 'package_name': 'part.' + msi_name}
print("Using Command: " + command)
subprocess.check_call(command)
@@ -764,14 +778,14 @@ def BuildRelease(target, source, env):
command = '"%(wix)s\\torch.exe" -nologo -p -t language %(package_name)s %(lang)s.msi -o %(lang)s.mst' % \
{'wix': wix_path,
'lang': culture,
- 'package_name': 'part.' + exe_name}
+ 'package_name': 'part.' + msi_name}
print("Using Command: " + command)
subprocess.check_call(command)
command = 'cscript "%(winsdk)s\wisubstg.vbs" %(package_name)s %(lang)s.mst %(langid)s' % \
{'winsdk': WinSDK_path,
'lang': culture,
- 'package_name': 'part.' + exe_name,
+ 'package_name': 'part.' + msi_name,
'langid': LCID}
print("Using Command: " + command)
subprocess.check_call(command)
@@ -783,7 +797,7 @@ def BuildRelease(target, source, env):
print("*** Add all supported languages to MSI Package attribute")
command = 'cscript "%(winsdk)s\WiLangId.vbs" %(package_name)s Package %(langid)s' % \
{'winsdk': WinSDK_path,
- 'package_name': 'part.' + exe_name,
+ 'package_name': 'part.' + msi_name,
'langid': langIds}
print("Using Command: " + command)
subprocess.check_call(command)
@@ -794,9 +808,9 @@ def BuildRelease(target, source, env):
bundlelocfile.close()
# Everything is OK, now rename the msi to final name
- if os.path.isfile(exe_name):
- os.remove(exe_name)
- os.rename('part.' + exe_name, exe_name)
+ if os.path.isfile(msi_name):
+ os.remove(msi_name)
+ os.rename('part.' + msi_name, msi_name)
print("*** Compiling Bundle")
# Compile bundle wix file
@@ -804,7 +818,7 @@ def BuildRelease(target, source, env):
{'wix': wix_path,
'winlibpath': build.winlib_path,
'arch': winArch,
- 'package_name': exe_name}
+ 'package_name': msi_name}
print("Using Command: " + command)
subprocess.check_call(command)
# bundle localisation references
@@ -812,17 +826,48 @@ def BuildRelease(target, source, env):
{'wix': wix_path,
'winlibpath': build.winlib_path,
'arch': winArch,
- 'package_name': exe_name}
+ 'package_name': msi_name}
print("Using Command: " + command)
subprocess.check_call(command)
+ exe_name = os.path.splitext(msi_name)[0] + '.exe'
command = '"%(wix)s\\light.exe" -cc .\ -nologo -sw1076 -spdb -ext WixUtilExtension -ext WixBalExtension -dMSIPackage=%(msi_name)s -cultures:%(deflang)s -loc build\wix\Localization\mixxx_%(deflang)s.wxl -out %(package_name)s build\\wix\\bundle\\*.wixobj' % \
{'wix': wix_path,
'deflang': defaultLanguage,
- 'msi_name': exe_name,
- 'package_name': os.path.splitext(exe_name)[0] + '.exe'}
+ 'msi_name': msi_name,
+ 'package_name': exe_name}
print("Using Command: " + command)
subprocess.check_call(command)
+ if 'sign' in COMMAND_LINE_TARGETS:
+ from build.windows import signtool
+ codesign_subject_name = SCons.ARGUMENTS.get('windows_codesign_subject_name', '')
+ if not codesign_subject_name:
+ raise Exception('Code-signing was requested but windows_codesign_subject_name was not provided.')
+
+ print("*** Signing Bundle")
+ # In addition to simply signing the installer executable, we have to
+ # extract and sign the "burn engine". See
+ # http://wixtoolset.org/documentation/manual/v3/overview/insignia.html for details.
+ command = ("%(wix)s\\insignia.exe -ib %(package_name)s -o setup.exe" % {
+ "wix": wix_path,
+ "package_name": exe_name,
+ })
+ print("Using Command: " + command)
+ subprocess.check_call(command)
+
+ # Imperatively sign the file since the whole WiX process is imperative.
+ signtool.signtool_path(codesign_subject_name, 'setup.exe')
+
+ command = ("%(wix)s\\insignia.exe -ab setup.exe %(package_name)s -o %(package_name)s" % {
+ "wix": wix_path,
+ "package_name": exe_name,
+ })
+ print("Using Command: " + command)
+ subprocess.check_call(command)
+
+ # Now sign the final package imperatively.
+ signtool.signtool_path(codesign_subject_name, exe_name)
+
# Some cleaning before leaving
for file in glob.glob('*.cab'):
os.remove(file)
@@ -832,7 +877,7 @@ def BuildRelease(target, source, env):
os.remove(file)
for file in glob.glob('build\wix\subdirs\*.wxs'):
os.remove(file)
- os.remove(exe_name)
+ os.remove(msi_name)
else:
print("Aborted building installer")
@@ -1109,5 +1154,5 @@ versiondebbld = Builder(action = BuildUbuntuPackage) #, suffix = '.foo', src_suf
env.Append(BUILDERS = {'BuildUbuntuPackage' : versiondebbld})
if 'makeubuntu' in COMMAND_LINE_TARGETS:
- makeubuntu = env.BuildUbuntuPackage("blah", "defs_version.h" ) #(binary_files)
+ makeubuntu = env.BuildUbuntuPackage("blah", "src/defs_version.h" ) #(binary_files)
env.Alias('makeubuntu', makeubuntu)
diff --git a/src/SConscript.env b/SConscript.env
index 17ea54e5c8..2ced2f7245 100644
--- a/src/SConscript.env
+++ b/SConscript.env
@@ -9,26 +9,29 @@ import shutil
from build import util, mixxx, depends
+print('SConscript.env cwd: ' + os.getcwd())
Import('build')
# Grab the created environment from the MixxxBuild
env = build.env
-# Check for old build.h file and delete it if it exists
-defs = str(SCons.Script.File('#src/build.h'))
-if os.path.exists(defs):
- print("Deleting deprecated build file: %s" % defs)
- os.remove(defs)
+# We are in the variant_dir (win|mac|lin)XX_build, and the 'src' subdirectory
+# may not exist yet.
+try:
+ os.mkdir('src')
+except:
+ pass
-if os.path.exists(os.path.join('..', 'build.h')):
+# TODO(rryan): This logic should be written in a more SCons-friendly way, since
+# it depends on the cwd being the variant_dir to work properly.
+if os.path.exists('../build.h'):
# If a build.h exists in the project root mixxx/ directory then use that
# instead of writing our own. This is mostly since when we build Debian
- # packages we don't have any of the Bazaar metadata so we can't write one
+ # packages we don't have any of the Git metadata so we can't write one
# ourselves.
- shutil.copy(os.path.join('..', 'build.h'), 'build.h')
+ shutil.copy('../build.h', 'src/build.h')
else:
- util.write_build_header('build.h')
-
+ util.write_build_header('src/build.h')
conf = Configure(env, custom_tests = { 'CheckForPKGConfig' : util.CheckForPKGConfig,
'CheckForPKG' : util.CheckForPKG })
@@ -128,7 +131,7 @@ build_flags = ' '.join(sorted(
[('%s=%s' % (k,v) if v is not None else k) for k,v in build.flags.items() if v is not None]))
### Put flags info into a file
-with open("build.h","a") as f:
+with open("src/build.h", "a") as f:
f.write('#define BUILD_FLAGS "' + build_flags + '"\n')
# Print the build flags. This is useful if the flags have been cached,
diff --git a/SConstruct b/SConstruct
index 7b4e22857e..910ac5d956 100644
--- a/SConstruct
+++ b/SConstruct
@@ -60,7 +60,6 @@ available_features = [features.Mad,
# "Features" of dubious quality
features.PerfTools,
features.AsmLib,
- features.IPod,
features.FFMPEG,
# Experimental features
@@ -74,14 +73,35 @@ Export('build')
# Run our configuration stuff to setup our build environment (detect
# platform/arch, find libraries, etc)
-SConscript(File('src/SConscript.env'), variant_dir=Dir(build.build_dir), duplicate=0)
+
+# If the variant_dir does not exist then we will not chdir into it when calling
+# SConscript.env, making the imperative logic (e.g. writing build.h) in
+# SConscript.env behave differently on the first invocation vs. subsequent
+# invocations.
+try:
+ os.mkdir(build.build_dir)
+except:
+ pass
+SConscript('SConscript.env', variant_dir=build.build_dir, duplicate=0)
# Grab the list of sources generated by SConscript.env
Import('sources')
+# Produce compile_commands.json, which is used by clang-tidy and related tools.
+build.env.Tool("compile_commands")
+build.env.Alias("compiledb", build.env.CompilationDatabase('compile_commands.json'))
+# Build compile_commands.json by default.
+build.env.Default("compile_commands.json")
+
+# Build VAMP plugins.
+mixxxminimal_plugins = SConscript(
+ 'vamp-plugins/SConscript',
+ variant_dir=build.build_dir + "/vamp-plugins",
+ duplicate=0, exports=['build'])
+
# Setup and build the "mixxx" executable target. Also sets up our install
# targets for each platform.
-SConscript(File('src/SConscript'), variant_dir=Dir(build.build_dir), duplicate=0,
+SConscript('SConscript', variant_dir=build.build_dir, duplicate=0,
exports=['build', 'sources'])
#On OS X, if the bundle has been built, copy it up:
diff --git a/build/compile_commands.py b/build/compile_commands.py
new file mode 100644
index 0000000000..161ac6061e
--- /dev/null
+++ b/build/compile_commands.py
@@ -0,0 +1,197 @@
+# Copyright 2015 MongoDB Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import json
+import SCons
+import itertools
+
+# Implements the ability for SCons to emit a compilation database for the MongoDB project. See
+# http://clang.llvm.org/docs/JSONCompilationDatabase.html for details on what a compilation
+# database is, and why you might want one. The only user visible entry point here is
+# 'env.CompilationDatabase'. This method takes an optional 'target' to name the file that
+# should hold the compilation database, otherwise, the file defaults to compile_commands.json,
+# which is the name that most clang tools search for by default.
+
+# TODO: Is there a better way to do this than this global? Right now this exists so that the
+# emitter we add can record all of the things it emits, so that the scanner for the top level
+# compilation database can access the complete list, and also so that the writer has easy
+# access to write all of the files. But it seems clunky. How can the emitter and the scanner
+# communicate more gracefully?
+__COMPILATION_DB_ENTRIES=[]
+
+# Cribbed from Tool/cc.py and Tool/c++.py. It would be better if
+# we could obtain this from SCons.
+_CSuffixes = ['.c']
+if not SCons.Util.case_sensitive_suffixes('.c', '.C'):
+ _CSuffixes.append('.C')
+
+_CXXSuffixes = ['.cpp', '.cc', '.cxx', '.c++', '.C++']
+if SCons.Util.case_sensitive_suffixes('.c', '.C'):
+ _CXXSuffixes.append('.C')
+
+# We make no effort to avoid rebuilding the entries. Someday, perhaps we could and even
+# integrate with the cache, but there doesn't seem to be much call for it.
+class __CompilationDbNode(SCons.Node.Python.Value):
+ def __init__(self, value):
+ SCons.Node.Python.Value.__init__(self, value)
+ self.Decider(changed_since_last_build_node)
+
+
+def changed_since_last_build_node(node, target, prev_ni):
+ """ Dummy decider to force alwasy building"""
+ return True
+
+
+def makeEmitCompilationDbEntry(comstr):
+ """
+ Effectively this creates a lambda function to capture:
+ * command line
+ * source
+ * target
+ :param comstr: unevaluated command line
+ :return: an emitter which has captured the above
+ """
+ user_action = SCons.Action.Action(comstr)
+
+ def EmitCompilationDbEntry(target, source, env):
+ """
+ This emitter will be added to each c/c++ object build to capture the info needed
+ for clang tools
+ :param target: target node(s)
+ :param source: source node(s)
+ :param env: Environment for use building this node