Skip to content

Commit

Permalink
Update dependency handling logic in meson and CMake (#9)
Browse files Browse the repository at this point in the history
- allow meson to find dependencies before falling back to subprojects
- install module files in meson builds
- add custom CMake finder for mctc-lib
- add CMake macro to find (cmake/pkgconf) or include (subproject/fetch) dependencies
  • Loading branch information
awvwgk authored Jul 26, 2021
1 parent 0184acc commit 974fb59
Show file tree
Hide file tree
Showing 9 changed files with 238 additions and 39 deletions.
16 changes: 11 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,18 @@ project(
# Follow GNU conventions for installing directories
include(GNUInstallDirs)

# Collect subprojects
set(lib-deps)
add_subdirectory("subprojects" EXCLUDE_FROM_ALL)

# General configuration information
add_subdirectory("config")

# Collect subprojects
if(NOT TARGET "mctc-lib::mctc-lib")
find_package("mctc-lib")
endif()
set(
lib-deps
"mctc-lib::mctc-lib"
)

# Collect source of the project
set(srcs)
add_subdirectory("src")
Expand Down Expand Up @@ -61,6 +66,7 @@ target_include_directories(
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/${module-dir}>
)

# Add example application
Expand Down Expand Up @@ -88,7 +94,7 @@ install(
install(
DIRECTORY
"${CMAKE_CURRENT_BINARY_DIR}/include/"
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}"
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${module-dir}"
)
# Package license files
install(
Expand Down
21 changes: 21 additions & 0 deletions config/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,19 @@

option(BUILD_SHARED_LIBS "Whether the libraries built should be shared" FALSE)

if(NOT DEFINED "${PROJECT_NAME}-dependeny-method")
set(
"${PROJECT_NAME}-dependency-method"
"subproject" "cmake" "pkgconf" "fetch"
)
endif()

set(
module-dir
"${PROJECT_NAME}/${CMAKE_Fortran_COMPILER_ID}-${CMAKE_Fortran_COMPILER_VERSION}"
)
set(module-dir "${module-dir}" PARENT_SCOPE)

# Set build type as CMake does not provide defaults
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(
Expand All @@ -28,6 +41,14 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
)
endif()

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" PARENT_SCOPE)
install(
DIRECTORY
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
)

include(CMakePackageConfigHelpers)
configure_package_config_file(
"${CMAKE_CURRENT_SOURCE_DIR}/template.cmake"
Expand Down
38 changes: 20 additions & 18 deletions subprojects/CMakeLists.txt → config/cmake/Findmctc-lib.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,27 @@
# See the License for the specific language governing permissions and
# limitations under the License.

# Include the mctc-lib project
if(NOT TARGET mctc-lib)
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/mctc-lib/CMakeLists.txt)
add_subdirectory("mctc-lib")
set(_lib "mctc-lib")
set(_pkg "MCTCLIB")
set(_url "https://github.com/grimme-lab/mctc-lib")

if(NOT DEFINED "${_pkg}_FIND_METHOD")
if(DEFINED "${PROJECT_NAME}-dependency-method")
set("${_pkg}_FIND_METHOD" "${${PROJECT_NAME}-dependency-method}")
else()
set("mctc-lib-url" "https://github.com/grimme-lab/mctc-lib")
message(STATUS "Retrieving mctc-lib from ${mctc-lib-url}")
include(FetchContent)
FetchContent_Declare(
"mctc-lib"
GIT_REPOSITORY "${mctc-lib-url}"
GIT_TAG "HEAD"
)
FetchContent_MakeAvailable("mctc-lib")
set("${_pkg}_FIND_METHOD" "cmake" "pkgconf" "subproject" "fetch")
endif()
set("_${_pkg}_FIND_METHOD")
endif()

list(
APPEND lib-deps
"mctc-lib"
)
set(lib-deps "${lib-deps}" PARENT_SCOPE)
include("${CMAKE_CURRENT_LIST_DIR}/mstore-utils.cmake")

mstore_find_package("${_lib}" "${${_pkg}_FIND_METHOD}" "${_url}")

if(DEFINED "_${_pkg}_FIND_METHOD")
unset("${_pkg}_FIND_METHOD")
unset("_${_pkg}_FIND_METHOD")
endif()
unset(_lib)
unset(_pkg)
unset(_url)
115 changes: 115 additions & 0 deletions config/cmake/mstore-utils.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# This file is part of mstore.
# SPDX-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Handling of subproject dependencies
macro(
"mstore_find_package"
package
methods
url
)
string(TOLOWER "${package}" _pkg_lc)
string(TOUPPER "${package}" _pkg_uc)

foreach(method in ITEMS ${methods})

if(TARGET "${package}::${package}")
break()
endif()

if("${method}" STREQUAL "cmake")
message(STATUS "${package}: Find installed package")
find_package("${package}" CONFIG)
if("${package}_FOUND")
message(STATUS "${package}: Found installed package")
break()
endif()
endif()

if("${method}" STREQUAL "pkgconf")
find_package(PkgConfig QUIET)
pkg_check_modules("${_pkg_uc}" QUIET "${package}")
if("${_pkg_uc}_FOUND")
message(STATUS "Found ${package} via pkg-config")

add_library("${package}::${package}" INTERFACE IMPORTED)
target_link_libraries(
"${package}::${package}"
INTERFACE
"${${_pkg_uc}_LINK_LIBRARIES}"
)
target_include_directories(
"${package}::${package}"
INTERFACE
"${${_pkg_uc}_INCLUDE_DIRS}"
)
break()
endif()
endif()

if("${method}" STREQUAL "subproject")
set("${_pkg_uc}_SOURCE_DIR" "${PROJECT_SOURCE_DIR}/subprojects/${package}")
set("${_pkg_uc}_BINARY_DIR" "${PROJECT_BINARY_DIR}/subprojects/${package}")
if(EXISTS "${${_pkg_uc}_SOURCE_DIR}/CMakeLists.txt")
message(STATUS "Include ${package} from subprojects")
add_subdirectory(
"${${_pkg_uc}_SOURCE_DIR}"
"${${_pkg_uc}_BINARY_DIR}"
)

add_library("${package}::${package}" INTERFACE IMPORTED)
target_link_libraries("${package}::${package}" INTERFACE "${package}")

# We need the module directory in the subproject before we finish the configure stage
if(NOT EXISTS "${${_pkg_uc}_BINARY_DIR}/include")
make_directory("${${_pkg_uc}_BINARY_DIR}/include")
endif()

break()
endif()
endif()

if("${method}" STREQUAL "fetch")
message(STATUS "Retrieving ${package} from ${url}")
include(FetchContent)
FetchContent_Declare(
"${_pkg_lc}"
GIT_REPOSITORY "${url}"
GIT_TAG "HEAD"
)
FetchContent_MakeAvailable("${_pkg_lc}")

add_library("${package}::${package}" INTERFACE IMPORTED)
target_link_libraries("${package}::${package}" INTERFACE "${package}")

# We need the module directory in the subproject before we finish the configure stage
FetchContent_GetProperties("${_pkg_lc}" BINARY_DIR "${_pkg_uc}_BINARY_DIR")
if(NOT EXISTS "${${_pkg_uc}_BINARY_DIR}/include")
make_directory("${${_pkg_uc}_BINARY_DIR}/include")
endif()

break()
endif()

endforeach()

unset(_pkg_lc)
unset(_pkg_uc)

if(NOT TARGET "${package}::${package}")
message(FATAL_ERROR "Could not find dependency ${package}")
endif()

endmacro()
44 changes: 44 additions & 0 deletions config/install-mod.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/usr/bin/env python
# This file is part of mstore.
# SPDX-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from os import environ, listdir, makedirs
from os.path import join, isdir, exists
from sys import argv
from shutil import copy

build_dir = environ["MESON_BUILD_ROOT"]
if "MESON_INSTALL_DESTDIR_PREFIX" in environ:
install_dir = environ["MESON_INSTALL_DESTDIR_PREFIX"]
else:
install_dir = environ["MESON_INSTALL_PREFIX"]

include_dir = argv[1] if len(argv) > 1 else "include"
module_dir = join(install_dir, include_dir)

modules = []
for d in listdir(build_dir):
bd = join(build_dir, d)
if isdir(bd):
for f in listdir(bd):
if f.endswith(".mod"):
modules.append(join(bd, f))

if not exists(module_dir):
makedirs(module_dir)

for mod in modules:
print("Installing", mod, "to", module_dir)
copy(mod, module_dir)
32 changes: 17 additions & 15 deletions config/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,22 @@ if get_option('openmp')
endif

# Create the tool chain library as subproject
mctc_prj = subproject(
'mctc-lib',
version: '>=0.1',
default_options: [
'default_library=static',
],
)
mctc_dep = mctc_prj.get_variable('mctc_dep')
lib_deps += mctc_dep
inc_dirs += mctc_prj.get_variable('mctc_inc')

if install
install_data(
mctc_prj.get_variable('mctc_lic'),
install_dir: get_option('datadir')/'licenses'/meson.project_name()/'mctc-lib'
mctc_dep = dependency('mctc-lib', required: false)
if not mctc_dep.found()
mctc_prj = subproject(
'mctc-lib',
version: '>=0.2',
default_options: [
'default_library=static',
],
)
mctc_dep = mctc_prj.get_variable('mctc_dep')

if install
install_data(
mctc_prj.get_variable('mctc_lic'),
install_dir: get_option('datadir')/'licenses'/meson.project_name()/'mctc-lib'
)
endif
endif
lib_deps += mctc_dep
2 changes: 2 additions & 0 deletions config/template.cmake
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
@PACKAGE_INIT@

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")

if(NOT TARGET "@PROJECT_NAME@::@PROJECT_NAME@")
include("${CMAKE_CURRENT_LIST_DIR}/@[email protected]")

Expand Down
2 changes: 1 addition & 1 deletion config/template.pc
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ Description: @PROJECT_DESCRIPTION@
Version: @PROJECT_VERSION@
Requires: mctc-lib
Libs: -L${libdir} -l@PROJECT_NAME@
Cflags: -I${includedir} -I${includedir}/@PROJECT_NAME@/modfiles
Cflags: -I${includedir} -I${includedir}/@module-dir@
7 changes: 7 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,16 @@ if install
install_dir: get_option('datadir')/'licenses'/meson.project_name()
)

module_id = meson.project_name() / fc_id + '-' + fc.version()
meson.add_install_script(
find_program(files('config'/'install-mod.py')),
get_option('includedir') / module_id,
)

pkg = import('pkgconfig')
pkg.generate(
mstore_lib,
description: 'Molecular structure store for testing',
subdirs: ['', module_id],
)
endif

0 comments on commit 974fb59

Please sign in to comment.