I have a static library written in C++ that I want to make available to Windows 8 and Windows Phone 8 applications written in .NET.
I'd like to minimize the number of separate projects to maintain by setting up my solution something like the following:
Attempt #1: Only UI projects are platform-specific
MySolution.sln
|
+- Library (virtual folder to group projects below)
| |
| +- LegacyLib.vcxproj Static Library project - Platform-independant, native C++ code using STL & CRT. Just enough C++/CX to make some types available to .NET and expose a few static methods.
| |
| +- LegacyPcl.csproj Portable Class Library project - References LegacyLib, adds some types, wrappers, interfaces, etc. written in C#.
|
+- SampleApp (virtual folder to group projects below)
|
+- CommonAppSrc Platform-independant C# source code (e.g. MVVM classes for Model and ViewModel).
|
+- SampleApp_Win8.csproj Platform-specific App project - References LegacyPcl, includes files from CommonAppSrc using "Add as Link".
|
+- SampleApp_Wp8.csproj Platform-specific App project - References LegacyPcl, includes files from CommonAppSrc using "Add as Link".
Problem: It seems that Portable Class Libraries don't support the inclusion of native C++ code in any form.
One suggested way of including native C++ in your Windows 8 and Windows Phone 8 apps is by creating a Windows Runtime Component. Unfortunately, WRC projects targeting Win8 and Wp8 are different project types; there is no option to create a Windows Runtime Component that targets multiple platforms.
So, creating a Windows Runtime Component project for each target platform yields the following:
Attempt #2 - UI projects are platform-specific, and so is LegacyLib wrapper
MySolution.sln
|
+- Library (virtual folder to group projects below)
| |
| +- LegacyLib.vcxproj Static Library project - Platform-independant, native C++ code using STL & CRT. Just enough C++/CX to make some types available to .NET and expose a few static methods.
| |
| +- LegacyWrc_Win8.csproj Platform-specific Windows Runtime Component project - References LegacyLib, adds some types, wrappers, interfaces, etc. written in C#.
| |
| +- LegacyWrc_Wp8.csproj Platform-specific Windows Runtime Component project - References LegacyLib, adds some types, wrappers, interfaces, etc. written in C#.
|
+- SampleApp (virtual folder to group projects below)
|
+- CommonAppSrc C# source code (e.g. Model and ViewModel classes).
|
+- SampleApp_Win8.csproj Platform-specific App project - References LegacyWrc_Win8, includes files from CommonAppSrc using "Add as Link".
|
+- SampleApp_Wp8.csproj Platform-specific App project - References LegacyWrc_Wp8, includes files from CommonAppSrc using "Add as Link".
Problem: When I try to reference LegacyLib from the LegacyWrc_Win8 project; I see the following warning:
Adding reference to 'LegacyLib' is not recommended because it is not compatible with Windows Store Apps.
The build environment is saying that to make the LegacyLib static library compatible with my Win8 Windows Runtime Component, I must enable Windows Store App Support in the LegacyLib project configuration (ignoring the warning only results in an error later on):
Project Properties > Configuration Properties > General > Project Defaults
Set Windows Store App Support to Yes
Next, when I try to do the same thing with the LegacyWrc_Wp8 project, I get the following error:
A reference to 'LegacyLib' cannot be added because the two projects target different platforms.
So, making the static library compatible with Windows 8 made it incompatible with Windows 8 Phone.
Looks like it's simply not possible to build a single static library that can be consumed by these two different platforms, even though the library itself contains no platform-specific code.
I don't necessarily have to maintain parallel versions of the source code, but I have to create/maintain two separate projects that each build a platform-specific version of the static library.
My solution now has a platform-specific version of every project:
Attempt #3 - EVERY PROJECT is platform-specific
MySolution.sln
|
+- Library (virtual folder to group projects below)
| |
| +- NativeCode (virtual folder to group projects below)
| | |
| | +- CommonLibSrc Native C++ source code using STL & CRT. Just enough C++/CX to make some types available to .NET and expose a few static methods.
| | |
| | +- LegacyLib_Win8.vcxproj Platform-specific Static Library project - Includes files from CommonLibSrc using "Add as Link".
| | |
| | +- LegacyLib_Wp8.vcxproj Platform-specific Static Library project - Includes files from CommonLibSrc using "Add as Link".
| |
| +- DotNetWrapper (virtual folder to group projects below)
| |
| +- CommonWrcSrc Platform-independant C# source code (types, wrappers, interfaces, etc. for LegacyLib support) for the Windows Runtime Component projects.
| |
| +- LegacyWrc_Win8.csproj Platform-specific Windows Runtime Component project - References LegacyLib_Win8, includes files from CommonWrcSrc using "Add as Link".
| |
| +- LegacyWrc_Wp8.csproj Platform-specific Windows Runtime Component project - References LegacyLib_Wp8, includes files from CommonWrcSrc using "Add as Link".
|
+- SampleApp (virtual folder to group projects below)
|
+- CommonAppSrc Platform-independant C# source code (e.g. Model, ViewModel).
|
+- SampleApp_Win8.csproj Platform-specific App project - References LegacyWrc_Win8, includes files from CommonAppSrc using "Add as Link".
|
+- SampleApp_Wp8.csproj Platform-specific App project - References LegacyWrc_Wp8, includes files from CommonAppSrc using "Add as Link".
Problem: None that I can see so far (other than the fact that this is ugly and higher-maintenance).
BTW, I did look into the possibility of using Build Configurations, but they're already being used for combinations of Debug/Release and x86/ARM. Adding Win8/Wp8 into the mix just doubles the configurations again, and you've shifted, rather than reduced the maintenance burden.
Am I missing something? It seems like this is a common thing to want to do. Has anyone else gone through this and come up with alternate/better ways of doing this?
EDIT FOR COMPLETENESS
Here's what I ended up doing...
MySolution.sln
|
+- LegacyApiLib (virtual folder to group projects below)
| |
| +- CommonCppSource Common C++ source code used by LegacyWrc_*.vcxproj projects
| | below
| |
| +- LegacyPcl.csproj Portable class library with C# API interfaces only; no
| | implementation classes.
| |
| +- LegacyWrc_Win8.vcxproj Platform-specific Windows Runtime Component project - includes
| | legacy C++ files, and uses C++/CX to expose static methods and
| | classes to .NET in Win8.
| |
| +- LegacyWrc_Wp8.vcxproj Platform-specific Windows Runtime Component project - includes
| legacy C++ files, and uses C++/CX to expose static methods and
| classes to .NET in WP8.
|
+- SampleApp (virtual folder to group projects below)
|
+- SampleAppBL.csproj Portable class library containing the app's business logic.
| References LegacyPcl.csproj for legacy API interface definitions.
| Business logic is written against those interfaces; never against
| specific classes. The Win8 or WP8 apps will reference the
| appropriate Windows Runtime Component project, create or register
| the concrete classes that implement the legacy API interface, and
| either pass it into the BL or register it with IOC mechanism. In
| this way, SampleAppBL.csproj never has to know about (or
| reference) any of the WRC projects.
|
+- SampleAppUI_Win8.csproj Platform-specific App project - References LegacyWrc_Win8.vcxproj
| and SampleAppBL. Contains minimal platform-specific Win8 UI code.
|
+- SampleAppUI_Wp8.csproj Platform-specific App project - References LegacyWrc_Wp8.vcxproj
and SampleAppBL. Contains minimal platform-specific WP8 UI code.
I realized that the few helper classes that LegacyApiLib exports could be written in managed C++ instead of C#. This meant that I could just bundle them with the WRC projects, which simplified things a bit.
As you've found, the native library needs to be compiled separately for each platform, so it can't be directly referenced from a Portable Class Library.
I'd suggest using the abstraction pattern to allow you to share most of your .NET code (ie models and view models) via a Portable Class Library. In a PCL, create interfaces or abstract classes for the functionality that you are exposing in the native library. Then implement those in platform-specific projects that forward the calls onto the native library. Finally use dependency injection to hook up the implementations of those interfaces so you can call them from your shared PCL.
Here are a few blog posts that cover this:
Using Target-Specific Code in a Portable Library
How to Make Portable Class Libraries Work for You
Related
Never have known if this is even possible - and if so - how?!!
But I have our MFC applications separated out into the exe project, and a set of associated resource-only .dll projects, one per translation.
We only need to maintain English, and then parse the resources using a 3rd party translation suite to extract translatable strings, get them translated, and then constitute a translated resource .dll project for shipping.
It's a neat coherent system but for the fact that I cannot use MSVC's built-in MFC editors to connect up visual interfaces back to the correct code in the .exe project files.
If I try to use the resource editor to - e.g. generate an MFC Dialog subclass as the code-behind for a given Dialog resource - then the MSVC environment tries to create such files in the resource .dll project - which is wrong and unhelpful.
Does anyone know of a technique to get a given resource project to say "Hey - all of my code-behind should be in this other project over there?
I have a number of very useful extension methods that I'd like to use in my Silverlight project.
I've pasted the Module here http://pastebin.com/TfBpNDWr
The problem I'm having is that visual studio complains that the dlls my module have been written against have not been built against the Silverlight runtime.
Is there an easy way to get these extension methods working in Silverlight?
I'm thinking my main hurdle is getting IObjectSet and ObjectContext to run against the Silverlight run-time - perhaps there's another way to expose these methods that I'm not aware of.
When you want to reuse code in such way, there are these three options I'm aware of:
Generally create all your basic class libraries as a Silverlight class library project, or, more officially, as a Portable Class Library. Throw all references out except for mscorlib.dll, System.dll and System.Core.dll. You can then link such kind of library in any full .NET project.
You can link individual code files from another project with the "Add as link" feature (Right click project -> Add Existing Item -> Change "Add" Button to "Add as link"). That way you can create a Silverlight project and link individual files from your full .NET project. However that can get tedious if you have a lot of files and you often add/remove files and folders in your source project.
To cure this problem, you may check out the Project Linker at http://msdn.microsoft.com/en-us/library/dd458870.aspx ... but I haven't tried it myself yet.
I have two projects which share quite a portion of logic, localizations, properties and even views (Logindialog, Popovers etc.). I now want to put the intersecting set into a new project, which should be used as some sort of common library.
I want to keep the common project as a git submodule in my other projects:
Project A
- Classes
- Resources
- CommonLibrary (git submodule)
Project B
- Classes
- Resources
- SomeBSpecificFolder
- CommonLibrary (git submodule)
The CommonLibrary would now probably also be it's own Xcode project. I am not sure now how I should tackle this problem. I know of the following options:
Use a library (.a-file and .h file)
TestFlight e.g. does it like this. I quite like the fact that I can just compile against a binary and don't "see" the source. So just a clean API for doing things.
Include the whole project (Project dependency)
Three20 does it like this and I find it quite annoying to have some 6 subprojects in my project. However in my case it would only be one project, so this might be an option too.
Just have loose source files without a project inside the CommonLibrary folder and manually add them to both of the projects. The project would then compile the sources along with any project-specific sources. This looks a big like a workaround to me and I guess I would prefer to somehow bundle the common sources. Also if there are new files, I always have to add them to the other projects.
Can you guys give me some advice and tell me if there is another option or what you think are the advantages and disadvantages about these approaches?
Thanks a lot for your help!
From a clean, non-application specific perspective, you should be looking to create a library/ framework. This provides:
the reusability you want
without extending build time of dependent projects,
while maintaining consistency of the code base (maintainability),
keeping your API consistent across using projects and
managing dependencies between layers
In terms of Xcode, if I remember correctly from my OpenStep days, you should be looking to create a new Framework project which will provide the relevant makefiles for that type of project. A cursory surf produced:
http://developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPFrameworks/Tasks/CreatingFrameworks.html
and the slightly more friendly:
http://atastypixel.com/blog/creating-applications-in-xcode-using-frameworks/
Furthermore, you might actually want to layer your frameworks to further improve reusability. That is, don't just create one framework, create one per tier: put common code in a Foundation framework, UI/ AppKit-based classes in a UI framework, etc. This way, your frameworks are relevant to whatever tier your using classes and projects live.
For instance, if you have a category on some foundation class, put it in a common/ foundation framework that can be reused by any other common/ foundation classes and projects you build. If you were to put it in a UI-tier framework with UI libraries and dependencies then it couldn't be reused by your foundation level projects (as these can't have UI-level dependencies).
Hope this helps...
I found a project called RestKit on github which seems to be a good example for a third-party framework, which can be included in an existing project.
The readme and the wiki describe nicely which steps need to be done in order to include the project. I guess this is a good starting point for someone who want to create a framework himself.
I have a working Windows Forms app (split into an EXE and a few DLLs). Now I've been asked to look at creating another app (MyAppLite) that has only a very small subset of the functionality. Think of it as similar to MS Word Viewer vs. MS Word.
Everything that I need to build MyAppLite is contained in the main solution - essentially I need to use a couple of the WinForms and whatever bits in the DLLs they call into.
What would be the best way to do this?
I was thinking of creating another Project in my solution for MyAppLite, then adding the necessary source files as links (using Add Existing Item > Add As Link in Solution Explorer).
I definitely wouldn't want to maintain 2 copies of the source code.
FYI it's a .NET 2.0 VB app, using VS2008.
You can create a new class library to contain your forms that are common to both projects. Create the new project and copy the forms from the original project into the new class library. Then you can import the class library into both the original project (after removing the original versions of the forms) and the MyAppLite version. If you need to change the forms, change it in the class library and then recompile your applications
You could refactor your project so that it would keep the common functionality in a MyAppCore project, and reference that from both MyApp and MyAppLite. The core dll would contain all the common functionality and take parameters as to what to allow and what to restrict, so the set of features in your lite version is customizable(say you have a customer that reaaaallly wants a preview of a certain feature).
Where can I obtain a complete listing of all NS-based classes?
As far as I recall, the Foundation, AppKit and Core Data frameworks contain all of the non-deprecated NS* classes. You can find the references for Foundation, AppKit, and Core Data on developer.apple.com or in the documentation installed locally with the Apple Developer Tools (use Xcode's Help->Documentation). For a list of all of the "Cocoa" frameworks, start here.
Xcode -> Help -> Documentation: look under AppKit Reference and Foundation Reference. I'm sure there's similar documentation on apple's dev website.
You will find an overview of both Foundation class hierarchy and Application Kit class hierarchy (grouped by topics) in the Cocoa Fundamentals Guide.
There is a free app that Andy Lee wrote that is very useful for quick method reference, called AppKiDo:
http://homepage.mac.com/aglee/downloads/appkido.html
It gives you the option of including individual frameworks in your search results.
If you just want to bang out a list of ALL objective c based classes just open up terminal a run
grep -Rho "#interface [a-zA-Z]\+" /Applications/Xcode.app/Contents/Developer/Platforms | cut -d" " -f2 | awk '!a[$0]++' | sort
You will need Xcode installed.
This will take a while but covers all platforms (macOS, tvOS, watchOS etc).
To just target a particular platform adjust the path accordingly.
So for just macOS change:
/Applications/Xcode.app/Contents/Developer/Platforms
to:
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk
or you could narrow it further to a particular framework. This will also work for protocols. Just change the #interface for #protocol.