How to Compile Bash

How to compile bash?

You can first run

cd bash-4.2

./configure --prefix=/usr \
--bindir=/bin \
--htmldir=/usr/share/doc/bash-4.2 \
--without-bash-malloc \
--with-installed-readline

make

make install

Also refer http://www.linuxfromscratch.org/lfs/view/development/chapter06/bash.html for more information

How to compile a linux shell script to be a standalone executable *binary* (i.e. not just e.g. chmod 755)?

The solution that fully meets my needs would be SHC - a free tool, or CCsh a commercial tool. Both compile shell scripts to C, which then can be compiled using a C compiler.

Links about SHC:

  • https://github.com/neurobin/shc
  • http://www.datsi.fi.upm.es/~frosal/
  • http://www.downloadplex.com/Linux/System-Utilities/Shell-Tools/Download-shc_70414.html

Links about CCsh:

  • http://www.comeaucomputing.com/faqs/ccshlit.html

Are there any languages that compile to Bash?

Since I originally asked this question, two projects have been released which attack this problem and do a pretty good job. Both reimplement many/most Unix tools in more programming-friendly runtimes.

Plumbum is implemented in Python and looks pretty solid:

http://plumbum.readthedocs.org/en/latest/index.html

ShellJS is implemented on Node.js and also looks pretty good:

https://github.com/arturadib/shelljs

Exciting developments! I'm looking forward to trying them out. If you already have, it'd be great to hear your experiences in the comments. Thanks!

How to write a bash file to compile and execute a c++ program

You have struggled for a few hours and put something together, but what happens if the compilation fails? What happens if there are no arguments? What happens if there are 4 arguments for the program?

When writing a script, or a program, the most important thing you can do is validate every necessary step! If you are expecting input, validate you received it. Once you have the input, validate it is what your expected. Is it a value within the usable range? Is it a filename that meets my requirements? Does it exist? Did my compile succeed or fail? Do I try and execute the program?

All of these need to be addressed. Otherwise, your script (or program) will stray off on some undefined path.

Bash provides a wealth of conditional expressions that can be used with test (or [...]) or using the bash [[...]] operator. See Bash Manual - 6.4 Bash Conditional Expressions. Make use of the language features to make your code robust.

Bash provides a wealth of string handling features through parameter expansions Bash Manual - 3.5.3 Shell Parameter Expansion, use them to check the extension to make sure it is c, cpp or c++

Putting those features together with a few if...then...fi statements will make your script much more reliable -- and actually do what it is you are trying to do.

The following short script takes arguments (bash Positional Parameters) requiring that at least the filename to compile be provided, and passing any additional arguments to the compiled program as command line arguments with ${@:2} (all bash positional parameters beginning with the 2nd one)

#!/bin/bash

if [ -z "$1" ] ## validate at least one argument given
then
printf "error: insufficient arguments\n" >&2
printf "usage: %s file.cpp [args]\n" "${0##*/}" >&2
exit 1
fi

if [ ! -r "$1" ] ## validate file is readable
then
printf "error: file not found '%s'\n" "$1" >&2
exit 1
fi

src="$1" ## give source file a handy name

## check the source file ends in '.c', '.cpp' or '.c++'
if [ "${src##*.}" != 'c' -a "${src##*.}" != 'cpp' -a "${src##*.}" != 'c++' ]
then
printf "error: first argument not a c/c++ file\n" >&2
exit 1
fi

ext="${src##*.}" ## save the extension

if [ "${#ext}" = 'c' ] ## check if ext is 'c' use gcc else use g++
then
## always enable compiler warnings, -Wall -Wextra -pedantic, minimum
# -Wshadow to catch shadowed variables, -Werror treat warnings as error
gcc -Wall -Wextra -pedantic -Wshadow -Werror \
-std=c11 -O3 -o "${src%.*}" "$src"
else
g++ -Wall -Wextra -pedantic -Wshadow -Werror \
-std=c++11 -O3 -o "${src%.*}" "$src"
fi

