From 97bfc7e23fe60ddfc5846c7fc2c823f2f5b9d7d8 Mon Sep 17 00:00:00 2001 From: Alex Burton Date: Thu, 11 May 2023 22:10:34 +1000 Subject: Added support for use of .di files, and added tests for three compilers. --- SCons/Tool/DCommon.py | 28 ++++++++++++- SCons/Tool/dmd.py | 14 +++++-- SCons/Tool/gdc.py | 18 +++++--- SCons/Tool/ldc.py | 14 +++++-- test/D/di/Common/__init__.py | 0 test/D/di/Common/common.py | 84 +++++++++++++++++++++++++++++++++++++ test/D/di/Image/SConstruct_template | 15 +++++++ test/D/di/Image/helloWorldMain.d | 6 +++ test/D/di/Image/source/helloWorld.d | 5 +++ test/D/di/sconstest-dmd.py | 37 ++++++++++++++++ test/D/di/sconstest-gdc.py | 37 ++++++++++++++++ test/D/di/sconstest-ldc.py | 37 ++++++++++++++++ 12 files changed, 280 insertions(+), 15 deletions(-) create mode 100644 test/D/di/Common/__init__.py create mode 100644 test/D/di/Common/common.py create mode 100644 test/D/di/Image/SConstruct_template create mode 100644 test/D/di/Image/helloWorldMain.d create mode 100644 test/D/di/Image/source/helloWorld.d create mode 100644 test/D/di/sconstest-dmd.py create mode 100644 test/D/di/sconstest-gdc.py create mode 100644 test/D/di/sconstest-ldc.py diff --git a/SCons/Tool/DCommon.py b/SCons/Tool/DCommon.py index a4f976d..64d1cbc 100644 --- a/SCons/Tool/DCommon.py +++ b/SCons/Tool/DCommon.py @@ -30,7 +30,7 @@ Coded by Russel Winder (russel@winder.org.uk) """ import os.path - +import SCons.Defaults def isD(env, source) -> int: if not source: @@ -57,6 +57,32 @@ def allAtOnceEmitter(target, source, env): env.Clean(target[0], str(target[0]) + '.o') return target, source +def _optWithIxes(pre,x,suf,env,f=lambda x: x, target=None, source=None): +# a single optional argument version of _concat +# print ("_optWithIxes",str(target),str(source)) + if x in env: + l = f(SCons.PathList.PathList([env[x]]).subst_path(env, target, source)) + return pre + str(l[0]) + suf + else: + return "" + +def DObjectEmitter(target,source,env): + if "DINTFDIR" in env: + if (len(target) != 1): + raise Exception("expect only one object target") + targetBase, targetName = os.path.split(SCons.Util.to_String(target[0])) + extraTarget = os.path.join(targetBase,str(env["DINTFDIR"]),targetName[:-len(env["OBJSUFFIX"])] + env["DIFILESUFFIX"]) + target.append(extraTarget) + return (target,source) + +def DStaticObjectEmitter(target,source,env): + target,source = SCons.Defaults.StaticObjectEmitter(target,source,env) + return DObjectEmitter(target,source,env) + +def DSharedObjectEmitter(target,source,env): + target,source = SCons.Defaults.SharedObjectEmitter(target,source,env) + return DObjectEmitter(target,source,env) + # Local Variables: # tab-width:4 # indent-tabs-mode:nil diff --git a/SCons/Tool/dmd.py b/SCons/Tool/dmd.py index 7b2a249..9755c90 100644 --- a/SCons/Tool/dmd.py +++ b/SCons/Tool/dmd.py @@ -87,18 +87,20 @@ def generate(env) -> None: static_obj.add_action('.d', SCons.Defaults.DAction) shared_obj.add_action('.d', SCons.Defaults.ShDAction) - static_obj.add_emitter('.d', SCons.Defaults.StaticObjectEmitter) - shared_obj.add_emitter('.d', SCons.Defaults.SharedObjectEmitter) + static_obj.add_emitter('.d', DCommon.DStaticObjectEmitter) + shared_obj.add_emitter('.d', DCommon.DSharedObjectEmitter) env['DC'] = env.Detect(['dmd', 'ldmd2', 'gdmd']) or 'dmd' - env['DCOM'] = '$DC $_DINCFLAGS $_DVERFLAGS $_DDEBUGFLAGS $_DFLAGS -c -of$TARGET $SOURCES' + env['DCOM'] = '$DC $_DINCFLAGS $_DVERFLAGS $_DDEBUGFLAGS $_DFLAGS $_DINTFDIR -c -of$TARGET $SOURCES' env['_DINCFLAGS'] = '${_concat(DINCPREFIX, DPATH, DINCSUFFIX, __env__, RDirs, TARGET, SOURCE)}' env['_DVERFLAGS'] = '${_concat(DVERPREFIX, DVERSIONS, DVERSUFFIX, __env__)}' env['_DDEBUGFLAGS'] = '${_concat(DDEBUGPREFIX, DDEBUG, DDEBUGSUFFIX, __env__)}' + env['_DINTFDIR'] = '${_optWithIxes(DINTFDIRPREFIX, DINTFDIRKEY, DINTFDIRSUFFIX, __env__, Dirs, TARGET, SOURCE)}' + env['_optWithIxes'] = DCommon._optWithIxes env['_DFLAGS'] = '${_concat(DFLAGPREFIX, DFLAGS, DFLAGSUFFIX, __env__)}' env['SHDC'] = '$DC' - env['SHDCOM'] = '$DC $_DINCFLAGS $_DVERFLAGS $_DDEBUGFLAGS $_DFLAGS -c -fPIC -of$TARGET $SOURCES' + env['SHDCOM'] = '$DC $_DINCFLAGS $_DVERFLAGS $_DDEBUGFLAGS $_DFLAGS $_DINTFDIR -c -fPIC -of$TARGET $SOURCES' env['DPATH'] = ['#/'] env['DFLAGS'] = [] @@ -117,6 +119,10 @@ def generate(env) -> None: env['DFLAGPREFIX'] = '-' env['DFLAGSUFFIX'] = '' env['DFILESUFFIX'] = '.d' + env['DIFILESUFFIX'] = '.di' + env['DINTFDIRKEY'] = 'DINTFDIR' + env['DINTFDIRPREFIX'] = '-Hd=' + env['DINTFDIRSUFFIX'] = '' env['DLINK'] = '$DC' env['DLINKFLAGS'] = SCons.Util.CLVar('') diff --git a/SCons/Tool/gdc.py b/SCons/Tool/gdc.py index c77e27a..6b34558 100644 --- a/SCons/Tool/gdc.py +++ b/SCons/Tool/gdc.py @@ -59,18 +59,20 @@ def generate(env) -> None: static_obj.add_action('.d', SCons.Defaults.DAction) shared_obj.add_action('.d', SCons.Defaults.ShDAction) - static_obj.add_emitter('.d', SCons.Defaults.StaticObjectEmitter) - shared_obj.add_emitter('.d', SCons.Defaults.SharedObjectEmitter) + static_obj.add_emitter('.d', DCommon.DStaticObjectEmitter) + shared_obj.add_emitter('.d', DCommon.DSharedObjectEmitter) env['DC'] = env.Detect('gdc') or 'gdc' - env['DCOM'] = '$DC $_DINCFLAGS $_DVERFLAGS $_DDEBUGFLAGS $_DFLAGS -c -o $TARGET $SOURCES' + env['DCOM'] = '$DC $_DINCFLAGS $_DVERFLAGS $_DDEBUGFLAGS $_DFLAGS $_DINTFDIR -c -o $TARGET $SOURCES' env['_DINCFLAGS'] = '${_concat(DINCPREFIX, DPATH, DINCSUFFIX, __env__, RDirs, TARGET, SOURCE)}' env['_DVERFLAGS'] = '${_concat(DVERPREFIX, DVERSIONS, DVERSUFFIX, __env__)}' env['_DDEBUGFLAGS'] = '${_concat(DDEBUGPREFIX, DDEBUG, DDEBUGSUFFIX, __env__)}' + env['_DINTFDIR'] = '${_optWithIxes(DINTFDIRPREFIX, DINTFDIRKEY, DINTFDIRSUFFIX, __env__, Dirs, TARGET, SOURCE)}' + env['_optWithIxes'] = DCommon._optWithIxes env['_DFLAGS'] = '${_concat(DFLAGPREFIX, DFLAGS, DFLAGSUFFIX, __env__)}' env['SHDC'] = '$DC' - env['SHDCOM'] = '$SHDC $_DINCFLAGS $_DVERFLAGS $_DDEBUGFLAGS $_DFLAGS -fPIC -c -o $TARGET $SOURCES' + env['SHDCOM'] = '$SHDC $_DINCFLAGS $_DVERFLAGS $_DDEBUGFLAGS $_DFLAGS $_DINTFDIR -fPIC -c -o $TARGET $SOURCES' env['DPATH'] = ['#/'] env['DFLAGS'] = [] @@ -82,13 +84,17 @@ def generate(env) -> None: env['DINCPREFIX'] = '-I' env['DINCSUFFIX'] = '' - env['DVERPREFIX'] = '-version=' + env['DVERPREFIX'] = '-fversion=' env['DVERSUFFIX'] = '' - env['DDEBUGPREFIX'] = '-debug=' + env['DDEBUGPREFIX'] = '-fdebug=' env['DDEBUGSUFFIX'] = '' env['DFLAGPREFIX'] = '-' env['DFLAGSUFFIX'] = '' env['DFILESUFFIX'] = '.d' + env['DIFILESUFFIX'] = '.di' + env['DINTFDIRKEY'] = 'DINTFDIR' + env['DINTFDIRPREFIX'] = '-Hd' + env['DINTFDIRSUFFIX'] = '' env['DLINK'] = '$DC' env['DLINKFLAGS'] = SCons.Util.CLVar('') diff --git a/SCons/Tool/ldc.py b/SCons/Tool/ldc.py index 7583853..a86d1b6 100644 --- a/SCons/Tool/ldc.py +++ b/SCons/Tool/ldc.py @@ -63,18 +63,20 @@ def generate(env) -> None: static_obj.add_action('.d', SCons.Defaults.DAction) shared_obj.add_action('.d', SCons.Defaults.ShDAction) - static_obj.add_emitter('.d', SCons.Defaults.StaticObjectEmitter) - shared_obj.add_emitter('.d', SCons.Defaults.SharedObjectEmitter) + static_obj.add_emitter('.d', DCommon.DStaticObjectEmitter) + shared_obj.add_emitter('.d', DCommon.DSharedObjectEmitter) env['DC'] = env.Detect('ldc2') or 'ldc2' - env['DCOM'] = '$DC $_DINCFLAGS $_DVERFLAGS $_DDEBUGFLAGS $_DFLAGS -c -of=$TARGET $SOURCES' + env['DCOM'] = '$DC $_DINCFLAGS $_DVERFLAGS $_DDEBUGFLAGS $_DFLAGS $_DINTFDIR -c -of=$TARGET $SOURCES' env['_DINCFLAGS'] = '${_concat(DINCPREFIX, DPATH, DINCSUFFIX, __env__, RDirs, TARGET, SOURCE)}' env['_DVERFLAGS'] = '${_concat(DVERPREFIX, DVERSIONS, DVERSUFFIX, __env__)}' env['_DDEBUGFLAGS'] = '${_concat(DDEBUGPREFIX, DDEBUG, DDEBUGSUFFIX, __env__)}' + env['_DINTFDIR'] = '${_optWithIxes(DINTFDIRPREFIX, DINTFDIRKEY, DINTFDIRSUFFIX, __env__, Dirs, TARGET, SOURCE)}' + env['_optWithIxes'] = DCommon._optWithIxes env['_DFLAGS'] = '${_concat(DFLAGPREFIX, DFLAGS, DFLAGSUFFIX, __env__)}' env['SHDC'] = '$DC' - env['SHDCOM'] = '$DC $_DINCFLAGS $_DVERFLAGS $_DDEBUGFLAGS $_DFLAGS -c -relocation-model=pic -of=$TARGET $SOURCES' + env['SHDCOM'] = '$DC $_DINCFLAGS $_DVERFLAGS $_DDEBUGFLAGS $_DFLAGS $_DINTFDIR -c -relocation-model=pic -of=$TARGET $SOURCES' env['DPATH'] = ['#/'] env['DFLAGS'] = [] @@ -93,6 +95,10 @@ def generate(env) -> None: env['DFLAGPREFIX'] = '-' env['DFLAGSUFFIX'] = '' env['DFILESUFFIX'] = '.d' + env['DIFILESUFFIX'] = '.di' + env['DINTFDIRKEY'] = 'DINTFDIR' + env['DINTFDIRPREFIX'] = '-Hd=' + env['DINTFDIRSUFFIX'] = '' env['DLINK'] = '$DC' env['DLINKFLAGS'] = SCons.Util.CLVar('') diff --git a/test/D/di/Common/__init__.py b/test/D/di/Common/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/D/di/Common/common.py b/test/D/di/Common/common.py new file mode 100644 index 0000000..a8c844e --- /dev/null +++ b/test/D/di/Common/common.py @@ -0,0 +1,84 @@ +""" +Support functions for all the tests. +""" + +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import TestSCons + +from os.path import abspath, dirname + +import sys +sys.path.insert(1, abspath(dirname(__file__) + '/../../Support')) + +from executablesSearch import isExecutableOfToolAvailable + +def testForTool(tool): + + test = TestSCons.TestSCons() + + if not isExecutableOfToolAvailable(test, tool) : + test.skip_test("Required executable for tool '{0}' not found, skipping test.\n".format(tool)) + + test.dir_fixture('Image') + with open('SConstruct_template', 'r') as f: + config = f.read().format(tool) + test.write('SConstruct', config) + + test.run(options="--debug=explain") + + test.must_exist('source/helloWorld.o') + test.must_exist('helloWorldMain.o') + test.must_exist('include/helloWorld.di') + test.must_exist('hw') + + test.run(program=test.workpath('hw'+TestSCons._exe)) + test.fail_test(test.stdout() != 'Hello World.\n') + + #add a comment and test that this doesn't result in a complete rebuild of all the files that include helloWorld.d because the comment doesn't change helloWorld.di + test.write("source/helloWorld.d",'''import std.stdio; +void go() +{ + //comment + writeln("Hello World."); +}''') + + test.not_up_to_date("source/helloWorld.o") + test.up_to_date("helloWorldMain.o hw") + + test.run("-c") + + test.must_not_exist('source/helloWorld.o') + test.must_not_exist('helloWorldMain.o') + test.must_not_exist('include/helloWorld.di') + test.must_not_exist('hw') + + test.pass_test() +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/D/di/Image/SConstruct_template b/test/D/di/Image/SConstruct_template new file mode 100644 index 0000000..478b39e --- /dev/null +++ b/test/D/di/Image/SConstruct_template @@ -0,0 +1,15 @@ +# -*- mode:python; coding:utf-8; -*- + +import os +import SCons.Node + +environment = Environment( + tools=['link','ar' ,'{}'] +) + +environment.Decider("content") + +o1 = environment.Object('source/helloWorld.d',DINTFDIR = "../include")[0] +o2 = environment.Object('helloWorldMain.d',DPATH="include") + +environment.Program('hw', [o2,o1]) diff --git a/test/D/di/Image/helloWorldMain.d b/test/D/di/Image/helloWorldMain.d new file mode 100644 index 0000000..419205d --- /dev/null +++ b/test/D/di/Image/helloWorldMain.d @@ -0,0 +1,6 @@ +import helloWorld; + +void main() +{ + go(); +} diff --git a/test/D/di/Image/source/helloWorld.d b/test/D/di/Image/source/helloWorld.d new file mode 100644 index 0000000..9912ec0 --- /dev/null +++ b/test/D/di/Image/source/helloWorld.d @@ -0,0 +1,5 @@ +import std.stdio; +void go() +{ + writeln("Hello World."); +} diff --git a/test/D/di/sconstest-dmd.py b/test/D/di/sconstest-dmd.py new file mode 100644 index 0000000..df6ddeb --- /dev/null +++ b/test/D/di/sconstest-dmd.py @@ -0,0 +1,37 @@ +""" +Test compiling and executing using the dmd tool. +""" + +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +from Common.common import testForTool +testForTool('dmd') + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/D/di/sconstest-gdc.py b/test/D/di/sconstest-gdc.py new file mode 100644 index 0000000..43bb8eb --- /dev/null +++ b/test/D/di/sconstest-gdc.py @@ -0,0 +1,37 @@ +""" +Test compiling and executing using the gcd tool. +""" + +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +from Common.common import testForTool +testForTool('gdc') + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/D/di/sconstest-ldc.py b/test/D/di/sconstest-ldc.py new file mode 100644 index 0000000..f61efbc --- /dev/null +++ b/test/D/di/sconstest-ldc.py @@ -0,0 +1,37 @@ +""" +Test compiling and executing using the ldc tool. +""" + +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +from Common.common import testForTool +testForTool('ldc') + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: -- cgit v0.12