0

this is my first question here, I hope to do everything in the right way.

I'm a quite new Ubuntu user and if possible I need some help with a specific Makefile. I downloaded QEMU 2.1.0 and I'm currently changing some source code files for a custom version. In particular I have an sd.c file like the following:

[...]
#include "hw/mydistribution.h"
[...]
Nac = poisson_distribution(Nac_mean);

and a mydistribution.h file where for example I define the poisson_distribution() using functions from GSL library:

#include <math.h>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
[...]
unsigned int poisson_distribution(double expected_value) {

const gsl_rng_type * T;
gsl_rng * r;
unsigned int k;

gsl_rng_env_setup();
T = gsl_rng_default;
r = gsl_rng_alloc (T);
k = gsl_ran_poisson (r, expected_value);
gsl_rng_free (r);

return k;
}

Now, I know that if I had all the aforementioned parts in the same file [e.g. myfile.c] I could compile from terminal using:

gcc myfile.c -o myfile -lgsl -lgslcblas -lm

and it works because I tried. But how to ask to QEMU Makefile to do this? honestly this Makefile seems too complex for my entry level. I googled info about makefiles and after reading I thought to find in QEMU Makefile something like:

LDLIBS := -lgsl -lgslcblas -lm
[...]
$(CC) -o $@ $^ $(LDLIBS)

but searching for the real QEMU Makefile implementation I found the rules.mak file where:

%.o: %.c
    $(call quiet-command,$(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) $($@-cflags) -c -o $@ $<,"  CC    $(TARGET_DIR)$@")

Maybe this is the line to tweak. The question is: how to tweak? I tried to edit this line as:

%.o: %.c
    $(call quiet-command,$(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) $($@-cflags) -c -o $@ $< -lgsl -lgslcblas -lm,"  CC    $(TARGET_DIR)$@")

but it didn't work and I got the following errors

ubuntu@ubuntu:~/Desktop/qemu-2.1.0$ make
  GEN   config-host.h
  GEN   trace/generated-tracers.h
  GEN   trace/generated-tracers.c
  GEN   arm-softmmu/config-target.h
  LINK  arm-softmmu/qemu-system-arm
../hw/sd/sd.o: In function `poisson_distribution':
/home/ubuntu/Desktop/qemu-2.1.0/include/hw/mycard.h:1630: undefined reference to `gsl_rng_env_setup'
/home/ubuntu/Desktop/qemu-2.1.0/include/hw/mycard.h:1632: undefined reference to `gsl_rng_default'
/home/ubuntu/Desktop/qemu-2.1.0/include/hw/mycard.h:1633: undefined reference to `gsl_rng_alloc'
/home/ubuntu/Desktop/qemu-2.1.0/include/hw/mycard.h:1641: undefined reference to `gsl_ran_poisson'
/home/ubuntu/Desktop/qemu-2.1.0/include/hw/mycard.h:1646: undefined reference to `gsl_rng_free'
../hw/sd/sd.o: In function `weibull_distribution':
/home/ubuntu/Desktop/qemu-2.1.0/include/hw/mycard.h:1676: undefined reference to `gsl_rng_env_setup'
/home/ubuntu/Desktop/qemu-2.1.0/include/hw/mycard.h:1678: undefined reference to `gsl_rng_default'
/home/ubuntu/Desktop/qemu-2.1.0/include/hw/mycard.h:1679: undefined reference to `gsl_rng_alloc'
/home/ubuntu/Desktop/qemu-2.1.0/include/hw/mycard.h:1687: undefined reference to `gsl_ran_weibull'
/home/ubuntu/Desktop/qemu-2.1.0/include/hw/mycard.h:1692: undefined reference to `gsl_rng_free'
collect2: error: ld returned 1 exit status
make[1]: *** [qemu-system-arm] Error 1
make: *** [subdir-arm-softmmu] Error 2

