У меня в моем проекте много библиотек и много отдельных приложений. В некоторых из моих библиотек есть библиотеки зависимостей, некоторые из них - внешние, и я бы хотел, чтобы файлы приложения 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":
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
С ростом сложности вашего проекта вы скоро узнаете, что несколько директив {link,include}_directories
, собранных в макросе, являются негибким решением, и они должны быть указаны явно.
Я рекомендую вам принять во внимание идею модулей (/usr/share/cmake/Modules/
): для каждой из ваших внешних зависимостей используйте файл Find*.cmake
который можно найти в каталоге cmake modules (см. Выше) или в пакетный (если его авторы написали соответствующий модуль). Или вы можете написать это самостоятельно.
Эти модули обычно определяют несколько переменных (например, Boost_INCLUDE_DIRS
, Boost_LIBRARY_DIRS
), которые вы будете использовать только в тех подпроектах, которые действительно нужны.
Таким образом, для каждого подпроекта, который вы указываете, include_...
директивы include_...
/link_...
явно ссылающиеся на переменные, определенные в модулях или в других ваших подпроектах (для внутренних зависимостей).
Более того, макросы и функции в cmake действительно очень непредсказуемы для пользователей, которые ожидают, что они будут вести себя как традиционные функции в известных языках программирования (C
, Java
, Ruby
,...), когда вы начинаете добавлять к ним аргументы; читайте о кэшировании переменных, оглавлениях и преобразованиях между строками и списками.
Я мог бы рекомендовать создание библиотеки 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