CMake: apka + własna biblioteka

0

Po obejrzeniu kilku kursów na YT (Pfeifera, Scotta oraz Bahadira) i po przeczytaniu kilku tutoriali. Chciałem stworzyć nastęujący bardzo prosty projekt, składający się z apki oraz wydzielonych plików na bibliotekę współdzieloną. Ogólnie to drzewo katalogów wygląda u mnie tak:

kkk/
├── app/
│   ├── CMakeLists.txt
│   └── src/
│       └── main.cpp
├── library/
│   └── foo/
│       ├── CMakeLists.txt
│       ├── include/
│       │   ├── FooTest_global.hpp
│       │   └── FooTest.hpp
│       └── src/
│          └── FooTest.cpp
└── CMakeLists.txt

Pliki CMakeowe wyglądają następująco:
kkk/CMakeLists.txt (główny)

cmake_minimum_required(VERSION 3.11)
project(Super-App
    VERSION 1.0.0
)

set(CMAKE_POSITION_INDEPENDENT_CODE ON)

add_subdirectory(library)
add_subdirectory(app)

kkk/library/foo/CMakeLists.txt

cmake_minimum_required(VERSION 3.11)
project(Foo-Library
    VERSION 1.0.0
)

add_library(Foo SHARED)
target_compile_definitions(Foo PRIVATE FOO_LIBRARY)
target_sources(Foo
    PRIVATE "src/FooTest.cpp"
    PRIVATE "include/FooTest_global.hpp"
    PUBLIC  "include/FooTest.hpp"
)

kkk/app/CMakeLists.txt

cmake_minimum_required(VERSION 3.11)
project(FooBar-App
    VERSION 1.0.0
)

add_executable(Bar)
target_sources(Bar
    PRIVATE "src/main.cpp"
)
target_link_libraries(Bar
	PRIVATE Foo
)

Teraz chodzi o to, że jeśli w pliku kkk/CMakeLists.txt zakomentuje linijkę add_subdirectory(app), wykonam polecenie cmake -S kkk/ -B build/, a później w tym katalogu make, to powstanie oczekiwany plik biblioteki.
Ale jeśli pozostawię ją odkomentowaną, to przy wykonywaniu polecenia cmake -S kkk/ -B build/ pokazuje się komunikat (fragment - żeby nie przedłużać):

CMake Warning (dev) at library/foo/CMakeLists.txt:11 (target_sources):
  Policy CMP0076 is not set: target_sources() command converts relative paths
  to absolute.  Run "cmake --help-policy CMP0076" for policy details.  Use
  the cmake_policy command to set the policy and suppress this warning.

  An interface source of target "Foo" has a relative path.
This warning is for project developers.  Use -Wno-dev to suppress it.

-- Configuring done
CMake Error at app/CMakeLists.txt:6 (add_executable):
  Cannot find source file:

    include/FooTest.hpp

Plik include/FooTest.hpp oczywiście jest co widać po drzewie katalogów.
Co jeszcze dopisać i gdzie żeby to zadziałało?

Dodam jeszcze, że chcę żeby był to taki najprostszy szkielet do dalszej pracy i następnych projektów bez plików konfiguracyjnych, które same zwiększają nr przebudowania projektu itp. Kiedyś znalazłem taki tutorial gdzie to działało ale teraz nie mogę go już odnaleźć.
Używam minimalnej wersji CMake: VERSION 3.11 bo wykorzystuję uproszczoną składnię add_library i add_executable (bez plików źródłowych, które dodaję później poprzez polecenia target_sources), natomiast mam zainstalowaną wersję 3.16.3.

0

po co masz przełącznik -S kkk?
Chyba brakuje gdzieś: add_subdirectory(foo) i CMakeLists.txt albo powinno być add_subdirectory(library/foo)

project ma występować tyko i wyłącznie w głównym CMakeLists.txt.

Nie wszystko złoto co się świci (w internecie).
Daj linki do tych linki do tych materiałów, z których korzystasz (może inni skorzystają), dostaniesz informacje ile są warte.
Ok po googlaniu widzę, że to są źródła godne zaufania.

0
MarekR22 napisał(a):

po co masz przełącznik -S kkk?

