Come eseguire attività Rake da attività Rake?


411

Ho un Rakefile che compila il progetto in due modi, secondo la variabile globale $build_type, che può essere :debugo :release(i risultati vanno in directory separate):

task :build => [:some_other_tasks] do
end

Vorrei creare un'attività che compili il progetto con entrambe le configurazioni a turno, qualcosa del genere:

task :build_all do
  [ :debug, :release ].each do |t|
    $build_type = t
    # call task :build with all the tasks it depends on (?)
  end
end

C'è un modo per chiamare un'attività come se fosse un metodo? O come posso ottenere qualcosa di simile?


7
qual è la risposta?
Nurettin,

Andrei con il voto della comunità e sceglierei la risposta votata 221 volte (al momento della stesura). Il poster originale ha lasciato SO
MPritchard il


Cordiali saluti, l'utilizzo di qualcosa del genere Rake::Task["build"].invokepuò essere molto più performante dell'utilizzo system rake buildperché non deve creare un nuovo thread e caricare l'ambiente Rails, cosa system rake buildche deve fare.
Joshua Pinter,

Risposte:


639

Se hai bisogno che l'attività si comporti come metodo, che ne dici di usare un metodo reale?

task :build => [:some_other_tasks] do
  build
end

task :build_all do
  [:debug, :release].each { |t| build t }
end

def build(type = :debug)
  # ...
end

Se preferisci attenersi ai rakemodi di dire, ecco le tue possibilità, compilate dalle risposte passate:

  • Questo esegue sempre l'attività, ma non esegue le sue dipendenze:

    Rake::Task["build"].execute
  • Questo esegue le dipendenze, ma esegue l'attività solo se non è già stata invocata:

    Rake::Task["build"].invoke
  • Questo prima ripristina lo stato già_invocato dell'attività, consentendo quindi di eseguire di nuovo l'attività, le dipendenze e tutto:

    Rake::Task["build"].reenable
    Rake::Task["build"].invoke
  • Si noti che le dipendenze già invocate non vengono rieseguite automaticamente a meno che non vengano riabilitate. In Rake> = 10.3.2, puoi usare quanto segue per riattivare anche quelli:

    Rake::Task["build"].all_prerequisite_tasks.each(&:reenable)

96
Se le attività sono negli spazi dei nomi, è necessario includere lo spazio dei nomi quando si richiama l'attività. Per esempio. Rake::Task['db:reset'].invoke
David Tuite,

126
Se l'attività nelle domande accetta argomenti, è possibile passarli come argomenti a #invoke. Per esempio. Rake::Task['with:args'].invoke("pizza")
Trotter

27
Se è necessario impostare una variabile di ambiente, farlo prima di chiamare invoke. Ad esempio: ENV['VERSION'] = '20110408170816'; Rake::Task['db:migrate'].invokevedi qui per ulteriori spiegazioni.
Michael Stalker,

13
Recentemente ho scoperto #reenable()che non riattiva i pre-req e ne avevo bisogno. Questa aggiunta a Rake (> = 10.3.2), #all_prerequisite_tasks()ripeterà tutte le attività, inclusi i pre-req dei pre-req. Quindi,Rake::Task[task].all_prerequisite_tasks.each &:reenable
Richard Michael,

4
@kch, puoi metterli insieme (come ad esempio sulla riga rake db:reset db:migratedi comando ). Puoi fare qualcosa del tipo: Rake::Task["db:reset", "db:migrate"].invoke
Jeff

125

per esempio:

Rake::Task["db:migrate"].invoke

6
Questo invoca l'attività solo se non era già stata invocata. Ma ho bisogno di invocare i compiti con tutti gli altri compiti da cui dipende due volte.

58
task :build_all do
  [ :debug, :release ].each do |t|
    $build_type = t
    Rake::Task["build"].reenable
    Rake::Task["build"].invoke
  end
end

Questo dovrebbe risolverti, avevo solo bisogno della stessa cosa.


Questo è funzionale, ma troppo dettagliato. Sicuro che non c'è niente di meglio?
kch,

13
task :invoke_another_task do
  # some code
  Rake::Task["another:task"].invoke
end

Uno dei motivi per cui avevo bisogno di una soluzione come questa, è perché il caricamento delle attività di rake richiede molto tempo. Implementando una soluzione come sopra, farà risparmiare tempo di caricamento?
Dipan Mehta,

11
task :build_all do
  [ :debug, :release ].each do |t|
    $build_type = t
    Rake::Task["build"].execute
  end
end

Non funziona perché esegue semplicemente il corpo dell'attività: build e non invoca le attività che dipendono da esso.

4

Se desideri che ogni attività venga eseguita indipendentemente da eventuali errori, puoi fare qualcosa del tipo:

task :build_all do
  [:debug, :release].each do |t| 
    ts = 0
    begin  
      Rake::Task["build"].invoke(t)
    rescue
      ts = 1
      next
    ensure
      Rake::Task["build"].reenable # If you need to reenable
    end
    return ts # Return exit code 1 if any failed, 0 if all success
  end
end

-1

Suggerirei di non creare attività generali di debug e di rilascio se il progetto è davvero qualcosa che viene compilato e quindi risulta in file. Dovresti andare con file-task che è abbastanza fattibile nel tuo esempio, come dici, che il tuo output va in diverse directory. Supponiamo che il tuo progetto compili un file test.c in out / debug / test.out e out / release / test.out con gcc e puoi configurare il tuo progetto in questo modo:

WAYS = ['debug', 'release']
FLAGS = {}
FLAGS['debug'] = '-g'
FLAGS['release'] = '-O'
def out_dir(way)
  File.join('out', way)
end
def out_file(way)
  File.join(out_dir(way), 'test.out')
end
WAYS.each do |way|
  desc "create output directory for #{way}"
  directory out_dir(way)

  desc "build in the #{way}-way"
  file out_file(way) => [out_dir(way), 'test.c'] do |t|
    sh "gcc #{FLAGS[way]} -c test.c -o #{t.name}"
  end
end
desc 'build all ways'
task :all => WAYS.map{|way|out_file(way)}

task :default => [:all]

Questa configurazione può essere utilizzata come:

rake all # (builds debug and release)
rake debug # (builds only debug)
rake release # (builds only release)

Questo fa un po 'di più come richiesto, ma mostra i miei punti:

  1. le directory di output vengono create, se necessario.
  2. i file vengono ricompilati solo se necessario (questo esempio è corretto solo per i file test.c più semplici).
  3. hai tutte le attività a portata di mano se vuoi attivare la build di rilascio o la build di debug.
  4. questo esempio include un modo per definire anche piccole differenze tra debug e build di rilascio.
  5. non è necessario riattivare un'attività di compilazione parametrizzata con una variabile globale, perché ora le diverse build hanno attività diverse. il codereuso dell'attività di compilazione viene eseguito riutilizzando il codice per definire le attività di compilazione. vedere come il ciclo non esegue la stessa attività due volte, ma invece crea attività che possono essere successivamente attivate (dall'all-task o scegliendone una dalla riga di comando del rake).
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.