Configuring Visual Studio Custom Build Tool properties from Premake5 - visual-studio

In the project I'm working on, I need to process certain filetypes with a custom command (building assemblies, namely, due to certain plugin / toolchain limitations, which are beside the point). This is configured from our premake script:
filter { "files:*.extension" }
buildcommands("blah.exe %(FullPath) --my --args")
buildoutputs("$(OutDir)%(FileName).obj")
The project will fail to build unless I set the Properties -> Custom Build Tool -> Link Objects property to No for each individual *.extension item. (These should not be linked as part of the custom step anyway.)
How can I configure this particular property from our premake script without resorting to hacks? (e.g. Anything similar to xcodebuildsettings)

Looks like a more recent master of premake supports a linkObjects file configuration function that does just that (not yet in the docs). Up we date...
Until then, one possible hack is to use buildmessage("false") then do a find-replace all in the generated project files for the Message XML tag to LinkObjects.

Related

How incorporate a MSBuild custom task into Visual Studio solution?

I have a project where there are files in a particular non-standard textual format. When these files are touched/modified, I want to run a certain custom compiler on them to generate XML, which is part of the output of the whole solution.
I'm considering creating a MSBuild task to do this. It will take as input the non-stadard file names and output the requisite XML files. The task will then be used in the other projects in the solution.
I want new developers on this project to have minimal setup. That means, I want to be able to take a clean copy of my solution directly from source control and have the build first build the custom task, then apply it as necessary to the other projects in the class.
I'm concerned that the build output of the project that builds the custom task needs to copy its output assembly to some known location so that the other projects can refer to it. What is the proper way of going about doing this?
You're about to walk into a mess here, because Visual Studio is going to lock the custom task Assembly when it's first used, thereby causing any further builds in Visual Studio (i.e. Build > Solution) to fail.
As #stijn commented, you should override the Build target and use another method of building the assembly with the custom task, e.g. using the Csc task or spawning another MSBuild.exe process (see answer to linked question).
The way I decided to go though was to create a separate solution, e.g. "Build Tools", containing the custom task assembly (among other tools), and required that it be built before anything else. I personally find the notion of checking-in prebuilt binaries of this source very unpalatable. If developers didn't want to build the Build Tools solution, they would copy the output from some nightly build.
Unfortunately there isn't an easy way of getting around "hardcoding" a known (relative) location. Using $(SolutionDir) usually works - just not if you try to run MSBuild on the project directly, instead of the solution (VS is a bit more intelligent when you open a project by itself).

$(shell some-command) equivalent for Visual Studio project macros?

