Sto sviluppando una gemma, che attualmente è puro Ruby, ma ho anche sviluppato una variante C più veloce per una delle funzionalità. La funzione è utilizzabile, ma a volte lenta, in puro Ruby. La lentezza influirebbe solo su alcuni dei potenziali utenti (dipende dalle caratteristiche di cui hanno bisogno e dal modo in cui li usano), quindi ha senso avere la gemma disponibile con un comodo fallback alle sole funzioni di Ruby se non può essere compilata su un sistema di destinazione.Le estensioni native sono di tipo puramente Ruby se non sono supportate sull'installazione gem
Vorrei mantenere le varianti Ruby e C della feature in un singolo gioiello e fornire l'esperienza migliore (ovvero la più veloce) dalla gemma durante l'installazione. Ciò mi permetterebbe di supportare la più ampia serie di potenziali utenti da un mio singolo progetto. Permetterebbe inoltre alle gemme dipendenti e ai progetti di altre persone di utilizzare la migliore dipendenza disponibile su un sistema di destinazione, a differenza di una versione con il minimo comune denominatore per la compatibilità.
mi aspetterei il require
di fallback in fase di esecuzione per apparire nel lib/foo.rb
file principale semplicemente in questo modo:
begin
require 'foo/foo_extended'
rescue LoadError
require 'foo/ext_bits_as_pure_ruby'
end
Tuttavia, non so come ottenere l'installazione gemma per controllare (o cercare di fail) per il supporto dell'estensione nativa in modo che la gem si installi correttamente, indipendentemente dal fatto che possa creare "foo_extended". Quando ho cercato come fare, ho trovato principalmente discussioni di alcuni anni fa, ad es. http://permalink.gmane.org/gmane.comp.lang.ruby.gems.devel/1479 e http://rubyforge.org/pipermail/rubygems-developers/2007-November/003220.html che implicano che le gemme Ruby non supportano realmente questa funzione. Niente di recente però, quindi spero che qualcuno su SO abbia delle conoscenze più aggiornate?
La mia soluzione ideale sarebbe un modo per rilevare, prima di tentare una build dell'estensione, che il Ruby di destinazione non supportasse (o forse semplicemente non volesse, a livello di progetto) estensioni native C. Ma anche un meccanismo try/catch sarebbe OK se non troppo sporco.
E 'possibile, se sì, come? Oppure il consiglio di pubblicare due varianti di gemme (ad esempio foo
e foo_ruby
), che sto riscontrando quando cerco, le best practice ancora correnti?
Due gemme vanno bene, ad es. la gemma json è disponibile in due varianti: ['json'] (https://rubygems.org/gems/json) (con estensione C) e [' json_pure'] (https://rubygems.org/gems/json_pure) (puro rubino). – Stefan
@Stefan: Nella conversazione che ho collegato, l'autore/maintaner di 'json' e' json_pure' a quanto pare preferirebbe diversamente. Oltre al lavoro extra che pubblica due varianti della gemma, i progetti dipendenti che possono essere essi stessi dipendenze di qualcos'altro, finiscono per dover usare il minimo comune denominatore o devono anche fornire due varianti solo per gestire le dipendenze che non codificano . Non direi che "va bene", ma se è il migliore possibile, allora è tutto quello che posso fare anch'io –
@Stefan: Sicuramente l'intenzione progettuale di Neil incarnata nell'OP è giusta. La sua domanda è grande e molto importante, sono interessato alla risposta, per favore, per favore. –