C++ και CMake - αδέρφια για πάντα, μέρος II

C++ και CMake - αδέρφια για πάντα, μέρος II

Στο προηγούμενο μέρος Αυτή η διασκεδαστική ιστορία μίλησε για την οργάνωση μιας βιβλιοθήκης κεφαλίδων μέσα στη γεννήτρια συστήματος δημιουργίας CMake.

Αυτή τη φορά θα προσθέσουμε μια μεταγλωττισμένη βιβλιοθήκη σε αυτήν και θα μιλήσουμε επίσης για τη σύνδεση των μονάδων μεταξύ τους.

Όπως και πριν, όσοι είναι ανυπόμονοι μπορούν αμέσως μεταβείτε στο ενημερωμένο αποθετήριο και αγγίξτε τα πάντα με τα χέρια σας.


περιεχόμενο

  1. διαιρέστε
  2. Κατακτώ

διαιρέστε

Το πρώτο πράγμα που πρέπει να κάνουμε για να επιτύχουμε τον υψηλό στόχο μας είναι να χωρίσουμε το λογισμικό που αναπτύσσουμε σε καθολικά, απομονωμένα μπλοκ που είναι ομοιόμορφα από τη σκοπιά του χρήστη.

Στο πρώτο μέρος, περιγράφηκε ένα τέτοιο τυπικό μπλοκ - ένα έργο με βιβλιοθήκη κεφαλίδων. Τώρα ας προσθέσουμε μια μεταγλωττισμένη βιβλιοθήκη στο έργο μας.

Για να γίνει αυτό, ας αφαιρέσουμε την υλοποίηση της συνάρτησης myfunc σε ξεχωριστό .cpp-αρχείο:

diff --git a/include/mylib/myfeature.hpp b/include/mylib/myfeature.hpp
index 43db388..ba62b4f 100644
--- a/include/mylib/myfeature.hpp
+++ b/include/mylib/myfeature.hpp
@@ -46,8 +46,5 @@ namespace mylib

         ~  see mystruct
      */
-    inline bool myfunc (mystruct)
-    {
-        return true;
-    }
+    bool myfunc (mystruct);
 }
diff --git a/src/mylib/myfeature.cpp b/src/mylib/myfeature.cpp
new file mode 100644
index 0000000..abb5004
--- /dev/null
+++ b/src/mylib/myfeature.cpp
@@ -0,0 +1,9 @@
+#include <mylib/myfeature.hpp>
+
+namespace mylib
+{
+    bool myfunc (mystruct)
+    {
+        return true;
+    }
+}

Στη συνέχεια ορίζουμε τη βιβλιοθήκη που θα μεταγλωττιστεί (myfeature), το οποίο θα αποτελείται από αυτό που λήφθηκε στο προηγούμενο βήμα .cpp-αρχείο. Η νέα βιβλιοθήκη προφανώς απαιτεί υπάρχουσες κεφαλίδες και για να το παρέχει αυτό, μπορεί και πρέπει να συνδεθεί με τον υπάρχοντα σκοπό mylib. Επιπλέον, η μεταξύ τους σύνδεση είναι δημόσια, πράγμα που σημαίνει ότι όλα με τα οποία θα συνδεθεί ο στόχος myfeature, θα λάβει αυτόματα το φορτίο και τον στόχο mylib (περισσότερα για τις μεθόδους πλεξίματος).

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 108045c..0de77b8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -64,6 +64,17 @@ target_compile_features(mylib INTERFACE cxx_std_17)

 add_library(Mylib::mylib ALIAS mylib)

+###################################################################################################
+##
+##      Компилируемая библиотека
+##
+###################################################################################################
+
+add_library(myfeature src/mylib/myfeature.cpp)
+target_link_libraries(myfeature PUBLIC mylib)
+
+add_library(Mylib::myfeature ALIAS myfeature)
+

Στη συνέχεια, θα βεβαιωθούμε ότι η νέα βιβλιοθήκη είναι επίσης εγκατεστημένη στο σύστημα:

@@ -72,7 +83,7 @@ add_library(Mylib::mylib ALIAS mylib)

 install(DIRECTORY include/mylib DESTINATION include)

-install(TARGETS mylib EXPORT MylibConfig)
+install(TARGETS mylib myfeature EXPORT MylibConfig)
 install(EXPORT MylibConfig NAMESPACE Mylib:: DESTINATION share/Mylib/cmake)

 include(CMakePackageConfigHelpers)

Πρέπει να σημειωθεί ότι για το σκοπό myfeature, όσον αφορά mylib δημιουργήθηκε ένα ψευδώνυμο με πρόθεμα Mylib::. Το ίδιο γράφεται και για τους δύο σκοπούς κατά την εξαγωγή τους για εγκατάσταση στο σύστημα. Αυτό καθιστά δυνατή την ομοιόμορφη εργασία με στόχους για οποιονδήποτε δεσμευτικό σύστημα.

