4

I'm working on a static library project for a c++ course I'm taking. The teacher insists that we define only one function per source file, grouping files/functions belonging to the same class in subdirectories for each class. This results in a structure like:

MyClass
    \MyClass.cc (constructor)
    \functionForMyClass.cc
    \anotherFunctionForMyClass.cc 
OtherClass
    \OtherClass.cc (constructor)

Whether this is good practice or not is something I'd not like to discuss, since I'm simply obliged to organize my project in this manner.

I'm working in visual studio 2008, and somehow got strange link errors when using an identically named function (and thus filename) in two classes. This appears to be caused by the fact that visual studio puts all .obj files (one for each source file) in one intermediate directory, overwriting earlier generated object files when compiling identically named source files.

This could be solved by putting the object files in subdirectories based on the relative path of the input file. Visual studio allows one to configure the names of object files it generates and has macros to use in there, but there appears to be no macro for 'relative path of input file'.

So, is there some way to get this to work? If not, is using one project for each class the best work-around?

TC.
  • 4,133
  • 3
  • 31
  • 33
  • Are you sure VS overwrites earlier generated object files? What link errors do you get? – Serge Jan 04 '10 at 12:33
  • @Serge: As a matter of fact, it actually appears to be skipping compilation after compiling the first source file. I've thrown in an #error in the file where the missing function is defined, and no compilation error comes up. Renaming the file to something different causes the file to be compiled. Regardless: there's only one object file after compiling the project. – TC. Jan 04 '10 at 12:40
  • The only good thing I can see here is that you are being stretched to find out how VS2008 really works, so that you will know where to look when someone else has painted themselves into a corner - a very dark corner. – quamrana Jan 04 '10 at 12:51
  • 1
    @TC: the reason I'd asked is that I've made a test project with two identically named source files in separate directories in VS2005 and it builds just fine. VS adds a '1' at the end of the second object file name (e.g. "test.obj" and "test1.obj"). So maybe the problem isn't where you think it's. – Serge Jan 04 '10 at 13:42
  • @Serge: This is a problem introduced in VS2008 – JoeG Jan 04 '10 at 13:50
  • "Whether this is good practice or not is something I'd not like to discuss". Out of interest, what does the teacher say about overloaded functions? I guess you could use the compiler-mangled name of the function as the filename in those cases, or number them, or something. But I'm curious to know what he recommends, and whether he's even considered function overloading... – Steve Jessop Jan 04 '10 at 14:42
  • @Steve Jossop: He suggests numbering them and putting a comment behind the declaration in the header file, documenting the number. – TC. Jan 04 '10 at 14:47
  • @TC. Ouch. What about operator overloading? Free functions in anonymous namespace? – JoeG Jan 04 '10 at 15:19
  • Operator overloading: "operatorassign.cc", don't know about free functions. – TC. Jan 04 '10 at 15:35
  • This is also answered here: [Visual Studio 2010 & 2008 can't handle source files with identical names in different folders?][1] [1]: http://stackoverflow.com/questions/3729515/visual-studio-2010-2008-cant-handle-source-files-with-identical-names-in-diff – jurujen Apr 16 '15 at 09:29

9 Answers9

8

Real answer:

Change

C/C++ => Output Files => Output File Name

to

$(IntDir)/%(RelativeDir)/

Every .obj file is going to be created in a sub folder so its not going to overwrite the previous on linking.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
ShadowCode
  • 111
  • 1
  • 3
6

You are right, by default all object files are put into the same directory and their filenames are based on the source file name. The only solution I can think of is to change conflicting file's output file path in here:

Project Properties-C/C++-Output Files-Object File Name http://img37.imageshack.us/img37/3695/outputfile.png

PS. It sounds like the lecturer has a crappy (probably written by the lecturer himself) automatic code verifier that imposes this restriction. To get extra marks, offer to rewrite the parser so it works with normal/sane/non-weird projet layout.

Igor Zevaka
  • 74,528
  • 26
  • 112
  • 128
  • 1
    Specifically, Igor is saying you need to right-click on each potentially conflicting file and change its properties. – moswald Jan 04 '10 at 21:54
  • Take a look at http://stackoverflow.com/a/3731577/17349 - it seems you can specify a project wide setting that works around this issue – Stephen Edmonds Aug 02 '12 at 10:44
4

I can't think of any way to fudge the project settings to get VStudio to automatically split out the intermediate files into separate folders.

You have a few chances -

  1. Build the class name into each file name. Most IDE's display just the file name in the tab view so if you do have several methods in different classes with the same name, its going to be difficult to tell them apart if the file name does not include the class name along with the method name. Which is really why I think your teachers advice is madness. I have not seen any programming style guide advocating that approach. Additionally it goes directly against the way various tools work - if you use Visual Studio to create a class, it creates one cpp file and one header, and automatically appends each new function to the single cpp file.

  2. You could create a static library per class. When linking in static libs the obj files are all packaged up inside the .lib so conflicts are no longer a problem.

  3. Switch comp-sci courses to one thats not being taught by a nut job. Seriously, this guy is completely out of touch with industry best practices and is trying to impose their own weird ideas on their students: Ideas that are going to have to be unlearnt the moment they leave the teaching environment.

Chris Becke
  • 34,244
  • 12
  • 79
  • 148
  • 3
    +1 particularly for point 3. Get the hell out of that course, it will do you more harm than good. – Joris Timmermans Jan 04 '10 at 12:33
  • 1
    Unless it's a prerequisite for the good stuff later. Suffering a certain amount of craziness for a worthy long-term goal isn't *entirely* useless experience ;-) – Steve Jessop Jan 04 '10 at 14:37
  • I (TS) am with Steve here. I was self-educated in c++, and the course and its teacher have definitely greatly improved my ability. And there is method to the madness: organizing this way does have benefits (compile time, neat small source files) as well as disadvantages. I just do what I do in any course: be critical, don't blindly adopt everything that's suggested and select the bits I deem useful :) – TC. Jan 04 '10 at 15:45
  • Sometimes even the most unorthodox methods teach us a valuable lesson - how *not* to do things. – AJ. Jan 04 '10 at 21:46
