रेक कार्यों के भीतर से रेक कार्यों को कैसे चलाया जाए?


411

मेरे पास एक Rakefile है जो परियोजना को दो तरह से संकलित करता है, वैश्विक चर के अनुसार $build_type, जो ( :debugया :releaseअलग निर्देशिका में परिणाम हो सकता है ):

task :build => [:some_other_tasks] do
end

मैं एक ऐसा कार्य बनाना चाहता हूँ जो परियोजना को दोनों विन्यासों के साथ संकलित करे, कुछ इस तरह से:

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

क्या किसी कार्य को कॉल करने का एक तरीका है जैसे कि यह एक विधि थी? या मैं कुछ भी समान कैसे प्राप्त कर सकता हूं?


7
कौन सा जवाब है?
nurettin

मैं समुदाय के वोट के साथ जाऊंगा और उत्तर को 221 बार (लिखने के समय) उठाया। मूल पोस्टर ने SO
MPritchard


FYI करें, जैसे कुछ का उपयोग करने Rake::Task["build"].invokeसे कहीं अधिक प्रदर्शनकारी हो सकता है system rake buildक्योंकि इसमें एक नया धागा बनाने और रेल पर्यावरण को लोड करने की system rake buildआवश्यकता नहीं होती है , जो कि करना पड़ता है।
जोशुआ पिंटर

जवाबों:


639

यदि आपको एक विधि के रूप में व्यवहार करने के लिए कार्य की आवश्यकता है, तो वास्तविक पद्धति का उपयोग करने के बारे में कैसे?

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

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

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

यदि आप इसके बजाय rakeमुहावरों से चिपके रहते हैं, तो यहां आपकी संभावनाएं हैं, पिछले उत्तरों से संकलित:

  • यह हमेशा कार्य निष्पादित करता है, लेकिन यह अपनी निर्भरता को निष्पादित नहीं करता है:

    Rake::Task["build"].execute
  • यह निर्भरता को निष्पादित करता है, लेकिन यह केवल उस कार्य को निष्पादित करता है यदि इसे पहले ही लागू नहीं किया गया है:

    Rake::Task["build"].invoke
  • यह पहले टास्क के पहले से निर्धारित स्थिति को रीसेट करता है, जिससे कार्य को फिर से निष्पादित किया जा सकता है, निर्भरताएं और सभी:

    Rake::Task["build"].reenable
    Rake::Task["build"].invoke
  • ध्यान दें कि पहले से ही निर्भरताएँ स्वचालित रूप से फिर से निष्पादित नहीं की जाती हैं जब तक कि वे फिर से सक्षम न हों। Rake> = 10.3.2 में, आप निम्नलिखित को फिर से सक्षम करने के लिए उपयोग कर सकते हैं:

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

96
ध्यान दें कि यदि आपके कार्य नामस्थान में हैं, तो कार्य को लागू करते समय आपको नामस्थान को शामिल करना होगा। उदाहरण के लिए। Rake::Task['db:reset'].invoke
डेविड टाइट

126
यदि सवालों में काम तर्क लेता है, तो आप उन्हें #invoke को तर्क के रूप में पारित कर सकते हैं। उदाहरण के लिए। Rake::Task['with:args'].invoke("pizza")
ट्रोटर

26
यदि आपको पर्यावरण चर सेट करने की आवश्यकता है, तो आह्वान करने से पहले ऐसा करें। उदाहरण के लिए: अधिक स्पष्टीकरण के लिए यहांENV['VERSION'] = '20110408170816'; Rake::Task['db:migrate'].invoke देखें ।
माइकल स्टेलर

13
मैंने हाल ही में खोज की #reenable()है कि प्री-रीक को फिर से सक्षम न करें, और इसकी आवश्यकता है। इसके अलावा Rake (> = 10.3.2), #all_prerequisite_tasks()पूर्व-रीक के पूर्व-रीक सहित सभी कार्यों को पुनरावृत्त करेगा। तो,Rake::Task[task].all_prerequisite_tasks.each &:reenable
रिचर्ड माइकल

