if(OGS_BUILD_WHEEL) return() endif() # CMake function to handle pybind11 version-compatible linker flags # This prevents the linker from stripping the module initialization function function(dont_strip_pybind11_init_function target_name module_name) # Only apply when building static libraries to prevent symbol stripping if(BUILD_SHARED_LIBS) return() endif() set(pybind11_init_function "") # Detect pybind11 version if(DEFINED pybind11_VERSION) if(pybind11_VERSION VERSION_GREATER_EQUAL "3.0") set(pybind11_init_function "pybind11_init_${module_name}") else() set(pybind11_init_function "pybind11_init_impl_${module_name}") endif() elseif(DEFINED PYBIND11_VERSION_MAJOR) if(PYBIND11_VERSION_MAJOR GREATER_EQUAL 3) set(pybind11_init_function "pybind11_init_${module_name}") else() set(pybind11_init_function "pybind11_init_impl_${module_name}") endif() endif() message(STATUS "Using pybind11 init function: ${pybind11_init_function}") # Linker flags to prevent symbol stripping if(COMPILER_IS_GCC OR COMPILER_IS_CLANG) if(APPLE) target_link_options(${target_name} PRIVATE "LINKER:-u,_${pybind11_init_function}") else() target_link_options(${target_name} PRIVATE "LINKER:--undefined=${pybind11_init_function}") endif() elseif(COMPILER_IS_MSVC) target_link_options(${target_name} PRIVATE "/INCLUDE:${pybind11_init_function}") else() # Fallback for unsupported compilers message(WARNING "Unsupported compiler, manual linker configuration may be needed") endif() message(STATUS "Applied linker flags to prevent stripping of ${pybind11_init_function}") endfunction() # Troubleshooting: If you get linker errors, such as ogs.cpp:(.text+0xb4): # undefined reference to `_Py_ZeroStruct' it could be that OGS is compiled with # the wrong Python version. I (Ch. Leh.) observed the following: The symbol # _Py_ZeroStruct could not be found in /usr/lib/libpython3.6m.so (I intended to # compile OGS with Python3). It's apparently a Python2 symbol (present in # /usr/lib/libpython2.7.so) The compiler command-line was the following: # ~~~ # /usr/bin/g++ ... -DvtkRenderingVolume_AUTOINIT="1(vtkRenderingVolumeOpenGL2)" \ # -I/usr/include/vtk -I/usr/include/python2.7 -I/usr/include/freetype2 \ # -I/usr/include/libxml2 ... -I/.../BaseLib ... \ # -isystem /usr/include/python3.6m ... -o CMakeFiles/ogs.dir/ogs.cpp.o \ # -c /.../Applications/CLI/ogs.cpp # ~~~ # In particular, the Python2 include path comes before the Python3 include path. # Compiling OGS with Python2 solved the issue. I assume (this is only a guess!) # that VTK pulls in Python2 dependencies (on my system). I assume that this is # related to https://github.com/ufz/ogs/pull/2158. Workaround: Always make sure # that OGS is compiled with the same Python version as VTK. The error described # above should be detected automatically by cmake and an appropriate message # should be presented. The note is kept for the case that the automatic # detection does not work due to whatever reason. # TODO: Make this work in python interpreters, # see https://github.com/pybind/pybind11/discussions/5079 ogs_add_library(ogs_embedded_python ogs_embedded_python.cpp) # Performance warning from # https://github.com/pybind/pybind11/blob/master/docs/compiling.rst: Since # pybind11 is a metatemplate library, it is crucial that certain compiler flags # are provided to ensure high quality code generation. In contrast to the # pybind11_add_module() command, the CMake interface library only provides the # minimal set of parameters to ensure that the code using pybind11 compiles, but # it does not pass these extra compiler flags (i.e. this is up to you). TODO: # Enable further compiler/linker flags. target_link_libraries( ogs_embedded_python PUBLIC pybind11::embed PRIVATE ProcessLibBoundaryConditionAndSourceTermPythonModule ) target_compile_definitions( ogs_embedded_python PUBLIC OGS_EMBED_PYTHON_INTERPRETER ) dont_strip_pybind11_init_function(ogs_embedded_python "OpenGeoSys") ogs_add_executable(ogs ogs.cpp CommandLineArgumentParser.cpp) target_link_libraries( ogs PRIVATE ApplicationsLib BaseLib CMakeInfoLib GitInfoLib MeshLib ProcessLib $<$,$>:MPI::MPI_CXX> $<$:InSituLib> $<$:petsc> tclap ) # ---- Tests ---- add_test(NAME ogs_no_args COMMAND ogs) set_tests_properties(ogs_no_args PROPERTIES WILL_FAIL TRUE LABELS "default") # ---- Installation ---- install(TARGETS ogs RUNTIME DESTINATION bin) set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} "ogs" "OGS Simulator" ) cpack_add_component( ogs_cli DISPLAY_NAME "OGS THMC Simulator" DESCRIPTION "The command line interface for OpenGeoSys." GROUP Applications )