I have a large amount of code, so I have tried to only include the relevant parts of the code here

I have a header file called "ASp.h"

namespace ASP
{
    class ASp
    {
        public:
            ASp();
            ASp(FILE* fp);  
            void T_B_P_N(const char* type, int num);
    }
}

another header file "ms.h"

bool aSpQ(int argc, char* argv[]);

a cpp file "ms.cpp"

bool aSpQ(int argc, char* argv[])
{
    if(argc != 7)
    {
        usageASpQ();
        return false;
    }
    FILE* input = fileRead(argv[3]);
    string type = string(argv[4]);
    int num = atoi(argv[5]);
    FILE* output    = fileWrite(argv[6]);
    ASp* asp = new ASp(input);
    asp->T_B_P_N(type.c_str(), num);

    for(int i = 0; i < asp->numtr; i++)
    {
        asp->fs[i]->print(output);
    }
    fclose(input);
    fclose(output);
    return true;
}

Those files compiled with no problems when they were included in another cpp file.

I have another file called "PBL.cpp". This compiled fine before, until I tried to include the files above in PBL.cpp

#include "ASp/ASp.h"

using namespace ASP;
using namespace std;

//bunch of code

bool aSpQ(char * fname_r, string type, int num, char * fname_q)
{
    FILE* input = fileRead(fname_r);
    FILE* output    = fileWrite(fname_q);

    ASp* asp = new ASp(input);
    asp->T_B_P_N(type.c_str(), num);

    for(int i = 0; i < asp->numtr; i++)
    {
        asp->fs[i]->print(output);
    }
    fclose(input);
    fclose(output);
    return true;
}

When I try to compile this, at the line of

ASp* asp = new ASp(input);

in the PBL.cpp file

I get the following errors:
I get errors of undefined reference to ASP::ASp::ASp(_IOFILE*) and undefined reference to ASP::ASp::T_B_P_N(char const*, int)

Recommended Answers

All 13 Replies