4
@chch, क्या आप इन्हें एक साथ जोड़ सकते हैं (जैसे कमांडलाइन rake db:reset db:migrateपर उदाहरण के लिए)। क्या आप ऐसा कुछ कर सकते हैं: Rake::Task["db:reset", "db:migrate"].invoke
जेफ

125

उदाहरण के लिए:

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

6
यह कार्य को केवल तभी लागू करता है जब इसे पहले ही लागू नहीं किया गया था। लेकिन मुझे अन्य सभी कार्यों के साथ कार्यों को लागू करने की आवश्यकता है जो यह दो बार निर्भर करता है।

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

वह आपको सुलझाना चाहिए, बस उसी चीज की जरूरत है।


यह क्रियाशील है, लेकिन तरीका बहुत क्रियात्मक है। यकीन है कि बेहतर कुछ नहीं है?
kch

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

इस कारण से मुझे इस तरह के समाधान की आवश्यकता थी, इसका कारण यह है कि रेक कार्य लोड करने में बहुत समय लगता है। ऊपर जैसा समाधान लागू करने से, क्या यह लोडिंग समय पर बचाएगा?
दीपन मेहता

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

यह काम नहीं करता है, क्योंकि यह सिर्फ शरीर को निष्पादित करता है: निर्माण कार्य और उस पर निर्भर कार्यों को लागू नहीं करता है।

4

यदि आप चाहते हैं कि प्रत्येक कार्य बिना किसी असफलता के चल रहा हो, तो आप कुछ ऐसा कर सकते हैं:

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

मैं सुझाव दूंगा कि सामान्य डिबग न बनाएं और कार्य जारी करें यदि परियोजना वास्तव में कुछ है जो संकलित हो जाती है और इसलिए फाइलों में परिणाम होता है। आपको फ़ाइल-कार्यों के साथ जाना चाहिए जो आपके उदाहरण में काफी उल्लेखनीय है, जैसा कि आप कहते हैं, कि आपका आउटपुट अलग-अलग निर्देशिकाओं में जाता है। कहते हैं कि आपकी परियोजना बस एक test.c फ़ाइल को बाहर / डीबग / टेस्ट करने के लिए संकलित करती है और बाहर / जारी / परीक्षण करें। इस प्रकार आप अपने प्रोजेक्ट को इस तरह सेटअप कर सकते हैं:

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]

इस सेटअप का उपयोग इस तरह किया जा सकता है:

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

यह थोड़ा और अधिक के लिए कहा जाता है, लेकिन मेरी बातों को दर्शाता है:

  1. आउटपुट डायरेक्टरीज़ आवश्यक के रूप में बनाई गई हैं।
  2. यदि आवश्यक हो तो फ़ाइलें केवल recompiled हैं (यह उदाहरण केवल test.c फ़ाइलों के सबसे सरल के लिए सही है)।
  3. यदि आप रिलीज़ बिल्ड या डीबग बिल्ड को ट्रिगर करना चाहते हैं, तो आपके पास आसानी से सभी कार्य हैं।
  4. इस उदाहरण में डिबग और रिलीज़-बिल्ड के बीच छोटे अंतर को भी परिभाषित करने का एक तरीका शामिल है।
  5. एक बिल्ड-टास्क को फिर से उपयोग करने की आवश्यकता नहीं है जो एक वैश्विक चर के साथ पैराट्राइज्ड है, क्योंकि अब अलग-अलग बिल्ड में अलग-अलग कार्य हैं। बिल्ड-टास्क का कोडरेक बिल्ड-कार्यों को परिभाषित करने के लिए कोड का पुन: उपयोग करके किया जाता है। देखें कि लूप एक ही कार्य को दो बार कैसे निष्पादित नहीं करता है, बल्कि बनाए गए कार्य हैं, जिसे बाद में ट्रिगर किया जा सकता है (या तो सभी कार्य द्वारा या रेक कमांडलाइन पर उनमें से किसी एक को चुना जा सकता है)।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.