#9303 - Effectively static link fortran utilities (and make them work on M1)#9676
#9303 - Effectively static link fortran utilities (and make them work on M1)#9676Myoldmopar merged 3 commits intodevelopfrom
Conversation
…ll statically link stuff
…1 doesn't exist yet ``` [24504] Operation \"Execute\" with arguments \"ln; -sf; @TargetDir@/energyplus.1; /usr/local/share/man/man1; UNDOEXECUTE; rm; /usr/local/share/man/man1/energyplus.1\" failed: Execution failed (Unexpected exit code: 1): \"ln -sf /Applications/EnergyPlus-22-2-0/energyplus.1 /usr/local/share/man/man1\" [24504] installationErrorWithCancel : Installer Error : Error during installation process (Symlinks): Execution failed (Unexpected exit code: 1): "ln -sf /Applications/EnergyPlus-22-2-0/energyplus.1 /usr/local/share/man/man1" Retry|Ignore|Cancel ```
| # `-static` isn't possible on mac. From gcc man page: | ||
| # > This option will not work on Mac OS X unless all libraries (including libgcc.a) have also been compiled with -static. | ||
| # > Since neither a static version of libSystem.dylib nor crt0.o are provided, this option is not useful to most people. | ||
|
|
||
| # master of gcc has a fix via a new `-static-libquadmath` but it's not even in gcc 12.2.0. So instead we have to do all kinds of shenanigans | ||
|
|
||
| enable_language(Fortran) # Needed to populate ${CMAKE_Fortran_IMPLICIT_LINK_DIRECTORIES} | ||
| # Debug: | ||
| # set(Fortran_VERBOSE "-v") | ||
| # Find the static libquadmath maually | ||
| find_library(static-libquadmath NAMES quadmath.a libquadmath.a REQUIRED PATHS ${CMAKE_Fortran_IMPLICIT_LINK_DIRECTORIES}) | ||
| message(STATUS "Found static-libquadmath at ${static-libquadmath} by searching in CMAKE_Fortran_IMPLICIT_LINK_DIRECTORIES=${CMAKE_Fortran_IMPLICIT_LINK_DIRECTORIES}") | ||
| target_compile_options(fortran_project_options INTERFACE | ||
| ${Fortran_VERBOSE} | ||
| ) | ||
| target_link_options(fortran_project_options INTERFACE | ||
| ${Fortran_VERBOSE} | ||
| -nodefaultlibs | ||
| -static-libgfortran | ||
| -lgfortran | ||
| -static-libgcc | ||
| -lgcc | ||
| -lemutls_w | ||
| ${static-libquadmath} | ||
| -lSystem | ||
| ) | ||
|
|
||
| message(DEBUG "CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES-${CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES}") | ||
| # => CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES-gfortran;emutls_w;gcc;quadmath;emutls_w;gcc;gcc | ||
| list(REMOVE_DUPLICATES CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES) | ||
| list(TRANSFORM CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES REPLACE "quadmath" " ${static-libquadmath}") | ||
| message(DEBUG "CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES-${CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES}") | ||
|
|
||
| # We unset this so that CMake doesn't try to read -lquadmath etc | ||
| unset(CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES) | ||
|
|
||
| # We could technically just set it to TRUE here. But it shouldn't do anything anyways, and it's a fallback | ||
| # set(FORTRAN_STATIC_EXE TRUE) |
There was a problem hiding this comment.
That's it. Obviously the pain point was clearly getting to a working implementation. I had to inspect the source code of both CMake and GCC.
I tried passing a custom -specs=${CMAKE_CURRENT_LIST_DIR}/libgfortran.spec with this content
%rename lib liborig2
*lib: %{!static-libgfortran: -lquadmath } %{static-libgfortran: libquadmath.a%s} %(libgcc) %(liborig2)
but that conflicted with the base spec somehow (/opt/homebrew//Cellar/gcc/12.2.0/lib/gcc/current/libgfortran.spec). In the system one if I make the same change it worked fine though, but that's not portable to another machine...
%rename lib liborig
-*lib: -lquadmath %(libgcc) %(liborig)
+*lib: %{!static-libgfortran: -lquadmath } %{static-libgfortran: libquadmath.a%s} %(libgcc) %(liborig)Note that in the future, GCC will have a -static-libquadmath option which should remove of this workaround. It's not in 12.2.0 though, only on master: gcc-mirror/gcc@745be54
There was a problem hiding this comment.
install_name_tool isn't called anymore, so there's no code signature invalidation, and therefore the utility runs on M1 (which has hardened runtime).
My initial try was to adjust fixup_executable in ProjectMacros.cmake (try to call codesign -s -f -- <mylib>) and try to pass RUNTIME_DEPENDENCIES to the individual install(TARGET) in the fortran subdirectory (eg https://github.com/NREL/EnergyPlus/blob/1d22b9a61f7cd00b9e7b0ef27e4b24ffb6b849f3/src/ParametricPreprocessor/CMakeLists.txt#L26) (which requires cmake 3.21 though), but it wasn't working cleanly and I realized I could potentially make (almost-)static linking work.
(Note: I say almost-static because technically this isn't a statically linked lib, but it doesn't depends on anything else than libSystemB.dylib)
|
|
||
| # You need at least one "install(..." command for it to be registered as a component | ||
| install(CODE "MESSAGE(\"Creating symlinks.\")" COMPONENT Symlinks) | ||
| install(FILES "${PROJECT_SOURCE_DIR}/doc/man/energyplus.1" DESTINATION "./" COMPONENT Symlinks) |
There was a problem hiding this comment.
Install man page on mac
| component.addElevatedOperation("Execute", "mkdir", "-p", linktarget); | ||
|
|
||
| component.addElevatedOperation("Execute", "ln", "-sf", "@TargetDir@/energyplus.1", linktarget + "/energyplus.1", |
There was a problem hiding this comment.
Install man page on mac (and linux): create the /usr/local/share/man/man1 directory if it doesn't exist (it doesn't by default) to you avoid this annoying warning
[24504] Operation \"Execute\" with arguments \"ln; -sf; @TargetDir@/energyplus.1; /usr/local/share/man/man1; UNDOEXECUTE; rm; /usr/local/share/man/man1/energyplus.1\" failed: Execution failed (Unexpected exit code: 1): \"ln -sf /Applications/EnergyPlus-22-2-0/energyplus.1 /usr/local/share/man/man1\"
[24504] installationErrorWithCancel : Installer Error : Error during installation process (Symlinks):
Execution failed (Unexpected exit code: 1): "ln -sf /Applications/EnergyPlus-22-2-0/energyplus.1 /usr/local/share/man/man1" Retry|Ignore|Cancel
Myoldmopar
left a comment
There was a problem hiding this comment.
Wow, this is some effort @jmarrec. I think I will tag RC3 after all and give this a quick test on my machine. I realize my machine isn't a clean VM, but if you are seeing success on your M1, and I'm seeing success on my machine, I'd feel pretty good about it.
|
@jmarrec Do these changes target only M1 Mac, or does it touch other platforms as well? |
3e02160 to
860fd63
Compare
Currently it tries to do an effective static linking of fortran libs on macOS (any arch) with Gfortran (not ifort). |
|
OK, that was some fun detective work. Great job @jmarrec and there are surely some things we can continue to clean up in here when time is better. Thanks! |
#9676 Follow Up - Make it more resilient to subtle differences in gfortran versions
Pull request overview
Pull Request Author
Add to this list or remove from it as applicable. This is a simple templated set of guidelines.
Reviewer
This will not be exhaustively relevant to every PR.