Мультиплатформенный проект C ++: Включение специфичных для платформы источников - PullRequest
2 голосов
/ 09 июля 2009

У меня для некоторых моих классов разные реализации для ОС.
Моя исходная структура выглядит так:

  • включить / AExample.h
  • включать / окна / WindowsExample.h
  • включить / Linux / LinuxExample.h
  • ЦСИ / AExample.cpp
  • ЦСИ / окна / WindowsExample.cpp
  • SRC / Linux / LinuxExample.cpp

классы A * являются интерфейсами для конкретных реализаций

Моя текущая сборочная система - cmake, но на данный момент она способна собирать только версию Linux.

В сборке Windows мне нужно только включить файл windows / *, а в linux только файлы linux / *

Мне нужно

  • включает только файлы, которые имеют отношение к моей текущей сборке
  • выберите правильную реализацию, когда мне нужен экземпляр AExample

Какие техники вы можете порекомендовать, чтобы реализовать это на профессиональном уровне?

Ответы [ 3 ]

8 голосов
/ 09 июля 2009

Это довольно просто в CMake.

Просто попросите файл CMakeLists.txt проверить платформу и добавьте соответствующие файлы или включите соответствующий подкаталог при необходимости.

Основной синтаксис:

IF(WIN32)
    # Do windows specific includes
ELSEIF(UNIX)
    # Do linux specific includes
ENDIF(WIN32)
2 голосов
/ 09 июля 2009

Если заголовки имеют одинаковые имена, но они находятся в разных иерархиях, вы можете просто правильно установить флаг -I (включить путь) для вашего компилятора.Это гораздо проще, чем обрабатывать все зависимые от платформы включения отдельно.

Если заголовки находятся в одном и том же каталоге и / или вы хотите что-то изменить, вы обычно делаете это в своем коде C / C ++:

#ifdef _WIN32
  .. include Win headers ..
#endif

#ifdef LINUX
  .. include Linux headers ...
#endif

Я бы не рекомендовал решение, специфичное для cmake, если вы не уверены, что в дальнейшем вам не нужно переключать систему сборки.

0 голосов
/ 09 июля 2015

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

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

Код, специфичный для платформы, должен быть четко определен на уровне файлов: например, используйте структуру каталогов с каталогами для каждой платформы и поместите все исходные файлы для конкретной платформы в соответствующий каталог. Исходные файлы не должны содержать код для нескольких платформ или любые проверки платформ препроцессора (за исключением одного исключения). Кроме того, источник, специфичный для платформы, как правило, не должен создаваться напрямую или #include d. Вместо этого, специфичный для платформы код должен использоваться только косвенно, через неплатформенные исходные файлы, которые не содержат ничего, кроме проверок платформы и #include s специфичных для платформы файлов.

Пример исходной организации:

src/
  main.cpp
  foo.h
  foo.cpp
  windows/
    foo.cpp.inc
  posix/
    foo.cpp.inc

Пример исходного содержимого:

// main.cpp
#include "foo.h"

int main() {
  foo();
}

// foo.h
void foo();

// foo.cpp
#if defined(_WIN32)
#  include "windows/foo.cpp.inc"
#elif __has_include(<unistd.h>)
#  include<unistd.h>
#  if defined(_POSIX_VERSION)
#    include "posix/foo.cpp.inc"
#  endif
#else
#  error Unknown platform
#endif

// windows/foo.cpp.inc
#include "foo.h"

#include <iostream>
#include <Windows.h>

void foo() {
  std::cout << "Windows\n";
}

// posix/foo.cpp.inc
#include "foo.h"

#include <iostream>
#include <unistd.h>

void foo() {
  std::cout << "POSIX\n";
}

Сборка и вывод Windows:

cl.exe /EHsc /W4 /WX src\main.cpp src\foo.cpp
main

Windows

Сборка и вывод Linux:

g++ -Wall -Wextra -Werror -Isrc src/main.cpp src/foo.cpp
./a.out

1042 * POSIX *

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

Также возможно смешать эту технику с использованием системы сборки; код, который разделяет файловую структуру между платформами, может использовать это, в то время как модули, уникальные для разных платформ, могут обрабатываться системой сборки.

...