And after all I think it would not be a perfect solution since the other files don't need GSL library and there's no need to apply -lgsl -lgslcblas -lm to every .c file. I would like to create a new Makefile where all the other files continue to be compiled like the original Makefile but when it comes to sd.c I would like it to be compiled as said before in order to avoid undefined references

Thanks in advance to the persons that will give me precise suggestions to help me fix this issue

0

Above this wildcard line:

%.o: %.c

add a specific rule for the particular file:

myfile.o: myfile.c
    gcc -c -o $@ $< -lgsl -lgslcblas -lm
  • Hi muru, in the meanwhile thanks for your quick answer. I added the rule as suggested but I still have the same undefined references. Nevertheless thanks again – Antonino Sep 29 '14 at 22:09
  • 1
    It's the link phase that's throwing the error - so I don't think that anything you do in the compile phase (i.e. .o: %.c rules) is going to help - you need to find the line that builds the executable target from the object (.o) files – steeldriver Sep 29 '14 at 22:15
  • Hi steeldriver, your first part of the answer is totally clear. The second part is clear only under the theoretical point of view but not in practice because my knowledge is not enough to understand some voices of the Makefile like DSOSUF, EXESUF, LINK, quiet-command and so on that are involved in building the executable target. If somebody can be more QEMU-specific I would be happier but thanks to you too for your kind post – Antonino Sep 30 '14 at 12:48
  • @Antonino look for a makefile rule that lists something like $(OBJ) or <something>.o on the right side of a :. That probably will contain the rule for linking. If not, post the makefile to paste.ubuntu.com so that we can examine it. – muru Sep 30 '14 at 13:03
  • Hi muru, since steeldriver post I was searching something in the form: CC=g++ CFLAGS=-c -Wall LDFLAGS= SOURCES=main.cpp hello.cpp factorial.cpp OBJECTS=$(SOURCES:.cpp=.o) EXECUTABLE=hello all: $(SOURCES) $(EXECUTABLE) $(EXECUTABLE): $(OBJECTS) $(CC) $(LDFLAGS) $(OBJECTS) -o $@ .cpp.o: $(CC) $(CFLAGS) $< -o $@ hoping that adding -lgsl -lgslcblas -lm to $(CC) $(LDFLAGS) $(OBJECTS) -o $@ could make the trick. But as said before this Makefile is far more complex. Then I attached 4 useful files to paste.ubuntu.com/8466403 Thanks again for your interest and your second reply – Antonino Sep 30 '14 at 14:43
0

I think after days of doubts, researches, manuals and so on I finally solved my problem and I want to share my efforts with you

After steeldriver comment I began to watch more closely the linking phase. The solution I found was adding the following lines to configure file just before the analogue librt section:

##########################################
# Do we need libgsl0-dev
cat > $TMPC << EOF
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
int main(void) { return (int) gsl_ran_weibull_pdf (11, 10, 5); }
EOF
if compile_prog "" "" ; then
  :
elif compile_prog "" "-lgsl -lgslcblas" ; then
  LIBS="-lgsl -lgslcblas $LIBS"
  libs_qga="-lgsl -lgslcblas $libs_qga"
else
  error_exit "libgsl0-dev check failed"
fi

the purpose of gsl_ran_weibull_pdf (11, 10, 5) is verifying the presence of libgsl0-dev. If we have it than when we find -lgsl -lgslcblas we can correctly interpretate them, else the user will be informed about the absence of this library

Now when I type: ubuntu@ubuntu:~/Desktop/qemu-2.1.0$ make

there are no more undefined references:

  GEN   config-host.h
  GEN   trace/generated-tracers.h
  GEN   trace/generated-tracers.c
  CC    hw/sd/sd.o
  GEN   arm-softmmu/config-target.h
  LINK  arm-softmmu/qemu-system-arm
  GEN   arm-linux-user/config-target.h

I'm sure this solution can be further refined and I'm open to new suggestions, if any. But I admit to be already extremely happy in finding this result

Special thanks to @muru and @steeldriver for their support

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.