Thread: Makefile help

  1. #1
    Registered User
    Join Date
    Nov 2008
    Posts
    56

    Makefile help

    Hello,

    I am trying to use make to compile and link two simple C programs in linux. Here is the two programs.
    combine1.c
    Code:
    //combine1.c
    #include <stdio.h>
    
    int main(void)
    {
    	int n;
    
    	printf("This is a test\n");
    	
    	printf("n=%d\n", input(n));
    	printf("Done");
    	return 0;
    }
    combine2.c
    Code:
    //combine2.c
    input(int n)
    {
    	n = 10;
    	return n;
    }
    I can compile and link these two using gcc without any trouble:
    Code:
     gcc -o combine combine1.c combine2.c
    I want to compile and link the two using make but I don't think I am doing my Makefile correctly. Can someone explain how to do this? Here is what I have for my Makefile:
    Code:
    project1:	combine1.o
    	gcc -o project1 combine1.o
    
    combine1.o:		combine1.c combine2.c
    	gcc -c combine1.c
    		
    clean:
    	rm project1 combine1.o
    When I type $make
    I get the following:
    Code:
    combine1.o: In function `main':
    combine1.c:(.text+0x1b): undefined reference to `input'
    collect2: ld returned 1 exit status
    make: *** [project1] Error 1
    Thanks for any help.

  2. #2
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    This should work
    Code:
    project1: combine1.o combine2.o
    	gcc -o project1 combine1.o combine2.o
    
    combine1.o: combine1.c
    	gcc -c combine1.c
    
    combine2.o: combine2.c
    	gcc -c combine2.c
    		
    clean:
    	rm project1 combine1.o

  3. #3
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    combine1.c doesn't include a header file for combine2.h, but you're trying to call a function that combine1.c doesn't know anything about.
    "I am probably the laziest programmer on the planet, a fact with which anyone who has ever seen my code will agree." - esbo, 11/15/2008

    "the internet is a scary place to be thats why i dont use it much." - billet, 03/17/2010

  4. #4
    Registered User
    Join Date
    Apr 2008
    Posts
    396
    combine1.c doesn't include a header file for combine2.h, but you're trying to call a function that combine1.c doesn't know anything about.
    Yes, that's true, the declaration is missing, but gcc can cope with that (assuming warnings are not enabled, which is really bad, as always); in our case, the error occurs at link time (gcc -o project1 combine1.o, combine2.o is missing, so input() is missing too).

  5. #5
    Registered User
    Join Date
    Nov 2008
    Posts
    56
    okay, C_ntua's suggestion woked well. What would be the proper way to call a function from main using a separate program? Would I declare the function before main in combine1.c:
    Code:
    //combine1.c
    #include <stdio.h>
    
    input(int n);
    
    int main(void)
    {
    	int n;
    
    	printf("This is a test\n");
    	
    	printf("n=%d\n", input(n));
    	printf("Done");
    	return 0;
    }
    Or would I just save combine2.h as a header file and include combine2.h in combine1.c
    Code:
    //combine1.c
    #include <stdio.h>
    #include <combine2.h>
    
    int main(void)
    {
    	int n;
    
    	printf("This is a test\n");
    	
    	printf("n=%d\n", input(n));
    	printf("Done");
    	return 0;
    }

  6. #6
    Registered User
    Join Date
    Apr 2008
    Posts
    396
    there are many ways to do things, but the 'proper' way is to divide each of your modules in two files: a .h (interface) and .c (implementation), the header only contains the declarations of the functions defined in the .c, and this .h is included in the other modules using those functions. In your case you should have a combine2.h (containing 'int input(int);' ) and combine2.c; combine2.c and combine1.c include combine2.h. combine1 is only the entry point (not included anywhere by definition, so you don't need an interface for it). but the 1st solution you propose above, is correct too, the second one is wrong (and will lead to conflicts if you still use separated compilation).
    Last edited by root4; 11-18-2008 at 12:46 PM.

  7. #7
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    You just rename combine2.c to a combine2.h file. Then you include that in combine1 as:
    Code:
    include "combine2.h"
    even if you include combine2.c to your combine1.c file it will work. The .h is just better to make clear it is a header file.

    Now, you will ask why do we have .o files then? Because then every time you compiled a program ALL files included would have to be compiled. To avoid this, you make an object file .o which isn't compiled every time.

    So in your case you should have a combine2.c. You will create an object file with gcc -c combine2.c. This will create combine2.o. Now, you will just have to include "combine2.c" to your combine1.c file and the linker will finde the combine2.o file and will do what you want, without re-compiling the .o file.

    A better way is to have also combine2.h file. In this file you will just add your functions using the extern keyword. So you will have:
    Code:
    //combine2.h
    extern int input(int n);
    
    //combine2.c
    int input(int n)
    {
    ...
    }
    
    //combine1.c
    include "combine1.h"
    That is what is commonly used to separate the code into files for better management.

  8. #8
    Registered User
    Join Date
    Nov 2008
    Posts
    56
    okay, so my first example, the declared function in the main program, worked. Provided I put the type int in for the function. I am not sure how to do this using a header file combine2.h though.

    See if I'm on the right track. I would need three files:
    combine1.c
    combine2.c
    combine2,h
    I would create a Makefile using these three files. If I am correct so far I will try Makefile for the three programs.

  9. #9
    Registered User
    Join Date
    Nov 2008
    Posts
    56
    okay, I edited my files and I am still having trouble. Here is what I have.

    Code:
    //combine1.c
    #include <stdio.h>
    #include "combine2.h"
    
    
    
    int main(void)
    {
    	int n;
    	
    	printf("This is a test\n");
    	
    	printf("n=%d\n", input(n));
    	printf("Done");
    	return 0;
    }
    
    //combine2.c
    
    #include "combine2.h"
    
    int input(int n)
    {
    	n = 10;
    	return n;
    }
    
    
    
    //combine2.h
    extern input(int n)
    {
    	n = 10;
    	return n;
    }
    
    #Makefile
    project1:	combine2.o combine1.o
    	gcc -o project1 combine2.o combine1.o
    
    combine2.o:		combine2.c combine2.h
    	gcc -c combine2.c
    	
    combine1.o:		combine2.h combine1.c
    	gcc -c combine1.c
    	
    clean:
    	rm project1 combine1.o
    Here is the errors I am getting when I run make:
    Code:
    scott@scott-laptop:~$ make
    gcc -c combine2.c
    combine2.c:6: error: redefinition of ‘input’
    combine2.h:3: error: previous definition of ‘input’ was here
    make: *** [combine2.o] Error 1
    scott@scott-laptop:~$
    I tried playing around with combine2.c and combine2.h but I can't get rid of the errors. Any ideas?

  10. #10
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    You should only have the prototype for input() in the .h file, not the entire function definition.

    Also, you should declare the return type of input, e.g.
    Code:
    int input(int n);
    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  11. #11
    Registered User
    Join Date
    Nov 2008
    Posts
    56
    I remove the prototype in combine2.c:
    Code:
    //combine2.c
    
    #include "combine2.h"
    
    
    {
    	n = 10;
    	return n;
    }
    I declare the return type of input in combine.h and I still get an error.
    Code:
    scott@scott-laptop:~$ make
    gcc -c combine2.c
    combine2.c:6: error: expected identifier or ‘(’ before ‘{’ token
    make: *** [combine2.o] Error 1
    scott@scott-laptop:~$

  12. #12
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    No, that's the wrong way to do it. In the header file, you declare that there is a function. You then REPEAT this in the function definition.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  13. #13
    Registered User
    Join Date
    Nov 2008
    Posts
    56
    I got it to work now. I remove everything from combine2.h but the declarization for input.
    Here is the finished product:
    Code:
    //combine1.c
    #include <stdio.h>
    #include "combine2.h"
    
    
    
    int main(void)
    {
    	int n;
    	
    	printf("This is a test\n");
    	
    	printf("n=&#37;d\n", input(n));
    	printf("Done");
    	return 0;
    }
    
    //combine2.c
    
    #include "combine2.h"
    
    int input(int n)
    {
    	n = 10;
    	return n;
    }
    //combine2.h
    int input(int n);
    
    
    #Makefile
    project1:	combine2.o combine1.o
    	gcc -o project1 combine2.o combine1.o
    
    combine2.o:		combine2.c combine2.h
    	gcc -c combine2.c
    	
    combine1.o:		combine2.h combine1.c
    	gcc -c combine1.c
    	
    clean:
    	rm project1 combine1.o
    Even though it works, is it correct?
    Am I understanding this correctly? If I have a file called main.c that has a function call in it. I would put the function definition in a second .c file example function.c and I would make a third file example function.h and put only the declarization for the function definition in it?
    Last edited by swappo; 11-19-2008 at 09:53 AM.

  14. #14
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Your latest post seems to repeat combine1.c twice, so you may want to post combine2.c

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  15. #15
    Registered User
    Join Date
    Nov 2008
    Posts
    56
    okay, I edited my last post to reflect combine2.c.
    Even though it works, is it correct?
    Am I understanding this correctly? If I have a file called main.c that has a function call in it. I would put the function definition in a second .c file example function.c and I would make a third file example function.h and put only the declarization for the function definition in it?
    Am I correct in this statement? If so, I think I now have a handle on things.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Makefile Problem: None rule to make target
    By chris24300 in forum Linux Programming
    Replies: 25
    Last Post: 06-17-2009, 09:45 AM
  2. Building a project using a Makefile
    By starcatcher in forum Windows Programming
    Replies: 2
    Last Post: 11-23-2008, 11:50 PM
  3. unix makefile won't work but works in Dev C++
    By jk1998 in forum C++ Programming
    Replies: 1
    Last Post: 06-09-2007, 03:54 PM
  4. makefile blues....
    By WaterNut in forum C Programming
    Replies: 6
    Last Post: 05-30-2005, 08:22 PM
  5. Need help with Makefile
    By xshapirox in forum C++ Programming
    Replies: 14
    Last Post: 09-28-2004, 03:32 PM