CMake - Макрос уровня проекта добавляет к уровню приложения target_link_libraries

0

У меня в моем проекте много библиотек и много отдельных приложений. В некоторых из моих библиотек есть библиотеки зависимостей, некоторые из них - внешние, и я бы хотел, чтобы файлы приложения CMakeList.txt были проще. Я надеюсь использовать макросы для упрощения.

Ниже представлен значительно сокращенный тестовый пример. Например, в моем проекте, включая одну из моих библиотек, требуется также include_directories, link_directories и target_link_libraries для ImageMagick, pugixml, jsoncpp, liboauthcpp и т.д. И некоторые из этих сторонних библиотек требуют флагов компилятора. Моя проектная версия макроса _LIB() ниже будет намного длиннее...

Вопрос: Есть ли способ, с помощью которого макрос _LIB() может автоматически добавлять что-то в target_link_libraries, которые вызывают макрос?

Я не уверен, как это сделать, потому что target_link_libraries аргумент 1 является целевым именем, которое изменяется для каждого приложения.

~/codeTest/CMakeLists.txt

cmake_minimum_required(VERSION 2.6)
project(codeTest)

macro(_LIB)
  include_directories(~/codeTest/lib)
  link_directories(~/codeTest/lib)
endmacro()

add_subdirectory(lib)
add_subdirectory(app)

~/codeTest/Library/CMakeLists.txt

include_directories(~/codeTest/lib)
add_library(lib lib.cpp)

~/codeTest/Library/lib.h

#ifndef __LIB__
#define __LIB__

namespace LIB {

unsigned long libFunc(unsigned long inValue);

}

#endif

~/codeTest/Library/lib.cpp

#include <lib.h>

namespace LIB {

unsigned long libFunc(unsigned long inValue) {
   return inValue+1;
}

}

~/codeTest/приложение /CMakeLists.txt

_LIB()
add_executable(app app.cpp)
target_link_libraries(app lib)

~/codeTest/приложение /app.cpp

#include <lib.h>
using namespace LIB;

int main() {
   unsigned long x = 1;
   unsigned long y = libFunc(x);
}
Теги:
cmake
macros

3 ответа

1

Рассмотрите возможность кодирования требований к использованию в самих мишенях вместо использования макросов.

Это будет "современный cmake":

http://www.cmake.org/cmake/help/git-next/manual/cmake-buildsystem.7.html

http://www.kdab.com/modern-cmake-with-qt-and-boost/

http://www.steveire.com/WhatWhyHowCMake.pdf

http://www.cmake.org/cmake/help/v3.0/manual/cmake-packages.7.html

1

С ростом сложности вашего проекта вы скоро узнаете, что несколько директив {link,include}_directories, собранных в макросе, являются негибким решением, и они должны быть указаны явно.

Я рекомендую вам принять во внимание идею модулей (/usr/share/cmake/Modules/): для каждой из ваших внешних зависимостей используйте файл Find*.cmake который можно найти в каталоге cmake modules (см. Выше) или в пакетный (если его авторы написали соответствующий модуль). Или вы можете написать это самостоятельно.

Эти модули обычно определяют несколько переменных (например, Boost_INCLUDE_DIRS, Boost_LIBRARY_DIRS), которые вы будете использовать только в тех подпроектах, которые действительно нужны.

Таким образом, для каждого подпроекта, который вы указываете, include_... директивы include_.../link_... явно ссылающиеся на переменные, определенные в модулях или в других ваших подпроектах (для внутренних зависимостей).

Более того, макросы и функции в cmake действительно очень непредсказуемы для пользователей, которые ожидают, что они будут вести себя как традиционные функции в известных языках программирования (C, Java, Ruby ,...), когда вы начинаете добавлять к ним аргументы; читайте о кэшировании переменных, оглавлениях и преобразованиях между строками и списками.

0

Я мог бы рекомендовать создание библиотеки INTERFACE, если вы можете группировать некоторые из ваших зависимостей в 1 цель таким образом.

Например,

add_library(ImageMagick ...)
#...etc gather all library targets however is conviennt

add_library(CoreDependencies INTERFACE)
target_link_libraries(CoreDependencies PUBLIC ImageMagick ...)

Тогда в ваших приложениях вы можете просто

target_link_libraries(MyApp PRIVATE CoreDependencies)

и это принесет все, что вам нужно. Вы можете создать несколько подмножеств библиотек, если у вас действительно много разных вариантов использования.

Следует отметить, что для этого подхода требуется CMake 3. https://cmake.org/cmake/help/v3.0/manual/cmake-buildsystem.7.html#interface-libraries

Ещё вопросы

Сообщество Overcoder
Наверх
Меню