Tecniche per garantire la compatibilità multipiattaforma (C ++)?


13

Stavo finendo uno dei miei primi progetti C ++ che (secondo il framework) dovrebbe essere multipiattaforma. Ho sviluppato il progetto completamente in Windows e Visual Studio, pensando che, dato che le librerie sono tutte multipiattaforma, fare la build dell'OSX "in seguito" sarebbe banale. Ciò si è rivelato non essere il caso, ma piuttosto il "codice di Windows" non funziona correttamente e alcuni errori di compilazione sono stati corretti.

Quali tecniche esistono per garantire in anticipo che il codice sia compatibile con tutte le piattaforme? Sviluppare tutte le piattaforme contemporaneamente, testando così il codice su ogni piattaforma contemporaneamente, quando vengono aggiunte nuove funzionalità, anziché sviluppare le diverse versioni della piattaforma una dopo l'altra? (*)

Cercare specificamente consigli che non dipendono dagli strumenti, ma piuttosto da "processi di sviluppo" che aiutano la compatibilità multipiattaforma, indipendentemente dagli strumenti utilizzati. Come quello (*) sopra.


In particolare sto sviluppando un plug-in VST con WDL-OL ( https://github.com/olilarkin/wdl-ol ) e alcune librerie DSP multipiattaforma. I progetti WDL-OL hanno entrambi i progetti VS e Xcode impostati, ma immagino che i problemi provengano dalle librerie e quindi dalle differenze nei compilatori.


1
non c'è modo di garantire la portabilità, solo modi per migliorare / massimizzare la portabilità
phuclv,

e perché questo non è un duplicato? Credo che ci fossero molte domande simili
phuclv,

Cosa sta facendo la tua applicazione? Come lo useresti? Sulla riga di comando o tramite un'interfaccia grafica? Si prega di modificare la tua domanda per migliorarlo.
Basile Starynkevitch il

E quale framework stai usando?
Basile Starynkevitch il

Risposte:


15

La creazione di codice portatile può essere molto impegnativa.

Innanzitutto alcuni ovvi consigli sulla lingua:

  • usa il C ++ standard ed evita attentamente qualsiasi comportamento indefinito
  • fare affidamento principalmente su librerie standard (e librerie portatili come boost )
  • includi sempre tutte le intestazioni previste. Non dare per scontato che non hai bisogno di un'intestazione perché è inclusa in un'altra (cioè in una specifica implementazione !): Questo può causare errori di compilazione
  • evitare costrutti che sono supportati dal compilatore ma non garantiti dallo standard C ++ (ad es. struttura anonima o array a lunghezza variabile ): possono causare errori di compilazione.
  • usa le opzioni del compilatore per aiutarti a far rispettare la conformità (disabilitando le estensioni specifiche del compilatore, massimizza il livello dei messaggi di avviso restituiti)
  • tieni presente che non è sufficiente che il codice funzioni: esistono molte insidie ​​della portabilità dipendenti dall'implementazione: dimensioni dei tipi di dati (anche elementari), caratteri che possono essere firmati o non firmati per impostazione predefinita , ipotesi sull'endianità , ordine di valutazione nelle espressioni quando queste usa effetti collaterali , ecc.

Quindi un paio di consigli sul design:

  • Preferisce una libreria standard alternativa alla funzionalità equivalente del sistema operativo
  • Isolare il più possibile l'utilizzo delle dipendenze del sistema operativo (ad esempio, in una funzione wrapper controllata con compilazione condizionale)

Finalmente i punti delicati:

  • codifica dei caratteri: su molti sistemi puoi fare affidamento su utf8 . Ma per Windows è più delicato in quanto il sistema si aspetta ansi o utf-16. Ovviamente puoi fare affidamento su un typedef (come TCHAR), ma questo può essere impegnativo in combinazione con la libreria standard (ad es. coutVs wcoutda usare a seconda dell'uso charo wchar_t)
  • Se per GUI / grafica / I / O avanzato non è possibile trovare una libreria portatile adatta alle proprie aspettative / requisiti, progettare l'architettura generale per isolare i componenti specifici del sistema operativo. Gli involucri potrebbero non essere sufficienti qui, a causa delle diverse interazioni e concetti coinvolti.
  • Approfitta di alcuni interessanti modelli di progettazione come ad esempio la fabbrica astratta (ideale per progettare famiglie di oggetti correlati come nell'interfaccia utente specifica del sistema operativo) o il mediatore (ideale per implementare la collaborazione tra famiglie di oggetti correlati) e usarli insieme alla compilazione condizionale .

Ma questi sono solo consigli. In questa zona non puoi ottenere certezza.


-Wall -Wextra -Werror
pipe

1
@pipe Dovresti anche essere -pedantic.
5gon12eder,

@ 5gon12eder Un ottimo punto nel contesto di questa risposta.
pipe il

11

Non c'è nulla che possa garantire che il codice sia compatibile con una piattaforma diversa dalla costruzione, dall'esecuzione e dal test lì. Pertanto, l'approccio di tutte le persone sane è quello di costruire, eseguire e testare la propria applicazione su ogni piattaforma su cui proiettano dovrà essere costruita, eseguita e testata.

L'integrazione continua (CI) può alleviare un po 'questo onere per i progetti più piccoli in quanto è possibile ottenere agenti di build economici o gratuiti per alcune piattaforme (principalmente Linux), eseguire lo sviluppo su Windows e semplicemente tornare a Linux quando si verifica un problema.

OSX CI è piuttosto complicato però.


Non c'è menzione, che cos'è CI?
mavavilj,

5
Integrazione continua - fondamentalmente un gruppo di server che eseguono build e test per te.
DeadMG

@DeadMG Intendi come Mozilla Tinderbox?
Damian Yerrick,

1
Travis CI fornisce host di build OSX gratuiti
Daenyth,

Usa Cmake.
raaj,

9

Se stai chiedendo "processi di sviluppo" e la tua piattaforma di sviluppo principale è Windows con Visual Studio, ti suggerirei di provare a costruire il tuo progetto senza "windows.h" incluso. Riceverai molti errori di compilazione che ti indicheranno molti luoghi in cui dovrai refactificare il tuo codice. Ad esempio, "DWORD" non sarà # definito e dovrai sostituirlo con il loro equivalente multipiattaforma (di nuovo, google è il tuo migliore amico, che mostrerà le domande e le risposte pertinenti nello stack * .com siti) . Probabilmente non riuscirai a trovare tutte le sostituzioni multipiattaforma pertinenti per il tuo codice e dovrai restituire la direttiva ma metterla sotto - maggiori dettagli quiuint32_t ovunque (google for stdint.he troverai informazioni utili sui tipi di numeri interi e le loro definizioni multipiattaforma). Successivamente, dovrai sostituire tutte le chiamate all'API Win32, come,Sleep()include "windows."#ifdef _WIN32

Continua a porre domande più concrete e a ottenere risposte: questo è un suggerimento generale per "quello che dovrebbe essere il processo di sviluppo"

EDIT 1 Un altro mio suggerimento è di usare gcc e / o clang sul tuo computer Windows (insieme a Visual Studio)


3

Dipende dagli "errori di compilazione" che menzioni. Senza sapere cosa fossero, è impossibile essere specifici.

Ho un codice multipiattaforma per Windows / Linux / iOS / Android / Mac. Ogni nuova piattaforma ha apportato alcuni errori e avvisi extra quando è stata aggiunta per la prima volta. Imparerai rapidamente quali costrutti portano problemi. O evitali, oppure sottragga le differenze in un'intestazione con #ifdefs. Non provare mai #ifdeftra le piattaforme all'interno del codice stesso.

Un esempio:

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

crea un'istanza temporanea di MyClasscui viene eliminata dopo la myfunctionrestituzione. Con alcuni dei miei compilatori C ++, quell'istanza è in lettura / scrittura (e il fatto che sia temporaneo e sarà presto distrutto non preoccupa il compilatore). Con altri, myfunctiondeve essere ridefinito per prendere un const MyClass &, o il compilatore si lamenta. Non importa cosa dice lo standard C ++ o quale compilatore sia giusto e quale sia sbagliato. Dopo aver incontrato l'errore un paio di volte so di (a) dichiarare una variabile temporanea di tipo MyClasse passare che a myfunctiono (b) dichiarare il riferimento constin myfunctione usare mutablequa e là per deconstify.

Bottom line: accumulare esperienza e sviluppare i propri standard di codifica.


2
Questa è una caratteristica errata di MSVC. Se il tuo punto è che lo sviluppo su 1 sistema consente a questi di insinuarsi, punto preso. Ma quella cosa specifica non è qualcosa che dovresti fare.
JDługosz,

1
Una cosa buona dell'uso di più catene di strumenti è che il sottoinsieme comune che accettano è più probabile che sia C ++ corretto, conforme agli standard rispetto a quello che ciascuno di essi accetta individualmente. Nel tuo caso, il codice mostrato è chiaramente sbagliato dallo standard ed entrambe le correzioni citate sono valide alternative. Direi che importa cosa dice lo standard.
5gon12eder

1
O direi che il C ++ multipiattaforma è più restrittivo di quello che dice lo standard. In altre parole, anche se lo standard lo dice, sei ancora soggetto al minimo comune denominatore (o, meno capacità del fornitore) per le piattaforme che devi supportare. Ci sono molte librerie open source che hanno dovuto escludere dicono C ++ 11 perché una frazione dei loro componenti (come nei cittadini) non è in grado di C ++ 11.
rwong,

3

Un possibile modo per aiutare la portabilità potrebbe essere quello di fare affidamento solo su dichiarazioni e funzionalità fornite dallo standard C ++ 11 e utilizzando librerie e framework multipiattaforma come POCO e Qt .

Ma anche questo non è a prova di errore. Ricorda l'aforisma

non esiste un programma portatile, ci sono solo programmi che sono stati portati con successo (su una particolare piattaforma)

Con la pratica, la disciplina e molta esperienza, il porting di un programma su un'altra piattaforma di solito può essere fatto rapidamente. Ma l'esperienza e il know-how sono importanti.


1
Un altro consiglio è che, quando il porting viene eseguito da persone e team diversi, le modifiche al codice devono essere reintegrate nella linea principale. Altrimenti, le differenze della piattaforma diventano una conoscenza accumulata dal team che l'ha fatto.
rwong,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.