1

You can also change output file name per file in its properties. Just make sure you use different names.

alemjerus
  • 8,023
  • 3
  • 32
  • 40
1

Can you use the class name in the filename to disambiguate? I'm thinking that you might have

MyClass \MyClass.cc (constructor) \function1_MyClass.cc \function2_MyClass.cc

That would mean that every file would have a unique-enough name to defeat the problem. Is that an acceptable strategy?

Michael Kohne
  • 11,888
  • 3
  • 47
  • 79
1

You could probably arrange the properties of the project to put the object files into a folder which is below the folder of each source file. Once the project has this property, then every source file should inherit this property. (But if you've done experiments like Igor has suggested, then you may need to go through the properties as reset them back to the parent).

Having looked at the help files, I think you should go to project properties/C C++/Outpuf Files/Object File Name: and enter $(InputDir) (no trailing backslash). Every source file should then inherit this property and your .obj files should be separated.

You may need to do a Clean Solution before you make any changes.

quamrana
  • 37,849
  • 12
  • 53
  • 71
1
  • Renaming the object files will work, but it's going to be a pain, and it will slow your compile/link cycle down. I've never figured out why, but it seems to confuse Visual Studio if the object files don't have the default names.

  • You could prefix the funciton name with the class name; e.g. myclass-ctor.cc, myclass-function1.cc etc.

  • You could have one .cc file per class which #includes the individual function files. In this case you'll need to prevent the #included files from being compiled seperately (either rename their extension or set Properties->Exclude From Build to 'Yes').

Out of curiosity, where does your teacher want you to put free functions e.g. local helper functions that might normally belong in an anonymous namespace?

If not, is using one project for each class the best work-around?

Not a good idea - apart from the fact that you won't end up with a single static library (without even more jiggery pokery), your link times are likely to increase and it will hide a lot of pertinent info from the optimizer.

On another note; If the course is actually about C++ not OO programming, do what you need to pass but take your teacher's advice with a pinch of salt.

JoeG
  • 12,994
  • 1
  • 38
  • 63
0

In Visual Studio 2010, I set

    Properties -> C/C++ -> Output Files -> Output File Name

to

    V:\%(Directory)$(PlatformName)_$(ConfigurationName)_%(Filename).obj

for OBJ files to end up next to the sources assuming the project lies on drive V (no idea whether there is a macro for it, yet).

By the way: $(InputDir) refers to the solution/project directory and will cause the same problem in another directory.

Dude
  • 583
  • 2
  • 9
0

You don't have to put them in different translation units... why not put each function in a .h and include them all in one .cc per class? That will very likely give better output from the compiler.

I'd be asking why the teacher is insisting on this odd structure, too, the reasoning behind it should be explained. I know you didn't ask that of us, so that's all I'll say.

Andrew McGregor
  • 31,730
  • 2
  • 29
  • 28
  • Show me how you can put two member function _declarations_ into separate header files.... (-1) – xtofl Jan 04 '10 at 13:48
  • The question wants the class (and member) *declaration* in a single header file and each member function *definition* in a seperate source file. That can be achived by having a seperate file for each functino definition that is #included in a single source file. The #included files should not be compiled seperately. – JoeG Jan 04 '10 at 14:08