diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e7ec789..cc1ae45 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,12 +7,14 @@ on: - ".github/workflows/ci.yml" - "fpm.toml" - "**.f90" + - "CMakelists.txt" pull_request: paths: - ".github/workflows/ci.yml" - "fpm.toml" - "**.f90" + - "CMakelists.txt" jobs: @@ -21,20 +23,24 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - name: CMake Configure + run: cmake -B build -S . -DCMAKE_BUILD_TYPE=Debug - name: Compile - run: cmake -DCMAKE_BUILD_TYPE=Debug -DSERIAL=1 . && make + run: cmake --build build - name: Test - run: make test + run: ctest --test-dir build gnu-cmake-release: name: gnu-cmake-release runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - name: CMake Configure + run: cmake -B build -S . -DCMAKE_BUILD_TYPE=Release - name: Compile - run: cmake -DCMAKE_BUILD_TYPE=Release -DSERIAL=1 . && make + run: cmake --build build - name: Test - run: make test + run: ctest --test-dir build gnu-fpm-debug: name: gnu-fpm-debug diff --git a/CMakeLists.txt b/CMakeLists.txt index 0340d6b..490f7ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,16 +54,25 @@ add_library(neural-fortran ) target_link_libraries(neural-fortran PRIVATE) +set_target_properties(neural-fortran PROPERTIES Fortran_MODULE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include) install(TARGETS neural-fortran) +# Install the module files +install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/ DESTINATION include) + +# Also install the cmake/Findneural-fortran.cmake file +install(FILES cmake/Findneural-fortran.cmake DESTINATION include/cmake/neural-fortran) + # Remove leading or trailing whitespace string(REGEX REPLACE "^ | $" "" LIBS "${LIBS}") if(${PROJECT_NAME}_BUILD_TESTING) + message(STATUS "Building tests") add_subdirectory(test) endif() if(${PROJECT_NAME}_BUILD_EXAMPLES) + message(STATUS "Building examples") add_subdirectory(example) endif() diff --git a/README.md b/README.md index d5bc86e..7e3a444 100644 --- a/README.md +++ b/README.md @@ -183,17 +183,31 @@ find or fetch an installation of this project while configuring your project. Th module makes sure that the `neural-fortran::neural-fortran` target is always generated regardless of how the neural-fortran is included in the project. -You can configure neural-fortran by setting the appropriate options before -including the subproject. +First, either copy `Findneural-fortran.cmake` to, say, your project's `cmake` directory +and then include it in your `CMakeLists.txt` file: + +```cmake +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +``` +or use the `CMAKE_MODULE_PATH` variable to point to the directory where it is installed. + +Next you need to set `neural-fortran_ROOT_DIR` to the directory where neural-fortran is installed +such that `neural-fortran_ROOT_DIR/lib/libneural-fortran.a` exists. The following should be added in the CMake file of your directory: ```cmake -if(NOT TARGET "neural-fortran::neural-fortran") - find_package("neural-fortran" REQUIRED) +if(NOT TARGET neural-fortran::neural-fortran) + find_package(neural-fortran REQUIRED) endif() ``` +and then to use the target in your project: + +```cmake +target_link_libraries(your_target PRIVATE neural-fortran::neural-fortran) +``` + ## Examples The easiest way to get a sense of how to use neural-fortran is to look at diff --git a/cmake/Findneural-fortran.cmake b/cmake/Findneural-fortran.cmake index 4fe8721..857df3e 100644 --- a/cmake/Findneural-fortran.cmake +++ b/cmake/Findneural-fortran.cmake @@ -1,179 +1,31 @@ -# SPDX-Identifier: MIT -# Based on https://github.com/fortran-lang/stdlib-cmake-example - -#[[.rst: -Find neural-fortran -------------------- - -Makes the neural-fortran library project available. - -Imported Targets -^^^^^^^^^^^^^^^^ - -This module provides the following imported target, if found: - -``neural-fortran::neural-fortran`` - The neural-fortran library - - -Result Variables -^^^^^^^^^^^^^^^^ - -This module will define the following variables: - -``NEURAL-FORTRAN_FOUND`` - True if the neural-fortran library is available - -``NEURAL-FORTRAN_SOURCE_DIR`` - Path to the source directory of the neural-fortran library project, - only set if the project is included as source. - -``NEURAL-FORTRAN_BINARY_DIR`` - Path to the binary directory of the neural-fortran library project, - only set if the project is included as source. - -Cache variables -^^^^^^^^^^^^^^^ - -The following cache variables may be set to influence the library detection: - -``NEURAL-FORTRAN_FIND_METHOD`` - Methods to find or make the project available. Available methods are - - ``cmake``: Try to find via CMake config file - - ``pkgconf``: Try to find via pkg-config file - - ``subproject``: Use source in subprojects directory - - ``fetch``: Fetch the source from upstream - -``NEURAL-FORTRAN_DIR`` - Used for searching the CMake config file - -``NEURAL-FORTRAN_SUBPROJECT`` -Directory to find the neural-fortran library subproject, relative to the project root - -#]] - -set(_lib "neural-fortran") -set(_pkg "NEURAL-FORTRAN") -set(_url "https://github.com/modern-fortran/neural-fortran.git") - -if(NOT DEFINED "${_pkg}_FIND_METHOD") - if(DEFINED "${PROJECT_NAME}-dependency-method") - set("${_pkg}_FIND_METHOD" "${${PROJECT_NAME}-dependency-method}") - else() - set("${_pkg}_FIND_METHOD" "cmake" "pkgconf" "subproject" "fetch") - endif() - set("_${_pkg}_FIND_METHOD") -endif() - -foreach(method ${${_pkg}_FIND_METHOD}) - if(TARGET "${_lib}::${_lib}") - break() - endif() - - if("${method}" STREQUAL "cmake") - message(STATUS "${_lib}: Find installed package") - if(DEFINED "${_pkg}_DIR") - set("_${_pkg}_DIR") - set("${_lib}_DIR" "${_pkg}_DIR") - endif() - find_package("${_lib}" CONFIG) - if("${_lib}_FOUND") - message(STATUS "${_lib}: Found installed package") - break() - endif() - endif() - - if("${method}" STREQUAL "pkgconf") - find_package(PkgConfig QUIET) - pkg_check_modules("${_pkg}" QUIET "${_lib}") - if("${_pkg}_FOUND") - message(STATUS "Found ${_lib} via pkg-config") - - add_library("${_lib}::${_lib}" INTERFACE IMPORTED) - target_link_libraries( - "${_lib}::${_lib}" - INTERFACE - "${${_pkg}_LINK_LIBRARIES}" - ) - target_include_directories( - "${_lib}::${_lib}" - INTERFACE - "${${_pkg}_INCLUDE_DIRS}" - ) - - break() - endif() - endif() - - if("${method}" STREQUAL "subproject") - if(NOT DEFINED "${_pkg}_SUBPROJECT") - set("_${_pkg}_SUBPROJECT") - set("${_pkg}_SUBPROJECT" "subprojects/${_lib}") - endif() - set("${_pkg}_SOURCE_DIR" "${PROJECT_SOURCE_DIR}/${${_pkg}_SUBPROJECT}") - set("${_pkg}_BINARY_DIR" "${PROJECT_BINARY_DIR}/${${_pkg}_SUBPROJECT}") - if(EXISTS "${${_pkg}_SOURCE_DIR}/CMakeLists.txt") - message(STATUS "Include ${_lib} from ${${_pkg}_SUBPROJECT}") - add_subdirectory( - "${${_pkg}_SOURCE_DIR}" - "${${_pkg}_BINARY_DIR}" - ) - - add_library("${_lib}::${_lib}" INTERFACE IMPORTED) - target_link_libraries("${_lib}::${_lib}" INTERFACE "${_lib}") - - # We need the module directory in the subproject before we finish the configure stage - if(NOT EXISTS "${${_pkg}_BINARY_DIR}/mod_files") - make_directory("${${_pkg}_BINARY_DIR}/mod_files") - endif() - - break() - endif() - endif() - - if("${method}" STREQUAL "fetch") - message(STATUS "Retrieving ${_lib} from ${_url}") - include(FetchContent) - FetchContent_Declare( - "${_lib}" - GIT_REPOSITORY "${_url}" - GIT_TAG "HEAD" - ) - FetchContent_MakeAvailable("${_lib}") - - add_library("${_lib}::${_lib}" INTERFACE IMPORTED) - target_link_libraries("${_lib}::${_lib}" INTERFACE "${_lib}") - - # We need the module directory in the subproject before we finish the configure stage - FetchContent_GetProperties("${_lib}" SOURCE_DIR "${_pkg}_SOURCE_DIR") - FetchContent_GetProperties("${_lib}" BINARY_DIR "${_pkg}_BINARY_DIR") - if(NOT EXISTS "${${_pkg}_BINARY_DIR}/mod_files") - make_directory("${${_pkg}_BINARY_DIR}/mod_files") - endif() - - break() - endif() - -endforeach() - -if(TARGET "${_lib}::${_lib}") - set("${_pkg}_FOUND" TRUE) -else() - set("${_pkg}_FOUND" FALSE) -endif() - -if(DEFINED "_${_pkg}_SUBPROJECT") - unset("${_pkg}_SUBPROJECT") - unset("_${_pkg}_SUBPROJECT") -endif() -if(DEFINED "_${_pkg}_DIR") - unset("${_lib}_DIR") - unset("_${_pkg}_DIR") -endif() -if(DEFINED "_${_pkg}_FIND_METHOD") - unset("${_pkg}_FIND_METHOD") - unset("_${_pkg}_FIND_METHOD") +# Find the native neural-fortran includes and library +# +# neural-fortran_INCLUDE_DIRS - where to find nf.mod, etc. +# neural-fortran_LIBRARIES - List of libraries when using neural-fortran. +# neural-fortran_FOUND - True if neural-fortran found. +# +# To use neural-fortran_ROOT_DIR to specify the prefix directory of neural-fortran + + +find_path(neural-fortran_INCLUDE_DIRS + NAMES nf.mod + HINTS ${neural-fortran_ROOT_DIR}/include ENV neural-fortran_INCLUDE_DIR) + +find_library(neural-fortran_LIBRARIES + NAMES neural-fortran + HINTS ${neural-fortran_ROOT_DIR}/lib ENV neural-fortran_LIB_DIR) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(neural-fortran DEFAULT_MSG neural-fortran_LIBRARIES neural-fortran_INCLUDE_DIRS) + +mark_as_advanced( + neural-fortran_LIBRARIES + neural-fortran_INCLUDE_DIRS) + +if(neural-fortran_FOUND AND NOT (TARGET neural-fortran::neural-fortran)) + add_library (neural-fortran::neural-fortran STATIC IMPORTED) + set_target_properties(neural-fortran::neural-fortran + PROPERTIES + IMPORTED_LOCATION ${neural-fortran_LIBRARIES} + INTERFACE_INCLUDE_DIRECTORIES ${neural-fortran_INCLUDE_DIRS}) endif() -unset(_lib) -unset(_pkg) -unset(_url)