I have two projects. One called projectA and the other called projectA-tests.
The first project is my actual project, and the second project contains GoogleTest unit tests for classes in projectA.
I have coded one very simple unit test so far and everything builds OK. Note that this first simple test depends on a single .h file of projectA that has only a static class method defined in the same .h file (no .cpp file). It's actually a "StringUtils" class with methods like ::startsWith() and so on.
After adding a second test I'm having linking problems. This second test depends con a Class of projectA that is declared in a .h file and defined in a .cpp file. I'm getting an undefined reference regarding this Class, trying to build this second test.
projectA-tests compiler settings are configured to include projectA/src in project -> properties -> C/C++ build -> settings -> C++ compiler -> includes. (I guess this is why the first compiles ok, because it only requires a .h file which is covered by this "includes" setting).
What I don't know is how to configure the C++ linker in projectA-test to include all .o files of projectA in the linkage process.
I'm more experienced in Java, and the equivalent would be simply adding the other project source folder as dependency of the build path. Whay is Eclipse CDT's C++ equivalent?
Thanks!
Related
I am trying Unit test using Gtest.
I am creating a another project that has file from the original project (By linking) that is to be tested. In the new project I then create Fake Implementation and Mocks of the additional dependencies of the function or Unit I want to test. In the file from the original project I am using #ifdef to include original dependencies or the fake implementation
The problem I am facing is I need to compile the files in particular order so that the fake implementations are included when test project is build.
I am using MCUXpresso on Windows 10 with MinGW, GNU Builder
Anticipating any workaround or way to get control over order in which files are compiled.
#ifdef IsTesting //This is part or original project, original header files
#include "Fake_dependency"
#else
#include "Original_Dependency"
#endif
Then in the new project I define
#define IsTesting true // Part of Test_Project, followed by other code for testing
when I compile the new project or test project I need this file having this variable defined to be compiled first or earlier than the file that I am linking from the Original project
Instead of defining IsTesting in your test code, you can add the definition to your Build Configuration for the test project.
Go to Properties -> C/C++ General -> Paths and Symbols -> Select the appropriate language (GNU C++) and add "IsTesting" (without any value)
If you want Eclipse to get the compiled code right (not compiled code is gray) you will have to toggle
Properties -> C/C++ General -> Indexer -> Use active build configuration as well
I wanted to have one project which would contain common header files that could be used by other projects in the same solution (Unfortunately I cannot accomplish this task). In order to accomplish this task here is what I tried
1-Created a new C++ console application called common.
2-From the properties of this project I changed the configuration type to static Library.
3-I added a simple header file commonheader.h to the project having a class person and built it as a result I got
C:\Users\Raj\Documents\Visual Studio 2010\Projects\Ctest\Debug\Common.lib
4-Now in order to use that header file from a different project I created another project
called Test. And in the properties of test I added Common as a reference
5-I then tried to access the person class however the VS2010 still complains that it cannot find the person class.
Any suggestions on what I might be doing wrong ? . I added the path
C:\Users\Raj\Documents\Visual Studio 2010\Projects\Ctest\Debug\ in addition include addition files of the Test project. Any ideas how I can access the person class
AFAIK the .lib files only contains the compiled source of your implementations, you still need to include the header files themselves to get access to the interface
I have a Visual Studio solution organised like this:
ProjectA // A static library I'm working on
ProjectB // A static library containing UnitTest++ test suites for ProjectA
ProjectC // An executable test runner which links to ProjectA and ProjectB
ProjectB contains two files which look like this:
// RunTests.h
#ifndef RUNTESTS_H
#define RUNTESTS_H
#include "UnitTest++.h"
int runAllTests();
#endif
and this:
// RunTests.cpp
#include "RunTests.h"
int runAllTests()
{
return UnitTest::RunAllTests();
}
As well as several files containing test suites e.g.:
// FooTests.cpp
#include "RunTests.h" //
#include "Foo.h" // From ProjectA
TEST(SomeTest)
{
CHECK(true);
}
ProjectC consists of a single file:
// main.cpp
#include "RunTests.h" // from ProjectB
int main()
{
return runAllTests();
}
The reason I have the tests and the test runner separated, is that I have another project which uses the same tests to analyse code coverage, which I need to keep separate as it is not cross-platform, whereas the test runner is.
The issue is, that when I compile and run ProjectC, no tests are actually run (UnitTest++ runs, but with zero tests). This is because ProjectC does not reference any symbols relating to the tests from ProjectB, so the linker doesn't link the object files from ProjectB.lib.
It is my understanding that if ProjectB was an executable, I would not have this issue (presumably because the linker would link all the object files), as per the documentation:
The general idea is that you keep one Main.cpp file with the
entry-point which calls RunAllTests().
Then you can simply compile and link new .cpp files at will, typically
one per test suite.
Each of the Test*.cpp files will contain one or more TEST macro incantations with the associated
test code. There are no source-level dependencies between Main.cpp and
Test*.cpp, as the TEST macro handles the registration and setup
necessary for RunAllTests() to find all tests compiled into the same
final executable.
How can I resolve this problem without having to declare all the tests in header files that ProjectC can see (which would kill UnitTest++'s ease of use)? One possibility I've noticed in Visual Studio is:
Project Settings > Configuration Properties > Linker > Input > Force Symbol References
However it would be rather tedious to have to add every single symbol, every time I write a new unit test. Is there some way I can force it to include the entire contents of ProjectB.lib? Or perhaps some code-based solution?
EDIT: What I'm looking for is something like this but for Visual Studio.
I was trying to use UnitTest++ the same way you've described and ran into the same problem. I ran across a suggestion in another forum that seems to work for my unittest executable (i.e. ProjectC).
For ProjectC:
Project Settings > Common Properties > (select ProjectB) > Use Library Dependency Inputs: True
This worked for me. I think what this does is effectively link any object files from ProjectB into ProjectC (as opposed to linking the library).
I have a Visual Studio solution containing 2 project: main project and test (via googletest). In main project I have myclass.cpp and myclass.h files. When I'm trying to compile test project, there are bunch of LNK2019 errors when I include "myclass.h" in my test.cpp file, but everything works fine if I include "myclass.cpp" instead. Is that normal? As far as I know, including of .cpp files is not recommended and generally can be avoided. Any suggestions?
It's normal. If you have 2 projects, 2 binaries will be generated.
Don't include the cpp file.
Instead, link the binaries together.
main project - generates .lib file and either .dll or .exe.
test project - includes header from main. You need to add the .lib generated by main in the additional dependencies of the test project. Somewhere in the Project Settings - Linker Options - Additional Dependencies.
You can generate both .exe and .lib file from a single project. To do this you set:
exe in Linker -> General -> Output File
lib in Linker -> Advanced -> Import Library
You may also need to mark exported functions with __declspec( dllexport ) in the .exe project (see docs), otherwise compiler won't generate a .lib file.
Steps to Use Classes form another project (Add header and solver linker errors)
1) To be able to add the header from another project, first go to "Properties > c++ > General > Additional Include Directories" and add the directory that contains the header. Now you will be able to add the header of the class from the other project, but running the project will still cause Linker Errors.
2) Add __declspec(dllexport) before the class you are using for the other project. This can be added in the header file of that class. This should be added right before the function or variable or class name. Now you will get a lib file. (if placed in wrong place, you can get this warning: https://msdn.microsoft.com/en-us/library/eehkcz60.aspx)
3) "Properties > Linker > Additional Library Directories". Specify the location of the lib file that is generated.
4) "Properties > Linker > Input > Additional Dependencies”: Add the name of the lib file.
I'm beginning to tear my hair out over this, so it's time to post here!
I have a C++ project in XCode, built as a Command Line Tool. All .cpp files have been renamed as .mm, there is one .hh and a few .h headers. I've specified 'Compile Sources As -> Objective-C++' in Build Settings.
I have another XCode project for an iOS app. This is set to 'Compile Sources As -> According to File Type'. I can't set it to compile everything as Objective-C++ since some parts of the project won't compile as Obj-C++.
There is one class in the iOS app where I wish to utilise my C++ project, and it consists of files MyClass.hh, MyClass.mm; they were simply .h and .m but I renamed them in the hope of remedying this problem.
I dragged my cpp project into the iOS project. I then added a Target Dependency in the iOS Build Phases to point to the cpp CLI application.
In MyClass.hh I have
#include "../path/to/CppProject/ImportAll.h"
..which is a header file that successively 'include's all headers from the cpp project. I then go about my business, creating one property within MyClass.hh which is a pointer to a cpp object, and various references within MyClass.mm to cpp classes.
The darn thing just won't compile though - I get a ton of messages relating to my cpp classes like this:
MyCPPFile.h:10: error: expected '=', ',', ';', 'asm' or '__attribute__' before '<' token
Is the compiler not recognising that MyClass.hh is Objective-C++ not Objective-C? Should I have a target dependency which is a library instead of pointing to this CLI app, perhaps?
I've googled around for a while trying to solve the problem. I've seen references to people using
#ifdef __cplusplus
or else having to rename files to .mm to get things working, but in other cases people simply say they drag and drop projects across with no issues.
Can someone please enlighten me, and explain what key steps I should be performing to make this work? I'd be very grateful! Thank you.
Thanks to everyone who gave me suggestions.
Having created my projects anew from scratch, I fiddled and logic-ed my way to the solution. Note that - at least in my case - no use of #ifdef __cplusplus was required, nor any other preprocessor directive. Only file suffix changing is essential (as detailed below).
Here's the process:
Create C++ Static Library and Include/Link with Objective-C Library (e.g. iOS app) in XCode 4:
In XCode 4 create a New Project of type Cocoa Touch Static Library. Hereafter we shall refer to this project as 'CProj'.
In CProj workspace create/import as many C++ classes as required. No special suffix for filenames is necessary - all my files are .h and .cpp.
In XCode create/open any Objective-C project e.g. iOS app. Hereafter we shall refer to this project as 'ObjProj'.
Find CProj.xcodeproj in Finder (typically /Documents/CProj/CProj.xcodeproj), drag it onto the visible ObjProj project icon at the top of your XCode Project Navigator (visible file/folder hierarchy on left side in XCode). This now places CProj as a nested project within ObjProj.
Left click ObjProj project icon in Project Navigator, a new pane emerges to the right, left click Build Phases in this pane.
Under Target Dependencies click '+' icon and select CProj library icon below listed CProj project. Click OK.
Under Link Binary With Libraries click '+' icon and select CProj library icon from within Workspace collapsible folder at top of window presented.
File Renaming Rules
Where including a CProj header in ObjProj, use path backtracking to identify import, e.g. #include "../../MyProj/MyImport.h" to step 2 dirs backwards then step into MyProj folder.
Any ObjProj implementation file including a CProj header must be renamed from .m to .mm . Any ObjProj header file including a CProj header must be renamed from .h to .hh .
Any ObjProj file including a file whose suffix is now .hh (consequence of step above) must be renamed in the same manner.
An example:
Consider you have files A.h, A.m, B.h, B.m.
A.m imports B.h, and B.h includes one or more CProj headers. B.m includes type references, using CProj classes included via B.h .
First renaming is B.h -> B.hh since it contains includes.
Then B.m -> B.mm since it contains type references to CProj (no includes necessary since B.h has already done them).
Then A.m -> A.mm since A.m which contained an include for B.h now has an include for the renamed file, B.hh .
P.S. Note that the C++ library doesn't like to auto-rebuild when it should - I often have to 'Clean' then 'Build' in ObjProj after updating CProj from within it.
It sounds like the crux of your problem is this:
Is the compiler not recognising that MyClass.hh is Objective-C++ not
Objective-C?
The compiler is not recognizing that MyClass.hh is Objective-C++ code. Or any other code; the compiler never sees MyClass.hh (in all likelyhood).
By convention, header files are never passed to the compiler by default. Only the source files (.cpp, .m, et cetera) are -- the preprocessor that is run on those files results a translation unit that contains the original source file plus all the included headers and resolved macros.
So the problem is that you probably have a .mm source file that imports MyClass.hh, which in turn includes the C++ header file. But the compiler is trying to compile the resulting translation unit as Objective-C++ and encountering some C++-specific stuff in that header. In fact, I suspect that this problem has nothing at all to do with the additional target dependencies and such that you've got set up: I think you could reproduce it minimally with a very simple Objective-C++ application that includes the header. You should try that and see, it will either confirm my theory (after all I'm just speculating since you haven't shown enough source for me to know for sure) or indicate that the problem is elsewhere.
The solution is probably to use preprocessor guards like #ifdef __cplusplus (there's a useful catalog of predefined symbols here) to hide the C++-specific code from the Objective-C++ compiler (or the other way around in some cases). Note that this may be difficult to impossible to do based on the actual content of the header.