CMAKE conditionals in python code

Here's the place for discussion related to coding in FreeCAD, C++ or Python. Design, interfaces and structures.
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
ickby
Veteran
Posts: 3116
Joined: Wed Oct 05, 2011 7:36 am

CMAKE conditionals in python code

Post by ickby »

Hello,

For the FEM postprocessing code I use cmake variable to check if this part of the code should be build. this works with c postprocessor directives #ifdef etc. One issue I now have is with the python init functions for registering loadable file types. One need to register those in the Init.py with

Code: Select all

FreeCAD.addImportType("FEM results (*.vtk *.vtp *.vts *.vtr *.vtu *.vti)","Fem")
Of course this makes only sense if choosen to build the vtk postprocessing stuff in cmake. How do I check for the cmake variable in python an include/exclude the file types?
wmayer
Founder
Posts: 20298
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: CMAKE conditionals in python code

Post by wmayer »

Use cmake's configure_file facility for this https://cmake.org/cmake/help/v3.2/comma ... _file.html

In Fem/CMakeLists.txt add something like:

Code: Select all

if (...) # True
    set(IMPORT_TYPE_FEM_RESULTS "FreeCAD.addImportType(\"FEM results (*.vtk *.vtp *.vts *.vtr *.vtu *.vti)\",\"Fem\")")
else()
    set(IMPORT_TYPE_FEM_RESULTS "") # it seems this can be omitted
endif()
    
configure_file(Init.py ${CMAKE_BINARY_DIR}/Mod/Fem/Init.py @ONLY)
Then edit the original Init.py file:

Code: Select all

FreeCAD.addExportType("TetGen file (*.poly)", "convert2TetGen")
FreeCAD.addImportType("FEM formats (*.unv *.med *.dat *.bdf)", "Fem")
FreeCAD.addExportType("FEM formats (*.unv *.med *.dat *.inp)", "Fem")
FreeCAD.addImportType("CalculiX result (*.frd)", "ccxFrdReader")
FreeCAD.addImportType("Abaqus file (*.inp)", "FemGui")
@IMPORT_TYPE_FEM_RESULTS@
When you run cmake the variable will be replaced with the actual content.

Be careful when implementing this idea. At the moment the Init.py files are copied over to the build directory at compile time. You have to modify the Fem/App/CMakeLists.txt file to not copy this file any more. Then in Fem/CMakeLists.txt the INSTALL target must also be adjusted to copy the "configured" file.
wmayer
Founder
Posts: 20298
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: CMAKE conditionals in python code

Post by wmayer »

When doing this then it's probably best to rename the original file to Init.py.cmake or Init.py.in
User avatar
f3nix
Posts: 346
Joined: Sat May 30, 2015 11:58 am

Re: CMAKE conditionals in python code

Post by f3nix »

Hi,
while doing some research for Pyside/Pyside2 coexistence I've found this:

https://github.com/evanplaice/pypreprocessor

And here is a page with some examples (old project page)
https://code.google.com/p/pypreprocessor/

Cheers,
Mateusz
wmayer
Founder
Posts: 20298
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: CMAKE conditionals in python code

Post by wmayer »

while doing some research for Pyside/Pyside2 coexistence I've found this:
It's an interesting idea but AFAICS the problem remains to inform the pre-processor which #define must be set and this means something additional must happen either at configure time or at compile time.
User avatar
f3nix
Posts: 346
Joined: Sat May 30, 2015 11:58 am

Re: CMAKE conditionals in python code

Post by f3nix »

Hi,
wmayer wrote:
while doing some research for Pyside/Pyside2 coexistence I've found this:
It's an interesting idea but AFAICS the problem remains to inform the pre-processor which #define must be set and this means something additional must happen either at configure time or at compile time.
you are absolutely right. I was thinking about generating a "header file" with the defines with CMake during configure stage and then importing it in the python code.

header.py (generated)

Code: Select all

#define VTK
#define Qt5
#define debug
And then running a preprocessor on them. I don't know what speed penalty would a real time preprocessing give.

Code: Select all

import sys

from pypreprocessor import pypreprocessor

#exclude
if sys.version[:3].split('.')[0] == '2':
    pypreprocessor.defines.append('python2')
if sys.version[:3].split('.')[0] == '3':
    pypreprocessor.defines.append('python3')
#endexclude

pypreprocessor.parse()

import header

#ifdef python2
print('You are using Python 2x')
#ifdef python3
print('You are using python 3x')
#else
print('Python version not supported')
#endif

#ifdef debug
print('The source is in debug mode')
#else
print('The source is not in debug mode')
#endif
Cheers,
Mateusz
ickby
Veteran
Posts: 3116
Joined: Wed Oct 05, 2011 7:36 am

Re: CMAKE conditionals in python code

Post by ickby »

It is also possible to print all defined vtk variables into a file at the end of configure

Code: Select all

cmake -LAH > variables.txt
Than one can write a little python parser for that file and have a set of python function available in freecad:

Code: Select all

cmake.isDefined('MyFanceCmakeVariable')
cmake.getType('MyFanceCmakeVariable')
cmake.getValue('MyFanceCmakeVariable')
ickby
Veteran
Posts: 3116
Joined: Wed Oct 05, 2011 7:36 am

Re: CMAKE conditionals in python code

Post by ickby »

Hello Werner,

as your Idea also needed some serious changes I decided to go the more general route and provide something that works for everyone in the feature. It creates a files with all cmake variables at compile time and loads this on FreeCAD startup in dict variable. This dict can than be accessed from python rather elegant:

Code: Select all

if("BUILD_FEM_VTK" in FreeCAD.__cmake__):
    FreeCAD.addImportType("FEM results (*.vtk *.vtp *.vts *.vtr *.vtu *.vti)","Fem")
Can you have a look if this is ok?

here is the relevant commit:
https://github.com/ickby/FreeCAD_sf_mas ... fda3d58792

(and this one to ensure the variable is set before modules are loaded: https://github.com/ickby/FreeCAD_sf_mas ... 51d6d364a3)
wmayer
Founder
Posts: 20298
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: CMAKE conditionals in python code

Post by wmayer »

Basically a nice idea but there area few thing you have to take care:
1. Really every variable gets exported to this file. So, it may also include file names a package builder isn't aware of. So, we should filter out everything we don't need or only write out stuff we really need.

2. Currently the file is too big in order to build on Windows. If point 1. is implemented this will be fixed, too.
Compiler wrote: C:\Projects\FreeCAD-git\x64\src\App\CMakeScript.h(621) : fatal error C1091: compiler limit: string exceeds 65535 bytes in length
3. Some variables include backslashes which results into warnings.
"\"SG_Filter_Dialog\Customize_GUID_CMAKE\" : \"\"\"8B50E83E-5D55-4CBE-AC9C-D6EAEFF34406\"\"\",\n"
Compiler wrote: C:\Projects\FreeCAD-git\x64\src\App\CMakeScript.h(493) : warning C4129: 'C' : unrecognized character escape sequence
These warnings only are reported for uninteresting variables.
ickby
Veteran
Posts: 3116
Joined: Wed Oct 05, 2011 7:36 am

Re: CMAKE conditionals in python code

Post by ickby »

Ok, good catches.
Really every variable gets exported to this file. So, it may also include file names a package builder isn't aware of. So, we should filter out everything we don't need or only write out stuff we really need.
I think we can export certain groups, like cmake-gui is grouping by the prefixes. For example BUILD_ and FREECAD_ groups can be added to the file.
Some variables include backslashes which results into warnings.
Ah yes, removed the quotes from the values but not the keys.

I will update it.
Post Reply