none
Create a static library that can be used in both WinRT and Win32

    Question

  • Hi, I'm trying to build a static library that can be used in both WinRT (Metro) and Win32 (for Windows Server 2008 R2). But I don't know how to deal with inconsistent APIs. For example, in WinRT, you have to use CreateFile2, while in earlier Windows, you have to use CreateFile. Similarly, in WinRT, you have to use Microsoft::WRL::ComPtr, while in previous Windows, you have to use CComPtr.

    I tried to use # ifdef:

    #ifdef METRO
        return CreateFile2(
            lpFileName,
            dwDesiredAccess,
            dwShareMode,
            dwCreationDisposition,
            nullptr);
    #else
        return CreateFile(
            lpFileName,
            dwDesiredAccess,
            dwShareMode,
            nullptr,
            dwCreationDisposition,
            FILE_ATTRIBUTE_NORMAL,
            nullptr);

    #ifdef METRO
            throw ref new Platform::Exception(hr);
    #else
            throw hr;
    #endif

    But the decision is made at compile time, not at link time. Since in the static library project, I don't have METRO defined, it is always compiled as if I target Win32.

    Is there a way to delay the decision until link time? I'd like to define METRO in my WinRT project, and not define it in the Win32 project.


    Sining Oh Blue Star

    Monday, June 11, 2012 10:00 AM

All replies

  • With static libs, you'd have to have separate build configurations for Metro and Desktop.

    The alternative is to just add the code to your main project (that way the conditional macros come into play). But this will slow down build time.


    http://blog.voidnish.com


    Monday, June 11, 2012 1:13 PM
  • Thanks, but what do you mean by "add the code to your main project"? I have two main projects, one for desktop and one for Metro. Do you mean I need to keep two separate code base?

    Sining Oh Blue Star

    Tuesday, June 12, 2012 1:13 AM
  •  

    Hello,

     

    I think you should separate them, the metro need include the winmd file into the library and the native library donot.

     

    So we can build a native library first, this can be used in Win32, then we create a WinRT wrapper to include it into Metro application.

     

    Best regards,

    Jesse


    Jesse Jiang [MSFT]
    MSDN Community Support | Feedback to us

    Tuesday, June 12, 2012 8:07 AM
    Moderator
  • Thanks. Can you elaborate? Let me provide some background.

    At first, I had an existing dll project that worked fine on Windows Server 2008 R2 (where WinRT is not supported).

    Then I tried to port it to Metro, as a custom WinRT component. The process is somewhat smooth, but I had to make a lot of changes. For example, CreateFile vs. CreateFile2, DrawTextW vs. DrawText, CComPtr vs. ComPtr, etc.

    Later I needed to add some new features to both projects, and fix some bugs. Whenever I updated the code, I had to remember to update 2 different places. If I forgot, very quickly the projects will be out of sync. Due to those API inconsistance, I could not simply copy the complete souce code from one project to the other. Everytime I had to check where I should update the code, and whether the update is enough.

    Then I realized I could try to use a single code base. So I created functions like:

    CreateFileCommon()

    {

        // For Win32

        CreateFile();

        // For WinRT

        CreateFile2();

    }

    In both projects, I created a file common.h, and put the above functions inside it. Now most code files can use the same code CreateFileCommon. So the only difference is I need 2 common.h. I also learnt to simulate WinRT's ComPtr using ATL's CComPtr. Something like:

    namespace Microsoft

    {

        namespace WRL

        {

            class ComPtr : public CComPtr

        }

    }

    At this stage, when I updated one project, I could copy everything except common.h to the other project, and it would work fine.

    However, this is still a lot of manual work. Ideally I don't want to copy the source code everytime I do some update. If VC++ allows me to add exising items as link (as we can do in C#), the problem will be solved. But this is not supported in VC++... So I think I need to create a common project, and reference it in both Win32 and WinRT's main project. Dll is not supported in WinRT, and WinRT component is not supported in Win32. So I think a static library is what I need. However, now I have this problem... Many code relies on the functions/classes defined in common.h, yet common.h are different for different versions. Without common.h, my static library project won't compile. But #ifdef only works at compile time, not link time. I have to use two different build configurations (for instance, one with /CX and one without). So it seems I still need two different projects...


    Sining Oh Blue Star

    Tuesday, June 12, 2012 12:29 PM
  • This comment is probably too late, but I've just come across your problem while looking for a solution to one of my own. In any case, I can think of two ways to get out of this situation without having to manually sync two copies of the same source code:

    1) Since you're programming for Win RT, I assume you're using VS 2012 in Win8 and VS 2010 in Win 2k8. Both of these support per-project property sheets for their VC++ directories. This means you could divide your project in three logical parts (you can further split them depending on your project's structure and recursively apply this same solution): common code, win RT code and win32 code. You can then have e.g. one copy of your "common.h" file (though this name obviously becomes inappropriate) in a WinRT folder and another one in the a folder, each one tuned to its own platform, and then have the Win8 project only include this WinRT as part of its VC++ directories, and the Win 2k8 project reference the Win32 folder.

    From your explanations I can't clearly understand whether you aren't doing so already; in case you are, then what copying the source code are you talking about when you're updating?

    2) You could set up some form of source control. That's always a good idea, even for your home projects. Then keep on having two copies of the files common to both projects, but don't worry about it. Have two branches, and have them share all the common files. Whenever you change one project, just push the relevant changes to the other one.

    Friday, July 06, 2012 11:34 PM
  • Write static lib with WRL for winrt instead of C++/CX.


    C++ DX11

    Saturday, July 07, 2012 1:08 PM