Μετά από αυτό, το μόνο που μένει είναι να συνδέσουμε τις δοκιμές μονάδων με τη νέα βιβλιοθήκη (συνάρτηση myfunc αφαιρέθηκε από τον τίτλο, οπότε τώρα πρέπει να συνδέσετε):

diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 5620be4..bc1266c 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -4,7 +4,7 @@ add_executable(mylib-unit-tests test_main.cpp)
 target_sources(mylib-unit-tests PRIVATE mylib/myfeature.cpp)
 target_link_libraries(mylib-unit-tests
     PRIVATE
-        Mylib::mylib
+        Mylib::myfeature
         doctest::doctest
 )

Επικεφαλίδες (Mylib::mylib) τώρα δεν χρειάζεται να συνδεθείτε ξεχωριστά, γιατί, όπως αναφέρθηκε ήδη, συνδέονται αυτόματα μαζί με τη βιβλιοθήκη (Mylib::myfeature).

Και ας προσθέσουμε μερικές αποχρώσεις για να εξασφαλίσουμε μετρήσεις κάλυψης λαμβάνοντας υπόψη τη νεοαφιχθέντα βιβλιοθήκη:

@@ -15,11 +15,16 @@ if(MYLIB_COVERAGE AND GCOVR_EXECUTABLE)
     target_compile_options(mylib-unit-tests PRIVATE --coverage)
     target_link_libraries(mylib-unit-tests PRIVATE gcov)

+    target_compile_options(myfeature PRIVATE --coverage)
+    target_link_libraries(myfeature PRIVATE gcov)
+
     add_custom_target(coverage
         COMMAND
             ${GCOVR_EXECUTABLE}
-                --root=${PROJECT_SOURCE_DIR}/include/
-                --object-directory=${CMAKE_CURRENT_BINARY_DIR}
+                --root=${PROJECT_SOURCE_DIR}/
+                --filter=${PROJECT_SOURCE_DIR}/include
+                --filter=${PROJECT_SOURCE_DIR}/src
+                --object-directory=${PROJECT_BINARY_DIR}
         DEPENDS
             check
     )

Μπορείτε να προσθέσετε περισσότερες βιβλιοθήκες, εκτελέσιμα κ.λπ. Δεν έχει σημασία πόσο ακριβώς συνδέονται μεταξύ τους μέσα στο έργο. Το μόνο σημαντικό πράγμα είναι ποιοι στόχοι είναι η διεπαφή της ενότητας μας, δηλαδή προεξέχουν.

Κατακτώ

Τώρα έχουμε τυπικές μονάδες μπλοκ και μπορούμε να τις κυριαρχήσουμε: να τις συνθέσουμε σε μια δομή οποιασδήποτε πολυπλοκότητας, να τις εγκαταστήσουμε σε ένα σύστημα ή να τις συνδέσουμε μεταξύ τους μέσα σε ένα ενιαίο σύστημα συναρμολόγησης.

Εγκατάσταση στο σύστημα

Μία από τις επιλογές για τη χρήση της μονάδας είναι να εγκαταστήσουμε τη μονάδα μας στο σύστημα.

cmake --build путь/к/сборочной/директории --target install

Μετά από αυτό, συνδέεται με οποιοδήποτε άλλο έργο χρησιμοποιώντας την εντολή find_package.

find_package(Mylib 1.0 REQUIRED)

Σύνδεση ως υπομονάδα

Μια άλλη επιλογή είναι να συνδέσουμε το φάκελο με το έργο μας σε ένα άλλο έργο ως υπομονάδα χρησιμοποιώντας την εντολή add_subdirectory.

Χρήση

Οι μέθοδοι δέσμευσης είναι διαφορετικές, αλλά το αποτέλεσμα είναι το ίδιο. Και στις δύο περιπτώσεις, οι στόχοι θα είναι διαθέσιμοι στο έργο χρησιμοποιώντας την ενότητα μας Mylib::myfeature и Mylib::mylib, το οποίο μπορεί να χρησιμοποιηθεί, για παράδειγμα, ως εξής:

add_executable(some_executable some.cpp sources.cpp)
target_link_libraries(some_executable PRIVATE Mylib::myfeature)

Συγκεκριμένα στην περίπτωσή μας η βιβλιοθήκη Mylib::myfeature πρέπει να συνδεθούν όταν είναι απαραίτητο να συνδεθούν με τη βιβλιοθήκη libmyfeature. Εάν υπάρχουν αρκετές κεφαλίδες, τότε αξίζει να χρησιμοποιήσετε τη βιβλιοθήκη Mylib::mylib.

Οι στόχοι CMake μπορεί να είναι δύσκολοι, για παράδειγμα, να προορίζονται μόνο για την προώθηση ορισμένων ιδιοτήτων, εξαρτήσεων κ.λπ. Ταυτόχρονα, η εργασία μαζί τους συμβαίνει με τον ίδιο τρόπο.

Αυτό έπρεπε να πάρουμε.

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο