views:

156

answers:

3

Direct Question: If I have two files with the same name (but in different directories), it appears that only Visual Studio 2005 can handle this transparently?? VS 2008 & 2010 require a bunch of tweaking? Aside from my naming convention, am I doing something wrong?

Background:

I'm developing C++ statistical libraries... I have two folders:

/ Univariate

Normal.cpp
Normal.h
Beta.cpp
Beta.h
Adaptive.cpp
Adaptive.h

/ Multivariate

Normal.cpp
Normal.h
Beta.cpp
Beta.h
Adaptive.cpp
Adaptive.h

I need to support cross compilation -- I'm using g++/make to compile these same files into a library in Linux. They work just fine.

I had been using Visual Studio 2005 without issue, but I need to upgrade to Visual Studio 2008 or 2010 (currently drooling over nVidia's nsight tool). However, I'm having trouble if I add files to a project with the same name (even if they're in a different directory). I'm willing to change my naming convention, but I'm curious if others have encountered this problem and have found any well documented solutions??

I'm further boggled by the fact that if I upgrade from 2005 projects to 2010 projects, it appears that VS 2010 is able to correctly handle two source files with the same name in different directories; however, if I remove one of the duplicate files and then add it back to the project I am greeted by the following warning:

Distributions\Release\Adaptive.obj : warning LNK4042: object specified more than once; extras ignored

Now I have the intermediate directory specified as $(ProjectName)\$(Configuration) -- I need to have my object files in a different location from my source tree. So I can see why it's copying the object files on top of each other, but when the projects are converted from 2005 to 2008 or 2010, a bunch of conditional compiles are added:

<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)%(Filename)1.obj</ObjectFileName>
<XMLDocumentationFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)%(Filename)1.xdc</XMLDocumentationFileName>

These are accessible from the Source file Properties page in C/C++ -> Output Files -> "Object File Name" & "XML Documentation File Name". But if I simply add the file directly (or remove and re-add them), VS doesn't complain until I try to compile, but also never adds the conditional directives -- So in order for things to work correctly, I have to add the conditional directives myself for every single configuration. Am I making a mistake / poor assumption or have I uncovered a valid bug in VS 2008 / 2010?

+4  A: 

You're right, VS can't handle that, and never could. The root problem is that it generates a .obj file for each .cpp file in the project, and they're all placed in the same folder. So you end up with multiple .cpp files compiling to Adaptive.obj in your case, for example.

At least the linker generates a warning for it now. That wasn't always the case.

You should be able to work around this by ensuring the files use different Intermediate Directory paths, but it is a bit of a hack around something that ought to be possible.

Of course, you could always file a bug report or feature request on it on Microsoft Connect

jalf
I think there might already be [a bug for this](http://connect.microsoft.com/VisualStudio/feedback/details/361228/visual-c-compilers-only-one-file-of-two-with-the-same-name). One of the recommended workarounds there is to manually change the generated object file name for one (or both) of your object files. You should be able to override this for all configurations at once, so it shouldn't be too tedious to implement.
Mike Ellery
Thank you for the suggestion, I submitted this to Microsoft Connect. It was previously a bug as Mike Ellery noted, but the tech claims it was to be fixed in 2010 -- I can confirm that it was not. If you or someone else has the ability, feel free to link the two reports: <a href="https://connect.microsoft.com/VisualStudio/feedback/details/599534/unable-to-compile-by-default-files-with-the-same-name-in-different-directories">VS 2010 Bug Report</a>
M. Tibbits
+2  A: 

This is easy to fix in the IDE. Click the first file in the folder, Shift+Click the last file so all of them are selected. Right-click, Properties, C++, Output Files. Change the Object File Name from $(IntDir)\ to, say, $(IntDir)\Univariate\. You can repeat for the Multivariate file group although that's not strictly necessary.

Hans Passant
A: 

So @Hans Passant pointed in the right direction, Thanks!! You don't have to list the file, a folder is sufficient. Then if you look in the defined macros at the bottom of the VS 2010 list, you'll see:

%(RelativeDir)/ Univariate/

The problem, as posted, was actually a simplified version of what I'm working on -- a couple of levels of folders in a single project and there are a couple of name conflicts. Hence, I really wanted someway to just "fix" it...

If you right click on the project in the solution explorer, choose C/C++ -> "Output Files" and type the following into the "Object File Name" box:

$(IntDir)/%(RelativeDir)/

Note that I also selected (All Configurations, All Platforms) from the drop downs. This will compile every file in a directory hierarchy which mirrors the source tree. VS2010 will begin the build by creating these directories if they don't exist. Further, for those who hate white space in their directory names, this macro does remove all spaces, so there is no need to play around with double quotes when using it.

This is exactly what I wanted -- identical to the way my Makefiles work on the Ubuntu side, while still keeping the source tree clean.

M. Tibbits
I have since tried this in Visual Studio 2008 and it does not work. I tried several modifications and can't find a solution beyond just altering the properties of each file separately with its unique relative path.
M. Tibbits