Compile symbol not used when building via MSBUILD? - msbuild

I have a project where I have added a compile symbol (MYSYMBOL) in the project properties. When building from VS it works just fine and the application acts accordingly.
Other projects has various symbols defined this way.
When building from MSBUILD, MYSYBOL is for some strange reason ignored and the application acts as if it was never set.
I tried adding /p:"DefineConstants=MYSYMBOL" to the msbuild call, but then the build fails as it seems to replace the other symbols of each project with this one alone, so one assembly e.g. requires MYSYMBOL + OTHERSYMBOL but now only gets MYSYMBOL.
This is strange since it actually does use OTHERSYMBOL for those projects that have it, when building via msbuild.
Does anyone have a clue what could be causing MYSYMBOL on the project properties not to be used when building via msbuild?

Turned out that the build script has stated a set of compiler symbols on its own, overwriting the ones in the separate project settings which in turn caused this issue.
As far as I understand, you can't add one or more compiler symbols since anything you state replaced the symbols of the projects.
Ended up having to pass every symbol every project in the entire solution uses.
Too bad :(

You will want to add a new symbol to the list of DefineConstants (as opposed to overriding the entire list of DefineConstants). This will do what you want:
<PropertyGroup>
<DefineConstants>MYSYMBOL;$(DefineConstants)</DefineConstants>
</PropertyGroup>

Related

In VS2022, how do I specify a conditional compilation symbol for a build configuration?

In VS2017, I had several different build configurations that built an application in different ways. One configuration would produce the default application. Another build configuration would produce the application with more features, etc.
This was done in the source code with #if FEATURE blocks. FEATURE was defined in the Conditional compilation symbols for a project's build configuration.
Now, I ported the code to Visual Studio 2022. It appears that the Conditional compilation symbols are now part of the project and not part of the build configuration. So I have to define FEATURE for the project and not the build configuration.
I've used #if FEATURE to put in attributes to classes and methods, so I can't replace this with a simple if statement in the source code.
I don't want to change the project settings every time I need to build the different applications.
What is the workaround for being able to build a project with different compilation symbols easily?
Realise this is a year old now, but I've been looking at conditional compilation symbols this morning.
First, have a look at this: https://learn.microsoft.com/en-gb/dotnet/csharp/language-reference/compiler-options/language
The <DefineConstants> section deals with conditional compilation.
Edit the .csproj file directly, and in any applicable property group you can define constants that you can reference in code. e.g.
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<DefineConstants>MYDEBUGCONSTANT</DefineConstants>
</PropertyGroup>
Then in code you can use:
#if MYDEBUGCONSTANT
// Some debug code
#endif
I had some issues with the conditions on the property groups, VS2022 got a little confused when two of the property groups applied at the same time. Once I sorted that everything worked as expected.
Hope that helps?

Auto generated Swift.h file keeps being not found

A number of times now the auto generated Swift.h file that's required to use swift code in objective-c is not being found.
I've removed and reinstalled Xcode. Made sure all the correct boxes for it to be generated are checked and that I'm using #objc on Swift classes.
Sometimes it works fine but then there are significant periods where for an unknown reason its no longer able to find that file.
The app does build successfully, but the editor after building claims the file is missing.
The project this is being used in has multiple targets but I've made sure that the Swift.h file is using the same name in all targets.
At this point it seems there is no way to consistently have the file be available for auto completion purposes.
Any suggestions on what else to try would be appreciated as I'm at a loss.
After seeing this issue occur randomly a number of times I discovered that I needed to build all the targets for this app. Doing that meant that the -Swift.h file that was missing was now available.
I had one target that I wasn't building as that app which was part of the project wasn't being actively worked on, but building that was the solution to the problem.

CMake: Remove header dependency

Is there any way to make CMake "forget" about a file in the dependency tree? My original problem (to avoid the XY situation) is the following: I want to timestamp the build of a set of tools which have complicated dependencies among them and to other tools. Right now, I want to use a pure timestamp, but later I might want add some info from the repository (SVN). Whatever system I end up implementing needs to have the following characteristics (my "X"):
No unnecessary rebuilding: the executables should not be rebuilt on every make if the only change would be the timestamp.
Update on any change: if any tool is going to be rebuilt or relinked, either by changes to its code or to one of its dependencies, the timestamp needs to be updated.
My current solution goes along the lines of creating a custom command+target that invokes CMake at make time (so the command calls CMake itself with -P script.cmake) to generate a timestamp.h file. The main files of my tools would include that file, and the projects would depend on the target so that it gets rebuilt first.
However, this has its drawbacks: if I do update the timestamp file on every call to make, then CMake's dependency scanner would know about that file even if I do not list it as an explicit dependency of my tools. Thus, every make would trigger at least a recompilation of the respective "main" files and the corresponding relink. With tens of tools, this means slowing down the build when I may be working on just two or three of them at once.
So, I was thinking that my solution would be to somehow make CMake forget about that file when building its dependency tree for the "main" file of each tool. I would keep the dependency on the custom target that does depend on the file, so that it would be regenerated first on each call to make. However, the build tool would not consider that file as relevant to determine whether it is necessary to actually rebuild each individual tool. Thus, tools only with other changes would be rebuilt (satisfying my first criterion), and any change that causes a rebuild of a tool would obviously use the version just generated (fulfilling the second criterion).
To my chagrin, I have not found a way to make the dependency scanner forget about this file, so my solution cannot be put to use. How would I go about doing such a thing? Is it even possible, or is it completely the wrong way to go about this? I am using CMake 3.4, and my code is currently C++, but I would like a solution that did not rely on C/C++ specifics, since I have a different project (written in Fortran) in which I would also like to have build timestamping.
I've had almost the same problem than you are. Simply solved by pushing the timestamp header file into standalone target containing only this header generator command. After that you have several choices:
1.. Exclude that project from the build by the IDE you are using. For example, for the Visual Studio you can do it by several ways:
1.1. Project->Project Dependencies...->uncheck project with that header (not always works: Error while removing project dependency in VS2010)
1.2. Build->Configuration Manager...->uncheck project with that header
2.. Create an environment variable and use the condition with that variable around the add_dependencies command in the CMakeLists.txt file.
3.. Generate 2 standalone solutions through the cmake generator with included and with excluded add_dependencies in the CMakeLists.txt file.
I've used particulary [1.2]. When i need build and debug, then i uncheck the dependecy. By default, dependecy always checked, so there is no problem to miss timestamp build for a build server.
Note:
The timestamp header will be included in all projects you want to include that header (for example, through the add_library and add_executable) and you still can observe it in the IDE under a project item menu even if a project depends on the timestamp project indirectly. This is useful if you don't want to search for the timestamp project with the header to open it from there and want to open it from any project which has included that header.
So, in case of removing the timestamp header from the add_library or add_executable you won't have that opportunity.

Is every single file compiled in Objective-C?

I would like to know, which code is compiled when i build the project in Objective-C - every single line of code in my project, or only those, that are called from the main.c and then from the ones that are called from them?
I mean, does the compiler separate the project to the simply connected domains and compiles the one that is linked to the main, or it just compiles it all?
Thank you, guys!
The compiler does not perform semantical analysis on your code. It compiles exactly what you tell it to compile -- Xcode generally invokes the compiler in a way that it compiles every file into your application. However, it's unnecessary to compile/link the files from which no classes/functions are used; although not compiling files from which you use classes/functions results in a linkage error (that is, the compiler won't be able to find some symbols in the binary file while putting together the object code for the final executable).
All files in your project get compiled, except for the header files that are not included from any of the .m files, or headers the inclusion of which is suppressed conditionally.
A Xcode project consists of one or more targets.
For each target you can define, what *.m-files get compiled
if you add a new file to the project, you can specify to what target it will be added. (actually this is a place, where I often see, that the main target is not selected — beware)

