first i used command : which gcc
If it shows location other than /usr/bin, then how to set the right path to compile the C program
It depends upon your $PATH. And that could be set to something starting with a directory containing some gcc command. Run echo $PATH to find out what is your current $PATH.
You could either type exactly /usr/bin/gcc, or add some alias to your interactive shell configuration (often ~/.bashrc which you might edit with great care), or change your PATH setting, or, assuming which gcc gives something like /home/zaid/bin/gcc (i.e. your $HOME/bin/gcc if $HOME/bin appears early in your $PATH), add a symbolic link ln -sv /usr/bin/gcc $HOME/bin/.
If you compile a program made of several translation units, you should use some build automation tool, probably GNU make. Try once make -p to understand the builtin rules known to your make and take advantage of these. Then, edit your Makefile, perhaps by adding near its beginning lines like
CC=/usr/bin/gcc
CFLAGS+= -Wall -g
The first line (with CC=) sets your C compiler in your Makefile. The second one (with CFLAGS+=) asks for all warnings (-Wall) & debug info (-g). Because you'll use the gdb debugger.
Related
I have a reasonably large project (4272 .o files) and I can't get it to link with GNU Make. I run into make: /bin/sh: Argument list too long. This is a Qt 5 project that uses qmake to generate the makefile.
I know there are lots of questions about this, but I don't know how to apply any of the solutions to my problem. I'm also not totally sure why I'm running into this at the linking step. The error I get is:
make: /bin/sh: Argument list too long
The makefile entry for linking my project looks like this:
build/debug/my_target/my_target: $(OBJECTS)
#test -d build/debug/my_target/ || mkdir -p build/debug/my_target/
$(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS)
which expands to something like:
#echo linking /build/debug/my_target/my_target && clang++ -ccc-gcc-name g++ -lc++ -L/path/to/licensing/lib -Wl,-rpath,/path/to/qt/lib -Wl,-rpath-link,/path/to/qt/lib -o build/debug/my_target/my_target build/debug/my_target/obj/object1.o build/debug/my_target/obj/object2.o ... build/debug/my_target/obj/object4272.o ... [ a bunch of moc_X.o ] ... [ a bunch of libs ] -lGL -lpthread -no-pie
This is pretty long. But here's where it gets weird: when I put the expanded command after the #echo linking build/debug/my_target/my_target && into a shell script, and it runs. The shell script is 202,420 characters (including the #!/bin/sh line). Also, if I get rid of the #echo ... && part of the command I can run make and linking works.
Another workaround: if I manually edit my makefile so that the linking command contains build/debug/my_target/*.o instead of $(OBJECTS) it works:
build/debug/my_target/my_target: $(OBJECTS)
#test -d build/debug/my_target/ || mkdir -p build/debug/my_target/
$(LINK) $(LFLAGS) -o $(TARGET) build/debug/my_target/*.o $(OBJCOMP) $(LIBS)
I don't think I can get qmake to do this, though, so I'm stuck manually editing my makefile unless I can find another solution.
Answers to similar problems seem to focus on line breaks and how they're handled in makefiles. My shell script only has two lines (one after #!/bin/sh and one after the actual command). Also, one solution that people have come up with (for example this one) uses a for loop to iteratively run a command on each argument. I'm not sure how I could apply this here, since (I think) I need all those object files in my linker command.
How does #echo cause the max argument length to be exceeded?
Questions I originally asked that aren't really relevant:
(Note: as originally posted this question missed the #echo at the beginning of the linking command. That seems to be the answer to "why is this happening" and as such I don't really need to know the answer to the second question, which is answered in the first comment in any case).
Why is this happening? How is it that make is running into this error with a command that I can apparently run in a shell script?
How can I get around this if there's no way to run my command as an iterative series of shorter commands?
Various details about my system that might be relevant:
I'm running a fairly up-to-date Arch Linux system, kernel 5.8.10
ARG_MAX value is 2097152, the output from xargs --show-limits is:
Your environment variables take up 2343 bytes
POSIX upper limit on argument length (this system): 2092761
POSIX smallest allowable upper limit on argument length (all systems): 4096
Maximum length of command we could actually use: 2090418
Size of command buffer we are actually using: 131072
Maximum parallelism (--max-procs must be no greater): 2147483647
ulimit -s output: 8192 (I've tried setting this to much larger values, e.g. ulimit -s 65536 without success, which maybe isn't surprising since ARG_MAX appears to be much larger than the linker command).
GNU Make version is 4.3
clang/clang++ version is 10.0.1
Qt version is 5.15.1 (I'm fairly certain this isn't relevant, we've just switched our project over from 5.9.6 and I had the same problem then as well).
Just FYI, the reason removing the echo fixes the problem (this is what I was going to suggest as well) is that when you remove the special shell operator && and just have a simple command invocation with no shell features like multiple commands, special quoting, globbing, etc. then make uses the "fast path" to invoke your command.
That is, if make can determine that the shell would do nothing special with your command, other than run it, make will skip invoking the shell and instead run your command directly.
In that case you will not run up against the single-argument limit because it doesn't use the /bin/sh -c '...' form.
Of course, this can be a little magical and inflexible since you have to be careful to ensure no special shell operations are ever included in your link line. But if you can ensure this then it should solve your problem.
Why is this happening? How is it that make is running into this error with a command that I can apparently run in a shell script?
Because make is running the shell commands (recipes) by passing them as a single argument to /bin/sh -c, and not only will that run into the OS's limit on command line arguments + environment variables, but also into the much lower limit that Linux is imposing on a single string from the command line or environment, which is usually 128k bytes.
How can I get around this if there's no way to run my command as an iterative series of shorter commands?
As suggested by #ephemient can use the #arglist argument of gcc or ld (which directs it to take its arguments from a file), and use the file function of GNU make to create that arglist file, which being internal to make, will not run into any that OS limit.
I had written a simple shell script (called test.sh) to compile a test C++ file using two different compilers (g++ and clang++) and put some echo statements in to compare the output. On the command line, I accidentally typed make test, even though there was no Makefile in that directory. Instead of complaining about no Makefile or no target defined, it executed the following commands (my system is running the 64-bit Debian stretch OS with GNU Make 4.1 ):
user#hostname test_dir$ make test
cat test.sh >test
chmod a+x test
user#hostname test_dir$
Curious about that, I made another shell script (other.sh) and did the same thing.
Here is my other.sh file:
#!/bin/bash
echo ""
echo "This is another test script!"
echo ""
Command line:
user#hostname test_dir$ make other
cat other.sh >other
chmod a+x other
user#hostname test_dir$
My question is why does make automatically create an executable script (without the .sh extension) when running the make command in the terminal? Is this normal/expected/standard behavior? Can I rely on this behavior on all Linux machines?
Side question/note: Is there a list of supported "implicit suffixes" for which make will automatically create an executable?
This is one of a number of "implicit rules" which are built into Gnu make. (Every make implementation will have some implicit rules, but there is no guarantee that they are the same.)
Why does make automatically create an executable script without the .sh extension?
There is an old source repository system called Source Code Control System (SCCS). Although it no longer has much use, it was once the most common way of maintaining source code repositories. It had the quirk that it did not preserve file permissions, so if you kept an (executable) shell script in SCCS and later checked it out, it would no longer be executable. Gnu make could automatically extract files from an SCCS repository; to compensate for the disappearing executable permission issue, it was common to use the .sh extension with shell scripts; make could then do a two-step extraction, where it first extracted foo.sh from the repository and then copied it to foo, adding the executable permission.
Is this normal/expected/standard behavior? Can I rely on this behavior on all Linux machines?
Linux systems with a development toolset installed tend to use Gnu make, so you should be able to count on this behaviour on Linux systems used for development.
BSD make also comes with a default rule for .sh, but it only copies the file; it doesn't change permissions (at least on the bsdmake distribution on my machine). So the behaviour is not universal.
Is there a list of supported "implicit suffixes" for which make will automatically create an executable?
Yes, there is. You'll find it in the make manual:
The default suffix list is: .out, .a, .ln, .o, .c, .cc, .C, .cpp, .p, .f, .F, .m, .r, .y, .l, .ym, .lm, .s,
.S, .mod, .sym, .def, .h, .info, .dvi, .tex, .texinfo, .texi, .txinfo, .w, .ch,
.web, .sh, .elc, .el.
For a more accurate list of implicit rules, you can use the command
make -p -f/dev/null
# or, if you like typing, make --print-data-base -f /dev/null
as described in the make options summary.
From the make man page:
The purpose of the make utility is to determine automatically
which
pieces of a large program need to be recompiled, and issue the commands
to recompile them. The manual describes the GNU implementation of
make, which was written by Richard Stallman and Roland McGrath, and is
currently maintained by Paul Smith. Our examples show C programs,
since they are most common, but you can use make with any programming
language whose compiler can be run with a shell command. In fact, make
is not limited to programs. You can use it to describe any task where
some files must be updated automatically from others whenever the others change.
make really is more than most people make it out to be...
Trying to use the 'make' command in linux to compile c programs for class. If I do make it works, but if I type 'make' and then start typing the file name and tab it doesn't autocomplete the file for me. It's kind of annoying and I'd like to be able to use it instead of typing gcc -o everytime to test my program. How can I fix this?
edit
I have GalliumOS - 2.0 (ubuntu 16.04) fully installed on a c720 chromebook (ChromeOS has been completely removed and replaced with this)
The shell is bash.
edit2
adding the line complete -f -X '!*' make in my ~/.bashrc file works, but now I need help making it ignore directories or make it so that only .c and compiled c programs are added to the autocomplete.
It probably does not complete, because the parameter following make is usually the name of the target (for the recipe) and not a filename.
It perhaps completes for options that expect a filename, like e.g. make -f mymakefile.
I have few path settings and alias in .bash_profile, and I am exporting those.
For eg:
alias gcc=/abc/def/......./myrtgcc
export gcc
And I want use myrtgcc to compile c programs either from terminal or from eclipse using the command "GCC", and I expect the system to use "myrtgcc" whenever I compile the programs using
myrtgcc somfile.c -o output
However this is not the case.
even after adding the above alias in .bash_profile, and restarting the system ( or use > source .bash_profile ) the changes are not reflected.
because, If I open the terminal and type
which gcc
I get /usr/bin/gcc and when eclipse uses "GCC" command it again invokes the same /usr/bin/gcc.
How do I make myrtgcc default across the system, for command gcc
Thank you.
Make a symbol link in /abc/def/xxx/myrtgcc
ln -s myrtgcc gcc
Put the path of myrtgcc in front of /usr/bin in your .bash_profile:
export PATH=/abc/def/xxx/myrtgcc:$PATH
how to go into the environment of "c". when using cygwin... please tell me the commands to go into the c environment....
If you want to cd to the C: drive then one way is:
$ cd /cygdrive/c
If you want to edit/compile/run/debug C programs, then it's:
$ emacs foo.c # edit
$ gcc -Wall foo.c -o foo # compile
$ ./foo # run
$ gdb ./foo # debug
Do you want to navigate to the C: drive when in the shell? If so, just do cd c:
Install cygwin from cygwin.org. Select development packages like gcc during the process. Open a cygwin shell and call gcc from the command line. Or whatever.
After reading the question, my first interpretation was that the question was about how to ensure that the C locale was set for the shell in Cygwin, rather than allowing the Windows locale to be inherited. Putting export LC_ALL=C or export LC_ALL=C.utf8 into your ~/.bashrc would force the C locale in all shell contexts. The command locale can be used to see your current locale before and after changing LC_ALL, which will help verify that the change is in effect. man bash (or your shell of choice) will provide more information on what is affected by the various locale-related environment variables.