Skip to content

Comments

#9303 - Effectively static link fortran utilities (and make them work on M1)#9676

Merged
Myoldmopar merged 3 commits intodevelopfrom
9303_Fortran_UtilitiesLinking
Sep 28, 2022
Merged

#9303 - Effectively static link fortran utilities (and make them work on M1)#9676
Myoldmopar merged 3 commits intodevelopfrom
9303_Fortran_UtilitiesLinking

Conversation

@jmarrec
Copy link
Contributor

@jmarrec jmarrec commented Sep 27, 2022

Pull request overview

Pull Request Author

Add to this list or remove from it as applicable. This is a simple templated set of guidelines.

  • Title of PR should be user-synopsis style (clearly understandable in a standalone changelog context)
  • Label the PR with at least one of: Defect, Refactoring, NewFeature, Performance, and/or DoNoPublish
  • Pull requests that impact EnergyPlus code must also include unit tests to cover enhancement or defect repair
  • Author should provide a "walkthrough" of relevant code changes using a GitHub code review comment process
  • If any diffs are expected, author must demonstrate they are justified using plots and descriptions
  • If changes fix a defect, the fix should be demonstrated in plots and descriptions
  • If any defect files are updated to a more recent version, upload new versions here or on DevSupport
  • If IDD requires transition, transition source, rules, ExpandObjects, and IDFs must be updated, and add IDDChange label
  • If structural output changes, add to output rules file and add OutputChange label
  • If adding/removing any LaTeX docs or figures, update that document's CMakeLists file dependencies

Reviewer

This will not be exhaustively relevant to every PR.

  • Perform a Code Review on GitHub
  • If branch is behind develop, merge develop and build locally to check for side effects of the merge
  • If defect, verify by running develop branch and reproducing defect, then running PR and reproducing fix
  • If feature, test running new feature, try creative ways to break it
  • CI status: all green or justified
  • Check that performance is not impacted (CI Linux results include performance check)
  • Run Unit Test(s) locally
  • Check any new function arguments for performance impacts
  • Verify IDF naming conventions and styles, memos and notes and defaults
  • If new idf included, locally check the err file and other outputs

…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
```
@jmarrec jmarrec requested a review from Myoldmopar September 27, 2022 14:35
@jmarrec jmarrec self-assigned this Sep 27, 2022
@jmarrec jmarrec changed the base branch from develop to PrepFor222 September 27, 2022 14:35
Comment on lines +14 to +51
# `-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)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

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)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Install man page on mac

Comment on lines +71 to +73
component.addElevatedOperation("Execute", "mkdir", "-p", linktarget);

component.addElevatedOperation("Execute", "ln", "-sf", "@TargetDir@/energyplus.1", linktarget + "/energyplus.1",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

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

Copy link
Member

@Myoldmopar Myoldmopar left a comment

Choose a reason for hiding this comment

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

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.

Base automatically changed from PrepFor222 to develop September 27, 2022 15:04
@mjwitte
Copy link
Contributor

mjwitte commented Sep 27, 2022

@jmarrec Do these changes target only M1 Mac, or does it touch other platforms as well?

@jmarrec jmarrec force-pushed the 9303_Fortran_UtilitiesLinking branch from 3e02160 to 860fd63 Compare September 27, 2022 19:37
@jmarrec
Copy link
Contributor Author

jmarrec commented Sep 27, 2022

@jmarrec Do these changes target only M1 Mac, or does it touch other platforms as well?

Currently it tries to do an effective static linking of fortran libs on macOS (any arch) with Gfortran (not ifort).

@Myoldmopar Myoldmopar added Defect Includes code to repair a defect in EnergyPlus Developer Issue Related to cmake, packaging, installers, or developer tooling (CI, etc) labels Sep 27, 2022
@Myoldmopar
Copy link
Member

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!

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

Labels

Defect Includes code to repair a defect in EnergyPlus Developer Issue Related to cmake, packaging, installers, or developer tooling (CI, etc)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fortran utilities do not work in mac M1 (arm64) package when installed

6 participants