Методи забезпечення сумісності між платформами (C ++)?


13

Я закінчував один із моїх ранніх проектів на C ++, який (згідно з рамками) повинен бути кросплатформним. Я повністю розробив проект в Windows і Visual Studio, думаючи, що оскільки бібліотеки все є платформними, то робити збірку OSX "пізніше" було б тривіально. Це виявилося не так, але, скоріше, "код Windows" не працює належним чином, і деякі помилки компіляції повинні бути виправлені.

Які методи існують заздалегідь, щоб забезпечити сумісність коду з усіма платформами? Розробка всіх платформ одночасно, таким чином тестування коду на кожній платформі одночасно, коли нові функції додаються, а не розробляються різні версії платформи одна за одною? (*)

Дивлячись конкретно, радимо це не залежати від інструментів, а швидше "процесів розробки", які допомагають сумісності між платформами, незалежно від того, які інструменти використовуються. Як і той, що (*) вище.


Зокрема, я розробляю плагін VST з WDL-OL ( https://github.com/olilarkin/wdl-ol ) та деякими міжплатформенними бібліотеками DSP. У проектах WDL-OL створені проекти VS та Xcode, але я думаю, що проблеми виникають у бібліотеках, а потім і у відмінностях у компіляторах.


1
немає можливості забезпечити портативність, є лише способи поліпшити / максимально покращити портативність
phuclv

і чому це не дублікат? Я вважаю, що було багато подібних запитань
phuclv

Що робить ваша програма? Як би ти ним користувався? У командному рядку чи через якийсь графічний інтерфейс? Будь ласка, відредагуйте своє запитання, щоб покращити його.
Базиль Старинкевич

І які рамки ви використовуєте?
Базиль Старинкевич

Відповіді:


15

Створення портативного коду може бути дуже складним.

Спочатку кілька очевидних порад щодо мови:

  • використовувати стандартний C ++ і обережно уникати будь-якої не визначеної поведінки
  • насамперед покладатися на стандартну бібліотеку (і портативні бібліотеки, такі як прискорення )
  • завжди включайте всі очікувані заголовки. Не припускайте, що вам не потрібен заголовок, оскільки він включений в інший (тобто в одну конкретну реалізацію !): Це може спричинити помилки компіляції
  • уникайте конструкцій, які підтримуються компілятором, але не гарантуються стандартом C ++ (наприклад, анонімна структура або масив змінної довжини ): можуть спричинити помилки компіляції.
  • використовуйте параметри компілятора, щоб допомогти вам забезпечити дотримання відповідності (вимкнення конкретних розширень компілятора, максимізація рівня попереджуваних повідомлень)
  • майте на увазі, що недостатньо, щоб код працював: існує багато підводних каменів, залежних від реалізації: розмір (навіть елементарних) типів даних, символи, які за замовчуванням можуть бути підписані або непідписані , припущення про витривалість , порядок оцінки в виразах, коли ці використовувати побічні ефекти тощо.

Потім пара рекомендацій по дизайну:

  • Віддайте перевагу стандартній альтернативі бібліотеці рівноцінному функціоналу операційної системи
  • Максимально ізолюйте використання залежностей операційної системи (наприклад, у функції обгортки, керованої умовною компіляцією)

Нарешті делікатні моменти:

  • кодування символів: у багатьох системах ви можете розраховувати на utf8 . Але для Windows це більш делікатно, оскільки система або очікує ansi, або utf-16. Ви, звичайно, можете покластися на typedef (наприклад TCHAR), але це може бути складним у поєднанні зі стандартною бібліотекою (наприклад, coutvs, wcoutяка використовується залежно від використання charабо wchar_t)
  • Якщо для графічного інтерфейсу / графіки / вдосконаленого вводу / виводу ви не можете знайти портативну бібліотеку, яка відповідає вашим очікуванням / вимогам, спроектуйте загальну архітектуру, щоб ізолювати конкретні для ОС компоненти. Упаковки тут може бути недостатньо через багато різних взаємодій та концепцій.
  • Скористайтеся цікавими моделями дизайну, такими як, наприклад, абстрактна фабрика (ідеально підходить для проектування сімейств пов'язаних об'єктів, таких як інтерфейс, що відповідає специфічній ОС) або посередник (ідеально підходить для співпраці між сімействами пов'язаних об'єктів) та використовуйте їх разом із умовною компіляцією .

Але це лише поради. У цій галузі ви не можете отримати впевненість.


-Wall -Wextra -Werror
труба

1
@pipe Ви також повинні бути -pedantic.
5gon12eder

@ 5gon12eder Дуже вдалий момент у контексті цієї відповіді.
труба

11

Немає нічого, що може гарантувати, що код сумісний з платформою, крім його створення, запуску та тестування на ньому. Тому підхід усіх розумних людей полягає в тому, щоб створити, запустити і протестувати їх застосування на кожній платформі, яку вони проектують, її потрібно буде побудувати, запустити і протестувати.

Безперервна інтеграція (CI) може полегшити цей тягар для невеликих проектів, оскільки ви можете отримати дешеві або безкоштовні агенти побудови для деяких платформ (переважно Linux), займатися розробкою в Windows і просто повернутися до Linux, коли є проблеми.

Хоча OSX CI досить складний.


Немає згадки, що таке CI?
mavavilj

5
Постійна інтеграція - це, в основному, купа серверів, які запускають збірки та тести для вас.
DeadMG

@DeadMG Ви маєте на увазі як Mozilla Tinderbox?
Даміян Єрік

1
Travis CI надає безкоштовні хости побудови OSX
Daenyth

Просто використовуйте Cmake.
raaj

9

Якщо ви запитуєте про "процеси розробки", а платформа первинної розробки - це Windows з Visual Studio, я б запропонував спробувати створити ваш проект без включення "windows.h". Ви отримаєте безліч помилок компіляції, які вкажуть на багато місць, де вам потрібно буде перефактурувати свій код. Наприклад, "DWORD" не буде #defined, і вам потрібно буде замінити його uint32_tскрізь (google для, stdint.hі ви знайдете корисну інформацію про цілі типи та їхні кросплатформні визначення). Далі вам потрібно буде замінити всі дзвінки API Win32, наприклад,Sleep()з їхнім кросплатформенним еквівалентом (знову ж, google - ваш найкращий друг, який покаже відповідні питання та відповіді на стекових * .com сайтах). Ймовірно, вам не вдасться знайти всі відповідні кросплатформні заміни для вашого коду, і вам доведеться повернути свою include "windows."директиву, але помістіть її #ifdef _WIN32- детальніше тут

Продовжуйте задавати конкретніші запитання та отримувати відповіді - це загальна пропозиція щодо того, "яким має бути процес розвитку"

EDIT 1 Ще одна моя пропозиція - використовувати gcc та / або кланг на вашій машині розвитку Windows (разом із Visual Studio)


3

Це залежить від згаданих вами "деяких помилок компіляції". Не знаючи, якими вони були, неможливо бути конкретним.

У мене є код крос-платформи для Windows / Linux / iOS / Android / Mac. Кожна нова платформа приносила додаткові помилки та попередження під час її першого додавання. Ви швидко дізнаєтесь, які конструкції приносять проблеми. Або уникайте їх, або абстрагуйте відмінності в заголовку з #ifdefs. Намагайтеся ніколи не знаходитись #ifdefміж платформами в межах самого коду.

Один приклад:

void myfunction(MyClass &);
myfunction(MyClass());

створює тимчасовий екземпляр, MyClassякий видаляється після myfunctionповернення. З деякими моїми компіляторами C ++ цей екземпляр читається / записується (а той факт, що він тимчасовий і незабаром буде знищений, не хвилює компілятора). З іншими myfunctionмає бути переосмислено, щоб взяти const MyClass &, або компілятор скаржиться. Не має значення, що говорить стандарт C ++, чи компілятор є правильним, а який - неправильним. Зіткнувшись помилку кілька разів , що я знаю (а) або оголосити тимчасову змінну типу MyClassі передати , що myfunctionабо (б) оголосити посилання constв myfunctionі використовувати mutableтут і там deconstify.

Підсумок: накопичуйте досвід та розробляйте власні стандарти кодування.


2
Це неправильна особливість MSVC. Якщо ваша думка полягає в тому, що розвиток на 1 системі дозволяє їм повзати, взяти пункт. Але ця конкретна річ - це не те, що ви повинні робити.
JDługosz

1
Хороша річ у використанні декількох ланцюжків інструментів - це те, що загальний підмножина, яку вони приймають, швидше за все є правильною, сумісною зі стандартами C ++, ніж те, що кожен з них приймає індивідуально. У вашому випадку показаний код явно неправильний стандартом, і обидва згадані виправлення є дійсними альтернативами. Я б сказав, що це має значення, що говорить стандарт.
5gon12eder

1
Або я б сказав, що платформа C ++ є більш обмежуючою, ніж те, що говорить стандарт. Іншими словами, навіть якщо стандарт так говорить, ви все ще підпадаєте під найменші загальні знаменники (або, найменше, можливості постачальника) для платформ, які ви повинні підтримувати. Існує безліч бібліотек з відкритим кодом, які повинні були виключити, наприклад, C ++ 11, оскільки частина їх складових (як у громадян) не здатна C ++ 11.
rwong

3

Можливим способом допомогти переносимості може бути покладатися лише на декларації та функції, передбачені стандартом C ++ 11 , а також на використанні міжплатформних бібліотек та рамок, таких як POCO & Qt .

Але навіть це не є невдалим. Згадайте афоризм

немає такої речі, як портативна програма, є лише програми, які успішно перенесені (на якусь певну платформу)

Маючи практику, дисципліну та багато досвіду, перенесення програми на іншу платформу, як правило, можна зробити швидко. Але досвід і ноу-хау дуже важливі.


1
Ще одна порада полягає в тому, що коли перенесення здійснюється різними людьми та командою, зміни коду повинні бути знову інтегровані в основну лінію. В іншому випадку відмінності платформ стають знаннями, які зберігає команда, яка це зробила.
rwong
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.