-
-
Notifications
You must be signed in to change notification settings - Fork 342
MSVS: update generation of the vcxproj embedded python script #4818
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
Changes:
* Replace the existing two code paths that generate the msvs tool vcxproj file with a single code path that generates the one-line python script string compatible with all cases. Prior to this change, the default test runs would not test the alternate path as SCONS_LIB_DIR is set in the test os environment.
* The msvs test case SCons version string was changed from `self.scons_version` to `SCons.__version__`. Depending on the tests run, the test framework version may not match the SCons library version being tested (e.g., retaining packaging version). The test now matches what the msvs tool uses.
* Modify the embedded vcxproj script and generated python executable string for consistency with each other with respect to SCons env and os.environ usage.
* Modify the embedded vcxproj script to retrieve SCONS_HOME and SCONS_LIB_DIR from the environment if needed.
* Priority order for msvs tool SCons library specification:
1. env['SCONS_HOME'] literal path when generated if True
2. os.environ.get('SCONS_HOME', <os.environ['SCONS_HOME'] path when generated>) if True
3. os.environ.get('SCONS_LIB_DIR', <os.environ['SCONS_LIB_DIR'] path when generated>) if True
4. <SCons parent when generated> if exists and is valid SCons library
5. first in list of generated locations that exists and is valid SCons library
* Modify generation of python executable path order:
1. env['PYTHON_ROOT'] literal path if True
2. $(PYTHON_ROOT) if os.environ['PYTHON_ROOT'] is True
3. sys.executable literal path
* Add bare asterisk after second argument in msvs_substitute function in testing/framework/TestSConsMSVS.py requiring keyword argument specifications for all optional arguments. The first two arguments are by position the remaining seven arguments must be keyword specified.
|
One (hopefully unrelated) AppVeyor test failed: Image: Visual Studio 2022; Environment: WINPYTHON=Python313: |
since it only failed on one of the four appveyor runs, it seems likely to be unrelated. Let's keep an eye on it. |
|
Did you miss #4817 ? ;) |
No. |
|
So if I understand the impact of your changes, rather than fix the location of SCons when generating the project file, you've changed the logic so it can be impacted by user's shell env variables when run via msvs which could be different than when the project file was generated? |
Your understanding is correct. In a nutshell, the generated vcxproj SCons library location logic is equivalent to that of the msvs tool. Background:
This PR attempts to achieve:
Here's an example used during testing (the diff format is used to show the source of the library path definition):
If one wants to ALWAYS generate a path that is used, the easiest way is to define import os.path
import SCons
env = Environment(
SCONS_HOME=os.path.abspath(os.path.join(os.path.dirname(SCons.__file__), "..")),
)
sources = ['hello.cpp']
program = env.Program(
target='hello.exe',
source=sources,
CPPFLAGS=['/EHsc'],
)
env.MSVSProject(
target='Hello' + env['MSVSPROJECTSUFFIX'],
srcs=sources,
buildtarget=program,
variant='Release',
)The proposed PR is more adaptive than it was before and there is only "one" generated script instead of two. Is it foolproof? No. Even if this PR is not accepted, there are plenty of reasons to adapt this PR to the equivalent code in #4817 (i.e., unify both code generation paths in a single script). I hope that answers the question and provides some background and rationale.
|
|
@jcbrill they only take a long time when there as thorough as you usually are! :) A few thoughts/notes:
|
Changes: * Change SCons/Tool/msvs.py function comment before getExecScriptMain and replace with docstring. Taken from PR SCons#4817. * Revert python executable code * Generate scons_home (user env, SCONS_HOME, or SCONS_LIB_DIR path specification) and scons_path (currently executing SCons module path) paths in unified script in SCons/Tool/msvs.py and testing/framework/TestSConsMSVS.py. Similar to the two code paths in PR SCons#4817. * Set the SCONS_HOME variable in the testenv as is done with SCONS_LIB_DIR. Add SCONS_HOME to testing/framework/TestSConsMSVS.py.
|
@bdbaddog The latest commit should be functionally equivalent to #4817. I need to do some more local testing. There was an earlier version of the generated script that detected when the generated SCons path would not be used and printed warnings: While it "appears" to work, the VS output console looked a little odd. It may have been interpreting the print statement as a command. I can't be sure. It was simple enough to force both warnings to be printed. I'm not wild about an SCons being picked up which is not the SCons at the generated path without some kind of feedback to the user. |
Changes: * Add check that the generated path contains SCons. * Add the generated path to the python system path only when it contains SCons. * Print an alert message when the generated path does not contain SCons. * Print an alert message when the generated path does not contain SCons and SCons was found on python system path.
|
It appears that printing a message with the word "warning" from the embedded python script triggers different behavior. |
runtest.py
Outdated
| # Because SCons is really aggressive about finding its modules, | ||
| # it sometimes finds SCons modules elsewhere on the system. | ||
| # This forces SCons to use the modules that are being tested. | ||
| testenv['SCONS_HOME'] = scons_lib_dir |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why add this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prior to this PR (i.e., current master):
- If
SCONS_HOMEis set in the environment when the test is run, it has to match theSCONS_LIB_DIRstring exactly. - In msvs.py,
SCONS_HOMEis used beforeSCONS_LIB_DIR. - In TestSConsMSVS.py, only
SCONS_LIB_DIRis used. SCONS_LIB_DIRis added to the testenv.SCONS_HOMEis not added to the testenv.
When forcing SCONS_LIB_DIR into the testenv, SCONS_HOME should be populated since it's used in the source code but not in the test suite.
SCONS_HOME was added to TestSConsMSVS.py for consistency with the source code.
Note: I'm testing significantly revised versions of msvs.py and TestSConsMSVS.py which I intend to push later today or in the morning tomorrow pending testing insights.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I say that probably neither should be set by runtest.py anymore SCONS_LIB_DIR was ancient and needed prior to re-org-ing the code and the packaging.
Since it's unlikely than any user would have either set, we should be testing without them..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With regards to the current code, I believe that might require a user to set SCONS_HOME or SCONS_LIB_DIR in their environment when running the test suite with a source distribution.
For example, testing an SCons source branch with a python that does not have SCons installed. If there are any tests that actually run devenv against the generated project files would have a problem.
The scoop issue reported is effectively the same problem. A standalone SCons distribution as opposed to SCons installed as a library. SCONS_HOME is the solution with current master.
I thought at one point in time, we had to set SCONS_HOME before running the test suite but I could be wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just commented out setting SCONS_LIB_DIR and SCONS_HOME from elif clause here and tests ran fine, with and without setting --baseline to another dir and with and without installing scons in the activated virtualenv.
diff --git a/runtest.py b/runtest.py
index ee264ecac..7cd4e9127 100755
--- a/runtest.py
+++ b/runtest.py
@@ -537,11 +537,12 @@ if scons:
# its own modules.
testenv['SCONS'] = scons
elif scons_lib_dir:
+ pass
# Because SCons is really aggressive about finding its modules,
# it sometimes finds SCons modules elsewhere on the system.
# This forces SCons to use the modules that are being tested.
- testenv['SCONS_HOME'] = scons_lib_dir
- testenv['SCONS_LIB_DIR'] = scons_lib_dir
+ # testenv['SCONS_HOME'] = scons_lib_dir
+ # testenv['SCONS_LIB_DIR'] = scons_lib_dir
if args.scons_exec:
testenv['SCONS_EXEC'] = '1'```
This used to be important, but hasn't been for a while as far as I'm aware.
Changes:
* Suppress generating the currently executing SCons module path if SCons appears to be installed as a python library (i.e., in the python installation tree).
* Modify the candidate evaluation priority similar to the current master code and add a new code path when using an out-of-python-tree SCons installation.
* The modified evaluation order is:
1. If scons_home is defined:
* Record scons_home as found iff the path contains SCons.
* Stop evaluating remaining alternatives.
2. If scons_abspath is defined:
* Record scons_abspath as found iff the path contains SCons.
* Stop evaluating remaining alternatives.
3. Evaluate known library locations:
* Record the first library path that contains SCons as found.
* Use importlib to find the SCons module path prior to import.
* Add a valid module spec origin path to the front of the sys.path list if:
* a module path was not found earlier, or
* the module spec origin path is different than the module path found earlier.
* Refine diagnostic messaging.
|
The latest commit was modified to be more like the existing code but is subtly different. I need to write-up some of the findings, behaviors, and differences. Hopefully sooner rather than later. The attached file below contains three versions of the All three versions emit diagnostic messages in the Visual Studio build window before SCons is imported and launched from the embedded script. Obviously, each file would need to be renamed to The attached file scons-4809-testfiles.zip contains the following files:
One of the "issues" issues with the current embedded script is that it is somewhat difficult to know which SCons installation is being launched. The SCons installation being launched may not be the installation expected. P.S.: The |
| if _exec_script_main_template is None: | ||
| _exec_script_main_template = "; ".join(textwrap.dedent( | ||
| """\ | ||
| import importlib.util |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
realistically I think we can just do python <path to current scons.py> where python is the python the scons being run was using.
All the rest of this like likely no longer needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that the SCons module path should only be generated for non-library installations of SCons.
Keep in mind that the generated python path can be deferred until execution of the vcxproj file by Visual Studio. As shown below, it is possible to have one python version executable importing SCons from another python version library site package location. That just seems like a bad idea.
See comment #4818 (comment) below.
|
Development insights. SCons MAN Page (emphasis added):
|
|
@mwichmann Another Windows permission error with a different test this time...
That looks to be the msvc cache file attempting to be removed. |
|
scons.py already handles a lot of the concerns we're replicating in the generated python code inserted into the ms project file. Seems like just using scons.py will always be more correct. (and easier to maintain if additional changes in finding paths are added there). All scoop does is run the scons.py which is in an extracted scons-local package. (For which scons.py knows how to set up the python path to run). (I tested scoop installed scons with updates from my pr) Also note that some of the text in MSProject() manpage is really outdated and predates our current version of scons.py (and should have been updated at that time). Previously there was scons.sh and scons.bat which set up SCONS_LIB_DIR and then ran scons.py which used that to find the path. None of that is needed anymore (and hasn't been for a while). While I think I understand your concerns in the context of what's in the manpage, and existing shell and env variables to affect this, realistically all of it should have been refactored, deprecated, and removed by now.. I don't think deferring evaluation of scons location etc until run by msvs is actually a good thing. This would allow the shell environment to impact scons's invocation in ways which violate scons' non-shell-env impact rules. (of course there are a few exceptions to this, but deferring such would allow shell env to have impacts other than the documented shell env vars). In my competing PR #4817 I'm only referencing PYTHON_ROOT and MSVS_SCONS (variable renamed as it only impacts MSVS project generation. Dropping usage of SCONS_LIB_DIR, SCONS_HOME. |
Changes:
* Revert setting SCONS_HOME in the testenv in runtest.py.
* Simplify the generated embedded python script.
* Simplified evaluation order:
1. If scons_home is defined:
* If SCons is not found using scons_home, display an error message and exit the embedded python script
2. If scons_abspath is defined:
* If SCons is not found using scons_abspath, display an error message and exit the embedded python script
3. Evaluate local library locations plus the python system path:
* If SCons is not found using the extended python system path, display an error message and exit the embedded python script
4. Add the found SCons path to the front of the python system path
5. Display the SCons path
6. Import and run SCons/Tool/msvs.py
|
Failed checks:
|
Alternative fix for #4809 for discussion purposes.
Caution
This description no longer accurately reflects the latest commit.
An updated description is planned.
Fixes some issues with the msvs tests.
Changes:
self.scons_versiontoSCons.__version__. Depending on the tests run, the test framework version may not match the SCons library version being tested (e.g., retaining packaging version). The test now matches what the msvs tool uses.Locally, passes msvc/msvs tests for all supported versions of VS using python 3.9. Passes scoop tests with SCons installed as an application and SCons installed via python.
Contributor Checklist:
CHANGES.txtandRELEASE.txt(and read theREADME.rst).