views:

417

answers:

7

I'm building a tool in managed code (mostly C++/CLI) in two versions, a 'normal user' version and a 'pro' version.

The fact that the core code is identical between the two versions has caused me a little trouble as I want to package the resulting tool as a single assembly (DLL) and I don't want to have to include the .cpp files for the common code in the projects of the two versions of the tools. I'd rather have a project for the common code and a project for each version of the tool and have each version of the tools project depend on the common code and link it in as desired.

In unmanaged C++ I'd do this by placing the common code in a static library and linking both versions of the tool to it. I don't seem to be able to get this to work in C++/CLI. It seems that I'm forced to build the common code into a DLL assembly and that results in more DLL's than I'd like.

So, in summary, I can't work out how to build the common code in one project and link it with each of the final product projects to produce two single DLL assemblies that both include the common code.

I'm probably doing something wrong but I tried to work out how to do this using netmodules and whatever and I just couldn't get it to work. In the end the only way I got it working was to tell the linker to link the build products of the common code assembly rather than the results which works but is a bit of a hack IMHO.

Anyway, does anyone have any suggestions for how I SHOULD be solving this problem?

Edited: I guess I should have mentioned the fact that the assemblies generated are not 100% managed code, they contain a mix of managed and unmanaged code as is, probably, quite common with assemblies produced with C++/CLI...

A: 

That's the downside of the .Net compilation process, you can't have things like static libraries and the header files that hold them together, everything is held in one big dll file and the only way to share information is to either build a common dll and reference it from other assemblies or to duplicate the code in each dll (possibly by copying/linking .cs files between projects).

Note that the 2nd way will declare different types, even though they have the same name. This will bite you on the ass with stuff like remoting (or anything that requires casting to specific shared interfaces between processes).

Blindy
Can you explain a little more about your second paragraph. Are you saying that if I have the linker link the common code assembly's build products into the final assembly then I'll have these problems?
Len Holgate
Yea, that's why when you do remoting, the common interfaces are held in a 3rd .dll file referenced by both the server and the client programs. Having a type with the same name and structure in 2 different assemblies creates 2 different types altogether, unlike unmanaged C++ libraries which hold no meta-data and so see the same structured type in both versions of the program.
Blindy
+2  A: 

If you are annoyed at all the DLLs, download ILMerge. I use this to bundle together multiple DLL's into an easy-to-use .EXE for my clients.

Paul McGuire
Thanks, I'll take a look.
Len Holgate
I guess I probably should have mentioned that one of the assemblies isn't 100% managed code... ILMerge doesn't work with it :(
Len Holgate
Paul, I've accepted this answer as it's the best answer for situations where there's no unmanaged code in the assemblies. I'm still looking for a solution that works with mixed assemblies. I haven't investigated the 'modules thing' yet.
Len Holgate
A: 

Remotesoft Salamander will hook you up. It's basically a native compiler and linker.

AngryHacker
Thanks, looks a little expensive for what I want but I'll take a look as it may also solve my obfuscation requirements...
Len Holgate
Again doesn't handle mixed managed/unmanaged assemblies...
Len Holgate
+1  A: 

As said ILmerge is one way, personally if your bundeling some exe with a lot of dll's I favor Netz.

Nils
Thanks Nils, I'll try it out!
Len Holgate
1) Looks like it needs the output to be an exe (my application is packaged as a dll).2) Doesn't handle mixed managed/unmanaged C++/CLI assemblies.
Len Holgate
1) yes - it can't handle "dll-only" packaging.. 2) Have you had a look on "mkbundle" (see other answer) - cygwin may be a rather strange prerequisite but IMO mkbundle does handle managed/unmanaged mixes - BUT: I havn't acually tried it. (always wanted, tough)
Nils
I haven't tried mkbundle but right now getting to the point where I can try it (i.e. have the time and inclination to get all of the prerequisites installed and working) will take a while.
Len Holgate
A: 

When using mono (or cygwin is an option) mkbundle may also be a valid choice.

Nils
A: 

You could use modules. You can link them into an assembly using the assembly linker, al.exe.

Anton Tykhyy
I tried that and couldn't get it to work, do you know of a non trivial example of how to set this up? Ideally so that the code can be built with VS2008 and the modules merged with a custom build step?
Len Holgate
No, I don't know. Modules are pretty esoteric.
Anton Tykhyy
+1  A: 

If I'm understanding this correctly, you have a solution which contains two projects. One project for the "normal" user and one project for the "pro" user. Visual Studio allows you to add a "link" to another file source from another project. If your "pro" version has the real core code file, and in your "normal" version you add existing -> find the file in the "pro" project, and click the down arrow by the Add button and select "Add as Link". Now you have single file that is literally the same between two projects.

Erik Philips
Erik, That might work, though it's a bit of a pain from a scalability point of view (i.e. not easy to add another project that depends on 90% of the code in project 1). I'll give it a go.
Len Holgate
True, but I would imagine the scalability problem is only going to be in an issue between different normal, pro, etc versions. If you're going to write code against your own DLL, I'd imagine you're going to use the pro version :).
Erik Philips