Thread: Makefile Not Finding Rule

  1. #1
    Registered User
    Join Date
    Sep 2022
    Posts
    8

    Makefile Not Finding Rule

    Hello all,

    I am having some trouble getting Make to work properly.

    I am trying to follow this tutorial:
    Getting started with Google Test (GTest) on Ubuntu – Erik Smistad

    But I am trying to adapt it to work with make. I broke the whattotest.cpp file into a header file and added a more normal directory structure.
    Folder PATH listing for volume D
    Volume serial number is 1A80-3041
    D:.
    │ makefile
    │ Notes.txt

    ├───bin
    │ .dirstamp

    ├───inc
    │ whattotest.hpp

    ├───obj
    │ .dirstamp

    ├───src
    │ whattotest.cpp

    └───tests
    tests.cpp


    whattotest.hpp
    Code:
    #pragma once
    #include <math.h>
    
    double squareRoot(const double a);
    whattotest.cpp
    Code:
    // whattotest.cpp
    #include <math.h>
    #include "whattotest.hpp"
     
    double squareRoot(const double a) {
        double b = sqrt(a);
        if(b != b) { // nan check
            return -1.0;
        }else{
            return sqrt(a);
        }
    }
    tests.cpp
    Code:
    // tests.cpp
    #include "whattotest.hpp"
    #include <gtest/gtest.h>
     
    TEST(SquareRootTest, PositiveNos) { 
        ASSERT_EQ(6, squareRoot(36.0));
        ASSERT_EQ(18.0, squareRoot(324.0));
        ASSERT_EQ(25.4, squareRoot(645.16));
        ASSERT_EQ(0, squareRoot(0.0));
    }
     
    TEST(SquareRootTest, NegativeNos) {
        ASSERT_EQ(-1.0, squareRoot(-15.0));
        ASSERT_EQ(-1.0, squareRoot(-0.2));
    }
     
    int main(int argc, char **argv) {
        testing::InitGoogleTest(&argc, argv);
        return RUN_ALL_TESTS();
    }
    makefile
    Code:
    CXX = g++
    BLDDIR = bin
    SRCDIR = src
    INCDIR = inc
    OBJDIR = obj
    TESTDIR = tests
    CPPFLAGS = -Iinc
    LXXFLAGS = -lgtest -lpthread
    GTEST = C:\MinGW\lib\libgtest.a
    
    .PHONY: all
    all: $(BLDDIR)/.dirstamp $(OBJDIR)/.dirstamp $(TESTDIR)/runTests
    
    $(BLDDIR)/.dirstamp:
        mkdir -p $(BLDDIR)
        touch $(BLDDIR)/.dirstamp
    
    $(OBJDIR)/.dirstamp:
        mkdir -p $(OBJDIR)
        touch $(OBJDIR)/.dirstamp
    
    $(TESTDIR)/runTests: $(OBJDIR)/tests.o $(OBJDIR)/whattotest.o $(GTEST)
        $(CXX) $(LXXFLAGS) -g $^ -o $@
    
    $(OBJDIR)/tests.o: $(TESTDIR)/tests.cpp
        $(CXX) $(CPPFLAGS) -c $< -o $@
        
    $(OBJDIR)/whattottest.o: $(SRCDIR)/whattottest.cpp
        $(CXX) $(CPPFLAGS) -c $< -o $@
    
    .PHONY: clean
    clean:
        rm $(BLDDIR)/*
        rm $(OBJDIR)/*.*
        rm $(TESTDIR)/runTests
    Make is failing this for:
    make: *** No rule to make target 'obj/whattotest.o', needed by 'tests/runTests'. Stop.

    What am I missing?

  2. #2
    Registered User
    Join Date
    Sep 2022
    Posts
    8
    I found the first error.
    I have an extra "t" in the whattotest file. I put "whattottest" instead of "whattotest".

    Now the next problem. Make is not able to find my gtest installation.

    I am not sure if I should start a new topic for that or not?

    I have built gtest and added the binaries produced to my compilers lib folder.
    I also copied the gtest and gmock folders to my compilers include folder.
    Then I also added all of these to my system PATH variable.
    This was working before, but now I get the 2 or 3 screens of errors that all the gtest methods are undefined.
    Last edited by Xilixian; 09-06-2022 at 06:38 AM.

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,426
    > GTEST = C:\MinGW\lib\libgtest.a
    A library would normally be specified using
    -L to tell the linker where to look
    -l to tell the linker the base name of the library.

    Eg
    Code:
    GTEST = -LC:\MinGW\lib -lgtest
    > I have built gtest and added the binaries produced to my compilers lib folder.
    > I also copied the gtest and gmock folders to my compilers include folder.
    Yeah, not such a good idea.
    Upgrade or change your compiler, and you're back to where you started.

    Use the -I and -L path options to tell the compiler and linker where to find things.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Registered User
    Join Date
    Sep 2022
    Posts
    8

    Thank you for the response!

    Hi Salem,

    Thank you for the response.

    The GTEST is actually just a make variable.
    But, to your point, I tried adding -LC:\MinGW\lib\libgtest.a to the linker flags. This still results in undefined errors for the googletest methods.

    Placing the gtest and gmock folders in the compiler directories was part of the instructions I had found for installing google test on windows.
    The weird thing is this was all working just fine until I had to upgrade my compiler, and like you said everything stopped working.
    But, I have re-installed the exact same way(I took detailed notes the first time because it was a nightmare) and now it doesn't work.

    I will try using your -L<path> and -l<moduleName> technique and and try pointing to where I unzipped GoogleTest. God I hope that works.

  5. #5
    Registered User
    Join Date
    Sep 2022
    Posts
    8
    Here is some of the stuff I have tried:
    1) Changing the GTEST variable to
    GTEST = -LC:\MinGW\lib -lgtest
    Causes Make to fail for: *** multiple target patterns. Stop.
    This makes sense kind of because the GTEST variable is intended to point to the .a library that is created when you build google test. That is located in a lib folder, not the gtest folder.
    Which takes us to the next thing on the list....

    2) Changing the GTEST variable to
    GTEST = -LC:\MinGW\lib -llibgtest.a
    Causes Make to throw all the "undefined" errors for all the gtest methods

    3) Changing everything to point to where I unzipped and build googletest
    LXXFLAGS = -LD:\myWorkspace\Gtest\googletest-release-1.11.0\googletest\include -lgtest -lpthread
    GTEST = D:\myWorkspace\Gtest\googletest-release-1.11.0\lib\libgtest.a
    Causes Make to throw all the "undefined" errors for all the gtest methods

    Is there anyone else out there having to use this crap on Windows? It works like a charm in linux, but I have to make this work in windows for my current situation.

  6. #6
    Registered User
    Join Date
    Feb 2019
    Posts
    1,040
    -L informs the linker only where the libraries are.
    -l informs the linker only which libraries must be linked.

    The -l option always search for a shared object (lib<lib>.so. Example: -lgtest tries to link libgtest.so). If you want to link a static library (.a file) you must use the full filename preceeded with :, like -l:gtest.a.

    Another thing: -l must be placed AFTER the object files, like:

    $ g++ -L/libpath/ -o test test.o -l:mylib.a

    Or

    $ g++ -L/libpath/ test.o -l:mylib.a -o test


    This is documented for ld.

    And there is a simple way to write your makefile using implicit rules... LDFLAGS is used as options to the linker and LDLIBS as library options:

    Code:
    CXXFLAGS=-g
    LDFLAGS=-g -LC:/mingw64/lib
    LDLIBS=-lgtest
    
    # OBS: Instead changing CC variable we could add -lstdc++ to LDLIBS and avoid
    # the line below.
    test: CC=$(CXX)   # change the "linker" to g++, instead o gcc
    
    # Implicit rule for linker
    test: test.o
    
    # Implicit rule for compiler
    test.o: test.cc
    Notice that your makefile is trying to link a dynamic library (shared object), libgtest.so, AND the static version, gtest.a. This is, probably, wrong
    Last edited by flp1969; 09-08-2022 at 07:02 AM.

  7. #7
    Registered User
    Join Date
    Feb 2019
    Posts
    1,040
    An example of factorial using libgmp, in C:

    Code:
    // fact.c
    #include <stdio.h>
    #include <stdlib.h>
    #include <gmp.h>
    #include <errno.h>
    #include <time.h>
    
    int main(int argc, char *argv[])
    {
      char *p;
      mpz_t r;
      unsigned long n, c, total;
      time_t t1, t2;
    
      if ( argc != 2 )
      {
        fprintf( stderr, "Usage: %s <value>\n", argv[0] );
        return EXIT_FAILURE;
      }
    
      errno = 0;
      n = strtoul( *++argv, &p, 10 );
      if ( errno == ERANGE || *p )
      {
        fputs( "ERROR: Invalid value.\n", stderr );
        return EXIT_FAILURE;
      }
    
      mpz_init_set_ui(r, 1);
    
      t1 = time( NULL );
    
      c = 0;
      total = n;
      while ( n >= 1 )
      {
        mpz_mul_ui( r, r, n-- );
        printf( "%.2f%% complete... \r", 100.0 * ++c / total );
      }
      putchar( '\n' );
    
      t2 = time( NULL );
    
      mpz_out_str( stdout, 10, r );
      putchar('\n');
    
      mpz_clear(r);
    
      printf( "Total time: %lu seconds.\n", t2 - t1 );
    
      return EXIT_SUCCESS;
    }
    Code:
    # Makefile
    CFLAGS=-O2
    LDLIBS=-lgmp
    
    fact: fact.o
    
    fact.o: fact.c
    Code:
    $ make
    cc -O2   -c -o fact.o fact.c
    cc -s  fact.o  -lgmp -o fact
    $ ./fact 100
    100.00% complete... 
    93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
    Total time: 0 seconds.

  8. #8
    Registered User
    Join Date
    Sep 2022
    Posts
    8
    I am quickly learning that no two people use make the same way and that is annoying.

    I am sorry Flp, but I cannot understand your Make stuff. I am trying to learn how to use Make and Googletest.

    I do understand your point about putting the linker flags after the object files.

    I am completely confused as to why you think I am trying to add gtest.a.
    I don't see that in my example at all.
    I am trying to include the gtest folder which contains all the header files for google test. ( I think?)

    The library I am trying to link to is libgtest.a not libgtest.so (unless this is the same thing? I don't know this.)

    I want to try to use your Make example but I have no idea how to translate that to my code.

  9. #9
    Registered User
    Join Date
    Feb 2019
    Posts
    1,040
    Quote Originally Posted by Xilixian View Post
    I am quickly learning that no two people use make the same way and that is annoying.
    Two people don't do a program the same way. Learn to live with it

    I am sorry Flp, but I cannot understand your Make stuff. I am trying to learn how to use Make and Googletest.
    Try to learn how to use Makefiles from 'make' documentation.

    I am completely confused as to why you think I am trying to add gtest.a.
    I don't see that in my example at all.
    Here:
    Code:
    LXXFLAGS = -lgtest -lpthread
    
    GTEST = C:\MinGW\lib\libgtest.a

    I am trying to include the gtest folder which contains all the header files for google test. ( I think?)
    In that case, use -I option.

    The library I am trying to link to is libgtest.a not libgtest.so (unless this is the same thing? I don't know this.)
    No, you are trying to link BOTH.

    I want to try to use your Make example but I have no idea how to translate that to my code.
    Read this: GNU make manual

  10. #10
    Registered User
    Join Date
    Sep 2022
    Posts
    8
    Thanks for the reply flp, I really do appreciate you taking the time to try to help.

    I have tried reading the google test and Make documentation with zero luck. So much of it makes no sense to me or it only applied to a super simple example like one simple helloworld.cpp file.
    (for example, google loves to talk about something called an "expectation" that I have never found a definition for. They put it in italics, so I am guessing it is some kind of thing and not the usual use of the word.)
    The makefile I have posted is from another tutorial, one of dozens I have tried to get working with no luck.
    I can't explain how incredibly frustrating this is.

    Anyways, I am going to mark this as closed as my initial makefile problem is fixed.
    I can already see the rest of this is just going to be waste of everyone's time.

  11. #11
    Registered User
    Join Date
    Feb 2019
    Posts
    1,040
    Here's what you are trying to do:
    Code:
    # Makefile
    CXXFLAGS=-g
    LDFLAGS=-g
    LDLIBS=-lm -lgtest
    
    TARGET=test
    OBJECTS=test.o whattotest.o
    
    $(TARGET): CC=$(CXX)
    $(TARGET): $(OBJECTS)
    
    test.o: test.cc whattotest.hpp
    whattotest.o: whattotest.cc whattotest.hpp
    
    .PHONY: clean distclean
    
    clean:
        -rm $(OBJECTS)
    
    distclean: clean
        rm $(TARGET)
    Code:
    // test.cc
    #include <gtest/gtest.h>
    #include "whattotest.hpp"
    
    TEST ( SquareRootTest, PositiveNos )
    {
      ASSERT_EQ ( 6, squareRoot ( 36.0 ) );
      ASSERT_EQ ( 18.0, squareRoot ( 324.0 ) );
      ASSERT_EQ ( 25.4, squareRoot ( 645.16 ) );
      ASSERT_EQ ( 0, squareRoot ( 0.0 ) );
    }
    
    TEST ( SquareRootTest, NegativeNos )
    {
      ASSERT_EQ ( -1.0, squareRoot ( -15.0 ) );
      ASSERT_EQ ( -1.0, squareRoot ( -0.2 ) );
    }
    
    int main ( int argc, char **argv )
    {
      testing::InitGoogleTest ( &argc, argv );
    
      return RUN_ALL_TESTS();
    }
    Code:
    // whattotest.cc
    #include <math.h>
    #include "whattotest.hpp"
    
    double squareRoot ( double a )
    {
      double b = sqrt ( a );
    
      if ( isnan(b) ) // nan check
        return -1.0;
    
      return b;
    }
    Code:
    // whattotest.hpp
    #ifndef WHATTOTEST_HPP_
    #define WHATTOTEST_HPP_
    
    double squareRoot(double);
    
    #endif
    Code:
    $ make
    g++ -g   -c -o test.o test.cc
    g++ -g   -c -o whattotest.o whattotest.cc
    g++ -g  test.o whattotest.o  -lm -lgtest -o test
    
    $ ./test
    [==========] Running 2 tests from 1 test suite.
    [----------] Global test environment set-up.
    [----------] 2 tests from SquareRootTest
    [ RUN      ] SquareRootTest.PositiveNos
    [       OK ] SquareRootTest.PositiveNos (0 ms)
    [ RUN      ] SquareRootTest.NegativeNos
    [       OK ] SquareRootTest.NegativeNos (0 ms)
    [----------] 2 tests from SquareRootTest (0 ms total)
    
    [----------] Global test environment tear-down
    [==========] 2 tests from 1 test suite ran. (0 ms total)
    [  PASSED  ] 2 tests.

  12. #12
    Registered User
    Join Date
    Sep 2022
    Posts
    8
    make: *** No rule to make target 'test.cc', needed by 'test.o'. Stop.

  13. #13
    Registered User
    Join Date
    Sep 2022
    Posts
    8
    If a mod or someone knows how to delete this thread or mark it solved please do so.
    I can't seem to find any way to edit the title or delete the thread.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Simpson's Rule (not composite simpson's rule)
    By Solas99 in forum C Programming
    Replies: 10
    Last Post: 04-02-2013, 12:37 PM
  2. Replies: 2
    Last Post: 04-27-2011, 04:14 PM
  3. Simpson's rule and Trapezoidal rule from fixed array
    By timwonderer in forum C++ Programming
    Replies: 1
    Last Post: 12-02-2010, 03:14 PM
  4. Makefile Problem: None rule to make target
    By chris24300 in forum Linux Programming
    Replies: 25
    Last Post: 06-17-2009, 09:45 AM
  5. difference makefile makefile.am makefile.in
    By Bargi in forum Linux Programming
    Replies: 7
    Last Post: 10-28-2007, 02:08 PM

Tags for this Thread