tags:

views:

205

answers:

4

Hi all,

I just installed gd2 using mac ports (sudo install gd2), which installed libraries in the following places:

/opt/local/include/gd.h
/opt/local/lib/libgd.dylib (link)
/opt/local/lib/libgd.la
/opt/local/lib/libgd.a

Here is my make file also:

dev: main.o
    g++ -L/opt/local/lib -I/opt/local/include -lgd -lpng -lz -ljpeg -lfreetype -lm main.o -o heatmap

main.o: main.cpp
    g++ -c main.cpp

So when I create my c++ app I add '#include "gd.h"', which throws:

main.cpp:4:16: error: gd.h: No such file or directory

If I set gd.h as an absolute path (as above)(not a solution, but was curious), I am thrown:

g++ -L/opt/local/include -L/opt/local/lib main.o -o heatmap
Undefined symbols:
  "_gdImagePng", referenced from:
      _main in main.o
  "_gdImageLine", referenced from:
      _main in main.o
  "_gdImageColorAllocate", referenced from:
      _main in main.o
      _main in main.o
  "_gdImageDestroy", referenced from:
      _main in main.o
  "_gdImageCreate", referenced from:
      _main in main.o
  "_gdImageJpeg", referenced from:
      _main in main.o
ld: symbol(s) not found

So, I understand this means that ld can not find the libraries it needs (hence trying to give it hints with the "-L" values). So after giving g++ the -L hints and the absolute path in #include, I can get it to work, but I don't think I have to do this, how can I make g++/ld search int eh right places for the libraries?

Drew J. Sonne.

PS. using: - OSX 10.6.2 - gcc version 4.2.1 (Apple Inc. build 5646) (dot 1)

EDIT: Ok, so after taking into account stfanB and Michael's answer, I've recompiled gd into a local directory (libraries) and thus, I've changed that first line of my Makefile (I will def check out cmake) to g++ -L./libraries/lib -I./libraries/include -lgd -lpng -lz -ljpeg -lfreetype -lm main.o -o heatmap But I'm still getting main.cpp:3:16: error: gd.h: No such file or directory

EDIT: Thanks all for the answers, here's my final (working) makefile for anyone else who many want an answer:

dev: main.o
    g++ -I./libraries/include -L./libraries/lib -lgd -lpng -lz -ljpeg -lfreetype -lm main.o -o heatmap

main.o: main.cpp
    g++ -I./libraries/include -c main.cpp
+6  A: 

Rather than invoke g++ directly, I strongly advise you to use CMake (watch the CMake Google Techtalk if you'd like to learn more) as it will make your life way easier and greatly simplifies locating and linking against a variety of libraries. That said, I believe the problem with your invocation is that you have not specified the library, which you would do with -lgd. Your -L/opt/local/lib correctly tells g++ to look in /opt/local/lib, but you never told it what to look for. As for finding the appropriate header, you can use -I/opt/local/include to put /opt/local/include in the compiler's include search path.

If you were to heed my advice to use CMake, doing this would look like:

FIND_PACKAGE(GD2 REQUIRED)
INCLUDE_DIRECTORIES(${GD2_INCLUDE_DIRS})
LINK_DIRECTORIES(${GD2_LIBRARY_DIRS})

ADD_EXECUTABLE(heatmap main Heatmap_Map Heatmap_Point)
TARGET_LINK_LIBRARIES(heatmap ${GD2_LIBRARIES})

If you are interested in learning more about CMake, you might want to take a look at the C++ Application Project Template and C++ Library Project Template, which make use of the CMake build system. CMake is available through MacPorts via the command "sudo port install cmake".

In case you are not interested in installing CMake, I should also point out that there are some environment variables that you might be interested in knowing about to make your life easier, namely:

  • CPATH
  • LIBRARY_PATH
  • DYLD_FALLBACK_LIBRARY_PATH

The CPATH environment variable is much like the PATH environment variable (it is a colon separated list of directories), except that the directories in that variable will automatically be used by gcc and g++ as if they were specified on the commandline with the -I flag (i.e. headers will be searched in those paths). The LIBRARY_PATH is the equivalent except that it is as if the folders were given with -L (i.e. libraries will automatically be searched in that path). DYLD_FALLBACK_LIBRARY_PATH will be used by the dynamic linker (so you should probably include the paths from LIBRARY_PATH into this variable).

You can read more about the environment variables affecting gcc at the link.

Michael Aaron Safyan
I've been using JamPlus lately and quite like it.
dash-tom-bang
+1  A: 

Header include directories need to be specified with -I option (only relative paths needed after this) and linker include directories with -L (relative paths here too).

For libraries, an alternative you could alternatively set the LD_LIBRARY_PATH but the -L method is safer.

Sameer
@Sameer, he correctly used the -L flag but forgot to specify a library with -l.
Michael Aaron Safyan
+3  A: 

The answer is quite complicated.

The short answer, when you compile your own libs/tools place them in some local directory such as you used above or /usr/local/lib and /usr/local/include or even ~/local/lib and ~/local/include and always add these to your compiler/linker.

The longer answer - read Programming Library HOWTO for Linux that explains what each of the tool involved looks for, from compiler/linker to execution, and have a look at standard directory structure of Linux system which is of course not binding but it's nice to know.

I'm assuming that you have a simple Makefile setup for each of your projects so you don't have to bother with typing all those commands. If you don't I strongly recommend to setup a simple Makefile template that you can reuse for your projects.

EDIT:

In your edited answer your paths may be incorrect.

The . in your path like ./libraries specifies current directory, meaning it will look into libraries directory in the current directory. If you ment libraries directory in root directory then remove the . so it should be like this -L/libraries/lib and similarly for -I/libraries/...

stefanB
@Michael it seems like he learned something from other answers as well so probably other answers are not completely irrelevant as you thought.
stefanB
@Michael, you got the tick, but stefanB's right, I got more out of the other answers as well. ;-)@stefanB, yep, I put it in my project dir.
Drew
I'm glad we all were able to help you ... the points are not important
stefanB
@stefanB, agreed. I have upvoted since your edit.
Michael Aaron Safyan
+1  A: 

I think your problem may be that your -I arguments need to be passed to the compile stage, too. Maybe something like this?

dev: main.o
    g++ -L/opt/local/lib -lgd -lpng -lz -ljpeg -lfreetype -lm main.o -o heatmap

main.o: main.cpp
    g++ -I/opt/local/include -c main.cpp

Not sure- I haven't used makefiles in 20 years (but as I mentioned in a comment to another post, I find JamPlus quite remarkable in its power).

Anyway- typically your compiler and linker flags will be put into variables and then expanded in the command line, but I'm not sure on the make syntax for that. Maybe simply:

CFLAGS=-I/opt/local/include
LINKFLAGS=-L/opt/local/lib -lgd -lpng -lz -ljpeg -lfreetype -lm 

dev: main.o
    g++ $(LINKFLAGS) main.o -o heatmap

main.o: main.cpp
    g++ $(CFLAGS) -c main.cpp
dash-tom-bang
@dash-tom-bang, FYI, CXXFLAGS are typically used for C++ settings while LDFLAGS are used for linker flags. You should use the predefined variable $(CXX) as the C++ compiler rather than hard-coding in g++. Also, main.o : main.cpp is automatically defined. Specifying main.o as a dependency is sufficient to get Make to automatically compiler main.cpp using the default C++ compiler and using any settings specified in CXXFLAGS.
Michael Aaron Safyan
@Michael thanks.
dash-tom-bang