Skip to content

CMake: Create grass.bat and add scripts to PATH - #6383

Open
HuidaeCho wants to merge 9 commits into
OSGeo:mainfrom
HuidaeCho:cmake_win
Open

HuidaeCho wants to merge 9 commits into
OSGeo:mainfrom
HuidaeCho:cmake_win

Conversation

@HuidaeCho

Copy link
Copy Markdown
Member

This PR

  • renames grass.py to grass<VERSION>.py to avoid
Traceback (most recent call last):
  File "C:\Users\hcho\usr\grass\grass\build\output\bin\grass.py", line 2473, in <module>
    main()
    ~~~~^^
  File "C:\Users\hcho\usr\grass\grass\build\output\bin\grass.py", line 2120, in main
    from grass.app.runtime import RuntimePaths
ModuleNotFoundError: No module named 'grass.app'; 'grass' is not a package
  • generates grass.bat from lib/init/grass.bat.in, and
  • adds scripts to PATH for batch files.

@github-actions github-actions Bot added Python Related code is in Python libraries CMake labels Sep 20, 2025
@nilason

nilason commented Sep 22, 2025

Copy link
Copy Markdown
Contributor

Would prepending GRASS_PYDIR to sys.path:

sys.path.append(GRASS_PYDIR)

be an alternative to versioning the file name?

@wenzeslaus

Copy link
Copy Markdown
Member

Hm, regardless, we should prepend. I'll adjust my PR.

We could also import in more low level way to avoid the version.

@HuidaeCho

Copy link
Copy Markdown
Member Author

Would prepending GRASS_PYDIR to sys.path:

sys.path.append(GRASS_PYDIR)

be an alternative to versioning the file name?

No, it doesn't work. Still trying to self-import because the main script name is the same as the package name.

@HuidaeCho

HuidaeCho commented Sep 23, 2025 •

Copy link
Copy Markdown
Member Author

It's OK on UN*X because the main script is grass with a shebang (not supported on Windows). If you rename grass to grass.py even on UN*X, you'll see this same issue.

@nilason

nilason commented Sep 23, 2025

Copy link
Copy Markdown
Contributor

Would prepending GRASS_PYDIR to sys.path:

sys.path.append(GRASS_PYDIR)

be an alternative to versioning the file name?

No, it doesn't work. Still trying to self-import because the main script name is the same as the package name.

Oh, too bad. Not sure what to do, it is not ideal to re-add the version to the main executive.

@HuidaeCho

HuidaeCho commented Sep 23, 2025 •

Copy link
Copy Markdown
Member Author

Would prepending GRASS_PYDIR to sys.path:

sys.path.append(GRASS_PYDIR)

be an alternative to versioning the file name?

No, it doesn't work. Still trying to self-import because the main script name is the same as the package name.

Oh, too bad. Not sure what to do, it is not ideal to re-add the version to the main executive.

This PR doesn't change anything for UN*X. grass is still the main executable on UN*X, but grass.bat is the main executable on Windows because we cannot directly run grass (renamed from grass.py) with no shebang support.

@nilason

nilason commented Sep 23, 2025

Copy link
Copy Markdown
Contributor

Oh, too bad. Not sure what to do, it is not ideal to re-add the version to the main executive.

This PR doesn't change anything for UNX. grass is still the main executable on UNX, but grass.bat is the main executable on Windows because we cannot directly run grass (renamed from grass.py) with no shebang support.

I understand it is only for Win. If you will do scripting on Win, wouldn't grass.py be the main executive?

@HuidaeCho

Copy link
Copy Markdown
Member Author

Oh, too bad. Not sure what to do, it is not ideal to re-add the version to the main executive.

This PR doesn't change anything for UN_X. grass is still the main executable on UN_X, but grass.bat is the main executable on Windows because we cannot directly run grass (renamed from grass.py) with no shebang support.

I understand it is only for Win. If you will do scripting on Win, wouldn't grass.py be the main executive?

