From 7a2b8b5aa619311b71473538cf2a39543aa42ad0 Mon Sep 17 00:00:00 2001 From: Matthew Thompson Date: Fri, 29 May 2026 11:13:38 -0400 Subject: [PATCH] cmake: fix shared lib build with NAG Fortran on macOS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Apple, the shared library link rule for Fortran used GCC-specific flags: -x f95-cpp-input (GCC preprocessing flag; NAG does not support it) -Wl,-shared (Linux linker flag; macOS needs -dynamiclib) The fix is NAG-specific — other non-GNU compilers (Intel, flang, Cray, etc.) are left alone since they may handle the existing code paths fine. Fix in two places (both already inside if(APPLE) / if(APPLE AND BUILD_STATIC_LIBS)): 1. Before add_library() (affects the main CMake Fortran shared lib rule): For NAG Fortran, substitute CMAKE_C_CREATE_SHARED_LIBRARY so the C compiler link rule is used instead. 2. Inside the APPLE AND BUILD_STATIC_LIBS block (the static->shared conversion trick for long argument lists): add an elseif(NAG) branch that uses the C compiler with -dynamiclib and auto-detects the NAG Fortran runtime (libf72rts) from the compiler's directory so that NAGf90_* symbols resolve. Tested with NAG 7.2.7243 on macOS/arm64. --- CMakeLists.txt | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f5fffe43d..6a145ac6be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -263,6 +263,14 @@ if(APPLE) if(NOT NOFORTRAN) set(CMAKE_Fortran_USE_RESPONSE_FILE_FOR_OBJECTS ON) set(CMAKE_Fortran_USE_RESPONSE_FILE_FOR_LIBRARIES ON) + # NAG Fortran does not support the GCC-specific -x f95-cpp-input flag + # used in the shared library link rule below. Override + # CMAKE_Fortran_CREATE_SHARED_LIBRARY early (before targets are defined) + # to use the C compiler link rule instead; the shared library contains + # only C and assembler objects so this is safe. + if(CMAKE_Fortran_COMPILER_ID MATCHES "NAG") + set(CMAKE_Fortran_CREATE_SHARED_LIBRARY ${CMAKE_C_CREATE_SHARED_LIBRARY}) + endif() endif() set(CMAKE_NINJA_FORCE_RESPONSE_FILE ON) endif() @@ -360,9 +368,32 @@ if(APPLE AND BUILD_STATIC_LIBS) if(NOT NOFORTRAN) set(CMAKE_Fortran_CREATE_STATIC_LIBRARY ${CREATE_STATIC_LIBRARY_COMMAND}) if(BUILD_SHARED_LIBS) - set(CMAKE_Fortran_CREATE_SHARED_LIBRARY - "sh -c 'echo \"\" | ${CMAKE_Fortran_COMPILER} -o dummy.o -c -x f95-cpp-input - '" - "sh -c '${CMAKE_Fortran_COMPILER} -fpic -shared -Wl,-all_load -Wl,-force_load,${STATIC_PATH} dummy.o -o ${SHARED_PATH} ${OMP_LIB}'") + if(CMAKE_Fortran_COMPILER_ID MATCHES "GNU") + set(CMAKE_Fortran_CREATE_SHARED_LIBRARY + "sh -c 'echo \"\" | ${CMAKE_Fortran_COMPILER} -o dummy.o -c -x f95-cpp-input - '" + "sh -c '${CMAKE_Fortran_COMPILER} -fpic -shared -Wl,-all_load -Wl,-force_load,${STATIC_PATH} dummy.o -o ${SHARED_PATH} ${OMP_LIB}'") + elseif(CMAKE_Fortran_COMPILER_ID MATCHES "NAG") + # NAG does not support -x f95-cpp-input, and macOS needs -dynamiclib + # rather than -Wl,-shared. Use the C compiler as the linker driver + # and add the NAG Fortran runtime so NAGf90_* symbols resolve. + # Locate the NAG Fortran runtime (libfrts) without hardcoding the + # version digits: NAG 7.1 ships libf71rts, 7.2 ships libf72rts, etc. + get_filename_component(_NAG_FC_DIR "${CMAKE_Fortran_COMPILER}" DIRECTORY) + set(_NAG_RTS_DIR "${_NAG_FC_DIR}/../lib/NAG_Fortran") + file(GLOB _NAG_RTS_CANDIDATES + "${_NAG_RTS_DIR}/libf*rts.dylib" + "${_NAG_RTS_DIR}/libf*rts.a") + if(_NAG_RTS_CANDIDATES) + list(GET _NAG_RTS_CANDIDATES 0 _NAG_RTS_LIB) + get_filename_component(_NAG_RTS_NAME "${_NAG_RTS_LIB}" NAME_WE) + string(REGEX REPLACE "^lib" "" _NAG_RTS_LIBNAME "${_NAG_RTS_NAME}") + set(_NAG_RTS_FLAGS "-L${_NAG_RTS_DIR} -l${_NAG_RTS_LIBNAME}") + else() + set(_NAG_RTS_FLAGS "") + endif() + set(CMAKE_Fortran_CREATE_SHARED_LIBRARY + "sh -c '${CMAKE_C_COMPILER} -dynamiclib -Wl,-all_load -Wl,-force_load,${STATIC_PATH} -o ${SHARED_PATH} ${OMP_LIB} ${_NAG_RTS_FLAGS}'") + endif() endif() else() set(CMAKE_C_CREATE_STATIC_LIBRARY ${CREATE_STATIC_LIBRARY_COMMAND})