-
-
Notifications
You must be signed in to change notification settings - Fork 341
Description
Describe the bug
The vcxproj file created using MSVSProject fails to build the project with the following error:
1>Traceback (most recent call last):
1> File "<string>", line 1, in <module>
1>ModuleNotFoundError: No module named 'SCons'
1>C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Microsoft\VC\v170\Microsoft.MakeFile.Targets(45,5): error MSB3073: The command "echo Starting SCons && "C:\Users\Marcel\scoop\apps\python\current\python.exe" -c "from os.path import join; import sys; sys.path = [ join(sys.prefix, 'Lib', 'site-packages', 'scons-4.9.1'), join(sys.prefix, 'scons-4.9.1'), join(sys.prefix, 'Lib', 'site-packages', 'scons'), join(sys.prefix, 'scons') ] + sys.path; import SCons.Script; SCons.Script.main()" -C "C:\Users\Marcel\Temp\SCons" -f SConstruct "C:\Users\Marcel\Temp\SCons\hello.exe"" exited with code 1.
1>Done building project "Hello.vcxproj" -- FAILED.
Required information
- Link to SCons Users thread discussing your issue: https://discord.com/channels/571796279483564041/1456022630631997662
- Version of SCons: 4.9.1
- Version of Python: 3.10.1
- Which python distribution if applicable (python.org, cygwin, anaconda, macports, brew,etc): scoop (https://scoop.sh/)
- How you installed SCons: scoop
- What Platform are you on? (Linux/Windows and which version): Windows 11 Home 24H2
- How to reproduce your issue? Please include a small self contained reproducer. Likely a SConstruct should do for most issues.
env = Environment()
sources = ['hello.cpp']
includes = ['hello.h']
program = env.Program(target='hello.exe', source=sources)
env.MSVSProject(
target='Hello' + env['MSVSPROJECTSUFFIX'],
srcs=sources,
incs=includes,
buildtarget=program,
variant='Release',
)
- How you invoke scons (The command line you're using "scons --flags some_arguments"):
scons
I think the problem lies with the way MSVSProject creates the NMake*Commands in the vcxproj file:
<NMakeBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">echo Starting SCons && "C:\Users\Marcel\scoop\apps\python\current\python.exe" -c "from os.path import join; import sys; sys.path = [ join(sys.prefix, 'Lib', 'site-packages', 'scons-4.9.1'), join(sys.prefix, 'scons-4.9.1'), join(sys.prefix, 'Lib', 'site-packages', 'scons'), join(sys.prefix, 'scons') ] + sys.path; import SCons.Script; SCons.Script.main()" -C "C:\Users\Marcel\Temp\SCons" -f SConstruct "C:\Users\Marcel\Temp\SCons\hello.exe"</NMakeBuildCommandLine>
<NMakeReBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">echo Starting SCons && "C:\Users\Marcel\scoop\apps\python\current\python.exe" -c "from os.path import join; import sys; sys.path = [ join(sys.prefix, 'Lib', 'site-packages', 'scons-4.9.1'), join(sys.prefix, 'scons-4.9.1'), join(sys.prefix, 'Lib', 'site-packages', 'scons'), join(sys.prefix, 'scons') ] + sys.path; import SCons.Script; SCons.Script.main()" -C "C:\Users\Marcel\Temp\SCons" -f SConstruct "C:\Users\Marcel\Temp\SCons\hello.exe"</NMakeReBuildCommandLine>
<NMakeCleanCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">echo Starting SCons && "C:\Users\Marcel\scoop\apps\python\current\python.exe" -c "from os.path import join; import sys; sys.path = [ join(sys.prefix, 'Lib', 'site-packages', 'scons-4.9.1'), join(sys.prefix, 'scons-4.9.1'), join(sys.prefix, 'Lib', 'site-packages', 'scons'), join(sys.prefix, 'scons') ] + sys.path; import SCons.Script; SCons.Script.main()" -C "C:\Users\Marcel\Temp\SCons" -f SConstruct -c "C:\Users\Marcel\Temp\SCons\hello.exe"</NMakeCleanCommandLine>
It appears to be a roundabout way of launching SCons: It launches python with -c and string for the following python script:
from os.path import join
import sys
sys.path = [
join(sys.prefix, 'Lib', 'site-packages', 'scons-4.9.1'),
join(sys.prefix, 'scons-4.9.1'),
join(sys.prefix, 'Lib', 'site-packages', 'scons'),
join(sys.prefix, 'scons')
] + sys.path;
import SCons.Script
SCons.Script.main()
If the script can't find the scons module in the modified sys.path it fails.
However, scons must (or at least should) be in the user's path; otherwise we wouldn't be able to run the SConstruct that is used to create the vcxproj file.
It works when I replace the
"C:\Users\Marcel\scoop\apps\python\current\python.exe" -c "from os.path import join; import sys; sys.path = [ join(sys.prefix, 'Lib', 'site-packages', 'scons-4.9.1'), join(sys.prefix, 'scons-4.9.1'), join(sys.prefix, 'Lib', 'site-packages', 'scons'), join(sys.prefix, 'scons') ] + sys.path; import SCons.Script; SCons.Script.main()"
with scons:
<NMakeBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">echo Starting SCons && scons -C "C:\Users\Marcel\Temp\SCons" -f SConstruct "C:\Users\Marcel\Temp\SCons\hello.exe"</NMakeBuildCommandLine>
<NMakeReBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">echo Starting SCons && scons -C "C:\Users\Marcel\Temp\SCons" -f SConstruct "C:\Users\Marcel\Temp\SCons\hello.exe"</NMakeReBuildCommandLine>
<NMakeCleanCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">echo Starting SCons && scons -C "C:\Users\Marcel\Temp\SCons" -f SConstruct -c "C:\Users\Marcel\Temp\SCons\hello.exe"</NMakeCleanCommandLine>
To get MSVSProject to create a working vcxproj file, I added the following line to the SConstruct file:
env["MSVSSCONS"] = "scons"
The updated SConstruct file:
env = Environment()
env["MSVSSCONS"] = "scons"
sources = ['hello.cpp']
includes = ['hello.h']
program = env.Program(target='hello.exe', source=sources)
env.MSVSProject(
target='Hello' + env['MSVSPROJECTSUFFIX'],
srcs=sources,
incs=includes,
buildtarget=program,
variant='Release',
)
Within SCons, the default value for MSVSSCONS is set here:
Lines 2145 to 2151 in f544c99
| # Allow consumers to provide their own versions of MSVSSCONS and | |
| # MSVSSCONSFLAGS. This helps support consumers who use wrapper scripts to | |
| # invoke scons. | |
| if 'MSVSSCONS' not in env: | |
| env['MSVSSCONS'] = '"%s" -c "%s"' % (python_executable, getExecScriptMain(env)) | |
| if 'MSVSSCONSFLAGS' not in env: | |
| env['MSVSSCONSFLAGS'] = '-C "${MSVSSCONSCRIPT.dir.get_abspath()}" -f ${MSVSSCONSCRIPT.name}' |
and it gets the values used from here:
Lines 162 to 187 in f544c99
| def getExecScriptMain(env, xml=None): | |
| if 'SCONS_HOME' not in env: | |
| env['SCONS_HOME'] = os.environ.get('SCONS_HOME') | |
| scons_home = env.get('SCONS_HOME') | |
| if not scons_home and 'SCONS_LIB_DIR' in os.environ: | |
| scons_home = os.environ['SCONS_LIB_DIR'] | |
| if scons_home: | |
| exec_script_main = "from os.path import join; import sys; sys.path = [ r'%s' ] + sys.path; import SCons.Script; SCons.Script.main()" % scons_home | |
| else: | |
| version = SCons.__version__ | |
| exec_script_main = "from os.path import join; import sys; sys.path = [ join(sys.prefix, 'Lib', 'site-packages', 'scons-%(version)s'), join(sys.prefix, 'scons-%(version)s'), join(sys.prefix, 'Lib', 'site-packages', 'scons'), join(sys.prefix, 'scons') ] + sys.path; import SCons.Script; SCons.Script.main()" % locals() | |
| if xml: | |
| exec_script_main = xmlify(exec_script_main) | |
| return exec_script_main | |
| # The string for the Python executable we tell the Project file to use | |
| # is either sys.executable or, if an external PYTHON_ROOT environment | |
| # variable exists, $(PYTHON)ROOT\\python.exe (generalized a little to | |
| # pluck the actual executable name from sys.executable). | |
| try: | |
| python_root = os.environ['PYTHON_ROOT'] | |
| except KeyError: | |
| python_executable = sys.executable | |
| else: | |
| python_executable = os.path.join('$$(PYTHON_ROOT)', | |
| os.path.split(sys.executable)[1]) |