Чтобы сделать одно ясно: вы a.cpp скомпилированы в lib «A». Это означает, что любому пользователю A нужно будет указать target_link_libraries
с A. Никоим образом не обойти его. Если у вас 10 приложений, использующих A, вам нужно будет указать target_link_libraries
десять раз.
Мой ответ касается второй проблемы вашего вопроса, и я считаю, что это более важно:
Как избавиться от цепочки включений?
Включив ah в bh и используя свой метод в bh, вы добавляете «неявную» зависимость. Как вы заметили, любой пользователь b.h также нуждается в a.h. Вообще говоря, существует два подхода.
Это не имеет ничего общего с CMake, но касается инкапсуляции. Пользователям вашей библиотеки (включая вас самих) не нужно беспокоиться о ее внутренней реализации. Это означает: не включать b.h в a.h.
Вместо этого переместите include в файл .cpp. Таким образом, вы нарушаете цепочку. Например. что-то вроде
// b.h
void f();
struct X
{
void g();
};
// b.cpp
#include b.h
#include a.h
void X::g( )
{
f();
}
Таким образом, использование a.h «содержится» в файле cpp, и любой, кто использует вашу библиотеку, должен включать только b.h и ссылку на b.lib.
Теперь есть ситуации, когда вам приходится принимать такую «зависимость» или где она является сознательным выбором. Например. когда у вас нет контроля над A или когда вы решили создать библиотеку, определенную в терминах классов / структур, внутренних для A.
В этом случае я предлагаю вам написать кусок кода CMake, который подготавливает все необходимые включенные в цепочку. Например. определите переменную «YOURLIB_INCLUDES» и «YOURLIB_LIBRARIES» в «YourLibConfig.cmake» и укажите, что любой пользователь вашей библиотеки должен импортировать «YourLibConfig.cmake». Это подход, который берут на себя несколько проектов на основе cmake. Например. OpenCV устанавливает файл OpenCVConfig.cmake
, VTK устанавливает VTKConfig.cmake
и подготавливает файл UseVTK.cmake
Вы можете использовать конвертер так:
xaml
:
xmlns:cnv="clr-namespace:Converters"
...
<TextBlock Text="{Binding Report, Converter={cnv:CustomNullToStringConverter NotNullValue=Solved,NullValue=''}}"/>
Конвертер:
class CustomNullToStringConverter : MarkupExtension, IValueConverter
{
public string NullValue { get; set; }
public string NotNullValue { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is string && String.IsNullOrEmpty(value as string)) return NullValue;
if (value == null) return NullValue;
return NotNullValue;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}