With Makefiles I'm used to being able to write things like:
includedir=$(shell pg_config --includedir)/server
to run an external program, pg_config, with argument(s) --includedir, and include the result in a variable or as part of a variable. So if pg_config --includedir output /usr/include to stdout, the value of includedir would become:
includedir=/usr/include/server
Is there any way to do the equivalent with a Visual Studio project? Run a command, get the result, and substitute it into a property?
I find myself having to edit properties pages all over the place - changing the include directories and library directories for both the x86 and x64 configurations of a project whenever I want to build an extension against a different PostgreSQL version. It is intensely frustrating.
I want to be able to put something like this into Configuration Properties -> C/C++ -> General -> Additional Include Directories:
%(shell pg_config --includedir)
or even better:
%(shell %(PG_CONFIG) --includedir)
where %(PG_CONFIG)'s location is defined in a single place for each platform in the project.
So I'm looking for at least user-defined macros, and preferably the ability to invoke a command line tool and replace the macro with the resulting standard output.
(Preferably in a way that doesn't involve delving into semi-documented UI elements that move and get renamed in every VS version, and that appear and disappear from the various Express editions).
This has been possible in Makefiles for 20 years, there must be a way to do it in VS, right? Or do "Real Windows Developers" generate their VS projects with scripts and build them using MSBuild?
I've looked at some similar questions without finding much of use, e.g.:
Visual Studio - Where to define custom path macros?
In particular, I'm aware of property sheets (View -> Other Windows -> Property Manager), but they don't seem to provide a way to set a value in just one place, they're still per-configuration and per-architecture, so if you have four configurations and two architectures it gets awkward. Unlike with the normal project property editor you can't even apply a change across a group of architectures/configurations, either.
I could use a VS extension, but they require installation into the user's VS, can be version-specific, and seem like a very big hammer for a small problem.
I find myself having to edit properties pages all over the place
That bugged me to no end as well. Property sheets to the rescue! When setting up a major solution in VS10, for example, I had every project pull in a settings.props that contained the common settings, made in only one place. Then go through all the generated or imported projects and kill any explicit value (even if blank) for everything possible. That way things will inherit from property sheets. Select "all configurations" and on each properly use the drop-down to "inherit from...".
I have property sheets for each special library too, just defining the proper #define, include paths, lib paths, etc. Projects that use that particular external lib simply use that property sheet. Users are told, in the worst case, to “edit the XML to change the path to where you have Boost”.
As for setting such a properly to a dynamic determined value, you can do that too. There are property functions you can use.
It sounds like you're going down the same path as I did.
More notes: “prop sheets are per configuration/platform”: If you include a prop sheet at the top-level node for the project itself (not the Debug|Win32, etc. child nodes) it will include it into all current configurations at once. If you edit the properly page, you can choose Multiple or All configurations on the Property dialog box, just as with the usual project use of the Property dialog.
“Custom user macros are well hidden” A property page shows up for that when in a property sheet you created, but not when opening property dialog on a proj file as in the normal File View. The macro will be set in one place (the prop page) and usable as a $(name) in all projects that include it, and even in other property pages that come later in the evaluation sequence.
Let me know how it goes. You should be able to do everything you asked.
—John
In addition to #jdlugosz's answer:
It looks like the traditional way to do this with Visual Studio, before the advent of property functions, was to write a new MSBuild Task. The task can potentially do things like modify a property sheet.
MSBuild supports "inline tasks" where the task code is in the MSBuild project file, rather than a separate assembly, so it might not be neccessary to create a new subproject just for the task.
There are a bunch of built-in tasks, like Exec and CreateProperty that may be useful.
The docs say that:
[The Exec task] is useful when a specific MSBuild task for the job that you want to perform is not available. However, the Exec task, unlike a more specific task, cannot gather output from the tool or command that it runs.
... but that seems to be outdated/wrong so you don't need horrible workarounds.
So, prior to .NET 4.5 I'd probably have to write a custom task for this simple job, because there's no way to feed the command stdout/stderr into the CreateProperty task or have Exec create a property directly. But in 4.5 it looks like I can do it directly. At least in VS Express support for tasks etc is very limited so you'll probably land up editing the XML.

Automatically specify build configuration settings for multiple generic QtCreator projects

I would like to automatically generate *.creator, *.files, *.includes, and *.config files for each of several hundred projects in a large workspace. I would like each project to build using an external tool via a custom build kit and set of build configurations. From what I've read about QtCreator, it seems to me that the only way to do this would be either to generate the *.creator.user file for each project in advance and include the necessary build configurations, or to open each project, allow QtCreator to generate the *.creator.user file for that project, and then insert the build configuration information into the file. Rather than generating or retroactively editing an entire *.creator.user file, I'd like to generate something like a *.pro.shared file (http://doc.qt.digia.com/qtcreator-2.4/creator-sharing-project-settings.html) that could be identical for every project and wouldn't require messing with all the other user settings. Unfortunately, it doesn't appear that there is any analogous *.creator.shared file that can be used by QtCreator to incorporate shared settings. Is there a better way to approach this problem?
The build settings are basically the reason why you can not share a .user file: They contain references to data that is specific to one Qt Creator instance. These are mostly ids for Qt versions, tool chains and kits.
You can create .user files, there should be no problem with that, provided you insert the ids that are used in your creator instance. If you do it wrong, then creator will just throw away those settings and then regenerate them using default values.
Make sure to include ProjectExplorer.Project.Updater.FileVersion or creator will update your configuration using a series of transformation steps, which will most likely break everything (provided you did not start out with data compatible with Qt Creator version 1.3:-).

How to emulate /p msbuild parameter in Visual Studio build?

That the logical follow-up for the my previous question: "How to check all projects in solution for some criteria?"
I was given quite a good answer to use CustomAfterMicrosoftCommonTargets, CustomBeforeMicrosoftCommonTargets. They do work, so I decided not to stop in the middle.
Issue is that I don't want machine-wide tasks. It's not a good idea neither for me (it will affect other builds. sure, this can be handled, but still), nor for my teammates (I don't want to let them put something in system folders... ), nor for build server.
What is needed: solution to be built from scratch out of source control on clean machine with either Visual Studio or MSBuild.
It appeared that Custom*MicrosoftCommonTargets are regular properties.
So, how to specify this property? It works pretty fine when to set it from command line.
That's strange, but it appears that bit of magic present here: property passed as command line parameter to one build is transitively passed to all nested builds!
That's fine for build server. But this won't work with Visual Studio build. And even declaring solution-level property won't help: neither static, nor dynamic properties are transfer to nested builds.
...I have a hacky idea to set environment variable on before solution build and erase it on after. But I don't like it. Any better ideas?
I use a bit different technique then #Spider M9. I want that all projects in solution tree/all subdirectories from current directory use extended build throw Custom*MicrosoftCommonTargets. I don't like to be forced to change every new project to import custom targets/props.
I place special file, let's say msbuild.include, in the root directory and my custom targets loader for every project tries to find it in ., ..\, ..\..\, and so on. msbuild.include contains flags that triggers execution of custom actions. If loader can't find this file it disables loading all custom targets and stoppes. This gives me ability to use my build extensions with projects from work repositories and to not use with opensource projects.
If you are interested in I can publish loader. It's a pretty simple and elegant solution.
For example I can sign any assembly in all projects in all subfolders with my key.
I always set up every project to import a standard .props file. Use the GetDirectoryNameOfFileAbove property function (see MSDN) to find it. Do this as the first line of every project file. Once established, you can redirect from that file to other imports. Another trick is to have that standard import (that would obviously be under version control) import conditionally another .props file only if it exists. This optional file would not be in version control, but is available for any developer to create and modify with their own private/temporary properties or other behavior.

Run a Visual Studio custom tool at build time

I have a script that will convert a text file into a resource file, so that I can have multiple language support by having text files for different languages converted into different resources. Once I run the script to get the resx file, I then have to run a custom build tool (as described here:Link to Code Project) in order to create the Designer.cs files to use the new files.
In keeping with the philosophy that I should be able to build the entire project with a single button click, how can I remove the step where I have to explicitly call the custom build tool in order to make the codebehind files?
I've tried automatically deleting the Designer.cs files as a pre-build step, since I would think that the custom build tool would automatically run if there were no Designer.cs files, but no dice.
So, I want my build script in Visual Studio/msbuild to do:
1) convert text to resx (done)
2) move resx files to appropriate directory (done)
3) create designer.cs files using a custom build tool (not done)
It's that last step...
Unfortunately I don't think there's an easy way of doing this. Custom Build Tools only run from within VS.NET - they don't run when you build your project using MSBuild from the command line.
In general, if you have the choice of writing a build tool as a Customer Build Tool or an MSBuild Task then choose the MSBuild Task every time as these Tasks will run in VS.NET and from the command line.
The designer.cs files for resources are there to support your coding. They give you the strongly typed access into the resource file. So, as long as you create your culture invariant resources in VS.NET (and let it create the .designer.cs files) then adding additional language support later (additional .resx files) should work fine.
If, however, your text files are your primary resource files, and you're adding new resource strings into these text files first, then you'll need to find another way of generating .cs files that allow you to code against those resources. If you HAD to, generating the .designer.cs file yourself (or somethign similar) wouldn't be that difficult. Using CodeDom or T4 you could create the helper class, using an existing .designer.cs file as a template.
There is a way to generate the *.Designer.cs for *.resx as part of the build process. There is a built-in MSBuild task GenerateResource, which basically a wrapper around the SDK tool resgen.exe. Here you can find an example how to use it.
Another thing you would find useful, if the generated *.Designer.cs version is not correct, basically, GenerateResource task is not calling the desired version of resgen.exe, setting property SdkToolsPath might help you.
Have you tried adding a Exec step in Before/AfterBuild step in your csproj? You have to manually edit the file for this, but that should solve your problem.
I'm not fully clear on if you want this done before or after the build. If you need it done sometime after Pass1/Pass2, you can hook into the targets directly. Try looking into Microsoft.Build.Common.Targets to get a feel for how to do this.

Resources