if [ $? -eq '0' ] ## check the compiler return, run only on success
then
./"${src%.*}" ${@:2}
else
printf "\nAn error occurred, executable not called\n\n" >&2
fi

Now a couple of short examples to make sure it works:

#include <stdio.h>

int main (int argc, char **argv) {

const char *s = "hello c file.";

printf ("%s\n", s);

for (int i = 1; i < argc; i++)
printf ("arg[%d]: %s\n", i, argv[i]);
}

Example Use/Output

$ bash compilewargs.sh cfile.c foo bar baz
hello c file.
arg[1]: foo
arg[2]: bar
arg[3]: baz

For C++

#include <iostream>
#include <string>

int main (int argc, char **argv) {

std::string s = "hello cpp file.";

std::cout << s << '\n';

for (int i = 1; i < argc; i++)
std::cout << "arg[" << i << "]: " << argv[i] << '\n';
}

Example Use/Output

$ bash compilewargs.sh cppfile.cpp foo bar baz
hello cpp file.
arg[1]: foo
arg[2]: bar
arg[3]: baz

Does the error-handling work?

#include <stdio.h>

int main (void) {

const char *s = "hello c file.";

printf ("%s\n", unknown);
}

Example Use/Output

$ bash compilewargs.sh cerrfile.c foo bar baz
cerrfile.c: In function ‘int main()’:
cerrfile.c:7:21: error: ‘unknown’ was not declared in this scope
printf ("%s\n", unknown);
^
cerrfile.c:5:17: error: unused variable ‘s’ [-Werror=unused-variable]
const char *s = "hello c file.";
^
cc1plus: all warnings being treated as errors

An error occurred, executable not called

What about a file that doesn't exist?

$ bash compilewargs.sh myfile.c foo bar baz
error: file not found 'myfile.c'

What about a text (or any other non-c, cpp or c++) file?

$ bash compilewargs.sh compilewargs.sh foo bar baz
error: first argument not a c/c++ file

By taking the time to think though what the dumbest user you know could ever try and do with your script -- and protecting against it, you can write reasonably robust scripts that will save you grief. Look things over and let me know if you have further questions.

Is Bash compiled or interpreted?

Bash is a single-pass interpreter which means it reads one command at a time, interprets, and runs it then and there. The same thing is true with other types of shells - sh, ksh, zsh, csh, etc.

Here is an example. I have a 3 line script called test.sh which looks like this:

echo one
echo two
'

When run as bash test.sh, it gives this output:

one
two
test.sh: line 3: unexpected EOF while looking for matching `''
test.sh: line 4: syntax error: unexpected end of file

It runs the first and second commands successfully and then encounters the dangling single quote and throws the error.

Let's say we write the same code in Perl, test.pl:

print "one\n"
print "two\n"
'

and run it with perl test.pl. We get:

syntax error at test.pl line 2, near "print"
Can't find string terminator "'" anywhere before EOF at test.pl line 3.

So, it didn't run the first two lines at all, though they were syntactically correct. That's because Perl makes two passes. In the first pass, it does syntax checks and converts the script into an internal form. In the second pass, it runs it.

The simplicity of shell's single-pass execution is its biggest limitation as well. Tolerating syntax errors, even running at all, makes it hard to build large and robust code with the shell language. However, shell scripting is an ideal choice for quick and throw-away code, especially something that makes use of a lot of command line utilities.



Related:

  • Shell Operation - GNU Bash Manual
  • Is Perl a compiled or an interpreted programming language?
  • Is bash an interpreted language?

Bash script to compile and run C++ program

If g++ fails it will return with a non-zero return-value which can be checked for with a Bash if command:

output=$(g++ $PROG_NAME 2>&1)
if [[ $? != 0 ]]; then
# There was an error, display the error in $output
echo -e "Error:\n$output"
else
# Compilation successfull
./a.out
fi

A possibly better solution (IMO) is to learn how to use makefiles, as it will allow more complex projects as well.



Related Topics



Leave a reply



Submit