2

Background: I originally learned C using Turbo C on DOS 6, in 1990; there were a lot of things that Turbo C treated as standard that apparently weren't (even then).

Now I'm refreshing myself by working through "88 C Programs". I've discovered that when I need to use functions from math.h on GCC (like sqrt(), log10(), etc.), I have to manually link the math libraries by appending -lm at the end of the GCC command. Is there a way to automate this action (say, with an environment variable), so that, if I have #include "math.h" I automatically get -lm added to the compile command and don't have to remember to type it?

As a single user on a quad-core CPU, I'm not terrifically concerned about tiny performance differences.

Potentially significant: I'm using the version of GCC and its dependencies found in the Ubuntu repositories, on Kubuntu 14.04.

Is there a way to set -lm as default for GCC?

Zeiss Ikon
  • 481
  • 4
  • 13
  • 1
    Seriously, just type those four extra keystrokes. Or learn to use `make` or some other build tool and be even more productive. – Mat Nov 09 '14 at 23:11
  • Related: *[Why do you have to link the math library in C?](https://stackoverflow.com/questions/1033898/why-do-you-have-to-link-the-math-library-in-c)* (18 answers. 314 upvotes. 2009.) – Peter Mortensen Oct 27 '22 at 23:47

3 Answers3

3

I suggest you to write a GNU Make script.

Put the following script into file named makefile:

LDFLAGS+=-lm

all:$elf

$elf:%.o

%.o:%.c

clean:
    rm -rf $elf *.o

Then when you want to compile, type make or make all.

Specifically, $elf stores the name you want to call your executable, substitute it, or

elf=name

without any space up front.


BTW, this makefile can be abused. It saves time, but please not use it unless you just want a small test.

You can use

elf=name1 name2 name3

or so, to generate multiple ELF files at one line. But in such a case, the linker will try to link all .o files together, which potentially will generate error messages which are hard to understand. But anyway, it sounds you just want some small test cases, so...

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jason Hu
  • 6,239
  • 1
  • 20
  • 41
  • It's `LDFLAGS`, not `LDFLAG`. And I wouldn't use the name `$elf`; it implies that object files are in ELF format, which may well be true but it's not something I should have to care about. – Keith Thompson Nov 09 '14 at 23:32
  • @KeithThompson sorry for typo. about `$elf`, anyway, it's just a symbol, still better than `$foo` right? it matters nothing if you don't care. – Jason Hu Nov 09 '14 at 23:35
  • `-lm` should not go into `LDFLAGS`! the `LDLIBS` is the right variable – DaBler Oct 31 '18 at 14:53
3

If you're using Bash (or some other Bourne-derived shell), you can define a shell function. For example:

gccm() { gcc "$@" -lm; }

An alias won't do the job, since the -lm argument has to follow the name of the source or object file that depends on the math library. (The -lm argument is passed to the linker, which keeps track of unresolved references for each file; those unresolved references may be resolved by later arguments.)

(C shell (csh) aliases are a little more powerful than Bash aliases—but C shell doesn't have shell functions.)

Note that this function requires you to use a different command name. If you want to type gcc and have it invoke the gcc command with an added argument, you need to do a little extra work to avoid having the function invoke itself:

gcc() { command gcc "$@" -lm; }

or:

gcc() { /usr/bin/gcc "$@" -lm; }

command is a Bash built-in that invokes a specified command while bypassing any shell function with the same name. Or you can specify the full path to gcc.

Creating a function like this also gives you an opportunity to add more default arguments. gcc's default mode is rather lax, and it supports the "gnu90" dialect of the language (C89 with GNU-specific extensions). You can specify additional arguments to recognize a more modern version of the language and to perform more compile-time checks:

gcc() { command gcc -std=c99 -pedantic -Wall -Wextra "$@" -lm; }

Another alternative is to write a wrapper script and put it in a directory ahead of /usr/bin in your $PATH, for example $HOME/bin.

(Some commands recognize environment variables that implicitly add command-line options; for example GNU grep recognizes $GREP_OPTIONS. gcc does not.)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • Apparently there's more I need to learn about creating a shell function; I'm using bash, and I tried putting this in a file like a shell script, but it does nothing I can detect (no error message, but no output file). More research... – Zeiss Ikon Nov 10 '14 at 00:41
  • @ZeissIkon: Typing that line just creates the function; it doesn't invoke it. You can add the line to your `.bashrc`; after you do that, the function will be available in future shells. (It won't affect your current shell process.) – Keith Thompson Nov 10 '14 at 01:04
  • Ah. I'd have to close any shells open when I make that change, so they can re-read the .bashrc. I'll try that later, but I've just about got the python thing going; I'll post it here when it quits complaining that the files that are there aren't there. – Zeiss Ikon Nov 10 '14 at 01:18
  • @ZeissIkon: No need to close any shells. You can just copy-and-paste the function definition into a running shell and then use it. – Keith Thompson Nov 10 '14 at 01:19
  • Yahoo, that worked! I still don't know what's up with the python bit I wrote, I'll post that as a separate question on a python tag and ask about it, since it's a useful possibility in and of itself to call a system program from python. – Zeiss Ikon Nov 10 '14 at 01:59
0

Another possibility to using a Makefile is to add an alias to your .bashrc file. In the example:

echo "alias gccm='gcc -lm'" >> ~/.bashrc

And then, after resourcing your .bashrc file, you can use it with: gccm. But seriously, it's just three more characters you're saving.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Lucas Godoy
  • 792
  • 8
  • 17
  • The `-lm` has to *follow* the name of the source or object file that needs the math library. This alias won't work. A similar shell function, like `gccm() { gcc "$@" -lm ; }` would. – Keith Thompson Nov 09 '14 at 23:31
  • You're right. I'm kinda new here, (1) Should it be better if I remove my answer? (2) Why didn't you post it your comment as an answer? – Lucas Godoy Nov 09 '14 at 23:34
  • Not an alias, but I could create a tiny shell script or python script named gccm that appends the -lm after the arguments provided. Generally I'm just typing `gcc -o source source.c` to wind up with compiled, assembled, and linked Linux executable; it'll be a while before I'm likely to write anything that needs a more complex build than that. – Zeiss Ikon Nov 10 '14 at 00:06
  • @ZeissIkon: If you're on a UNIX-like system, a Python script needs `#!/usr/bib/python` on the first line, and need to be made executable with `chmod +x`. Then you can execute it directly without mentioning `python`. As for why the command didn't work for you, of hand to see exactly what you tried. Keep in mind that the `gcc` command doesn't print anything unless they're a problem. – Keith Thompson Nov 10 '14 at 00:41
  • @KeithThompson Ah, "Learn Python the Hard Way" hasn't gotten to that yet, but I can already write a script that can accept the filename to target and add the extras, then use "system" to invoke gcc with the expanded command line. Yes, gcc gives no output back to console when there are no warnings or errors, but it does output the compiled file -- I deleted the compiled file for the program that needed math.h and got no compiled file out. – Zeiss Ikon Nov 10 '14 at 00:55