Skip to content

♻️ Refactor CMake structure and replace submodules with FetchContent #515

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/codecov.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
ignore:
- "extern/**/*"
- "**/python"
- "test/**/*"

Expand Down
11 changes: 0 additions & 11 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,5 @@
version: 2
updates:
- package-ecosystem: "gitsubmodule"
directory: "/"
groups:
submodules:
patterns:
- "*"
schedule:
interval: "monthly"
time: "06:00"
timezone: "Europe/Vienna"

- package-ecosystem: "github-actions"
directory: "/"
groups:
Expand Down
25 changes: 0 additions & 25 deletions .gitmodules

This file was deleted.

2 changes: 0 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,6 @@ repos:
hooks:
- id: cmake-format
additional_dependencies: [pyyaml]
- id: cmake-lint
additional_dependencies: [pyyaml]

# Format configuration files with prettier
- repo: https://github.com/pre-commit/mirrors-prettier
Expand Down
4 changes: 0 additions & 4 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
version: 2

submodules:
include: all
recursive: true

build:
os: ubuntu-22.04
tools:
Expand Down
20 changes: 4 additions & 16 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,25 @@ project(
LANGUAGES CXX
DESCRIPTION "MQT Core - The Backbone of the Munich Quantum Toolkit")

# this is to create aliases and maintain backwards compatibility
set(OLD_PROJECT_NAME "qfr")

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

include(cmake/StandardProjectSettings.cmake)
include(cmake/PreventInSourceBuilds.cmake)
include(cmake/CheckSubmodule.cmake)
include(cmake/PackageAddTest.cmake)
include(cmake/Cache.cmake)

option(BUILD_MQT_CORE_TESTS "Also build tests for the MQT Core project" ON)
option(BUILD_MQT_CORE_BENCHMARKS "Also build benchmarks for the MQT Core project")
option(BUILD_MQT_CORE_BINDINGS "Build the MQT Core Python bindings" OFF)

if(BUILD_MQT_CORE_BINDINGS)
# ensure that the BINDINGS option is set
set(BINDINGS
ON
CACHE BOOL "Enable settings related to Python bindings" FORCE)
# cmake-lint: disable=C0103
set(Python_FIND_VIRTUALENV
FIRST
CACHE STRING "Give precedence to virtualenvs when searching for Python")
# cmake-lint: disable=C0103
set(Python_ARTIFACTS_INTERACTIVE
ON
CACHE BOOL "Prevent multiple searches for Python and instead cache the results.")
Expand Down Expand Up @@ -60,27 +57,18 @@ if(NOT TARGET project_options)
enable_sanitizers(project_options)
endif()

check_submodule_present(json)
check_submodule_present(pybind11_json)
check_submodule_present(boost/config)
check_submodule_present(boost/multiprecision)
include(cmake/ExternalDependencies.cmake)

# add main library code
add_subdirectory(src)

# add test code
option(BUILD_MQT_CORE_TESTS "Also build tests for the MQT Core project" ON)
if(BUILD_MQT_CORE_TESTS)
check_submodule_present(googletest)
enable_testing()
include(GoogleTest)
add_subdirectory(test)
endif()

