0

I'm trying to create an executable that uses my earlier created shared library, which by the way is now static which includes the openSSL static library. So I used the same Makefile that I was using to create that library, and hacked it to make it work here. This is how it looks

LIBBASE=/home/AB/Documents/APP/APP_2.17.0
OPENSSL1.0.2p_INSTALL_LOC=/home/AB/Documents/APP/OpenSSL-1.0.2p-installation
CC=gcc
CXX=g++
CFLAGS= -Wall -g -pedantic
CPPFLAGS= -Wall -g -pedantic 
RM= rm -f
.PHONY: all clean

c_src=$(shell find . -iname "*.c")
$(info source=$(c_src))

cpp_src=$(shell find . -iname "*.cpp")
$(info cppsource=$(cpp_src))

INC=-I$(LIBBASE)/include
$(info includes=$(INC))

# need to link pthread library here as well
LIB = -pthread

# aforementioned library
LIB+=-L$(LIBBASE)/lib 
LIB+= -l:libSCA.a

#need to add SSL related libraries
LIB+= -L$(OPENSSL1.0.2p_INSTALL_LOC)/lib
LIB+= -l:libssl.a -l:libcrypto.a -static-libgcc

# As mentioned, we need to link dl and libz libraries as well
LIB+= -ldl -lz

$(info links=$(LIB))

obj=$(c_src:.c=.o) $(cpp_src:.cpp=.o)
all: APP
clean:
    $(RM) *.o APP
    $(shell find $(APPBASE) -type f -iname "*.o" -exec rm -rf {} \;)

.c.o:
    ${CXX} -static ${CPPFLAGS} $(INC) -c $< -o $@
    #${CC} -static ${CFLAGS} $(INC) -c $< -o $@

.cpp.o:
    ${CXX} -static ${CPPFLAGS} $(INC) -c $< -o $@

APP: $(obj)
    $(LINK.cxx) $^ -o $@ $(LIB)

I am, however unable to get this to work. I am getting a whole lot of undefined references to symbols that my library defines. I've taken care of using extern C around those symbols in the cpp files but it doesn't seem to help.

BTW, Is there a more straightforward or easier way than this?

Also, while browsing through the various answers here, I came across the statement that, targets like .c.o are rather obsolete and shouldn't be used anymore. Is there a definitive guide to Makefiles that is recent, exhaustive and practical (is it too much to ask)??

UPDATE 1: So here that I have access to the logs, I've noticed that all the undefined reference errors I am getting are related to symbols defined by the SSL library that I was statically linking to my shared library. A sample of my err log:

/home/AB/Documents/APP/APP_2.17.0_Linux/libAPP.so: undefined reference to `SSL_CTX_free'
/home/AB/Documents/APP/APP_2.17.0_Linux/libAPP.so: undefined reference to `X509_set_issuer_name'

So I thought of making a static library that will internally link against (or rather incorporate) libssl.a. Modified my aforementioned makefile and created a static libAPP.a. But I still kept getting those errors.

I finally added libssl.a and libcrypto.a to this makefile and voila, a lot of those errors got fixed. I still had some errors related to dlopen and pthreads so I added those as well. I also compile everything with the CXX compiler to eliminate issues due to name mangling.

