Предположим, что я пишу кроссплатформенную библиотеку, я должен организовать код таким образом, чтобы было разное поведение для разных платформ, и это поведение (или определение) выбиралось во время компиляции на основе платформы, где моя библиотека составляется.
«Обычный» способ сделать это в C ++ — это загрязнить код большим количеством #ifdef
при написании метода или класса.
Проблема с подходом заключается в том, что:
#ifdef
Поскольку в C ++ 11 появилось много новых функций, мне было интересно, если что-то изменилось и есть ли новые опции для этого.
Вы должны использовать свою систему сборки для этого. Вы должны предоставить заголовкам независимые от платформы объявления функций и определений классов. Затем, в зависимости от целевой платформы, система сборки должна скомпилировать соответствующие реализации этих функций и классов.
Например, давайте рассмотрим создание окон для отображения графики или элементов графического интерфейса. Если вы не используете библиотеку для этого, вы должны написать кросс-платформенный код самостоятельно. Во-первых, вы должны подумать о том, каким должен быть независимый от платформы интерфейс. Возможно, у вас есть window
класс и некоторые вспомогательные функции. Затем вы можете предоставить определение для этого класса и объявления вспомогательных функций в заголовочном файле и предоставить отдельные реализации для каждой платформы. Тогда у вас будет набор таких файлов:
window.h
window_wayland.cpp
window_winapi.cpp
window_x11.cpp
Теперь все файлы, которые должны использовать ваш класс и функции, должны просто #include <window.h>
, Все они получают одинаковые объявления функций. Однако вы указываете в конфигурации вашей системы сборки, что window_x11.cpp
должны быть скомпилированы в системах с оконной системой X11, window_wayland.cpp
в системах с Wayland, и window_winapi
на винде. Это означает, что в зависимости от платформы, на которой вы строите, вы получите реализацию этого заголовка, которая работает на целевой платформе.
Это имеет несколько хороших преимуществ:
Это не означает, что в использовании определений для выборочной компиляции различных частей вашего кода нет ничего плохого. Я предпочитаю видеть это только с небольшим количеством кода, который был локализован в зависимых от платформы частях. В идеале, обернуть зависимый от платформы код в функцию и иметь #ifdef
просто поменять реализацию.
Как именно вы делаете это выборочное построение, зависит от используемой вами системы сборки. Для системы сборки GNU вы можете добиться условной компиляции с помощью automake. Некоторые примеры приведены в документации. Простой приведенный пример:
bin_PROGRAMS = hello
if LINUX
hello_SOURCES = hello-linux.c hello-common.c
else
hello_SOURCES = hello-generic.c hello-common.c
endif
Бег automake
с этой конфигурацией сгенерирует соответствующий make-файл.
Других решений пока нет …