option(BUILD_MQT_CORE_BENCHMARKS "Also build benchmarks for the MQT Core project")
if(BUILD_MQT_CORE_BENCHMARKS)
check_submodule_present(googletest)
enable_testing()
include(GoogleTest)
add_subdirectory(eval)
endif()
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,15 @@ MQT Core encompasses:
Building (and running) is continuously tested under Linux, MacOS, and Windows using the [latest available system versions for GitHub Actions](https://github.com/actions/runner-images).
However, the implementation should be compatible with any current C++ compiler supporting C++17 and a minimum CMake version of 3.19.

MQT Core relies on some external dependencies:

- [nlohmann/json](https://github.com/nlohmann/json): A JSON library for modern C++.
- [boost/multiprecision](https://github.com/boostorg/multiprecision): A library for multiprecision arithmetic (used in the ZX package).
- [google/googletest](https://github.com/google/googletest): A testing framework for C++ (only used in tests).
- [pybind/pybind11_json](https://github.com/pybind/pybind11_json): Using nlohmann::json with pybind11 (only used for creating the Python bindings).

CMake will automatically look for installed versions of these libraries. If it does not find them, they will be fetched automatically at configure time via the [FetchContent](https://cmake.org/cmake/help/latest/module/FetchContent.html) module (check out the documentation for more information on how to customize this behavior).

It is recommended (although not required) to have [GraphViz](https://www.graphviz.org) installed for visualization purposes.

If you want to use the ZX library, it is recommended (although not strictly necessary) to have [GMP](https://gmplib.org/) installed in your system.
Expand Down
10 changes: 0 additions & 10 deletions cmake/CheckSubmodule.cmake

This file was deleted.

142 changes: 142 additions & 0 deletions cmake/ExternalDependencies.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# Declare all external dependencies and make sure that they are available.

include(FetchContent)
set(FETCH_PACKAGES "")

# A macro to declare a dependency that takes into account the different CMake versions and the
# features that they make available. In particular: - CMake 3.24 introduced the `FIND_PACKAGE_ARGS`
# option to `FetchContent` which allows to combine `FetchContent_Declare` and `find_package` in a
# single call. - CMake 3.25 introduced the `SYSTEM` option to `FetchContent_Declare` which marks the
# dependency as a system dependency. This is useful to avoid compiler warnings from external header
# only libraries. - CMake 3.28 introduced the `EXCLUDE_FROM_ALL` option to `FetchContent_Declare`
# which allows to exclude all targets from the dependency from the `all` target.
macro(DECLARE_DEPENDENCY)
cmake_parse_arguments(DEPENDENCY "SYSTEM;EXCLUDE_FROM_ALL" "NAME;URL;MD5;MIN_VERSION;ALT_NAME" ""
${ARGN})
set(ADDITIONAL_OPTIONS "")
if(DEPENDENCY_SYSTEM AND CMAKE_VERSION VERSION_GREATER_EQUAL 3.25)
list(APPEND ADDITIONAL_OPTIONS SYSTEM)
endif()
if(DEPENDENCY_EXCLUDE_FROM_ALL AND CMAKE_VERSION VERSION_GREATER_EQUAL 3.28)
list(APPEND ADDITIONAL_OPTIONS EXCLUDE_FROM_ALL)
endif()
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.28)
FetchContent_Declare(
${DEPENDENCY_NAME}
URL ${DEPENDENCY_URL}
URL_MD5 ${DEPENDENCY_MD5}
${ADDITIONAL_OPTIONS} FIND_PACKAGE_ARGS ${DEPENDENCY_MIN_VERSION} NAMES
${DEPENDENCY_ALT_NAME})
list(APPEND FETCH_PACKAGES ${DEPENDENCY_NAME})
elseif(CMAKE_VERSION VERSION_GREATER_EQUAL 3.25)
FetchContent_Declare(
${DEPENDENCY_NAME}
URL ${DEPENDENCY_URL}
URL_MD5 ${DEPENDENCY_MD5}
${ADDITIONAL_OPTIONS} FIND_PACKAGE_ARGS ${DEPENDENCY_MIN_VERSION} NAMES
${DEPENDENCY_ALT_NAME})
list(APPEND FETCH_PACKAGES ${DEPENDENCY_NAME})
elseif(CMAKE_VERSION VERSION_GREATER_EQUAL 3.24)
FetchContent_Declare(
${DEPENDENCY_NAME}
URL ${DEPENDENCY_URL}
URL_MD5 ${DEPENDENCY_MD5}
${ADDITIONAL_OPTIONS} FIND_PACKAGE_ARGS ${DEPENDENCY_MIN_VERSION} NAMES
${DEPENDENCY_ALT_NAME})
list(APPEND FETCH_PACKAGES ${DEPENDENCY_NAME})
else()
# try to get the system installed version
find_package(${DEPENDENCY_NAME} ${DEPENDENCY_MIN_VERSION} QUIET NAMES ${DEPENDENCY_ALT_NAME})
if(NOT ${DEPENDENCY_NAME}_FOUND)
FetchContent_Declare(
${DEPENDENCY_NAME}
URL ${DEPENDENCY_URL}
URL_MD5 ${DEPENDENCY_MD5})
list(APPEND FETCH_PACKAGES ${DEPENDENCY_NAME})
endif()
endif()
endmacro()

set(JSON_BuildTests
OFF
CACHE INTERNAL "")
set(JSON_MultipleHeaders
OFF
CACHE INTERNAL "")
declare_dependency(
NAME
nlohmann_json
URL
https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz
MD5
c23a33f04786d85c29fda8d16b5f0efd
MIN_VERSION
3.11.3
SYSTEM
EXCLUDE_FROM_ALL)

set(BOOST_MP_STANDALONE
ON
CACHE INTERNAL "Use standalone boost multiprecision")
declare_dependency(
NAME
boost_multiprecision
URL
https://github.com/boostorg/multiprecision/archive/refs/tags/Boost_1_84_0.tar.gz
MD5
b829378c90f4b268c79a796025c43eee
MIN_VERSION
1.74.0
ALT_NAME
Boost
SYSTEM
EXCLUDE_FROM_ALL)

if(BUILD_MQT_CORE_TESTS)
set(gtest_force_shared_crt
ON
CACHE BOOL "" FORCE)
set(FP_ARGS 1.14.0 NAMES GTest)
declare_dependency(
NAME
googletest
URL
https://github.com/google/googletest/archive/refs/tags/v1.14.0.tar.gz
MD5
c8340a482851ef6a3fe618a082304cfc
MIN_VERSION
1.14.0
ALT_NAME
GTest
SYSTEM
EXCLUDE_FROM_ALL)
endif()

if(BINDINGS)
if(NOT SKBUILD)
# Manually detect the installed pybind11 package and import it into CMake.
execute_process(
COMMAND "${Python_EXECUTABLE}" -m pybind11 --cmakedir
OUTPUT_STRIP_TRAILING_WHITESPACE
OUTPUT_VARIABLE pybind11_DIR)
list(APPEND CMAKE_PREFIX_PATH "${pybind11_DIR}")
endif()

# add pybind11 library
find_package(pybind11 CONFIG REQUIRED)

declare_dependency(
NAME
pybind11_json
URL
https://github.com/pybind/pybind11_json/archive/refs/tags/0.2.13.tar.gz
MD5
93ebbea2bb69f71febe0f83c8f88ced2
MIN_VERSION
0.2.13
SYSTEM
EXCLUDE_FROM_ALL)
endif()

# Make all declared dependencies available.
FetchContent_MakeAvailable(${FETCH_PACKAGES})
7 changes: 1 addition & 6 deletions docs/DevelopmentGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,9 @@ Ready to contribute to the project? Here is how to set up a local development en
2. Clone your fork locally

```console
$ git clone [email protected]:your_name_here/mqt-core --recursive
$ git clone [email protected]:your_name_here/mqt-core.git
```

:::{warning}
The {code}`--recursive` flag is required to also clone all the required submodules.
If you happen to forget passing the flag on your initial clone, you can initialize all the submodules by executing {code}`git submodule update --init --recursive` in the main project directory.
:::

3. Change into the project directory

```console
Expand Down
1 change: 0 additions & 1 deletion extern/boost/config
Submodule config deleted from d3b299
1 change: 0 additions & 1 deletion extern/boost/multiprecision
Submodule multiprecision deleted from 7f1dc8
1 change: 0 additions & 1 deletion extern/googletest
Submodule googletest deleted from dddb21
Loading