Bo polecenie cmake -S kkk/ -B build/ wywołuję z katalogu nadrzędnego, w którym znajdują się te katalogi: kkk/ i build/. Mógłbym dać build/ wewnątrz kkk/ ale nie lubię mieć binarek w tym samym katalogu co pliki źródłowe. Polecenie cmake -S . -B ../build/ też mi jakoś nie przypasowało ;)

MarekR22 napisał(a):

Chyba brakuje gdzieś: add_subdirectory(foo) i CMakeLists.txt albo powinno być add_subdirectory(library/foo)

mam add_subdirectory(library/foo) po prostu wkleiłem jakimś cudem starszą wersję, gdzie biblioteka znajdowała się bezpośrednio w katalogu library/.

MarekR22 napisał(a):

project ma występować tyko i wyłącznie w głównym CMakeLists.txt.

Ok usunąłem ale problem nie zniknął

0
ReallyGrid napisał(a):
MarekR22 napisał(a):

po co masz przełącznik -S kkk?

Bo polecenie cmake -S kkk/ -B build/ wywołuję z katalogu nadrzędnego, w którym znajdują się te katalogi: kkk/ i build/. Mógłbym dać build/ wewnątrz kkk/ ale nie lubię mieć binarek w tym samym katalogu co pliki źródłowe. Polecenie cmake -S . -B ../build/ też mi jakoś nie przypasowało ;)

A dobra już łapię. Doczytałem help i po prostu ja robię to zwykle tak:

mkdir build
cd build
cmake ../kkk

Czyli używam pierwszej formy a ty trzeciej:

$ cmake --help
Usage

  cmake [options] <path-to-source>
  cmake [options] <path-to-existing-build>
  cmake [options] -S <path-to-source> -B <path-to-build>

Specify a source directory to (re-)generate a build system for it in the
current working directory.  Specify an existing build directory to
re-generate its build system.

Options
  -S <path-to-source>          = Explicitly specify a source directory.
  -B <path-to-build>           = Explicitly specify a build directory.
0

Problem rozwiązałem ale nie rozumiem do końca dlaczego takie rozwiązanie działa.
Mianowicie musiałem w pliku library/foo/CMakeFiles.txt dodać linijki 12-15 czyli wywołanie target_include_directories. Plik z symbolami do exportu biblioteki nie jest konieczny na tym etapie więc go usunąłem. Cały plik wygląda teraz następująco:

cmake_minimum_required(VERSION 3.11)
project(Foo-Library
    VERSION 1.0.0
    DESCRIPTION "The internal math-libraries."
)

add_library(Foo SHARED)
target_sources(Foo
    PRIVATE "src/FooTest.cpp"
    PUBLIC  "${CMAKE_CURRENT_SOURCE_DIR}/include/FooTest.hpp"   # musiałem dodać ${CMAKE_CURRENT_SOURCE_DIR}/, zmiana od cmake 3.13
)
target_include_directories(Foo                  # linijka dodana
    PUBLIC ${PROJECT_SOURCE_DIR}/include        # linijka dodana
    PRIVATE ${PROJECT_SOURCE_DIR}/src           # linijka dodana
)                                               # linijka dodana

Nie rozumiem po co muszę dodać to wywołanie target_include_directories skoro wyżej mam już target_sources, gdzie określam wszystkie pliki źródłowe wraz z ich widocznością do zbudowania celu. Dokumentacja cmake dla tych dwóch wywołań też niespecjalnie się różni:
Dla target_include_directories

Specifies include directories to use when compiling a given target.

Dla target_sources

Specifies sources to use when building a target and/or its dependents.

Jedno i drugie służy by określic źródła/katalogi, które posłużą do zbudowania konkretnego celu. Po co więc się powtarzać?

0

Wydaje mi się, że to chodzi o to:

PUBLIC and INTERFACE items will populate the INTERFACE_INCLUDE_DIRECTORIES property of <target>. The following arguments specify include directories.
https://cmake.org/cmake/help/latest/command/target_include_directories.html

Zobacz czy manualne ustawienie INTERFACE_INCLUDE_DIRECTORIES nie da tego samego efektu.

1

target_include_directories oraz target_sources to jednak nie to samo. Może ten link wyjaśni co nieco.

1 użytkowników online, w tym zalogowanych: 0, gości: 1