0

I had been working on a project that uses different sources and codes from many authors (in physics) and I want to merge them together and communicate between them. The problem is that some of those sources and makefiles call first the linked libraries and then the c files:

$(CC) $(lflags) -o smith2demo smith2demo.o smith2.o

Until now on my institute's computer and in some other systems everything was working fine. There I have this gcc compiler:

$gcc --version
gcc (Debian 4.9.2-10) 4.9.2
Copyright (C) 2014 Free Software Foundation, Inc.

So, I had not noticed this problem until I tried to run my code on Ubuntu:

gcc (Ubuntu 4.9.3-5ubuntu1) 4.9.3
Copyright (C) 2015 Free Software Foundation, Inc.

In ubuntu I get things like:

smith2.c:(.text+0x29b): undefined reference to `sincos'

I am aware of the linked libraries specifications and the reason for this, answered here:

GCC C++ Linker errors: Undefined reference to 'vtable for XXX', Undefined reference to 'ClassName::ClassName()'

Why does the order in which libraries are linked sometimes cause errors in GCC?

Why am I getting a gcc "undefined reference" error trying to create shared objects?

So, I have two questions:

Why if both gcc's are of recent versions, I do not have this problem in the Debian system?

How can I do to distribute this code to other people, without me telling them to change all makefiles where the libraries are called before the C files?

In most of the cases within my project, I use an overall Makefile and then I just change to the source folder and perform $(MAKE) in there.

Is there a way to set the --no-as-needed in general as an option for everyone or a more intelligent way of doing this?

I have very little experience with makefiles.

Community
  • 1
  • 1
Santiago
  • 226
  • 2
  • 14
  • Perhaps you should use a more complete build system like *cmake*. It's hard to help you because a lot more information is needed. Like, are the libraries you mentions system libraries? or are they distributed with your project? – Iharob Al Asimi Nov 27 '15 at 03:01
  • @iharob How would `cmake` help here? I can't see how it possibly could. – Etan Reisner Nov 27 '15 at 03:09
  • 1
    I would **very** carefully double-check that you don't have the problem on the debian machine. I don't see how you wouldn't (unless you weren't compiling when you thought you were or something else about the process was different that you missed). You can't add flags generally unless there are variables in use that you can give values to that the make recipes use. The built-in make rules have variables for this purpose for a reason. And telling people to fix their makefiles is something that happens a lot once you learn how they are supposed to work. – Etan Reisner Nov 27 '15 at 03:11
  • Thanks, but yes I am pretty sure that in Debian the problem is not appearing. Probably as it was just mentioned below, it has to do with environments, I will check. Yes, I know that it is common to change a certain makefile, but if people have to do this for 4 or 5 sub-directories, then it starts getting unpractical for them to use my project. – Santiago Nov 27 '15 at 03:41
  • In most of the cases I am just linking system libraries like -lm o -lgsl. – Santiago Nov 27 '15 at 03:50
  • @EtanReisner By determinig which libraries are needed and generating the correct makefiles, etc. It's a scripting language which can help in generating distribution specific makefiles. – Iharob Al Asimi Nov 27 '15 at 03:56
  • why was one of the answers below, simply removed? – Santiago Nov 27 '15 at 08:53
  • 1
    @iharob The OP has makefiles produced by *other* people that they need to interact with. How will cmake help correct those makefiles when they are incorrectly written? How will it allow for providing `--as-needed` to all those compilation recipes? – Etan Reisner Nov 27 '15 at 13:53
  • It was deleted by the poster for some reason. Presumably because it was seen as not really being an answer to the question. If you still have the debian machine I would again **strongly** suggest going back to it and attempting this process from scratch there and making sure it doesn't have this problem. Assuming it doesn't you can compare the output from `env`/`printenv` on both machines and see if/where they differ. – Etan Reisner Nov 27 '15 at 13:57
  • @EtanReisner Have you used *cmake* or *autotools* or any of the other ones? – Iharob Al Asimi Nov 27 '15 at 14:52
  • 1
    @iharob Yes, I have. Though I avoid cmake as a general rule because every time I look into it I get more annoyed by its poor internal decision making (in how it is built). It doesn't help with *other* projects makefiles. It doesn't help with setting flags for unrelated projects. It *could* help with getting the main project's flags in order, etc. but that's not the question. – Etan Reisner Nov 27 '15 at 17:25

1 Answers1

0

In my personal life, I use my own Makefile. Here is the simpler version of it.

    MAIN = main
    HEADER_DEFINITIONS = fibo
    CC = g++-4.9 -std=c++11
    COMPILE = -c
    EXE = $(MAIN)
    OPTIMIZE = -Os
    SHELL = /bin/bash
    ARGS = 20
    all: link
    @echo "Executing..........."
    @echo " > > > > > > OUTPUT < < < < < < "
    @$(SHELL) -c './$(EXE) $(ARGS)'
    link: compile
    @echo -n "Linking............."
    @$(SHELL) -c '$(CC) -o $(EXE) *.o'
    compile: $(MAIN).cpp $(HEADER_DEFINITIONS).cpp
    @echo -n "Compiling........."
    @$(SHELL) -c '$(CC) $(OPTIMIZE) $(COMPILE) $^'
    clean:
    @echo "Cleaning............"
    @$(SHELL) -c 'rm -f *~ *.o $(EXE)'

If you want to further modify and add certain linker flags, it is completely possible

Edit 2 My personal Makefile

#
# A simple makefile for managing build of project composed of C source files.
#


# It is likely that default C compiler is already gcc, but explicitly
# set, just to be sure
CC = gcc

# The CFLAGS variable sets compile flags for gcc:
#  -g        compile with debug information
#  -Wall     give verbose compiler warnings
#  -O0       do not optimize generated code
#  -std=c99  use the C99 standard language definition
#  -m32      CS107 targets architecture IA32 (32-bit)
CFLAGS = -g -Wall -O0 -std=c99 -m32

# The LDFLAGS variable sets flags for linker
#  -lm   says to link in libm (the math library)
LDFLAGS = -lm

# In this section, you list the files that are part of the project.
# If you add/change names of source files, here is where you
# edit the Makefile.
SOURCES = demo.c vector.c map.c
OBJECTS = $(SOURCES:.c=.o)
TARGET = demo


# The first target defined in the makefile is the one
# used when make is invoked with no argument. Given the definitions
# above, this Makefile file will build the one named TARGET and
# assume that it depends on all the named OBJECTS files.

$(TARGET) : $(OBJECTS)
    $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)


.PHONY: clean

clean:
    @rm -f $(TARGET) $(OBJECTS) core
Mayukh Sarkar
  • 2,289
  • 1
  • 14
  • 38
  • This is a fairly poor makefile as it doesn't let make do any of what is is designed to do, namely it can't avoid recompiling when sources haven't changed. It also requires modification for every file in the project (because it isn't using pattern rules). – Etan Reisner Nov 27 '15 at 13:55
  • Yes but "basic and wrong" is not very helpful. The second one is much better. Though using the built-in recipe for linking would be even better. – Etan Reisner Nov 27 '15 at 17:24
  • In real life I use my own python script to build my source code for bigger projects which can read all the parameters of the build process from a meta file `(.build file)`. It can also use regEx to solve duplicate file names, any other dependency list and even exclude some file from build process. – Mayukh Sarkar Nov 27 '15 at 17:34