From c9485a8f3ff51bbab9869830e2762b81449bec71 Mon Sep 17 00:00:00 2001 From: Alexis Montoison Date: Tue, 20 Oct 2026 16:40:52 -0600 Subject: [PATCH] build: compile each backend archive with one section per procedure Each module compiles to one object, and a linker extracts whole objects from an archive, so a program calling one rocBLAS wrapper linked all of them, and a wrapper naming a C function the installed library does not export broke every link of that library. Compile libhipfort-amdgcn.a and libhipfort-nvptx.a with -ffunction-sections -fdata-sections (GNU, LLVMFlang, Flang, NVHPC; the Intel compilers do not split the sections), and link the tests with -Wl,--gc-sections, spelled -Wl, because CMake 3.27 passes LINKER:--gc-sections to LLVMFlang as a bare flag. --- CHANGELOG.md | 7 +++++++ lib/CMakeLists.txt | 10 ++++++++++ test/CMakeLists.txt | 8 ++++++++ 3 files changed, 25 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1eaf017c4..197a79b2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,13 @@ ### Changed +* Each backend archive (`libhipfort-amdgcn.a`, `libhipfort-nvptx.a`) is + compiled with one section per procedure (`-ffunction-sections + -fdata-sections`). A program linked with `-Wl,--gc-sections` keeps only the + wrappers it calls, instead of all of a library's wrappers, and still links + when another wrapper names a C function that the installed library does not + export. The tests link that way. A shared library that links an archive also + needs `-Wl,--exclude-libs,ALL`. * **Breaking.** The array overloads of `hipMalloc`, `hipMallocManaged`, `hipHostMalloc`, `hipFree`, `hipHostFree`, the `hipMemcpy` families and the `hipHostRegister` family are now part of the Fortran 2008 array overloads, like diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index ce5cfca10..8800e6935 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -115,6 +115,14 @@ if(HIPFORT_ASSUMED_RANK AND NOT (HIPFORT_USE_FPOINTER_INTERFACES AND CMAKE_Fortr "Use the F2018 assumed-rank array interfaces" FORCE) endif() +# Each module compiles to one object, and a linker extracts whole objects from an +# archive, so a program that calls one wrapper links all of that module's. One +# section per procedure lets a program linked with -Wl,--gc-sections keep only +# the wrappers it calls; without that flag it changes nothing. Only these +# compilers split the sections (the Intel ones accept the flags but do not). +set(HIPFORT_SECTION_FLAGS + "$<$:-ffunction-sections;-fdata-sections>") + if(HIPFORT_BUILD_AMDGCN) set(HIPFORT_ARCH "amdgcn") # amdgcn @@ -138,6 +146,7 @@ set(HIPFORT_ARCH "amdgcn") target_compile_definitions(${HIPFORT_LIB} PRIVATE USE_ASSUMED_SHAPE) ENDIF() target_compile_definitions(${HIPFORT_LIB} PRIVATE _HIPFORT_ARCH='${HIPFORT_ARCH}') + target_compile_options(${HIPFORT_LIB} PRIVATE "${HIPFORT_SECTION_FLAGS}") # Install Target hipfort-amdgcn # CMAKE_INSTALL_LIBDIR/INCLUDEDIR already carry the toolchain-specific # subdirectory (see HIPFORT_MULTITOOLCHAIN_LAYOUT in the top-level @@ -183,6 +192,7 @@ set(HIPFORT_ARCH "nvptx") ENDIF() target_compile_definitions(${HIPFORT_LIB} PRIVATE USE_CUDA_NAMES) target_compile_definitions(${HIPFORT_LIB} PRIVATE _HIPFORT_ARCH='${HIPFORT_ARCH}') + target_compile_options(${HIPFORT_LIB} PRIVATE "${HIPFORT_SECTION_FLAGS}") # Install Target hipfort-nvptx rocm_install_targets( TARGETS ${HIPFORT_LIB} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f3e0e2ee2..525242602 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -52,6 +52,14 @@ if(BUILD_TESTING) CMAKE_Fortran_PREPROCESS_SOURCE "${CMAKE_Fortran_PREPROCESS_SOURCE}") endif() + # Keep only the binding wrappers a test calls (the archives are built with one + # section per procedure), so a test links even when another wrapper names a C + # symbol the installed library does not export. Spelled -Wl, rather than + # LINKER:, which CMake 3.27 passes to LLVMFlang as a bare --gc-sections. + if(NOT APPLE AND NOT WIN32) + add_link_options(-Wl,--gc-sections) + endif() + # Which backend the tests link: hipfort::hip carries the archive of the one # lib/ built the components for (nvptx when HIPFORT_BUILD_AMDGCN is OFF, even on # an AMD host). On the CUDA backend the symbol tests are compiled with