Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Makefile değil, Rakefile

Makefile değil, Rakefile

Efsanevi `ruby` build tool'u

Uğur Özyılmazel

October 05, 2019
Tweet

More Decks by Uğur Özyılmazel

Other Decks in Programming

Transcript

  1. `Makefile` nedir? `make` uygulamasının işini yapabilmesi için gereken işlemlerin akışının

    saklandığı dosya, yani bir tür reçetedir. https://opensource.com/article/18/8/what-how-makefile
  2. `Makefile` faydaları ? Bir kısım kural içerir, bu kurallar birbirine

    bağlı olabilirler ya da sırayla birbirini takip edebilirler. https://opensource.com/article/18/8/what-how-makefile
  3. `Makefile` örneği https://github.com/azer/go-makefile-example/blob/master/Makefile https://kodfabrik.com/journal/a-good-makefile-for-go/ start: @bash -c "trap 'make stop'

    EXIT; $(MAKE) clean compile start-server watch run='make clean compile start-server'" ## stop: Stop development mode. stop: stop-server start-server: stop-server @echo " > $(PROJECTNAME) is available at $(ADDR)" @-$(GOBIN)/$(PROJECTNAME) 2>&1 & echo $$! > $(PID) @cat $(PID) | sed "/^/s/^/ \> PID: /" stop-server: @-touch $(PID) @-kill `cat $(PID)` 2> /dev/null || true @-rm $(PID) ## watch: Run given command when code changes. e.g; make watch run="echo 'hey'" watch: @GOPATH=$(GOPATH) GOBIN=$(GOBIN) yolo -i . -e vendor -e bin -c "$(run)" restart-server: stop-server start-server ## compile: Compile the binary. compile: @-touch $(STDERR) @-rm $(STDERR) @-$(MAKE) -s go-compile 2> $(STDERR) @cat $(STDERR) | sed -e '1s/. */\nError:\n/' | sed 's/make\[. */ /' | sed "/^/s/^/ /" 1>&2
  4. `Makefile` ve `make` özetle... • bash diline benziyor • unix

    türevleri ve windows’da çalışıyor (cygwin, mingw) • karmaşıklık artıkça anlaşılırlık da azalıyor • orta zorluk seviyesinde https://opensource.com/article/18/8/what-how-makefile
  5. `rake` nedir? • `make`’in Ruby’cesidir. • Ruby kurulumunda beraber gelir,

    bir gem’dir. • Komut satırı ortamında her projede kullanılabilir. • Domain Specific Language (DSL) için en iyi örnektir. • En güncel sürümü için `gem install rake` yeterlidir.
  6. `rake` in babası kimdir ? https://www.wikiwand.com/en/Jim_Weirich • Jim Nolan Weirich

    tarafından geliştirildi. (1956-2014) • macOS 10.5 (Leopard)’dan beri birlikte geliyor (2006). • https://l.vigo.io/rake-10-5
  7. Diğer build tool’lardan farkı ? • `make` kendine mahsus farklı

    DSL’i var • `ant` XML tabanlı farklı bir DSL’i var • `rake` Ruby DSL’i var :)
  8. Neden tercih ediyorum ? • Bash hız açısından iyi ama

    limitli • macOS ile birlikte `ruby` geldiği için `rake` de built-in, ek bir araca ihtiyaç yok! • Local (folder bazında) ya da Global (tüm sistem bazında) çalışan Rakefile tanımlamak mümkün • Çünkü ruby ❤
  9. basit bir task desc "Merhaba Ruby Türkiye" task :hello do

    puts "Merhaba Rubyiciler!" end $ rake -T $ rake —tasks $ rake hello # Merhaba Ruby Türkiye
  10. default task $ rake rake aborted! Don't know how to

    build task 'default' (See the list of available tasks with `rake --tasks`) (See full trace by running task with --trace)
  11. default task desc "Merhaba Ruby Türkiye" task :hello do puts

    "Merhaba Rubyiciler!" end desc "Bu varsayılan task'i çalıştırır: :hello" task :default => [:hello] $ rake —tasks rake default # Bu varsayılan task'i çalıştırır: :hello rake hello # Merhaba Ruby Türkiye
  12. Task (görev/iş) türleri • Basit task’ler • Önşart’lı task’ler /

    zincileme task’ler • File, Directory task’leri • Paralel çalışan task’ler • Rule bazlı task’ler
  13. Çoklu çağırma desc ":hello task" task :hello do print "hello

    " end desc ":world task" task :world do print "world " end $ rake —T rake hello # :hello task rake world # :world task $ rake hello world # hello world
  14. Önşartlı task / zincirleme task :check_env do abort "environment variable

    FOO is not set" unless ENV['FOO'] end desc "say hello world" task :hello_world => [:check_env] do puts "hello world with FOO: #{ENV['FOO']}" end $ rake -T rake hello_world # say hello world $ rake hello_world environment variable FOO is not set $ FOO=1 rake hello_world hello world with FOO: 1
  15. File task’leri file "/path/to/output" => "/path/to/input" do # your code

    here end file "/path/to/output" => ["/path/to/input1", "/path/to/input2"] do |t| # your code here end file "merged.txt" => ["file1", "file2"] do |t| sh "cat #{t.prerequisites.join(' ')} > #{t.name}" # cat file1 file2 > merged.txt end $ rake merged.txt
  16. rake task’leri ne zaman çalışmaz ? • `merged.txt`dosyası fiziksel olarak

    var ise • `file1` ve `file2` dosyaları değişmemişse
  17. File task’leri %W[doc-1.md doc-2.md doc-3.md].each do |md_file| html_file = File.basename(md_file,

    ".md") + ".html" file html_file => md_file do puts "convert markdown: #{md_file} to html: #{html_file}" touch html_file end end $ touch doc-{1,2,3}.md # fake dosyaları oluşturduk $ rake doc-1.html convert markdown: doc-1.md to html: doc-1.html touch doc-1.html $ rake doc-1.html # tekrar çağırdık, çalışmadı, çünkü değişen dosya yok! http://www.virtuouscode.com/2014/04/21/rake-part-1-basics/
  18. Directory task’leri directory "merged_files" file "merged.txt" => "merged_files" do |t|

    puts "create folder called: #{t.prerequisites.first}/ unless it exists" puts "name of task: #{t.name}" puts "prerequisite(s) of task: #{t.prerequisites.first}" end $ rake merged.txt mkdir -p merged_files create folder called: merged_files/ unless it exists name of task: merged.txt prerequisite(s) of task: merged_files
  19. Directory task’leri directory "merged_files" file "merged.txt" => ["merged_files", "file1.txt", "file2.txt"]

    do |t| folder_name = t.prerequisites.first file_names = t.prerequisites[1 ..].join(' ') sh "cat #{file_names} > #{folder_name}/ #{t.name}" end $ rake merged.txt cat file1.txt file2.txt > merged_files/merged.txt
  20. FileUtils: `ri FileUtils` • mkdir • mkdir_p • rm •

    rm_r • rm_rf • rm_dir • touch • ln • ln_s • ln_sf • cp • cp_r • mv • chmod
  21. Argüman alan task’ler desc "greet user" task :greet, [:user_name] do

    |_, args| puts "hello #{args.user_name}" end $ rake greet["vigo"] # ya da $ rake greet[vigo] # zsh: rake greet\[vigo\] hello vigo $ rake greet["vigo kadriyani"] # space karakteri varsa $ rake "greet[vigo kadriyani]”
  22. Argüman alan task’ler desc "greet user" task :greet, [:user_name] do

    |_, args| args.with_defaults(user_name: "unknown person") puts "hello #{args.user_name}" end $ rake -T rake greet[user_name] # greet user $ rake greet # parametre/argüman olmadan hello unknown person $ rake greet[vigo] hello vigo
  23. Paralel çalışan task’ler multitask copy_files: %w[copy_src copy_doc copy_bin] do puts

    "All Copies Complete" end task :copy_src do puts "copy src task" end task :copy_doc do puts "copy doc task" end task :copy_bin do puts "copy bin task" end $ rake copy_files copy bin task copy src task copy doc task All Copies Complete
  24. rule # önceki kod ... %W[doc-1.md doc-2.md doc-3.md].each do |md_file|

    html_file = File.basename(md_file, ".md") + ".html" file html_file => md_file do puts "convert markdown: #{md_file} to html: #{html_file}" touch html_file end end # rake doc-1.html task :clean do rm Dir.glob('*.html') end task :default => :html task :html => %W[doc-1.html doc-2.html doc-3.html] rule ".html" => ".md" do |t| puts "convert markdown: #{t.source} to html: #{t.name}" touch " #{t.name}" end $ rake clean $ rm doc-1.html doc-2.html doc-3.html # eğer varsa ... $ rake convert markdown: doc-1.md to html: doc-1.html touch doc-1.html convert markdown: doc-2.md to html: doc-2.html touch doc-2.html convert markdown: doc-3.md to html: doc-3.html touch doc-3.html
  25. Diğer özellikler: FileList files = Rake ::FileList["*.md", “*.html”] task :default

    => :html task :html do puts "files: #{files}" puts files end $ rake files: doc-1.md doc-2.md doc-3.md doc-1.html doc-2.html doc-3.html doc-1.md doc-2.md doc-3.md doc-1.html doc-2.html doc-3.html
  26. Diğer özellikler: invoke task :check_settings do Rake ::Task["check_virtualenv"].invoke Rake ::Task["check_django_env"].invoke

    end task :check_virtualenv do abort "Please activate your virtual environment" unless ENV['VIRTUAL_ENV'] end task :check_django_env do abort "Please define DJANGO_ENV variable" unless ENV['DJANGO_ENV'] end task :check_settings => [:check_virtualenv, :check_django_env] do |t| puts "task #{t.name} called ..." end task :check_virtualenv do abort "Please activate your virtual environment" unless ENV['VIRTUAL_ENV'] end task :check_django_env do abort "Please define DJANGO_ENV variable" unless ENV['DJANGO_ENV'] end
  27. Diğer özellikler: invoke task :default => [:run] task :run =>

    [:step1, :step2] do Rake ::Task["step1"].invoke Rake ::Task["step1"].invoke Rake ::Task["step2"].invoke Rake ::Task["step2"].invoke end task :step1 do puts "step1 is called" end task :step2 do puts "step2 is called" end $ rake step1 is called step2 is called
  28. Diğer özellikler: execute task :default => [:run] task :run =>

    [:step1, :step2] do Rake ::Task["step1"].execute Rake ::Task["step1"].execute Rake ::Task["step2"].execute Rake ::Task["step2"].execute end task :step1 do puts "step1 is called" end task :step2 do puts "step2 is called" end $ rake step1 is called step2 is called step1 is called step1 is called step2 is called step2 is called https://medium.com/@sampatbadhe/rake-task-invoke-or-execute-419cd689c3bd
  29. Diğer özellikler: namespace namespace :db do desc "Make migration" task

    :migrate do puts "running migrations ..." end namespace :private do desc "Delete database ..." task :zapp do puts "noooooooooooooo" end end end desc "Call migration" task :call_migrate => ["db:migrate"] do puts "called db:migrate" end $ rake -T rake call_migrate # Call migration rake db:migrate # Make migration rake db:private:zapp # Delete database .. $ rake call_migrate running migrations ... called db:migrate $ rake db:private:zapp noooooooooooooo
  30. Diğer özellikler: invoke + argüman namespace :db do task :delete_db_file,

    [:db_file] do |_, args| psql = %x{ command -v psql } if psql.empty? fn = "project/db/ #{args.db_file}.sqlite3" if File.exists?(fn) puts "Deleting: #{fn}" rm(fn) else puts " #{fn} not exists ..." end else puts "Dropping and re-creating PostgreSQL database" system "dropdb #{POSTGRES_DB_NAME} --if-exists" system "createdb #{POSTGRES_DB_NAME}" end end task :delete_development_db do Rake ::Task["db:delete_db_file"].invoke('development') end end
  31. Argüman ve bağımlılık task :check_settings do abort "environment variable FOO

    is not set" unless ENV['FOO'] end desc "Run development server (default task)" task :run_server, [:port] => [:check_settings] do |_, args| args.with_defaults(:port => 8000) puts "python manage.py runserver_plus #{args.port} --nothreading" end $ FOO=1 rake run_server[9000] python manage.py runserver_plus 9000 --nothreading
  32. task :default => [:install] desc "Remove/Delete build ..." task :clean

    do rm_rf %w(build dist) rm_rf Dir.glob("*.egg-info") puts "Build files are removed ..." end desc "Install package for local development purpose" task :install => [:build] do system "pip install -e ." end desc "Build package" task :build => [:clean] do system "python setup.py sdist bdist_wheel" end namespace :upload do desc "Upload package to main distro (release)" task :main => [:build] do puts "Uploading package to MAIN distro ..." system "twine upload --repository pypi dist /*" end desc "Upload package to test distro" task :test => [:build] do puts "Uploading package to TEST distro ..." system "twine upload --repository testpypi dist /*" end end AVAILABLE_REVISIONS = ["major", "minor", "patch"] desc "Bump version" task :bump, [:revision] do |t, args| args.with_defaults(revision: "patch") abort "Please provide valid revision: #{AVAILABLE_REVISIONS.join(',')}" unless AVAILABLE_REVISIONS.include?(args.revision) system "bumpversion #{args.revision}" end https://github.com/vbyazilim/django-vb-baseapp
  33. Kaynaklar • http://www.virtuouscode.com/2014/04/21/rake-part-1-basics/ • http://www.virtuouscode.com/2014/04/22/rake-part-2-file-lists/ • http://www.virtuouscode.com/2014/04/23/rake-part-3-rules/ • http://www.virtuouscode.com/2014/04/24/rake-part-4-pathmap/ •

    http://www.virtuouscode.com/2014/04/25/rake-part-5-file-operations/ • http://www.virtuouscode.com/2014/04/28/rake-part-6-clean-and-clobber/ • http://www.virtuouscode.com/2014/04/29/rake-part-7-multitask/ Avdi Grimm
  34. Kaynaklar • https://martinfowler.com/articles/rake.html • https://www.stuartellis.name/articles/rake/ • https://lukaszwrobel.pl/blog/rake-tutorial/ • https://www.youtube.com/watch?v=AFPWDzHWjEY •

    https://github.com/seattlerb/rake-remote_task • https://l.vigo.io/rakefile-example • https://pragprog.com/screencast/v-jwsceasy/source-control-made-easy