What bugs me now is that the SSL related symbols are supposed to be already present in libAPP.a (although nm reports them as undefined and which might need another question on it's own :D ). But I still need to specify the libSSL.a and libcrypto.a here for the linker to find them! So what good is creating an archive (libAPP.a) instead of a shared library (libAPP.so)?

Finally during the linking phase, my linker cannot find lz

/usr/bin/ld: cannot find -lz

Just for the heck of it, I tried adding the same flag into the makefile that creates that archive and that one has no problem finding it. Any suggestions??

AjB
  • 890
  • 13
  • 34
  • The manual for GnuMake has some enlightening chapters. – the busybee Nov 08 '19 at 18:19
  • Of course it does I'm sure. But being in a production env yourself, I hope you do understand I am rather short on time (which dev isn't these days :) ). If you have a quick fix or can point out an obvious flaw in this or suggest an easier way to go about things like these, I'd be greatly obliged!! – AjB Nov 08 '19 at 18:23
  • @thebusybee BTW, I will definitely check out those chapters when I am relaxed and looking to learn something new – AjB Nov 08 '19 at 18:30
  • 2
    The first thing you should understand is that your problem is NOT with make or makefiles. If you are getting linking errors, that means that the problem is that your compile or link commands are wrong. So trying to blame make or makefiles for it won't get you anywhere. If you're not familiar with how to use the compiler and linker with shared libraries, a helpful exercise is to try running the compile commands directly at the shell prompt until you figure out what the right ones are. THEN you can worry about how to put them into your makefile the most efficient way. – MadScientist Nov 08 '19 at 18:35
  • It's unlikely that anyone can figure out the reason for the link failures based solely on the information shown in the question, as fully explained in the preceding comment. Furthermore, recommendations for off-site resources (documentation, guides, etc...) is off-topic for stackoverflow.com – Sam Varshavchik Nov 08 '19 at 18:36
  • The makefile you show here doesn't try to build a shared library, and you don't actually show what compile and link commands are run when you invoke make, AND you don't show any examples of the errors you're getting. So it's unlikely we can make any headway here. But almost certainly your problem is that when you link a shared library only the symbols actually used by that library are included. – MadScientist Nov 08 '19 at 18:38
  • Oh, the "modern" way to write patterns like `.c.o` is `%.o: %.c`. – the busybee Nov 08 '19 at 18:39
  • When you are ready to work on a makefile, the first thing you must decide is what vintage of make you want to use. If you want your makefile to work with any make which adheres to the POSIX spec, then you have to use suffix rules like `.c.o` because that's all that POSIX defines. If you're willing to require GNU make, then you have many more options such as pattern rules etc. – MadScientist Nov 08 '19 at 18:40
  • 1
    By convention, `CXXFLAGS` are flags for the C++ compiler, while `CPPFLAGS` are flags for the C pre-processor. – William Pursell Nov 08 '19 at 18:48
  • ie, `-DNDEBUG` belongs in CPPFLAGS. The default rules are `$(CC) $(CPPFLAGS) $(CFLAGS) -c` for *.c files, and `$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c` for *.cc files – William Pursell Nov 08 '19 at 18:51
  • try to add "-lssl -lcrypto" to LIB. – tfmoraes Nov 08 '19 at 19:03
  • @MadScientist I am NOT trying to build a library here. I already did that in my previous question (linked herein). I'm trying to use that library here with both C and C++ sources. As for using shared libraries, I know how to use them and craft compiler commands by hand. I was trying to use a Makefile as the number of files is more this time – AjB Nov 09 '19 at 02:16
  • thanks everyone for the comments. Wasn't able to include the error here as I was away from my work computer when I wrote this. Will try these suggestions and come back to you soon on Monday! Enjoy the weekend fellas! – AjB Nov 09 '19 at 02:38
  • If you know what the compile commands aught to be for a successful build, it should be straightforward to compare that to the compile commands that make actually ran and see where it went wrong. That will lead you directly to where in your makefile the problem might be. If you need help fixing it the providing this information in your question is a good first step. – MadScientist Nov 09 '19 at 13:59
  • @MadScientist sure! I will on Monday! Thanks – AjB Nov 09 '19 at 16:30
  • so now I hope I've added sufficient background information for the good folks here at SO to take a shot at it – AjB Nov 12 '19 at 06:44

2 Answers2

1

I would do this in these steps:

  1. Collect all commands to build everything "by hand." Only if that works it makes sense to move on if you're a beginner. These commands could be put in a batch file.
  2. Extract the dependencies and rules.
  3. Write that in the Makefile; at the end of the day a Makefile is just that: condensed knowledge how to build.
  4. Try the Makefile.
  5. If I experience errors, I'll use make's options -d, -p and -n to see what it's thinking. There might be more useful options.
the busybee
  • 10,755
  • 3
  • 13
  • 30
0

Most obvious problem is that you are using $(LINK.c) to link when your program contains C++ components, so you aren't getting any C++ libraries or such. Try using $(LINK.C) or $(LINK.cc) or $(LINK.cpp) or $(LINK.cxx) (which you need for C++ varies on make version, but at least one of them should be predefined.)

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
  • I would like to link ALL the object files into a single executable. Those that got generated from C files as well as those that got generated from cpp files. if `LINK.c' is not the right way to go about it, what is? – AjB Nov 09 '19 at 02:13
  • try `$(LINK.cpp)` -- or one of the the others if that isn't defined in the version of make you are using. – Chris Dodd Nov 09 '19 at 04:15
  • will {LINK.cpp} be inferred by make directly or do I need to define it explicitly? Also, can I link all the objects no matter their source (C/C++) ?? – AjB Nov 09 '19 at 16:30