1

I am trying to replicate CS50x's sandbox on my Gentoo system, but I am getting this kind of error when running make

% make price
cc     price.c   -o price
/usr/lib/gcc/x86_64-pc-linux-gnu/9.3.0/../../../../x86_64-pc-linux-gnu/bin/ld: /tmp/cc9TASaL.o: in function `main':
price.c:(.text+0x15): undefined reference to `get_float'
collect2: error: ld returned 1 exit status
make: *** [<builtin>: price] Error 1

For reference, this is the source file:

% cat price.c
#include <stdio.h>
#include <cs50.h>

int main(void)
{
    float price = get_float("What's the price?\n");
    printf("Your total is %.2f (VAT included)\n", price * 1.22);
}

I have manually installed libcs50 on my system:

# ldconfig -p | grep cs50 
libcs50.so.10 (libc6,x86-64) => /usr/local/lib64/libcs50.so.10
libcs50.so (libc6,x86-64) => /usr/local/lib64/libcs50.so

And when I compile the file with

% gcc -lcs50 price.c -o price

I am getting no errors. Have I configured something wrong on my system, or have I misunderstood how make works? After watching the lecture, I was under the impression that make would "automagically" add the -lcs50 parameter.

Thanks!

SOLUTION Set CC, CFLAGS and LDLIBS according to these instructions: https://cs50.readthedocs.io/libraries/cs50/c/ . All the "automagical" stuff in the lecture videos is possible thanks to those environment variables.

  • How would it know how to "magically" add some random library? (i.e., no, it won't do that). – MadScientist Jul 14 '20 at 17:43
  • I thought it'd add it. since I have installed the library in my system, and I have called it with `#include ` . At this point, I think the instructor must have configured something extra in his sandbox, because he ran `make` without a Makefile or further arguments, and it compiled fine. I am wondering if there is a commonly used way to replicate that? – Francesco C Jul 14 '20 at 18:39
  • You probably have at least 1,000 different libraries installed on your system for different reasons (a quick review shows 1,400 `lib*` packages installed on mine); it would definitely be incorrect for make to simply add them all to every link line. As for the `#include`, first make doesn't parse your source code at all, and second there's no way it could reliably map an include file name to a library: there's no reason they will or should have the same name; many do not. – MadScientist Jul 14 '20 at 21:44
  • As for how your instructor did this, if he truly did not have a makefile then he must have had an environment variable set, something like `export LDLIBS='-lcs50'` in his shell setup file (`~/.bashrc`). Are you _sure_ he didn't have a makefile? That would certainly be unusual. Keeping that in the environment is not a great idea because it applies to any make you run. – MadScientist Jul 14 '20 at 21:46
  • the mistake is the in the makefile, you've forgotten to link the library there. Could you post the makefile? – Chase Jul 15 '20 at 08:32
  • also, I can assure you - the CS50 instructor definitely had a makefile in the current directory (and a valid one) before running `make`. – Chase Jul 15 '20 at 08:33
  • Mystery solved! Thank you for your insights! All the "automagical" stuff that was happening was due to a custom configuration of the sandbox he's running / providing to the students. For future reference, `echo $LDLIBS` returns `-lcrypt -lcs50 -lm` and `make price` returns `clang -fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow price.c -lcrypt -lcs50 -lm -o price` when run from the sandbox. – Francesco C Jul 15 '20 at 09:00

1 Answers1

0

Make has a built-in rule that can build an executable from a single .c file:

%: %.c
#  recipe to execute (built-in):
    $(LINK.c) $^ $(LOADLIBES) $(LDLIBS) -o $@

That way you don't have to write a Makefile for most simple tasks like this one.
You can find it using make -p | grep -C 3 '%: %.c\b'.

The built-in variable LINK.C evaluates to:

LINK.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)

Seeing your last comment, all you have to do it call make while overriding the right variables:

make price CC=clang CFLAGS="-fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow" LDLIBS="-lcrypt -lcs50 -lm"
Chnossos
  • 9,971
  • 4
  • 28
  • 40