Page 1 of 3 123 LastLast
Results 1 to 10 of 21

Thread: Multiple source files, compile makefile

  1. #1
    Join Date
    Jan 2006
    Beans
    295

    Multiple source files, compile makefile

    Hi,

    I am fairly new to programming in linux. For my current project, I have two .cc source files and one .h header file. I have a makefile that I am using to compile everything.

    The source files are project.cc, inputMap.cc and the header file is header.h. The header file includes all the headers needed for the project and also function declarations for the functions in both the files. project.cc contains the main() function and inputMap.cc contains only one function void inputMap(int output) for which I have declaration in header.h.

    I am using the following makefile to compile my code:
    CC=g++
    INCLUDES=/usr/include/player-2.0
    ARGS=/usr/share/player/examples/libplayerc++
    LIBS=/usr/lib/libplayerc++.so.2
    CFLAGS=-g -Wall -I$(INCLUDES) -I$(ARGS)
    EXECUTABLES=project

    all: $(EXECUTABLES)

    clean:
    rm -f core $(EXECUTABLES) *.o

    .SUFFIXES: .cc .o

    .cc.o:
    $(CC) $(CFLAGS) -c *.cc

    project: project.o inputMap.o
    $(CC) -o project project.o $(LIBS)

    inputMap: inputMap
    $(CC) -o inputMap inputMap.o

    Now when I call inputMap from my project.cc file in the main() function, I get an error for undefined reference. But I am including the header file header.h which has the function declaration for inputMap. header.h is:

    #ifndef HEADER_H
    #define HEADER_H

    #include <libplayerc++/playerc++.h>
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <unistd.h>
    #include <fstream>
    #include <string>
    #include "args.h"

    const double pi = 3.14159265;

    using namespace PlayerCc;
    using namespace std;

    void inputMap(int output);
    #endif

    Furthermore, I am sure whether inputMap is a dependency for project.cc or not. I just call upon a function from inputMap.cc..does that make it a dependency. I am finding it hard to understand how to compile all this together. Any help is appreciated.

    Thanks.
    Custom Build:
    Windows 10 and Kubuntu 18.04

  2. #2
    WW is offline Iced Blended Vanilla Crème Ubuntu
    Join Date
    Oct 2004
    Beans
    1,532

    Re: Multiple source files, compile makefile

    It looks like you are missing inputMap.o in the linking command here:
    Code:
    project: project.o inputMap.o
    	$(CC) -o project project.o $(LIBS)
    Change that to
    Code:
    project: project.o inputMap.o
    	$(CC) -o project project.o inputMap.o $(LIBS)
    Now when I call inputMap from my project.cc file in the main() function, I get an error for undefined reference.
    If the above suggestion doesn't fix the problem, be sure to show us the actual error message that you get.


    EDIT 2:
    I didn't look at the Makefile close enough the first time. This part
    Code:
    inputMap: inputMap
    $(CC) -o inputMap inputMap.o
    doesn't make sense.


    EDIT 1:

    P.S. I notice that you include the system header cmath. cmath defines M_PI, the value of pi, so you could change this
    Code:
    const double pi = 3.14159265;
    to
    Code:
    const double pi = M_PI;
    or just use M_PI instead of your constant pi.
    Last edited by WW; October 20th, 2008 at 05:42 AM. Reason: Add P.S. about M_PI

  3. #3
    Join Date
    Jan 2006
    Beans
    295

    Re: Multiple source files, compile makefile

    Hi,
    Thanks for your reply.

    If the above suggestion doesn't fix the problem, be sure to show us the actual error message that you get.
    Here are the error messages:
    Code:
    g++ -g -Wall -I/usr/include/player-2.0 -I/usr/share/player/examples/libplayerc++ -c *.cc
    g++ -o project project.o inputMap.o /usr/lib/libplayerc++.so.2
    inputMap.o:/usr/include/c++/4.2/bits/stl_algobase.h:182: multiple definition of `gHostname'
    project.o:/usr/include/c++/4.2/bits/locale_facets.tcc:2560: first defined here
    inputMap.o: In function `print_usage(int, char**)':
    /usr/share/player/examples/libplayerc++/args.h:59: multiple definition of `print_usage(int, char**)'
    project.o:/usr/share/player/examples/libplayerc++/args.h:59: first defined here
    inputMap.o: In function `parse_args(int, char**)':
    /usr/share/player/examples/libplayerc++/args.h:15: multiple definition of `parse_args(int, char**)'
    project.o:/usr/share/player/examples/libplayerc++/args.h:15: first defined here
    inputMap.o:(.data+0x0): multiple definition of `gPort'
    project.o:(.data+0x0): first defined here
    inputMap.o:/usr/include/c++/4.2/bits/stl_algobase.h:182: multiple definition of `gIndex'
    project.o:/usr/include/c++/4.2/bits/locale_facets.tcc:2560: first defined here
    inputMap.o:/usr/include/c++/4.2/bits/locale_facets.tcc:2562: multiple definition of `gDebug'
    project.o:/usr/include/c++/4.2/bits/locale_facets.tcc:2562: first defined here
    inputMap.o:(.data+0x4): multiple definition of `gFrequency'
    project.o:(.data+0x4): first defined here
    inputMap.o:(.data+0x8): multiple definition of `gDataMode'
    project.o:(.data+0x8): first defined here
    inputMap.o:/usr/include/c++/4.2/bits/locale_facets.tcc:2562: multiple definition of `gUseLaser'
    project.o:/usr/include/c++/4.2/bits/locale_facets.tcc:2562: first defined here
    collect2: ld returned 1 exit status
    make: *** [project] Error 1
    I didn't look at the Makefile close enough the first time. This part
    Code:
    inputMap: inputMap
    $(CC) -o inputMap inputMap.o
    doesn't make sense.
    That part is for compiling inputMap.cc. I just extended the commands of project to inputMap. I didnt really think it through. So if I dont need that, how do I get inputMap.o without compiling it?

    Thanks for the info on pi!
    Custom Build:
    Windows 10 and Kubuntu 18.04

  4. #4
    WW is offline Iced Blended Vanilla Crème Ubuntu
    Join Date
    Oct 2004
    Beans
    1,532

    Re: Multiple source files, compile makefile

    Quote Originally Posted by linuxnovice View Post
    That part is for compiling inputMap.cc. I just extended the commands of project to inputMap. I didnt really think it through. So if I dont need that, how do I get inputMap.o without compiling it?
    You are using the implicit rule for compiling .cc files into .o files. I'm a bit rusty on the syntax, but assuming you have that set up correctly, you don't need an explicit command to compile inputMap.c. What you have now has two problems: (1) you are saying that the file inputMap depends on the file inputMap,which doesn't make sense, and (2) the command is going to try to build an executable called inputMap from inputMap.o, which won't work because there is no main function in inputMap.c. Try removing those two lines completely.

    However, I don't think that is the source of your errors. It is difficult to say what is causing your errors without seeing the code. These two lines
    Code:
    inputMap.o:/usr/include/c++/4.2/bits/stl_algobase.h:182: multiple definition of `gHostname'
    project.o:/usr/include/c++/4.2/bits/locale_facets.tcc:2560: first defined here
    say that something called "gHostname" is being defined in both inputMap.c and project.c, apparently because of two different header files that have been included.

  5. #5
    Join Date
    Feb 2007
    Beans
    4,045
    Distro
    Ubuntu 9.10 Karmic Koala

    Re: Multiple source files, compile makefile

    LIBS contain the path to a shared library, that won't work. Rather make a LDFLAGS variable that uses the -l option to link the shared library properly. (This is probably the reason for the errors you got when linking)

    Also, ARGS is pointing to a set of examples that happens to contain a header file. Put that header file along with your code instead, and remove the ARGS variable.

    This should be sufficient for the first part.
    Code:
    CC=g++
    LDFLAGS=-lplayerc++
    CFLAGS=-g -Wall -I/usr/include/player-2.0
    EXECUTABLES=project
    
    all: $(EXECUTABLES)
    
    clean:
    	rm -f core $(EXECUTABLES) *.o
    
    .SUFFIXES: .cc .o

    Code:
    .cc.o:
    	$(CC) $(CFLAGS) -c *.cc
    This will compile all .cc files even if you only need to compile one. Use the special $@ and $< to represent the object file and source file respectively.
    Code:
    .cc.o:
    	$(CC) $(CFLAGS) -c -o $@ $<
    As mentioned before, the inputMap target is unnecessary, and the project target needs to be changed to use the LDFLAGS instead of LIBS:

    Code:
    project: project.o inputMap.o
    	$(CC) $(LDFLAGS) -o $@ project.o inputMap.o

  6. #6
    Join Date
    Jan 2006
    Beans
    295

    Re: Multiple source files, compile makefile

    Hi,

    Thanks for the reply guys.

    I have made the changes that you suggested but I am still getting same error when I run make. I am attaching the code as text files to this reply. I did not write inputMap.cc..it was given to us as part of our project source.

    I need some help understanding stuff that you guys have suggested.

    First,
    You are using the implicit rule for compiling .cc files into .o files. I'm a bit rusty on the syntax, but assuming you have that set up correctly, you don't need an explicit command to compile inputMap.c. What you have now has two problems: (1) you are saying that the file inputMap depends on the file inputMap,which doesn't make sense, and (2) the command is going to try to build an executable called inputMap from inputMap.o, which won't work because there is no main function in inputMap.c. Try removing those two lines completely.
    I am assuming that implicit rule means basically since I need inputMap.o for project and I have inputMap.cc in the directory, make will automatically find it and compile it. Is that correct?

    Second,
    Rather make a LDFLAGS variable that uses the -l option to link the shared library properly. (This is probably the reason for the errors you got when linking)
    What are LDFLAGS? I have not worked with makefiles before, so this is pretty new to me. I have googled for tutorials but they dont explain the meaning of the flags.

    Third,
    As mentioned before, the inputMap target is unnecessary, and the project target needs to be changed to use the LDFLAGS instead of LIBS:
    I made that change..but I have no idea what that means. Could someone please explain that to me.

    Finally, here are my current makefile and header.h:

    Code:
    CC=g++
    LDFLAGS=-lplayerc++
    CFLAGS=-g -Wall -I/usr/include/player-2.0 
    EXECUTABLES=project
    
    all: $(EXECUTABLES)
    
    clean:
    	rm -f core $(EXECUTABLES) *.o
    
    .SUFFIXES: .cc .o
    
    .cc.o:
    	$(CC) $(CFLAGS) -c -o $@ $<
    
    project: project.o inputMap.o
    	$(CC) $(LDFLAGS) -o $@ project.o inputMap.o
    Code:
    #ifndef HEADER_H
    #define HEADER_H
    
    #include <libplayerc++/playerc++.h>
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <unistd.h>
    #include <fstream>
    #include <string>
    #include </usr/share/player/examples/libplayerc++/args.h>
    
    const double pi = M_PI;
    
    using namespace PlayerCc;
    using namespace std;
    
    void inputMap(int output);
    #endif
    Here is the error I am getting right now:

    Code:
    g++ -g -Wall -I/usr/include/player-2.0  -c -o project.o project.cc
    g++ -g -Wall -I/usr/include/player-2.0  -c -o inputMap.o inputMap.cc
    g++ -lplayerc++ -o project project.o inputMap.o
    inputMap.o:/usr/include/c++/4.2/bits/stl_algobase.h:182: multiple definition of `gHostname'
    project.o:/usr/include/c++/4.2/bits/locale_facets.tcc:2560: first defined here
    inputMap.o: In function `print_usage(int, char**)':
    /usr/share/player/examples/libplayerc++/args.h:59: multiple definition of `print_usage(int, char**)'
    project.o:/usr/share/player/examples/libplayerc++/args.h:59: first defined here
    inputMap.o: In function `parse_args(int, char**)':
    /usr/share/player/examples/libplayerc++/args.h:15: multiple definition of `parse_args(int, char**)'
    project.o:/usr/share/player/examples/libplayerc++/args.h:15: first defined here
    inputMap.o:(.data+0x0): multiple definition of `gPort'
    project.o:(.data+0x0): first defined here
    inputMap.o:/usr/include/c++/4.2/bits/stl_algobase.h:182: multiple definition of `gIndex'
    project.o:/usr/include/c++/4.2/bits/locale_facets.tcc:2560: first defined here
    inputMap.o:/usr/include/c++/4.2/bits/locale_facets.tcc:2562: multiple definition of `gDebug'
    project.o:/usr/include/c++/4.2/bits/locale_facets.tcc:2562: first defined here
    inputMap.o:(.data+0x4): multiple definition of `gFrequency'
    project.o:(.data+0x4): first defined here
    inputMap.o:(.data+0x8): multiple definition of `gDataMode'
    project.o:(.data+0x8): first defined here
    inputMap.o:/usr/include/c++/4.2/bits/locale_facets.tcc:2562: multiple definition of `gUseLaser'
    project.o:/usr/include/c++/4.2/bits/locale_facets.tcc:2562: first defined here
    collect2: ld returned 1 exit status
    make: *** [project] Error 1
    Thanks.
    Attached Files Attached Files
    Custom Build:
    Windows 10 and Kubuntu 18.04

  7. #7
    Join Date
    Feb 2007
    Beans
    4,045
    Distro
    Ubuntu 9.10 Karmic Koala

    Re: Multiple source files, compile makefile

    LDFLAGS is a commonly used variable name to put linker flags in, as CFLAGS is for compilation flags.

    I had a look at args.h, and it's not a "regular" header file. It's not intended to be included from several modules. I suggest you copy the code you require from it into project.cc or create a seperate cc-file for that code.

  8. #8
    Join Date
    Jan 2006
    Beans
    295

    Re: Multiple source files, compile makefile

    Hi,

    I finally got it to compile. I really dont have an idea what made it to work. But the current project.cc, input.cc, header.h and makefile are attached as text files into this reply.

    The change I did was basically instead of including args.h in header.h, I included it only in project.cc. Secondly, inputMap.cc did not require stuff that was in header.h so I did not include it there and only included whatever that was needed by inputMap.cc (iostream, fstream, string etc). And now it compiled properly.

    I have some questions. I have another file called lasernoise.cpp (it was named lasernoise.cc, I changed it to lasernoise.cpp).

    First, what is a *.cc file....I see it a lot in unix systems but I dont know what it is. I know cpp is c++ file and .c is a C file.

    Second, suppose I wanted to use the function defined in lasernoise.cpp (or lasernoise.cc) in my project.cc file. What changes do I need to do in my makefile in order to do this? Furthermore, do I need to declare a function prototype of the lasernoise.cpp function in my header.h?

    Thanks.
    Custom Build:
    Windows 10 and Kubuntu 18.04

  9. #9
    Join Date
    Feb 2007
    Beans
    4,045
    Distro
    Ubuntu 9.10 Karmic Koala

    Re: Multiple source files, compile makefile

    Both the two cc-files included header.h which in turn included args.h, so that was indeed the reason since args.h mostly contains code that should be in .cc-/.cpp-files. I still think you should avoid including the args.h file from /usr/share/wherever, and rather put it in a .cc-file.

    1. .cc and .cpp are both c++ source files. .cpp is the more commonly used file extension, but they are otherwise equal.

    2. Put the the prototypes in either header.h or a new header file, and make both project.cc and lasernoice.cc include that header. In the makefile, you just add lasernoice.o to the lists of .o-files (the project-line and the one below)

    I can give you a quick overview of what happens with make:

    When you run make with no arguments, it will read Makefile and look for the all target. The all target in your case doesn't do anything, but it depends on project, so it must fulfil that dependency.

    The project target depends on the two (soon to be three) .o-files which must be fulfilled before it can run the commands for project.

    The special .cc.o target matches a .o-file if there exist a .cc-file by the same name. So for each .o-file it will do "g++ $(CFLAGS) -c -o <filename.o> <filename.cc>" if the .cc-file is newer than the .o-file. Thus, if you do a change only in project.cc, it will only compile that file next time your run make.

    Once that is done the dependencies for the project target is fulfilled, and it can run the linking command.

    Lastly it returns to the all target, which it can now run, but there is nothing to do, so make exits.

  10. #10
    Join Date
    Jan 2006
    Beans
    295

    Re: Multiple source files, compile makefile

    I think I understand. Basically, headers shouldnt contain code that do stuff right? I mean headers are only for including header file, declaring functions, global variables etc. But args.h actually has a couple of functions which run loops and print out stuff. So it would not typically be a "header file" right?

    Suppose, I create a source args.cc and put the code in args.h into args.cc. I then add args.o as one of the dependency for target. This should work right, because args.cc would be treated as a source and compiled like another file instead of being treated as a header.

    Finally, in the dependency for project, I do not include header.h. In some makefile examples I have seen them include headers as part of the prequisite as well. Is that ok? or should I include header.h as a prequisite for project?

    Thanks.
    Custom Build:
    Windows 10 and Kubuntu 18.04

Page 1 of 3 123 LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •