views:

261

answers:

5

Here is my folder structure:

/
|
 -- program.cpp
 -- utility.h
 -- utility.cpp
|
 -- module/
    |
     -- utility.h
     -- utility.cpp

// Note that I have two files named utility.h and two named utility.cpp

On building the project, I get a link error (LNK2028: unresolved token and so on...) saying that some symbols aren't defined. I have confirmed that all symbols are defined and that all declared functions have a corresponding definition.

I have a feeling that on compiling my project, the utility.cpp files from both folders are compiled into the same utility.obj in the output folder. As a result, one overwrites the other.

  1. Is this expected behaviour?
  2. How do I build a C++ binary which has two files with the same name (though in different folders)?
+2  A: 

You could try adding another project to your solution, which will build a static mudule.lib file from your module's .cpp .h, then link your main project with that lib. It should make VS to output .obj files in a separate directory, and you should be able to link without problems.

Dmitry
A: 

Maybe libraries (static or dynamic) would help with your case. But you will still have problem if there are any public symbols with the same name like in executable or other library.

Dominic.wig
A: 

I don't know the VS compiling chain.

However, each .cpp is first compiled into a .obj file. The linking steps merges them together.

It's very common, to put all the .obj files in a same directory. So, as you guessed, when compiling the second one, erases the first one. Therefor some symbols are missing during compilation.

There probably is an option (again, I don't work with VS) to leave the .obj in the same directory as the .cpp file. The drawback is some garbage on your source code tree.

My personnal opinion would be to refactor.

Tristram Gräbener
+1  A: 

Do you really WANT two different but same-named files in the same project?

mickeyf
Sure. The `utility.h` and `utility.cpp` in the sub-folder add functionality specific to the feature implemented in that folder.
Vulcan Eager
You often don't have a choice if you are including other utilities in your build.
Martin Beckett
+5  A: 

Right click both/either .cpp files > properties > C/C++ > Output Files > Object File Name > set a custom name. e.g. if both files are named MyFile.cpp in folder A and another in folder B, you can set the output to be AMyFile and BMyFile.

Alternatively, you can also use a macro to prefix the object names with the immediate parent folder name (i.e. using $(IntDir)\$(SafeParentName)$(SafeInputName)). If this is not enough (e.g. you have A/B/MyFile.cpp and C/B/MyFile.cpp) and you don't mind having some object files cluttering your source tree, you can also use $(InputDir)\ which will put the object files in the same folder as the source file.

the cpp files will then be compiled into two different object files..

enjoy!

btw, if the contents have the same name, do you separate them using different namespaces?

namespace A { // in folder A
    class CMyFile {};
};

namespace B{ // in folder B
    class CMyFile {};
};

// client.cpp
#include "A/MyFile.h"
#include "B/MyFile.h"
int main() {
    A::CMyFile aMyFile;
    B::CMyFile bMyFile;
    return 0;
}

I don't know if it matters but it's definitely clearer to human : D

afriza
This is the solution - but be warned, for some reason have different names for the .cpp file and the .obj file dramatically slows the compile/link cycle down. I've no idea why.
Joe Gauterin
This *should* work and *should* be the solution, but it didn't work for me. VS would create both .obj files but would try to link in only one of them.
Michael Burr
I take it back - reloading the solution seemed to make this technique work (like it should). +1. VS is being touchy for me this morning for some reason.
Michael Burr
@afriza, AMyFile and BMyFile... looks like hardcoding. Is there a macro which I can use to insert the relative path of the `.cpp` as part of the path of the '.obj`?
Vulcan Eager
@agnel-kurian what about $(SafeParentName)$(SafeInputName) ? Thus, the complete path will be $(IntDir)\$(SafeParentName)$(SafeInputName). But this will not work if the files have same ParentName (immediate parent folder name). Thus, if you don't mind to clutter your source code folders, you can use $(InputDir)\$(SafeInputName) instead, which will put the object file in the same folder as the source files.
afriza