-->

Trouble Linking object files from project in Tests

2019-07-31 12:38发布

问题:

I am trying to link some of the object files so that I can write tests using UnitTest++ in the Codelite IDE. Mysteriously, the tutorial does not say how to use .o files from a (different) project.

If I was using the command line, this thread shows me how to do that. However, I am having more difficulty in the Codelite editor. The accepted answer in this other thread says "[i]n the codelite's IDE, this is added in the linker's option textbox," however, I am not finding that to be the case.

I add the path to these .o files in the Library Search Path spot, and then I add the name of the individual files in the Libraries spot just below this. When I do this I get the /usr/bin/ld: cannot find -l<stuff> error. If I omit the names of the specific files in the Library spot, I get the undefined reference to error.

Do I have to compile the original project as a library to get around this? Or is there a solution I don't see? The my_class_test.cpp file that I want to run looks something like this:

#include <UnitTest++/UnitTest++.h>

#include "my_class.h"

SUITE(MyClassTest)
{

class MCFixture
{
public:
    MyClass me;
    MCFixture() : me("a", "b", "c") {};
};

TEST_FIXTURE(MCFixture, ConstructorTest)
{
    CHECK_EQUAL(1.0, 1.0);
}

} //SUITE(MyClassTest)

回答1:

CodeLite assumes that the names you write in Libraries box are values you want to pass to the linker -l option.

The linker option -lfoo directs the linker to search, first in the directories you specify with the -Ldir option, then in its default search directories, for either of the files libfoo.so (a shared library) or libfoo.a (a static library). It stops searching when it finds either one. If it finds both or them in the same search directory it will prefer libfoo.so. The selected library, if found, will be input to the linkage. Otherwise the linker will given an error: cannot find -lfoo.

So, if you've specified a linker search directory - /home/me/other/project/Debug, say - and in the Libraries box you've entered maybe foo.o, bar.o, then the linker is going to search for files:

/home/me/other/project/Debug/libfoo.o.{so|a}
/home/me/other/project/Debug/libbar.o.{so|a}

which don't exist, and is going to tell you: cannot find -l{foo|bar}.o

There is a variation of the -l option, -l:name, which instructs the linker that name is the exact name of the file to search for. So, if you remove foo.o, bar.o from the Libraries box, and enter:

-l:foo.o
-l:bar.o

in the Linker options box, your linkage will succeed (barring other errors).

Of course, foo.o and bar.o are object files, not libraries, either static or dynamic, so coercing the linkage to find them in library search is a bit of a kludge even when you do it right.

It seems that you've written some application project and now you want to write another project to unit-test functions and/or classes employed by the application.

This is a commonplace situation to which the standard solution is three projects:

  • Project A: Builds a (static or shared) library that implements the components to be tested and exports their APIs.
  • Project B: Builds your application, #include-ing the header file(s) and linking the library from Project A.
  • Project C: Builds the unit-test runner, also #include-ing the header file(s) and linking the library from Project A.

Make Projects B and C depend on project A. In CodeLite you can do this with the Build Order project settings.

You'll find this solution more maintainable in the long run than keeping the unit-test runner's linkage options up-to-date with whatever object files are generated by your application.