I have a shell script compileRun that compiles and execute C source file.
#!/bin/sh
gcc bar.c -o ./bar
./bar
what i actualy wish to achieve is when we
ln -s compileRun bar.c
./bar.c
I would like bar.c to be compiled and executed.
I appreciate any help.
I understand what OP wants.
What follows would work only if source files are explicitly stored in a different place than symlinks. A path can be prepended to $0 in the bash script.
Your should replace somefile.c by $0 in your bash script.
This special shell expression returns the name of the file being currently executed. Which would be in your case, bar.c.
For example:
ln execute_c_file my_file.c
./my_file.c
If my_file.c is a running bash script $0 will evaluates to my_file.c.
I suggest you edit your question to clear up the semantic/meaning of your code.
Related
I just got started writing some C programs.
To start with I was just running them through VS code. Nice and easy, I just had to press a button and bam, there it was.
But now I need to pass files as arguments to my program, which creates the need of running it from the command line.
The way I do it now, is using this two step process, (which I think is just the basic way of doing it):
ask#Garsy:~/Notes/ethHack/crpytifiles$ gcc test.c -o test
and then running the file:
ask#Garsy:~/Notes/ethHack/crpytifiles$ ./test
This is a bit tedious in the long run. Is there any way I could do this process in one step?
And perhaps also without creating the executable?
It would be really cool if I could just run it as you normally would with a python or java file, one command, and the thing runs.
You could do that with a makefile. More about GNU Make here.
all:
gcc test.c -o test
./test
The file should be called Makefile or makefile (it can have different names,just keeping it simple), and you can run it by executing:
make
Assuming you have GNU Make installed and test.c is located in the same directory with makefile.
This is a bit tedious in the long run. Is there any way I could do this process in one step?
Yes. You could create a shell function (or an alias if your shell supports alias arguments, which bash does not), e.g.:
ccr() { gcc "$1" -o x.$$ && ./x.$$; rm -f x.$$ }
$ ccr hello.c
Hello, world!
$
which will compile the script, run it if compilation succeeded, then remove the compiled binary.
And perhaps also without creating the execuable?
No (well, not easily). Executing binaries is offloaded to the exec*() function family, and the operations performed are complex and, I suspect, incompatible with stdin operations. So you cannot send the executable to a pipe and execute it from the pipe.
What you can do is use a C interpreter, albeit it is not exactly the same thing.
I am wondering that nobody is issuing the general comparison between an IDE and shell. So yes IDE may give you some comfort. But you will be happy if you learnt the fundamentals of linking & Co from scratch - otherwise the configuration of the
IDE can get pretty challenging, when you start stuff that does not work out of the box.
The rest are helpful tips to increase the efficiency on the shell - like make or
other automation builders. Shell editors provide additional tools and plugins to increase your workflow - eg with vim as an shell editor (and some plugins) you come pretty close to an IDE. This includes syntax highlight,
code check, compile and run of the program, etc... just my 2 cents
As #alex01011 correctly stated, what you need is a Makefile, and his solution should work. What I want to suggest here is a better Makefile.
First make already know how to use build test from test.c in the simple case. It will add parameters to the preprocessor, compilation and linker steps from Makefile variables, so it is better to use the built-in command for better fleksibility.
# Tell make that `all` and `run` is technically not files that will be built
.PHONY : all run
# These flags are passed to the compiler, we always want to compile with
# warnings when developing
CFLAGS= -Wall
# `all` is the first rule, so that is the one that will be build not
# specifying anything on the command line
# `all` also depends on `test` so that will be built from `test.c` calling
# `make` or `make all`
all: test
# `make run` will run your command. `run` depends on `all` to make sure the
# program exist before calling `./test`
# Note the the indent must be made with a tab and not spaces
run: all
./test
If your program is composed of more files, things get a lit more complicated, but still easily manageable:
# Example of a Makefile for a project that is composed of the files
# test.c foo.c, bar.c, foo.h and bar.h
# The main-function is in test.c, and the generated program will be
# called `test`
#
.PHONY: all run
CFLAGS= -Wall
all: test
# foo.c includes foo.h therefore foo.o depends on foo.h in addition to foo.c
foo.o: foo.h
# bar.c includes bar.h therefore foo.o depends on bar.h in addition to bar.c
bar.o: bar.h
# test.c includes both foo.h and bar.h
test.o: foo.h bar.h
# test should be linked with foo.o and bar.o in addition to test.o
test: foo.o bar.o
run: all
./test
Now typing make run will automatically build and link test, if needed, and the run ./test if there was no errors.
Other variables you may set in addition to CFLAGS are CC, CPPFLAGS, LDFLAGS, LOADLIBES and LDLIBS.
Often you also want to have a clean targets in your Makefile for typing make clean to remove generated files. See info make for more details.
Can I use Preprocessor Directives in .ld file?
I need to to use one of two sets of .ld file and wants to let Build engine deside that using macro, Can I do that?
Yes, you can. You need to run preprocessor manually for your linker script, like this:
in="your_linker_script.ld"
out="generated_script.ld"
cflags=-Iinclude/
gcc -E -P -x c $cflags $in >$out
Flags:
-E specifies GCC to only run preprocessor
-P prevents preprocessor from generating linemarkers (#line directives)
-x c tells GCC to treat your linker script as C source file (it's needed to run GCC with your LD script)
Or you can simply use cpp tool, which is actually C preprocessor.
After this you will be able to use generated linker script to build your program (e.g. in Makefile).
Example
Here is how I solved this problem in my project:
Here is my linker script uses preprocessor (#include directive and CONFIG_TEXT_BASE constant). Excerpt:
#include <config.h>
. = CONFIG_TEXT_BASE;
Here is script to generate preprocessed linker script. Excerpt:
gcc -E -P -x c -Iinclude $cflags $in >>$out
Here is my Makefile, it's generating preprocessed linker script at $(LDS_GEN) target (line 53) and the this generated script is being used to build result binary (line 42). Excerpt:
$(LDS_GEN): $(LDS)
build/gen-lds.sh $(LDS) $(LDS_GEN) $(CFLAGS)
$(APP).bin: $(OBJS) $(LDS_GEN)
$(LD) $(OBJS) -T $(LDS_GEN) -o $(APP).elf
Small update after long time. This way of pre-processing works until the memory file does not contain lines that are fooling the pre-processor. E.g.:
"KEEP(*path/*.o(.rodata .rodata*))"
The "/*" after path is considered comment start (the line contains what is considered a C multi-line comment start and not a match pattern).
This line is valid for the linker but it is considered comment and the output from C pre-processor will remove everything till a supposed closing comment is found:
"KEEP(*path"
The resulting file is clearly invalid for the linker. I have no solution at the moment.
As a simplification of Sam's answer, I added the below to my makefile and away we go :)
PRE_LD_FILE = $(PROG_NAME).ld
LD_FILE = $(PROG_NAME)_generated.ld
$(LD_FILE) : $(PRE_LD_FILE)
cpp $(PRE_LD_FILE) | grep -v '^#' >>$(LD_FILE)
I have written a simple helloworld.c program. I can compile it and run it on linux terminal using gcc and ./a.out command. My query is regarding calling .o file without any extension. For example, to run my program instead of typing "./helloworld.out", I want to run it using keyword "helloworld" on my terminal. Any hints???
Thank You.
Just compile using
gcc -o helloworld helloworld.c
The -o option is for the output file name
Then use:
./helloworld
You need the ./ to tell the shell where the executable resides, since the current directory is unlikely to be in $PATH.
I wrote this .sh file to compile any c source file, so that when I run it, it asks for a filename and gcc compiles it and then, runs the executable a.out.
But this doesn't work properly when error is present in .c files. It also shows that a.out is not present. I don't want this error message ( a.out is not present ) but just want to print only the error message generated for the .c files..
Here's the script..
echo `clear`
echo enter file name
read FILE
gcc $FILE
./a.out
echo -e '\n'
If you enable abort-on-error in shell scripts, life will be a lot easier:
#!/bin/sh
set -eu # makes your program exit on error or unbound variable
# ...your code here...
Utilizing builtin rules as an alternative to your script you might want to use make as an alternative to a handcrafted script. To compile file.c and run the generated executable all you need to do is:
make file && ./file
If you don't know it, I strongly suggest you take a look at the make utility as it will ease your work a lot. Managing anything more than a one file project can get really nasty without it.
You can chain compilation and execution commands:
echo `clear`
echo enter file name
read FILE
gcc $FILE && ./a.out
echo -e '\n'
Here, if gcc will fail, the shell will drop the ./a.out command.
You may also protect the file name with double quotes :
#! /bin/bash
clear
echo -n "Enter file name: "
read FILE
gcc -Wall -W "$FILE" && ./a.out
echo
I there hope this is what you were looking it only requires this command:
./compile executableName myCProgram.c -lm
you can place more C files ahead of each others and add more libraries at the end of the line and executableName does not require the .exe
#!/bin/bash
args="$#"
quant=$#
#Copies in case you need the -lm(math library) params
biblio=${args#*-}
#grabs all params except the first one which should be the name of the executable
firstCommand=${*:2:${#args}}
#Remove the "-lm -lc" from firstCommand
firstCommand=${firstCommand%%-*}
printf "\nEXECUTING: gcc -W -Wall -c $firstCommand\n"
#Creates the object file ".o"
gcc -W -Wall -c $firstCommand
#Convert the files names from example.c to example.o
args=${args//.c/.o}
printf "\nEXECUTING: gcc -o $args\n\n"
#Creates the executable
gcc -o $args
printf "\n**Now execute comand: ./$1 **\n\n"
Is it possible to compile a stream of data rather than compiling a .c file using gcc? for example, is it possible that instead of having my code stored in any xyz.c file, I can directly compile the code?
Use gcc options -x and -
$ echo -e '#include <stdio.h>\nmain(){puts("Hello world");return 0;}' | gcc -xc -ogarbage - && ./garbage && rm garbage
Hello world
The single line command above is made up of the following parts:
echo -e '#include <stdio.h>\nmain(){puts("Hello world");return 0;}' # "source"
| # pipe
gcc -xc -ogarbage - # compile
&& # and
./garbage # run
&& # and
rm garbage # delete
This may answer you question, though it is rarely useful.
You can create a file, stream the code into it, then create another process(that is, the compiler) giving it the file as an argument. Then create another process(that is, the linker) and it will create an exe for you. And finally you can launch that exe as a new process. But why?!:)