Command line arguments with makefile - c

Edit:
This is different than the other question because the variables that I put on the unix command line will be "p2 -s input.txt", where my main.c file will manipulate them.
So normally when working with command line arguments, my code would be something like:
int main(int argc, char argv[])
{
printf("%d", argc);
return 0;
}
How would I do this with a makefile?

GNU make is not C.
Passing arguments cannot be done the same way.
If you'd like to provide custom arguments to your makefile,
you may consider doing this through variable assignments.
for example, take the following makefile:
all:
#echo $(FOO)
It can be called via the command line like this:
make FOO="test"
and it will print test.
Other options to consider:
setting environment variables before calling make
relying on
different targets specified inside the Makefile

Use a makefile like this:
COMMAND = echo 'You did not specify make COMMAND="cmd 2 run" on the command line'
all:
${COMMAND}
Now when you run make COMMAND="p2 Hi", you will get that command run and the appropriate output. If you forget to specify COMMAND="something or another" then you get an appropriate memory jogger.

Related

Executable path as a variable parameter to exec

I've an application which needs to call a specific program 'mips64-unknown-linux-gcc' for linking all objects from a script with all required args for linking.
I am writing an exec function to call the compiler passed by script along with it's args. For this I wrote the code:
//prog.c : gcc prog.c -o prog
int main(int argc, char *argv[]) {
execvp("mips64-unknown-linux-gcc",argv);
}
This works, but the mips64-unknown-linux-gcc and argv are variables from script input.
I need execv first argument to be a variable which is compiler to be invoked. I can somehow (maybe) retrieve it by getenv(”CC”) but due to other dependencies my requirement is that exec shall accept the compiler and args at runtime (something like below). Is there any way I can do this?
./prog mips64-unknown-linux-gcc --sysroot=<<...>> -O3 -Wl -L <<...>> -L <<...>> -I <<...>> -L <<...>> abcd.o a1.o b2.o -o prog
I described my problem at my best. Please ask if anything is not clear.
From your example command line it seems that you want to take the first argument from command line as your command to execute and everything else should be passed to that command.
That is basically the same command line execpt for the first argument.
This makes things rather easy.
Looking at argv you will find these string:
char *argv[] = {"proc","mips64-unkown-linux-gcc", "--sysroot=<<...>>", ..., "-o", "prog", NULL};`
You can use that and call your command:
execvp(argv[1], argv+1);
Of course you should check whether you have at least one argument.
If you want do filter some options and handle in your own program instead of blindly passing it to execvp you must rebuild your own array of arguments where you do not include those options.

How to pass run time arguments to a function in c through a shell script

I have a shell script which has to take arguments from the command line and pass it to a function in C. I tried to search but didn't find understandable solutions. Kindly help me out.
Should the arguments be passed via an option as a command in the shell script?
I have a main function like this:
int main(int argc, char *argv[])
{
if(argc>1)
{
if(!strcmp(argv[1], "ABC"))
{
}
else if(!strcmp(argv[1], "XYZ"))
{
}
}
}
How to pass the parameters ABC/XYZ from the command line through a shell script which in turn uses a makefile to compile the code?
You cannot meaningfully compare strings with == which is a pointer equality test. You could use strcmp as something like argc>1 && !strcmp(argv[1], "XYZ"). The arguments of main have certain properties, see here.
BTW, main's argc is at least 1. So your test argc==0 is never true. Generally argv[0] is the program name.
However, if you use GNU glibc (e.g. on Linux), it provides several ways for parsing program arguments.
There are conventions and habits regarding program arguments, and you'll better follow them. POSIX specifies getopt(3), but on GNU systems, getopt_long is even more handy.
Be also aware that globbing is done by the shell on Unix-like systems. See glob(7).
(On Windows, things are different, and the command line might be parsed by some startup routine à la crt0)
In practice, you'll better use some system functions for parsing program arguments. Some libraries provide a way for that, e.g. GTK has gtk_init_with_args. Otherwise, if you have it, use getopt_long ...
Look also, for inspiration, into the source code of some free software program. You'll find many of them on github or elsewhere.
How to pass the parameters ABC/XYZ from the command line through a shell script
If you compile your C++ program into an executable, e.g. /some/path/to/yourexecutable, you just have to run a command like
/some/path/to/yourexecutable ABC
and if the directory /some/path/to/ containing yourexecutable is in your PATH variable, you can simply run yourexecutable ABC. How to set that PATH variable (which you can query using echo $PATH in your Unix shell) is a different question (you could edit some shell startup file, perhaps your $HOME/.bashrc, with a source code editor such as GNU emacs, vim, gedit, etc...; you could run some export PATH=.... command with an appropriate, colon-separated, sequence of directories).
which in turn uses a makefile to compile the code?
Then you should look into that Makefile and you'll know what is the executable file.
You are using and coding on/for Linux, so you should read something about Linux programming (e.g. ALP or something newer; see also intro(2) & syscalls(2)...) and you need to understand more about operating systems (so read Operating Systems: Three Easy Pieces).
See following simple example:
$ cat foo.c
#include <stdio.h>
int main(int argc, char ** argv)
{
int i;
for (i = 0; i < argc; ++i) {
printf("[%d] %s\n", i, argv[i]);
}
return 0;
}
$ gcc foo.c
$ ./a.out foo bar
[0] ./a.out
[1] foo
[2] bar
$

how to run a c program with reading command line parameters in openvms?

I built a simple program try to print the command line parameters.
The code is below and I built an executable file (TEST.EXE).
int main(int argc, char *argv[])
{
int i;
printf("%s\n",argv[0]);
for (i = 1; i < argc; i++)
printf("argument %d: %s\n", i, argv[i]);
exit (EXIT_SUCCESS);
}
I try to run the TEST.EXE and print the parameters but fail.
The result of command RUN TEST.EXE test1 test2:
%DCL-W-MAXPARM, too many parameters - reenter command with fewer parameters
What can I do to print "test1" and "test2"?
The RUN command doesn't support any command line arguments. Define a foreign command and use that instead. From David Mathog's beginner FAQ:
How do I start a program?
Method 2: Use the RUN command:
$ run program_nameNo command line arguments allowed
Method 3: Define a foreign command for it, then run it. In the
following
example where is a logical name equivalent to the
location of the program.
$ new_command :== $where:program_name
$ new_command [command line arguments]
Defining a foreign command as per 'a3f' is the 'proper' way to do it albeit somewhat tedious and 2-stepped.
You may also want to try the MCR 'trick'.
MCR being short for the Monitor Command Routine from the 40+ year old PDPD-11 Operating System RSX.
Now MCR defaults to look for program in SYS$SYSTEM, so you do have to specify the current location:
$ MCR dev:[dir]TEST this is a test.
There is also a 1-1/2 step approach using DCL$PATH.
This works mostly like the Unix and Windows path, providing places to look for DCL scripts or programs if an unknown command is entered.
For example
$ DEFINE DCL$PATH SYS$DISK:[],SYS$LOGIN:,SYS$SYSTEM:
Now just type : TEST this.
Hein
In addition, if you need to preserve the case of the arguments, you have to quote these arguments or enter
$ SET PROCESS/PARSE_STYLE=EXTENDED
once in the lifetime of your process and
$ DEFINE/USER DECC$ARGV_PARSE_STYLE TRUE
before running your program with a specific foreign command or by using automatic foreign commands (DCL$PATH). Otherwise all the unquoted arguments are converted to lowercase characters.
PS: VMS has a command language, that is, you have to enter a command to run a program. By default, file names are no commands. With defining DCL$PATH you change this default behaviour.

command line arguments into make file

I have a C file for which I want to give cmd line arguments.
Say
$ make --argument1
or something like this.
So that in my main program I should be able to do argv[1] and be able to access the variable.
I have tried looking for ways of doing this. Is there actually a way of doing this?
These were the relevant content I found on the GNULinux manual about make.
variables defined on the command line are passed to the sub-make
through MAKEFLAGS. Words in the value of MAKEFLAGS that contain ‘=’,
make treats as variable definitions just as if they appeared on the
command line.
Is this what I need to read up more or is this in a different context?
Do let me know.
I think you misunderstand the use of command line arguments - they are given when the executable is executed not when it is compiled.
Better example
foo.c
#include <stdio.h>
int main()
{
int myval=DEFVAL;
printf("myval=%d\n", myval);
return 0;
}
Makefile
DEFVAL=17
foo: foo.c
gcc -DDEFVAL=${DEFVAL} foo.c -o $#
Your question doesn't make a whole lot of sense, so I'm going to read between the lines and guess that you have a Makefile that someone else wrote, and when you run make, it runs some program, and that's the program that you want to give command line arguments.
In order to do that, you'll probably have to modify the Makefile. In order to that, it helps to understand how make works and how to use it (you might want to find a book on the subject, such as this one), but it may possible to modify the Makefile without too much trouble.
Somewhere in the Makefile, you'll find the action line that is used to invoke you're program. If you can find that line, you can add the argument you want.

"Too few arguments" error trying to run my compiled program

I'm trying to code to refresh my memory preparing myself for a course.
int main(){
int x;
for( x = 0;x < 10; x++){
printf("Hello world\n");
}
return 0;
}
But when I tried to run this I get Too few arguments
I compiled the code above using gcc -o repeat file.c Then to run this I just type repeat
Sorry if this was a stupid question, it has been a while since I took the introduction class.
When you type
filename
at a prompt, your OS searches the path. By default, Linux doesn't include the current directory in the path, so you end up running something like /bin/filename, which complains because it wants arguments. To find out what file you actually ran, try
which filename
To run the filename file gcc created in the working directory, use
./filename
Your code compiles fine. Try:
gcc -o helloworld file.c
./helloworld
UPDATE :
Based on more recent comments, the problem is that the executable is named repeat, and you're using csh or tcsh, so repeat is a built-in command.
Type ./repeat rather than repeat.
And when asking questions, don't omit details like that; copy-and-paste your source code, any commands you typed, and any messages you received.
The executable is named file, which is also a command.
To run your own program, type
./file
EDIT :
The above was an educated guess, based on the assumption that:
The actual compilation command was gcc file.c -o file or gcc -o file file.c; and
The predefined file command (man file for information) would produce that error message if you invoke it without arguments.
The question originally said that the compilation command was gcc file.c; now it says gcc -o filename file.c. (And the file command prints a different error message if you run it without arguments).
The correct way to do this is:
gcc file.c -o filename && ./filename
(I'd usually call the executable file to match the name of the source file, but you can do it either way.)
The gcc command, if it succeeds, gives you an executable file in your current directory named filename. The && says to execute the second command only if the first one succeeds (no point in trying to run your program if it didn't compile). ./filename explicitly says to run the filename executable that's in the current directory (.); otherwise it will search your $PATH for it.
If you get an error message Too few arguments, it's not coming from your program; you won't see that message unless something prints it explicitly. The explanation must be that you're running some other program. Perhaps there's already a command on your system called filename.
So try doing this:
gcc file.c -o filename && ./filename
and see what happens; it should run your program. If that works, try typing just
filename
and see what that does. If that doesn't run your program, then type
type -a filename
or
which filename
to see what you're actually executing.
And just to avoid situations like this, cultivate the habit of using ./whatever to execute a program in the current directory.

Resources