Setting DefineConstants dynamically via MSBuild import - msbuild

I have an .msbuild import that defines a property group containing preprocessor definitions, among other things:
<PropertyGroup>
<DefineConstants>$(DefineConstants);MY_CONSTANT_VALUE</DefineConstants>
</PropertyGroup>
This is <import>ed into both csproj and vcxproj files. At build time, the C# preprocessor appears not to have visibility of the defined constants. However, an equivalent C++ preprocessor definition in the same file works correctly, and the constants are discovered:
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>$(PreProcessorDefinitions);MY_CONSTANT_VALUE</PreprocessorDefinitions>
</ClCompile>
<ItemDefinitionGroup>
Any ideas why this only works in C++?

Default property group declaration doesn't cater about previously existed properties and defined like this:
<DefineConstants>TRACE</DefineConstants>
So make sure you are importing your .msbuild file at the end of your .csproj.vbproj, not in the beginning.
If this doesn't help - can you provide a log of msbuild with diagnostic level of verbosity and post link here.

Related

Problems with midl.exe and cppwinrt.exe from CMake

This is somewhat of a follow-on to How to use midlrt.exe to compile .idl to .winmd?
I have this in my CMakeLists.txt . My questions are less about the CMake logic and more about the output of the midl and cppwinrt commands, and subsequent errors in compiling and linking. I suspect maybe I'm missing some command-line options.
# Pathnames for WinRT References
set (WINSDKREFDIR "$ENV{WindowsSdkDir}References\\$ENV{WindowsSDKVersion}")
# Remove trailing \ from $ENV{WindowsSDKVersion}
string (REGEX MATCH "[^\\]*" WINSDKVER $ENV{WindowsSDKVersion})
# COMMAND lines wrapped in this post for readability, not wrapped in the actual CMakeLists.txt
add_custom_target (MYLIB_PREBUILD ALL
COMMAND midl /winrt /ns_prefix /x64 /nomidl
/metadata_dir
"${WINSDKREFDIR}windows.foundation.foundationcontract\\3.0.0.0"
/reference
"${WINSDKREFDIR}windows.foundation.foundationcontract\\3.0.0.0\\Windows.Foundation.FoundationContract.winmd"
/reference
"${WINSDKREFDIR}Windows.Foundation.UniversalApiContract\\8.0.0.0\\Windows.Foundation.UniversalApiContract.winmd"
/out "${MYDIR}\\GeneratedFiles" "${MYDIR}\\MyClass.idl"
COMMAND cppwinrt
-in "${MYDIR}\\GeneratedFiles\\MyClass.winmd"
-ref ${WINSDKVER} -component -pch "pch.h" -out "${MYDIR}\\GeneratedFiles"
)
add_dependencies (MYLIB MYLIB_PREBUILD)
In the cppwinrt command, I've tried different forms of -ref [spec] and -pch options, but seem to get the same results regardless. These are the problems I've run into:
MIDLRT generates a header file "MyClass.h" with several problems:
It #includes <windows.h>, which ultimately #defines preprocessor macros for GetClassName and GetCurrentTime that cause compiler errors in WinRT functions with those names.
I spent some hours tracking that down and learning to compile with #define COM_NO_WINDOWS_H to prevent that.
It #includes non-existent *.h files from WinRT References Contracts directories instead of the Include directories:
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Foundation.FoundationContract\3.0.0.0\Windows.Foundation.FoundationContract.h"
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Foundation.UniversalApiContract\8.0.0.0\Windows.Foundation.UniversalApiContract.h"
So I made a copy of this file and replaced those with
#include <winrt/Windows.Foundation.h>
CPPWINRT generates "module.g.cpp" that #includes "MyNamespace.MyClass.h", but does not also generate that .h file. It does generate "MyNamespace/MyClass.h" (note "/" instead of "."), so I created the former .h and simply #include the latter .h from it.
CPPWINRT doesn't generate all of the base headers that I see in Microsoft examples. It generates only headers directly related to MyClass -- e.g., defining the template base class winrt::MyNamespace::implementation::MyClassT<>, the wrapper winrt::MyNamespace::MyClass, etc.
winrt::MyNamespace::factory_implementation::MyClass is not defined. MyClassT<> is defined there, but not MyClass. I find a paradigm for that from a Microsoft example and paste it in:
// Missing from the generated stuff -- derived from a Microsoft example:
namespace winrt::MyNamespace::factory_implementation
{
struct MyClass : MyClassT<MyClass, implementation::MyClass>
{
};
}
I received compiler warnings about inconsistent definitions of CHECK_NS_PREFIX_STATE: in some places it was "always" and in other places it was "never". So now I #define MIDL_NS_PREFIX and #define CHECK_NS_PREFIX_STATE="always"
Now the build gets through the compiler, but I have unresolved external symbols in the linker. I think these things are supposed to be defined inline in a "winrt/base.h", but cppwinrt did not export such a file (as I see in Microsoft examples), and the equivalent file in the system directory contains only prototypes, not bodies:
WINRT_GetRestrictedErrorInfo
WINRT_RoInitialize
WINRT_RoOriginateLanguageException
WINRT_SetRestrictedErrorInfo
WINRT_WindowsCreateString
WINRT_WindowsCreateStringReference
WINRT_WindowsDeleteString
WINRT_WindowsPreallocateStringBuffer
WINRT_WindowsDeleteStringBuffer
WINRT_WindowsPromoteStringBuffer
WINRT_WindowsGetStringRawBuffer
WINRT_RoGetActivationFactory
WINRT_WindowsDuplicateString
Am I missing some simple thing that would resolve all of these problems with missing, incomplete, and incorrect generated files?
The unresolved external symbol errors indicate that you are missing an import library. In this case you will want to link against the WindowsApp.lib umbrella library, that exports the required symbols.
Note that the symbol names you are observing are an artifact of C++/WinRT's requirement to build with as well as without the Windows SDK headers. It addresses this by declaring the imports (with a WINRT_ prefix to prevent clashes with the SDK header declarations), and then maps the renamed symbols using the /ALTERNATENAME linker switch.
I'm not sure this is going to solve all of your issues, but you certainly would want to add ${MYDIR}\\GeneratedFiles to your additional include directories. That should take care of the inability to include the generated headers from the winrt subdirectory (base.h as well as the projected Windows Runtime type headers).
cppwinrt also writes stub implementations for your own types into ${MYDIR}\\GeneratedFiles\\sources, when it processes the .winmd file previously complied from your .idl(s). It's unfortunate, but there's a manual step involved here: You need to copy the generated .h and .cpp files to your source tree, and implement the skeleton implementations. This is required whenever you modify one of your interface definitions.
As a note, the module.g.cpp files generated for my projects do not include any of my custom type headers. Maybe you are using an older version of C++/WinRT (I'm using v2.0.200203.5). I believe this was changed with the introduction of type-erased factories in C++/WinRT version 2.0. Unless you are doing this already, you should use cppwinrt from the Microsoft.Windows.CppWinRT NuGet package as opposed to the binary that (used to) ship with the Windows SDK.

Is there an include once command for cmake files?

Does anyone know a simple way to apply the "include once" pattern in CMake files? In C/C++ it used to require a #ifdef / #endif pair in the beginning and end of the header file until #pragma once became common. Of course, it's possible to do the same in CMake, but I thought it'd be nice if it didn't require an explicit conditional statement.
Re-edition: It seems that the return() command should do it. And I'd define a macro like this:
macro(include_once)
if (INCLUDED_${CMAKE_CURRENT_LIST_FILE})
return()
endif()
set(INCLUDED_${CMAKE_CURRENT_LIST_FILE} true)
endmacro()
Use the macro in the beginning of your file, without any arguments. Because it's a macro, the return is from the include command for the file, not from the macro itself.
Notice that the created variable has an odd name, but CMake seems to accept this.
I used to use the logic that others have suggested as the solution. Then I learned that cmake has this functionality built in.
Take a look at the include_guard() command. I believe this will do what you want.
New in version 3.10.
Provides an include guard for the file currently being processed by CMake.
include_guard([DIRECTORY|GLOBAL])
Sets up an include guard for the current CMake file (see the CMAKE_CURRENT_LIST_FILE variable documentation).
CMake will end its processing of the current file at the location of the include_guard() command if the current file has already been processed for the applicable scope (see below). This provides functionality similar to the include guards commonly used in source headers or to the #pragma once directive. If the current file has been processed previously for the applicable scope, the effect is as though return() had been called. Do not call this command from inside a function being defined within the current file.
An optional argument specifying the scope of the guard may be provided. Possible values for the option are:
DIRECTORY
The include guard applies within the current directory and below. The file will only be included once within this directory scope, but may be included again by other files outside of this directory (i.e. a parent directory or another directory not pulled in by add_subdirectory() or include() from the current file or its children).
GLOBAL
The include guard applies globally to the whole build. The current file will only be included once regardless of the scope.
If no arguments given, include_guard has the same scope as a variable, meaning that the include guard effect is isolated by the most recent function scope or current directory if no inner function scopes exist. In this case the command behavior is the same as:
if(__CURRENT_FILE_VAR__)
return()
endif()
set(__CURRENT_FILE_VAR__ TRUE)
The simplest guard pattern against multiple module's inclusion would be
if(<something-which-is-defined-in-your-module>)
return()
endif()
E.g., if your CMake module defines a function foo_func, you may use this guard:
if(COMMAND foo_func)
return()
endif()
Do you actually need a guard?
Depended on things, defined in the module, the module may require protection agains multiple inclusion or not.
In many simple cases a guard is not needed: the module's code will work even when included multiple times.
But in some other cases, wrong protection may break the usage of the proptected module.
A module defines a function or a macro: guard is not needed.
CMake allows to define the functions and macros many times.
A module defines a constant variable: guard is not needed.
Like with function, CMake allows to define the variable many times.
But if you use guard in that case, it should check variable, not a function:
if(foo_var)
return()
endif()
This is because functions have global visibility, but variables have local visibility. That is, if you module will be included into other subtree, the function will be already visible in that subtree, but the variable is not.
A module defines a global variable via set(CACHE): guard is needed only if variable is defined as set(CACHE INTERNAL).
Variables defined via, e.g., set(CACHE STRING) or find_library don't require guards.
A module defines global property: guard is needed.
Note, that if your module uses simple (not CACHE) variable as global, it cannot work in multiple subtrees, so guard should be
if(foo_var)
message(SEND_ERROR "Module <...> cannot be included twice")
endif()

Set MSBuild properties on Build target input items based on metadata

I'm using a code-generation tool (Entity Framework, in this case) in one of my projects, and it generates code that causes the compiler to emit warnings. I'd like to ignore those warnings for a particular set of files. My first thought was that I might be able to set up an ItemGroup to set per-file properties for the compiler, something semantically like this:
<ItemGroup>
<Files Include="Migrations/**/*.cs">
<Properties>
<DisabledWarnings>CS12345;CS4321</DisabledWarnings>
</Properties>
</Files>
</ItemGroup>
I recognize that this isn't valid MSBuild syntax, but it expresses the essence of what I'd like to do.
This question seems somewhat related: Using Item functions on metadata values
Is there a way to do this?
You can't use MSBuild to disable compiler warnings per file. Instead, you need to use #pragma statements in the code.
For example, lets say you wan to disable warnings about usage of obsolete APIs (build warning CS0618). You can surround the code like this to suppress the warning.
#pragma warning disable CS0618
public void Method()
{
new Class1().CallSomeObsoleteMessage();
}
#pragma warning restore CS0618
Alternatively, you can disable warnings for an entire project.
<PropertyGroup>
<NoWarn>$(NoWarn);CS0618</NoWarn>
</PropertyGroup>

module.map for accessing (Swift and Objective-C) classes in main target from test target

I am in the process of adding Swift classes to an existing Objective-C project. As part of this, I have added a MyProjectTests.swift to the target MyProjectTests. It imports Swift classes from target MyProject with import MyProject and that works just fine.
I now want to use #import Swift; in MyProjectTests.mas well. However, the compiler issues the error Module 'MyProject' not found.
I have these questions:
Make both import and #import succeed in test target
Why can it be the case that the Swift compiler sees module MyProject but the Objective-C compiler does not? What build settings in MyProjectTest do I have to change to make #import MyProject succeed as well.
Export Objective-C classes from main target
Ultimately MyProjectTest.swift and MyProjectTest.m also need access to Objective-C classes from target MyProject. So far I have multi-targetted such files, but I want to switch to using modules also here.
My current understanding is that this is a matter of providing a module.map file which would list header files for the classes I wish to "export".
What are the exact steps I have to go through? Where should I place the header file and which build settings do I need to change in the two targets MyProject and MyProjectTests?
I currently have a (so far empty) module.map inside my project and build settings for target MyProject include Defines Module: Yes, Product Module Name: MyProject.
UPDATE I am by now wondering whether it might be impossible to expose (Objective-C) files from an iOS application (instead of framework) project as a module. But then it already seems to work for Swift files (somehow).
I've by now concluded that this is not possible with current Xcode (6.1.1) tooling. (What a waste of time!)
The old scheme of bi-targeting source files to both MyProject and MyProjetTest also presents several challenges for a mixed Objective-C/Swift project with a non-trivial amount of code:
Its Objective-C part defines a legacy NS_ENUM(Integer, Repeat) which name-clashes with Swift.Repeat<T>. Referring to it as MyProject.Repeat (not MyProjectTests.Repeat) causes problems when compiling for target MyProjectTests, which changing this target's Project Name (also) to MyProject (not: MyProjectTests) does not seem to solve.
Compilation of constructs where Swift class A employs Objective-C class B, which in turn employs Swift class C does not seem to be possible in a straightforward way. Since the compiler has not yet produced MyProject-Swift.h with the definition of C, it cannot compile B. But since it cannot compile B it cannot compile A and therefore cannot produce MyProject-Swift.h. Catch 22, or so it seems.
Bi-targeted Swift code imports Swift classes from auto-generated MyProject-Swift.h. For the target MyProjectTests this name does not apply, yet that's what it is in the source files. I did not want to go down the road of changing MyProjectTests' Project Name (see above). Importing the right auto-generated file via the targets *.pch may be possible, but then it may be not ...

after importing '.h' into the '.m' file, are they FOREVER linked?

I have a CarClass.h file that declares CarClass.
I then #import this CarClass.h file into my CarClass.m file where I of course then go on to implement all my CarClass methods.
Finally, my CarAPP.m file (which contains the main) ALSO #imports CarClass.h - and everything works just fine.
Ss there are actually no problems there :-)
However, I'm not sure I understand WHY it works - cause the linkage seems a little off: if CarAPP.m imports ONLY the CarClass.h file - without also importing the CarClass.m file, then where does it GET or SEE the implementations from?
Is it the case that once the ".m" file - which imports the ".h" file - is compiled, then the two files (.h and .m) are sorta forever linked or something?
I just don't get it...
The compiling process is split in different phases, and #import directives are interpreted long before any linkage occurs.
When you give code files (.c, .m) to your compiler, it will try to generate a code object file (.o) from it; that is, a binary representation of your code. This file is not yet executable because it needs more information. Especially, it's not linked to any other file. Header files, supposed to contain only declarations and no definition, typically don't get their own matching .o file.
After all your code files have been made into code objects, the compiler will put them all together and invoke the linker. The linker will resolve all external references, and then will produce an executable file.
The point is that header files tell the compiler that a function or method exists somewhere. This is enough at the current phase of compilation to produce object files: the compiler just needs to be told what exists, not where's the definition. Only when you actually link you need to know this.
Since all your code object files get packaged together, your whole program gets access to everything that was publicly declared within itself. This is why you don't need to explicitly "link" CarAPP.m against CarClass.m.
It's also possible to mislead the compiler and declare functions in header files that not defined anywhere. If you use them in your program, the first phases of compilation will go just fine (no syntax error, no "undeclared function") but it will break at link-time, since the linker won't be able to locate the nonexistent function.
When you have #import whatEver.h, the pre-processer tries to finds the corresponding file in the default location. If found, it just pastes the content of the whatEver.h to the corresponding source file where ever you use #import whatEver.h. So, to get a final executable, your source files should pass Pre-Process, Compile and Linker stages.
When you have CarClass.h in CarAPP.m, the linker goes to find the implementations of CarClass.h in CarClass.m. Strictly, speaking it goes to find the definitions in CarClass.o. Compiler is happy as long as there are declarations of what you use and the linker is happy as long as there are definitions for the declarations when you intend to use.
When you import CarClass.h to your CarAPP.m, you are saying to linker to find the CarClass.h method implementations in CarClass.o. So, your final executable is a combination of CarAPP.o and CarClass.o. To understand more about how compiling and linking is done, Program Compilation. Though link is C/C++ specific, it should give you an idea.