From 93a3157ef5611c33338e553bc61af9c9db30bf4e Mon Sep 17 00:00:00 2001 From: Mark Piper Date: Wed, 13 Mar 2024 16:50:35 -0600 Subject: [PATCH] Use pkgconfig to expose libraries (#21) * Use pkg-config to find installed bmi-fortran spec * Add pkg-config files for heatf model and its BMI * Use CMAKE_CURRENT_BINARY_DIR instead of CMAKE_BINARY_DIR * Require bmif library * Add pkg-config dependency to test environment * Use LIBRARY_PREFIX env variable on Windows * Test for pkg-config files; run ctest * Make SHLIB_EXT env variable for unix-based systems * Test for installed files * Remove duplicate sample configuration file * List pkg-config requirement --- .github/workflows/test.yml | 47 ++++++++++++++++++++++++++------------ CMakeLists.txt | 24 ++++++------------- README.md | 16 +++++++------ bmi_heat/CMakeLists.txt | 12 +++++++++- bmi_heat/bmiheatf.pc.cmake | 11 +++++++++ heat/CMakeLists.txt | 10 ++++++++ heat/heatf.pc.cmake | 10 ++++++++ sample.cfg | 0 8 files changed, 91 insertions(+), 39 deletions(-) create mode 100644 bmi_heat/bmiheatf.pc.cmake create mode 100644 heat/heatf.pc.cmake delete mode 100644 sample.cfg diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 853467b..e2e0bb1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,6 +14,9 @@ jobs: run: shell: bash -l {0} + env: + SHLIB_EXT: ${{ matrix.os == 'ubuntu-latest' && '.so' || '.dylib' }} + strategy: matrix: os: [ubuntu-latest, macos-latest] @@ -28,6 +31,7 @@ jobs: environment-name: testing create-args: >- cmake + pkg-config fortran-compiler bmi-fortran @@ -45,7 +49,16 @@ jobs: working-directory: ${{ github.workspace }}/build run: cmake --build . --target install --config ${{ matrix.build-type }} - - name: Test + - name: Test for installed files + run: | + test -h $CONDA_PREFIX/lib/libheatf${{ env.SHLIB_EXT }} + test -f $CONDA_PREFIX/include/heatf.mod + test -f $CONDA_PREFIX/lib/pkgconfig/heatf.pc + test -h $CONDA_PREFIX/lib/libbmiheatf${{ env.SHLIB_EXT }} + test -f $CONDA_PREFIX/include/bmiheatf.mod + test -f $CONDA_PREFIX/lib/pkgconfig/bmiheatf.pc + + - name: Run CTest working-directory: ${{ github.workspace }}/build run: ctest -C ${{ matrix.build-type }} --output-on-failure @@ -70,6 +83,9 @@ jobs: runs-on: windows-latest + env: + LIBRARY_PREFIX: $env:CONDA_PREFIX\Library + steps: - uses: actions/checkout@v4 - uses: ilammy/msvc-dev-cmd@v1 @@ -79,6 +95,7 @@ jobs: environment-name: testing create-args: >- cmake + pkg-config cxx-compiler init-shell: >- powershell @@ -94,7 +111,7 @@ jobs: unzip bmi-fortran.zip cd bmi-fortran-master mkdir build && cd build - cmake .. -G "NMake Makefiles" -DCMAKE_INSTALL_PREFIX="$env:CONDA_PREFIX" -DCMAKE_BUILD_TYPE=Release + cmake .. -G "NMake Makefiles" -DCMAKE_INSTALL_PREFIX="${{ env.LIBRARY_PREFIX }}" -DCMAKE_BUILD_TYPE=Release cmake --build . --target install --config Release cd ${{ github.workspace }} @@ -104,18 +121,20 @@ jobs: - name: Configure, build, and install working-directory: ${{ github.workspace }}/build run: | - cmake .. -G "NMake Makefiles" -DCMAKE_INSTALL_PREFIX="$env:CONDA_PREFIX" -DCMAKE_BUILD_TYPE=Release + cmake .. -G "NMake Makefiles" -DCMAKE_INSTALL_PREFIX="${{ env.LIBRARY_PREFIX }}" -DCMAKE_BUILD_TYPE=Release cmake --build . --target install --config Release - - name: Test installed files + - name: Test for installed files run: | - if ( -not ( Test-Path -Path $env:CONDA_PREFIX\lib\libheatf.a ) ){ exit 1 } - if ( -not ( Test-Path -Path $env:CONDA_PREFIX\bin\run_heatf.exe ) ){ exit 1 } - if ( -not ( Test-Path -Path $env:CONDA_PREFIX\include\heatf.mod ) ){ exit 1 } - if ( -not ( Test-Path -Path $env:CONDA_PREFIX\bin\run_bmiheatf.exe ) ){ exit 1 } - if ( -not ( Test-Path -Path $env:CONDA_PREFIX\lib\libbmiheatf.a ) ){ exit 1 } - if ( -not ( Test-Path -Path $env:CONDA_PREFIX\include\bmiheatf.mod ) ){ exit 1 } - - # - name: Unit test with CTest - # working-directory: ${{ github.workspace }}/build - # run: ctest -C Release -VV --output-on-failure + if ( -not ( Test-Path -Path ${{ env.LIBRARY_PREFIX }}\lib\libheatf.a ) ){ exit 1 } + if ( -not ( Test-Path -Path ${{ env.LIBRARY_PREFIX }}\bin\run_heatf.exe ) ){ exit 1 } + if ( -not ( Test-Path -Path ${{ env.LIBRARY_PREFIX }}\include\heatf.mod ) ){ exit 1 } + if ( -not ( Test-Path -Path ${{ env.LIBRARY_PREFIX }}\lib\pkgconfig\heatf.pc ) ){ exit 1 } + if ( -not ( Test-Path -Path ${{ env.LIBRARY_PREFIX }}\bin\run_bmiheatf.exe ) ){ exit 1 } + if ( -not ( Test-Path -Path ${{ env.LIBRARY_PREFIX }}\lib\libbmiheatf.a ) ){ exit 1 } + if ( -not ( Test-Path -Path ${{ env.LIBRARY_PREFIX }}\include\bmiheatf.mod ) ){ exit 1 } + if ( -not ( Test-Path -Path ${{ env.LIBRARY_PREFIX }}\lib\pkgconfig\bmiheatf.pc ) ){ exit 1 } + + - name: Run CTest + working-directory: ${{ github.workspace }}/build + run: ctest -C Release -VV --output-on-failure diff --git a/CMakeLists.txt b/CMakeLists.txt index 0cffe4c..af7d232 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,26 +12,16 @@ include(GNUInstallDirs) set(model_name heatf) set(bmi_name bmi${model_name}) -# Determine the Fortran BMI version. -if(DEFINED ENV{BMIF_VERSION}) - set(bmif_version $ENV{BMIF_VERSION}) -else() - set(bmif_version "2.0") -endif() -string(REPLACE "." "_" bmif_module_version ${bmif_version}) -message("-- BMIF version - ${bmif_version}") -message("-- BMIF module version - ${bmif_module_version}") +find_package(PkgConfig REQUIRED) +pkg_check_modules(BMIF REQUIRED IMPORTED_TARGET bmif) +string(REPLACE "." "_" bmif_module_version ${BMIF_VERSION}) +message("-- bmif module version - ${bmif_module_version}") +message("-- bmif library path - ${BMIF_LINK_LIBRARIES}") +message("-- bmif include dir - ${BMIF_INCLUDE_DIRS}") +include_directories(${BMIF_INCLUDE_DIRS}) set(CMAKE_Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/mod) -# Locate the installed Fortran BMI bindings (bmif library and module file) -# through CMAKE_PREFIX_PATH. -find_library(bmif_lib bmif) -find_path(bmif_inc bmif_${bmif_module_version}.mod) -include_directories(${bmif_inc}) -message("-- bmif_lib - ${bmif_lib}") -message("-- bmif_inc - ${bmif_inc}") - add_subdirectory(heat) add_subdirectory(bmi_heat) add_subdirectory(test) diff --git a/README.md b/README.md index 24e6372..46731f0 100644 --- a/README.md +++ b/README.md @@ -46,13 +46,13 @@ This example can be built on Linux, macOS, and Windows. in that repository. You can choose to build them from source or install them through a conda binary. If using fpm, the binding will be automatically downloaded and built for you. +* pkg-config ### CMake - Linux and macOS To build this example from source with CMake, using the current Fortran BMI version, run - export BMIF_VERSION=2.0 mkdir _build && cd _build cmake .. -DCMAKE_INSTALL_PREFIX= make @@ -80,12 +80,15 @@ The installation will look like | |-- bmiheatf.mod | `-- heatf.mod `-- lib - |-- libbmif.2.0.dylib - |-- libbmif.dylib -> libbmif.2.0.dylib + |-- libbmif.a + |-- libbmif.2.0.2.dylib + |-- libbmif.dylib -> libbmif.2.0.2.dylib |-- libbmiheatf.dylib - `-- libheatf.dylib - -3 directories, 9 files + |-- libheatf.dylib + `-- pkgconfig + |-- bmif.pc + |-- bmiheatf.pc + `-- heatf.pc ``` From the build directory, @@ -103,7 +106,6 @@ To configure this example from source with cmake using the current Fortran BMI version, run the following in a [Developer Command Prompt](https://docs.microsoft.com/en-us/dotnet/framework/tools/developer-command-prompt-for-vs) - set "BMIF_VERSION=2.0" mkdir _build && cd _build cmake .. ^ -G "NMake Makefiles" ^ diff --git a/bmi_heat/CMakeLists.txt b/bmi_heat/CMakeLists.txt index 8f86d3b..862cc21 100644 --- a/bmi_heat/CMakeLists.txt +++ b/bmi_heat/CMakeLists.txt @@ -1,12 +1,18 @@ # bmi-heat +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/${bmi_name}.pc.cmake + ${CMAKE_CURRENT_BINARY_DIR}/${bmi_name}.pc + @ONLY +) + # Create shared library, except on Windows. if(WIN32) add_library(${bmi_name} bmi_heat.f90) else() add_library(${bmi_name} SHARED bmi_heat.f90) endif() -target_link_libraries(${bmi_name} ${model_name} ${bmif_lib}) +target_link_libraries(${bmi_name} ${model_name} ${BMIF_LINK_LIBRARIES}) add_executable(run_${bmi_name} bmi_main.f90) target_link_libraries(run_${bmi_name} ${bmi_name}) @@ -25,3 +31,7 @@ install( FILES ${CMAKE_Fortran_MODULE_DIRECTORY}/${bmi_name}.mod DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) +install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/${bmi_name}.pc + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig +) diff --git a/bmi_heat/bmiheatf.pc.cmake b/bmi_heat/bmiheatf.pc.cmake new file mode 100644 index 0000000..000cde1 --- /dev/null +++ b/bmi_heat/bmiheatf.pc.cmake @@ -0,0 +1,11 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: @bmi_name@ +Description: BMI for the heatf model +Version: @CMAKE_PROJECT_VERSION@ +Requires: @model_name@, @BMIF_LIBRARIES@ +Libs: -L${libdir} -l@bmi_name@ +Cflags: -I${includedir} diff --git a/heat/CMakeLists.txt b/heat/CMakeLists.txt index 98f0781..710f352 100644 --- a/heat/CMakeLists.txt +++ b/heat/CMakeLists.txt @@ -1,5 +1,11 @@ # heat +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/${model_name}.pc.cmake + ${CMAKE_CURRENT_BINARY_DIR}/${model_name}.pc + @ONLY +) + # Create shared library, except on Windows. if(WIN32) add_library(${model_name} heat.f90) @@ -24,3 +30,7 @@ install( FILES ${CMAKE_Fortran_MODULE_DIRECTORY}/${model_name}.mod DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) +install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/${model_name}.pc + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig +) diff --git a/heat/heatf.pc.cmake b/heat/heatf.pc.cmake new file mode 100644 index 0000000..3e305de --- /dev/null +++ b/heat/heatf.pc.cmake @@ -0,0 +1,10 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: @model_name@ +Description: The two-dimensional heat equation in Fortran +Version: @CMAKE_PROJECT_VERSION@ +Libs: -L${libdir} -l@model_name@ +Cflags: -I${includedir} diff --git a/sample.cfg b/sample.cfg deleted file mode 100644 index e69de29..0000000