Why can I use some environment variables in some of the elements in the csproj file but not others in msbuild?

What reasons could there be for the following strange behaviour, and how might I track down the issues?
We use a combination of make files and msbuild.
I have a project which needs to be strongly named. I was previously setting the snk to use in the project file like this:
<AssemblyOriginatorKeyFile>$(EnvironmentVariable)TheKeyName.snk</AssemblyOriginatorKeyFile>
where EnvironmentVariable was defined in the batch file that launched the shell for the build like this:
set EnvironmentVariable='SomePath'
and this worked ok. Now I need the string name key to be able to be changed, so it can be different on the dev machine and the release build server. There is a variable which exists to hold the full path to the strong name key file, called StrongNameKeyFile. This is defined in the msbuild environment, and if I put some text output in the targets or properties files that are included as part of the msbuild task which build the project then I can see that this StrongNameKeyFile points to the correct location. So I changed the csproj to have this instead:
<AssemblyOriginatorKeyFile>$(StrongNameKeyFile)</AssemblyOriginatorKeyFile>
but when I try and compile this is evaluating to empty and no /keyfile is specified during the build.
We also have variable defined in the make files and these can be accessed in the csproj as well. These are used to point to the locations of referenced dlls, so that they can be different on dev and build machines. I know that these are set as the references come out correctly and everything compiles, but if I try and use one of these variables in the AssemblyOriginatorKeyFile element then it evaluates to empty in that element, but works in the reference element.
Why might this be? Is AssemblyOriginatorKeyFile treated specially somehow? How can I go about tracking the cause of this down?
There's no good reason why this should happen - as you know it normally Just Works; it's likely to be something in the chain dropping it on the floor.
One thing to try is explicitly passing it via /p:StrongNameKeyFile=XX - that would eliminate environment variables and the correct propagation thereof from your inquiries.
Another potential thing is that something is clobbering the variable as the name is used vy something else?
Run with /v:diag and you'll get dumps of all the inputs and/or variables as they change.
Or if on V4, use the MSBuild Debugger
And buy the Hashimi et al MSBuild book