For Python scripting, yes grass.py is the main entry point. We just cannot name it grass.py on Windows. It doesn't have to have a version number. It can be grass_main.py.

@wenzeslaus

Copy link
Copy Markdown
Member

If I understand correctly, the situation now is:

  • unix: grass representing grass.py
  • windows: grass.bat pointing to grass85.py

This looks platform-appropriate to me.

Anyway, I made the change with prepend in #6393.

In my local test on Linux, it seems that insert(0, helps, assuming you didn't try to import it beforehand, which #6393 purposefully does.

PYTHONPATH=.../dist.x86_64-pc-linux-gnu/etc/python python
Python 3.12.3 (main, Aug 14 2025, 17:47:21) [GCC 13.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path
['', '.../dist.x86_64-pc-linux-gnu/etc/python', '/usr/lib/python312.zip', '/usr/lib/python3.12', '/usr/lib/python3.12/lib-dynload', '/usr/local/lib/python3.12/dist-packages', '/usr/lib/python3/dist-packages']
>>> sys.path.insert(0, ".../dist.x86_64-pc-linux-gnu/etc/python")
>>> sys.path
['.../dist.x86_64-pc-linux-gnu/etc/python', '', '.../dist.x86_64-pc-linux-gnu/etc/python', '/usr/lib/python312.zip', '/usr/lib/python3.12', '/usr/lib/python3.12/lib-dynload', '/usr/local/lib/python3.12/dist-packages', '/usr/lib/python3/dist-packages']
>>> import grass.script

PYTHONPATH goes only after '' but insert(0, works as expected.

@wenzeslaus wenzeslaus left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would be for merging the versioned part of this PR right now. If we want to make it better in the future, we can refine #6393, use importlib, or the __main__.py file Python mechanics.

The scripts part is not clear to me. With Autotools we don't have separate scripts on Linux, but we may have them for Windows. I don't know what is the exact reasoning behind that. It is clear that Linux just treats all the executables the same, while more care is needed to run a Python script on Windows.

Comment thread python/grass/app/runtime.py Resolved
Comment thread lib/init/CMakeLists.txt Resolved
@wenzeslaus

wenzeslaus commented Sep 23, 2025 •

Copy link
Copy Markdown
Member

I made even further changes to #6393 and it works for me on Linux with grass.py. I would give it a try before merging the version piece here. We may still want to avoid the failed import with the "versioned" file, but we don't have to, because that's handled gracefully with #6393. #6393 needs a review.

Edit: #6393 is now merged.

@HuidaeCho

Copy link
Copy Markdown
Member Author

I made even further changes to #6393 and it works for me on Linux with grass.py. I would give it a try before merging the version piece here. We may still want to avoid the failed import with the "versioned" file, but we don't have to, because that's handled gracefully with #6393. #6393 needs a review.

Edit: #6393 is now merged.

Testing the main without this PR.

Comment thread python/grass/app/runtime.py Resolved
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@HuidaeCho

Copy link
Copy Markdown
Member Author

I made even further changes to #6393 and it works for me on Linux with grass.py. I would give it a try before merging the version piece here. We may still want to avoid the failed import with the "versioned" file, but we don't have to, because that's handled gracefully with #6393. #6393 needs a review.
Edit: #6393 is now merged.

Testing the main without this PR.

job-logs.txt

Getting the same error:

2026-04-28T23:15:06.4127032Z Traceback (most recent call last):
2026-04-28T23:15:06.4128108Z   File "C:\Users\runneradmin\micromamba\envs\build\conda-bld\grass_1777416597374\_test_env\Library\lib\grass86\etc\grass.py", line 2534, in <module>
2026-04-28T23:15:06.4134132Z     main()
2026-04-28T23:15:06.4134934Z   File "C:\Users\runneradmin\micromamba\envs\build\conda-bld\grass_1777416597374\_test_env\Library\lib\grass86\etc\grass.py", line 2175, in main
2026-04-28T23:15:06.4141064Z     find_grass_python_package()
2026-04-28T23:15:06.4142072Z   File "C:\Users\runneradmin\micromamba\envs\build\conda-bld\grass_1777416597374\_test_env\Library\lib\grass86\etc\grass.py", line 2124, in find_grass_python_package
2026-04-28T23:15:06.4147232Z     raise RuntimeError(msg)
2026-04-28T23:15:06.4148763Z RuntimeError: C:\Users\runneradmin\micromamba\envs\build\conda-bld\grass_1777416597374\work\build\output\lib\grass86\etc\python with the grass Python package does not exist. Is the installation of GRASS complete?
2026-04-28T23:15:08.2025464Z WARNING: Tests failed for grass-dev-py310h82bb817_0.conda - moving package to C:\Users\runneradmin\micromamba\envs\build\conda-bld\broken
2026-04-28T23:15:08.2604287Z 
2026-04-28T23:15:08.2605062Z CondaBuildUserError: TESTS FAILED: grass-dev-py310h82bb817_0.conda

I'm renaming grass.py to grass_main.py.

@github-actions github-actions Bot added the windows Microsoft Windows specific label Apr 29, 2026
@HuidaeCho

HuidaeCho commented Apr 29, 2026 •

Copy link
Copy Markdown
Member Author

First Windows conda packages: https://grass-conda.isnew.info/

wenzeslaus
wenzeslaus previously approved these changes May 6, 2026

@wenzeslaus wenzeslaus left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is disappointing that the rename is needed since my tests on Linux with conda seemed to show it works. I'm for renaming anyway, though, because it is more robust solution. The Python script is not touched by anything user related. Python imports don't use it and executable is the .bat file, so the name is internal.

The rest looks reasonable. The scripts on path is a confusion which we are hopefully finally addressing by this.

Suggested commit message (please check; PR description out of date at this point):

Rename the Windows startup script from grass.py to grass_main.py to avoid a name collision with the grass Python package, which caused import grass to fail because Python treated the script itself as the grass module/package.

Generate grass.bat from lib/init/grass.bat.in during the CMake build and install it to bin, and resolve GISBASE relative to the script location instead of baking in the build-tree path.

Always add the script directory to PATH when it exists so Windows batch wrappers in scripts/ are reachable. Non-Windows behavior is unchanged because it was already behaving that way.

@HuidaeCho

HuidaeCho commented May 6, 2026 •

Copy link
Copy Markdown
Member Author

Hmm... I'm not sure why r.coin and v.class tests fail in OSGeo4W with this PR when they are both binaries.

@wenzeslaus any ideas?

@echoix

echoix commented May 6, 2026

Copy link
Copy Markdown
Member

The r.coin failed test seems to be failing because of « missing » r.stats.

@HuidaeCho

HuidaeCho commented May 6, 2026 •

Copy link
Copy Markdown
Member Author

The r.coin failed test seems to be failing because of « missing » r.stats.

Yes 026-05-06T13:15:31.5855272Z 'r.stats' is not recognized as an internal or external command,

r.stats is compiled. It might be grass.bat.in changes. Most likely GISBASE. I need to see how OSGeo4W build is compiled.

No, it uses its own template mswindows/osgeo4w/grass.bat.tmpl... then adding scripts to PATH broke this test?

@echoix

echoix commented May 6, 2026

Copy link
Copy Markdown
Member

Also note that what we build as « osgeo4w » here is not using the same scripts and all as what is actually shipped by « osgeo4w », some differences being in the unit (paths and bat file names), among others. Fixing CI might still cause problems in the nightlies of osgeo4w

@echoix

echoix commented May 6, 2026

Copy link
Copy Markdown
Member

Before going too far, I launched a rerun

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CMake libraries Python Related code is in Python windows Microsoft Windows specific

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants