# Writing a ersatz for a makefile using 'option\_parser'

**URL:** <https://forum.crystal-lang.org/t/writing-a-ersatz-for-a-makefile-using-option-parser/5329>\
**Category:** Help & Support\
**Created:** [February 5, 2023, 2:43pm UTC](https://forum.crystal-lang.org/t/writing-a-ersatz-for-a-makefile-using-option-parser/5329 "2023-02-05T14:43:05Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![serge-hulne](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/serge-hulne/32/1211_2.png) [@serge-hulne](https://forum.crystal-lang.org/u/serge-hulne)\
**Post date:** [February 5, 2023, 2:43pm UTC](https://forum.crystal-lang.org/t/writing-a-ersatz-for-a-makefile-using-option-parser/5329/1 "2023-02-05T14:43:05Z")

</div>

I’m trying to substitute a makefile with a CLI, using ‘option\_parser’ to parse the options and launch the commands, however using backticks commands to that end only works when the executable which is launched returns immediately, otherwise, the result of the operation is only displayed when the process is stopped.

Is there a better alternative?

Here is an excerpt from the Makefile:

```auto
cla: src/cla.cr
	crystal build src/cla.cr

init : # inits the installation of the required libs (shards)
	shards install

init_svelte :
	npm create vite@latest svelte --template svelte-ts
	cd svelte && npm install

svelte_dev :
	cd svelte && npm run dev

dev : src/main.cr # dev
	RUCKSACK_MODE=0 DEBUG=true DEVELOP=true crystal build -Dpreview_mt ./src/main.cr
	./main&

```

Here is the corresponding excerpt from the Crystal CLI code:

```auto
  # init
  parser.on "-i", "--init", "Install Crystal dependencies" do
    cmd = `shards install`
    puts cmd
    exit
  end

  # Svelte dev
  parser.on "-d", "--dev", "Start Svelte dev server (dev phase)" do
    cmd = `cd svelte && npm run dev`
    puts cmd
    exit
  end

  # dev
  parser.on "-c", "--compile", "Compiles app (dev phase)" do
    cmd = `RUCKSACK_MODE=0 DEBUG=true DEVELOP=true crystal build -Dpreview_mt ./src/main.cr`
    puts cmd
    cmd = `./main&`
    puts cmd
    exit
  end
``
```

---

<div class="post-metadata">

**Author:** ![serge-hulne](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/serge-hulne/32/1211_2.png) [@serge-hulne](https://forum.crystal-lang.org/u/serge-hulne)\
**Post date:** [February 5, 2023, 3:08pm UTC](https://forum.crystal-lang.org/t/writing-a-ersatz-for-a-makefile-using-option-parser/5329/2 "2023-02-05T15:08:01Z")

</div>

Alternative formulation:

How can I run the executable corresponding to:

```auto
# hello.cr
i = 0
while true
  i+=1
  sleep(0.1)
  p "next step : #{i}"
end

```

Using an alternative to 🙂

```auto
require "option_parser"

if ARGV.size == 0
  puts %('./cla -h' for help)
end

option_parser = OptionParser.parse do |parser|
  parser.banner = "cla : command-line for CrystApp:\n--------------------------------"

  parser.on "-v", "--version", "Show version" do
    puts "version 1.0"
    exit
  end

  parser.on "-h", "--help", "Show help" do
    puts parser
    exit
  end

  parser.on "-r", "--run", "runs the hello executable" do
    cmd = `./hello`
    puts cmd
    exit
  end

  parser.missing_option do |option_flag|
    STDERR.puts "ERROR: #{option_flag} is missing something."
    STDERR.puts ""
    STDERR.puts parser
    exit(1)
  end
  parser.invalid_option do |option_flag|
    STDERR.puts "ERROR: #{option_flag} is not a valid option."
    STDERR.puts parser
    exit(1)
  end
end

```

The code using the options parser will run the other exec, but the output will not be displayed.

I guess I’ill have to use some more sophisticated IPC, any ideas, examples of how that’s done in Crystal?

---

<div class="post-metadata">

**Author:** ![serge-hulne](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/serge-hulne/32/1211_2.png) [@serge-hulne](https://forum.crystal-lang.org/u/serge-hulne)\
**Post date:** [February 5, 2023, 3:33pm UTC](https://forum.crystal-lang.org/t/writing-a-ersatz-for-a-makefile-using-option-parser/5329/3 "2023-02-05T15:33:25Z")

</div>

I have tried:

```auto
    stdout = IO::Memory.new
    process = Process.new("./hello", [""], output: stdout)
    status = process.wait
    output = stdout.to_s

```

but I get the error:

```auto
In /opt/homebrew/Cellar/crystal/1.7.2/share/crystal/src/IO.cr:62:3

 62 | DEFAULT_BUFFER_SIZE = 32768
      ^------------------
Error: already initialized constant IO::DEFAULT_BUFFER_SIZE
make: *** [hello] Error 1

```

at compilation time.

---

<div class="post-metadata">

**Author:** ![npn](https://avatars.discourse-cdn.com/v4/letter/n/e68b1a/32.png) [@npn](https://forum.crystal-lang.org/u/npn)\
**Post date:** [February 5, 2023, 3:44pm UTC](https://forum.crystal-lang.org/t/writing-a-ersatz-for-a-makefile-using-option-parser/5329/4 "2023-02-05T15:44:30Z")

</div>

try this: `Process.run("your_command", output: :inherit)`

---

<div class="post-metadata">

**Author:** ![serge-hulne](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/serge-hulne/32/1211_2.png) [@serge-hulne](https://forum.crystal-lang.org/u/serge-hulne)\
**Post date:** [February 5, 2023, 3:48pm UTC](https://forum.crystal-lang.org/t/writing-a-ersatz-for-a-makefile-using-option-parser/5329/5 "2023-02-05T15:48:41Z")

</div>

> [@npn](#):
>
> Process.run(“your\_command”, output: :inherit")

Thanks, I tried and also tried:

```auto
    stdout = IO::Memory.new
    process = Process.new("ls -lAF", [""], output: stdout)
    status = process.wait
    output = stdout.to_s
    exit

[quote="npn, post:4, topic:5329"]
Process.run("your_command", output: :inherit")
[/quote]

```

but I’m having an issue with processes on my machine, I filed an issue:

> <https://github.com/crystal-lang/crystal/issues/13047>
>
> \# Code
> 
> \`\`\`cr
> require "option\_parser"
> require "process"
> require "IO"
> 
> if …ARGV.size == 0
> puts %('./cla -h' for help)
> end
> 
> option\_parser = OptionParser.parse do |parser|
> parser.banner = "cla : command-line for CrystApp:\\n--------------------------------"
> 
> parser.on "-v", "--version", "Show version" do
> puts "version 1.0"
> exit
> end
> 
> parser.on "-h", "--help", "Show help" do
> puts parser
> exit
> end
> 
> parser.on "-r", "--run", "runs the hello executable" do
> 
> stdout = IO::Memory.new
> process = Process.new("ls -lAF", \["."\], output: stdout)
> status = process.wait
> output = stdout.to\_s
> 
> exit
> end
> 
> parser.missing\_option do |option\_flag|
> STDERR.puts "ERROR: #{option\_flag} is missing something."
> STDERR.puts ""
> STDERR.puts parser
> exit(1)
> end
> parser.invalid\_option do |option\_flag|
> STDERR.puts "ERROR: #{option\_flag} is not a valid option."
> STDERR.puts parser
> exit(1)
> end
> end
> \`\`\`
> 
> \# Compilation command:
> \`\`\`
> crystal build src/run\_hello.cr -o run\_hello
> \`\`\`
> 
> \# Error message:
> \`\`\`
> In /opt/homebrew/Cellar/crystal/1.7.2/share/crystal/src/IO.cr:62:3
> 
> 62 | DEFAULT\_BUFFER\_SIZE = 32768
> ^------------------
> Error: already initialized constant IO::DEFAULT\_BUFFER\_SIZE
> make: \*\*\* \[hello\] Error 1
> \`\`\`
> 
> \# Data:
> 
> \`\`\`
> Crystal 1.7.2 (2023-01-23)
> LLVM: 14.0.6
> Default target: aarch64-apple-darwin22.2.0
> Mac M1
> Ventura 13.1
> \`\`\`

---

<div class="post-metadata">

**Author:** ![serge-hulne](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/serge-hulne/32/1211_2.png) [@serge-hulne](https://forum.crystal-lang.org/u/serge-hulne)\
**Post date:** [February 5, 2023, 3:54pm UTC](https://forum.crystal-lang.org/t/writing-a-ersatz-for-a-makefile-using-option-parser/5329/6 "2023-02-05T15:54:53Z")

</div>

Thank you, it works now !

😀