Undefined reference means that the linker cannot find the compiled code for those functions. Where did you write those functions? Presumably in some *.cpp file. Either those functions do not exist (wrote declarations, didn't write the actual functions), or you haven't compiled the file containing them, or your linker has not been told to link against the compiled files.

"ASp* asp = new ASp(input);" was written in ASp.cpp, and "T_B_P_N(char const*, int)" was written in b.cpp, even though there is no b.h file.

[quote] or you haven't compiled the file containing them, or your linker has not been told to link against the compiled files.[/quote]

How do I get the linker to link against the ASp.cpp file? I am new to using Unix

The person who wrote the code before me did this. Apparently this was not a problem before, because everything compiled successfully before I made the changes to the PBL.cpp file

"ASp* asp = new ASp(input);" was written in ASp.cpp

That attempts to call a function. The function you're trying to call is a constructor function for the ASp object. That function was written somewhere. You need to provide that function. It lives in another cpp file, or it lives in a library.

If you have all the code (including the cpp file that the ASp constructor function was written in), you can compile and link it all together at the command line with (using g++ or a similar compiler):

g++ nameOfFile.cpp nameOfOtherFile.cpp nameOfYetAnotherFile.cpp nameOfAnotherFile.cpp ...

You should take the time to learn how a C++ program is made; your problems here stem from not understanding how files go from *.cpp to a finished program. Mike's article is a good place to start: https://www.daniweb.com/software-development/cpp/tutorials/466177/understanding-c-from-source-to-binaries

Thanks for that article, it was really helpful. I see now I am getting the 'undefined reference' errors because I need to link PBL.cpp with ASp and ms, and that the problem is that I need to configure the additional directories for ms.cpp and ASp.cpp into CMakeLists.txt. But I don't know how to do that. Where in CMakeLists.txt do I add the additional directories?

My coworker told me the problem is probably with the directories and libraries that are written in CMakeLists.txt. He tried to help briefly, but now he says that he can't help anymore

I have included the relevant parts of the CMakeLists to see if anyone can help

in /ws/larryburns/cmake/ME/Build/sc/ME/CMakeLists.txt:

SET(ME_LINK_LIBS
  MEAPI
  InLJ
  InEl
  El
  LJ
  PE
  CP
  GOAFT
  ASp
  LB
  Con
)

SET(ME_LINK_LIBS ${ME_LINK_LIBS}
  Blu
  DPG
  PP
  MEU
  SVD
  VFT
  GFT
  Geo
  Cur
  Con
  BO
  UM
  ${O_LIBRARY}
  l4c
#  GL
#  GLU
)

and in /ws/larryburns/cmake/ME/Build/sc/CMakeLists.txt:

ADD_SUBDIRECTORY (Ut)
ADD_SUBDIRECTORY (ASp)
ADD_SUBDIRECTORY (LB)
ADD_SUBDIRECTORY (Con)
ADD_SUBDIRECTORY (El)
ADD_SUBDIRECTORY (LJ)
ADD_SUBDIRECTORY (InLJ)
ADD_SUBDIRECTORY (InEl)
ADD_SUBDIRECTORY (MEU)
ADD_SUBDIRECTORY (PE)
ADD_SUBDIRECTORY (GB)
ADD_SUBDIRECTORY (GOAFT)
ADD_SUBDIRECTORY (CP)
ADD_SUBDIRECTORY (MEAPI)
ADD_SUBDIRECTORY (Blu)
ADD_SUBDIRECTORY (DPG)
ADD_SUBDIRECTORY (PP)
ADD_SUBDIRECTORY (UM)
ADD_SUBDIRECTORY (SVD)
ADD_SUBDIRECTORY (VFT)
ADD_SUBDIRECTORY (Geo)
ADD_SUBDIRECTORY (GFT)
ADD_SUBDIRECTORY (Con)
ADD_SUBDIRECTORY (BO)
ADD_SUBDIRECTORY (Cur)
ADD_SUBDIRECTORY (l4c)

As can be seen, even when I add ASp in both CMakeLists as a subdirectory and library, but I still get the undefined reference errors

This is a very weird looking cmake file. It must be very incomplete.

Why do you have such a long list of targets... are all these targets from your own source code?

I assume that your file /ws/larryburns/cmake/ME/Build/sc/ASp/CMakeLists.txt contains the following line (where "ASP_SOURCES" would be some cmake variable containing a list of source files, including ASp.cpp):

add_library(ASp STATIC ${ASP_SOURCES})

And that you have for your application, which has the main() function, a cmake file with lines like this:

add_executable(my_exec my_exec.cpp)
target_link_libraries(my_exec ${ME_LINK_LIBS})

That should give a successful compilation and linking of my_exec.cpp (or whatever you name it).

I have to say that your CMakeLists.txt files look very bizarre and that you almost certainly are not doing things correctly. It's weird to have all the targets collected into long lists like that and link everything together at the end like that. If things belong to a single library, they should be compiled as such, in general. Otherwise, they should be linked with in a more fine-grained fashion. Object targets can also be used in this kind of context.

Also, on another note, to avoid having to add all those sub-directories with manual add_subdirectory calls, I use this simple custom macro as follows:

macro(add_all_valid_subdirs)
  file(GLOB children RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/*")
  foreach(child ${children})
    if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${child})
      if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${child}/CMakeLists.txt")
        add_subdirectory(${child})
      endif()
    endif()
  endforeach(child)
endmacro(add_all_valid_subdirs)

Which can simply be called as:

add_all_valid_subdirs()

and it will replace all your "add_subdirectory" calls by adding all the subdirectories that contain a CMakeLists.txt file.

"Why do you have such a long list of targets... are all these targets from your own source code?"

Those source files are needed to compile the whole program. Most of this was written by the people before me

The cmakelists actually has

ADD_EXECUTABLE (ME MACOSX_BUNDLE ${SOURCE_FILES} ${INCLUDE_FILES})


TARGET_LINK_LIBRARIES(ME ${ME_LINK_LIBS})

I made a mistake when I posted the contents of /ws/larryburns/cmake/ME/Build/sc/CMakeLists.txt. There should be a "ADD_SUBDIRECTORY(ME) at the end, like this:

ADD_SUBDIRECTORY (Cur)
ADD_SUBDIRECTORY (l4c)
 ...
ADD_SUBDIRECTORY(ME)

To clarify, in ws/larryburns/cmake/ME/sc, there are the subdirectories, each of which contains cpp files. For example, ASp.cpp is in

ws/larryburns/cmake/ME/sc/ASp/ASp.cpp

Also, ms.cpp is in

ws/larryburns/cmake/ME/sc/Blu/ms.cpp

I am not creating or modifying a new subdirectory. Asp.cpp and ms.cpp compiled in a different project, so I just copied the directories (ASp and Blu) they were from to this ME project

Alot of this is unclear to me to since there's no documentation and the previous coworkers who wrote alot of this aren't here anymore while my existing coworker doesn't want to help

But

ADD_EXECUTABLE (ME MACOSX_BUNDLE ${SOURCE_FILES} ${INCLUDE_FILES})
TARGET_LINK_LIBRARIES(ME ${ME_LINK_LIBS})

are in

/ws/larryburns/cmake/ME/Build/sc/ME/CMakeLists.txt

I don't see "add_library(ASp ASP_function_implementation.cpp ...)" anywhere. I think the /ws/larryburns/cmake/ME/Build/sc/ME/CMakeLists.txt compiled the executable using it?

One thing that is weird is that you keep talking about the files that are under /ws/larryburns/cmake/ME/Build/sc/, which are files that are copied from the files under /ws/larryburns/cmake/ME/sc/, at least, that's how it's normally done. You should not modify the files under the "Build" directory. Instead, modify the files under the ME/sc directory, because that's the ones that cmake looks at.

In the file /ws/larryburns/cmake/ME/sc/ASp/CMakeLists.txt, you should have the following:

add_library(ASp ASp.cpp)

with whatever other source files you have in that directory.

In the file /ws/larryburns/cmake/ME/sc/Blu/CMakeLists.txt, you should have the following:

add_library(Blu ms.cpp)

with whatever other source files you have in that directory.

In the file /ws/larryburns/cmake/ME/sc/ME/CMakeLists.txt, you should have the following:

ADD_EXECUTABLE (ME MACOSX_BUNDLE ${SOURCE_FILES})
TARGET_LINK_LIBRARIES(ME ${ME_LINK_LIBS})

notice that the ${INCLUDE_FILES} should not be needed, you only need to compile source files, not headers, that's a classic beginner's mistake.

I don't see "add_library(ASp ASP_function_implementation.cpp ...)" anywhere. I think the /ws/larryburns/cmake/ME/Build/sc/ME/CMakeLists.txt compiled the executable using it?

Again, whatever is in the "Build" directory is not something you should touch, because these are files generated by cmake, and if you modify them without modifying the original files, in the "ME/sc" folder, you might simply be corrupting the existing cmake configuration with weird or no effects on the actual build process.

If you don't have a add_library(ASp ..) line in the ME/sc/ASp/CMakeLists.txt file, then cmake should complain that it has "no rules for building the 'ASp' target" when you try to compile the ME executable target. If it doesn't complain about that, it means that either there is such a line in the CMakeLists.txt file, or it means that the cmake configuration is corrupt. To reset the cmake configuration, the easiest trick is to do this:

$ cd /ws/larryburns/cmake/ME/Build/
$ rm -R *
$ cmake ..
$ make

note that the cmake .. command could also be cmake ../sc, depending on where your top-level CMakeLists.txt file is (in the "ME" or "ME/sc" folder).

Normally, if you build the ME executable, by doing $ make ME in the Build folder, it should first compile the ASp library (you should see it appear in the console as one of the targets being built). This is because ASp appears in the list ME_LINK_LIBS, which is a list of all the other cmake targets (including ASp library) that needs to be linked with your executable (which means they must be compiled before the ME executable is compiled). That's how cmake works when it comes to dependencies (libraries / targets that are needed by other libraries / executables / targets).

Most of this was written by the people before me
...
Alot of this is unclear to me to since there's no documentation and the previous coworkers who wrote alot of this aren't here anymore while my existing coworker doesn't want to help

Have you ever heard the saying "standing on the shoulder of giants" (meaning that you are building upon the works of people who did great work before you)... well, it appears that you are stumbling on the toes of midgets, if I may say so, to reverse the saying. ;)

The people who set this up before you were clearly incompetent or lazy... probably both.

I would also suggest that you work through some cmake tutorials or something, to learn and understand how it works. It's very difficult to help you with those issues like this, without a complete view of the setup. CMake is quite easy to work with once you understand the logic of it (which your predecessors clearly didn't).

In the file /ws/larryburns/cmake/ME/sc/ASp/CMakeLists.txt, I have:

ADD_LIBRARY (ASp STATIC ${SOURCE_FILES} ${INCLUDE_FILES})

In the file /ws/larryburns/cmake/ME/sc/Blu/CMakeLists.txt,
I have

ADD_LIBRARY (Blu STATIC ${SOURCE_FILES} ${INCLUDE_FILES})

In the file /ws/larryburns/cmake/ME/sc/ME/CMakeLists.txt, I have the following:

ADD_EXECUTABLE (ME MACOSX_BUNDLE ${SOURCE_FILES} ${INCLUDE_FILES})

TARGET_LINK_LIBRARIES(ME ${ME_LINK_LIBS})

Since I have add_library(ASp STATIC ${SOURCE_FILES} ${INCLUDE_FILES}), but it does not have the cpp explicity, as in Asp.cpp,
in the ME/sc/ASp/CMakeLists.txt file, then because my cmake did not complain "no rules for building the 'ASp' target", should I still reset the cmake configuration by following the steps below?:

$ cd /ws/larryburns/cmake/ME/Build/
$ rm -R *
$ cmake ..
$ make

"Normally, if you build the ME executable, by doing $ make ME in the Build folder, it should first compile the ASp library ..."

It doesn't seem to compile ASp first, but 5 other libraries are built before it, when running 'make'

it does not have the cpp explicity, as in Asp.cpp

That makes no difference. I assume that Asp.cpp is one of the source files listed in the definition of SOURCE_FILES for that directory's CMakeLists.txt.

because my cmake did not complain "no rules for building the 'ASp' target"

From the looks of it, your CMakeLists.txt files seem correct (assuming that the SOURCE_FILES variable definitions in them contain the correct cpp files listed in them). This should work. Something else must be causing the issue.

should I still reset the cmake configuration by following the steps below?

Yes. It never hurts to do this (except that it will recompile everything, which could take time, that's all). Whenever I feel a bit weird about how cmake is behaving, I do this kind of a reset. Another, lesser option is to do make clean and then make, which is basically to clean any previous compilation and compile everything again, but that usually doesn't solve cmake problems, but it can help sometimes when cmake has gotten out-of-sync with the source file modifications.

So, you should first do a make-clean-make, and if that doesn't work, to a full reset with the procedure I gave you earlier.

If that doesn't work, you should post all the console messages you got when running cmake and when running "make ME".

If everything is in order, as it appears to be now, then the problem must be in the source code. A big part of the difficulty of trying to help you solve this problem is that there is no complete picture of it, just random fragments.

cd /ws/larryburns/cmake/ME/Build/
$ rm -R *
$ cmake ..
$ make

This is basically the same as just deleting all the files in the ../ME/Build directory, right? I did that, ran cmake and make again, and I'm getting the same 'undefined reference' errors I got before, that I posted in the OP

Where is you "PBL.cpp" file?

You have to understand that ordering matters in the list of linked libraries. The "ASp" library should appear in the list of link libraries after the library in which the "PBL.cpp" file is compiled. That's because the PBL-containing library depends on the ASp library. In fact, you PBL-containing library should list the ASp library in its dependencies. In other words, let's say your PBL-containing library is called "PBL", then you would have something like this in its relevant cmake file:

add_library(PBL STATIC PBL.cpp)

target_link_libraries(PBL ASp)

Which will tell cmake that ASp must be compiled before PBL, and that anything that links with PBL must also link with ASp afterwards, to resolve the symbols in PBL to their definitions found in ASp.

This is why I think your whole cmake configuration is terrible, because you are not supposed to just list all the libraries in one variable like you do in the ME_LINK_LIBS variable. Instead, each library should list whatever other libraries it depends on, and your executables should just list the few top-level libraries that it uses and needs to link to, and cmake is going to do the rest of the work of pulling all the other dependencies (in the correct order) into the linking command for your executables / shared-libs.

Thank you very much for your reply again. I really appreciate it

Unfortunately, I am still not getting this to work

First, I did not try your suggestion to use
"add_library" and "target_link_libraries". I just modified the CMakeLists so that it ordered directories based on the order they should be compiled. I was able to get rid of most of the 'undefined reference errors' this way, but have one left. The undefined reference message is referring to a function that has an undefined reference to another function. However, they are both in the same folder in the same cpp.o file, and I am unable to open that file and see its contents with gedit

Then, I followed your suggestion to use 'add_library' and 'target_link_libraries'.

I edited it as:

add_library(PB2 STATIC PBL.cpp)

target_link_libraries(PB2 ASp)
target_link_libraries(ASp LB)
...

The errors I now get are

Make Error at src/ME/CMakeLists.txt:46 (add_library):
  add_library cannot create target "PB2" because another target with the same
  name already exists.  The existing target is a static library created in  source directory "/ws/larryburns/cmake/ME/src/PB2"


CMake Error at src/ME/CMakeLists.txt:48 (target_link_libraries):
  Attempt to add link library "ASp" to target "PB2" which is not built in
  this directory.
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.