📜 ⬆️ ⬇️

syncProj - utility for generating Visual Studio C ++ projects

syncProj is a utility for generating Visual Studio C ++ projects.


Hey. I want to share the experience of writing a project generator for Visual Studio.


In general, up to this point, I myself actively used premake5 - and, in principle, I would still exchange it, but I still occasionally ran into non-joins and direct bugs in premake5. Repairing premake5 did not arouse much enthusiasm, since premake5 is based on the scripting language Lua, and this is another programming language with its own ways and gags. Our company is dominated by C ++ and C #, I thought, why not try something new and make it concisely and neatly.


At some point I experimented with C # and knew that C # can be compiled and run in the manner of a script without any special problems - well, I thought that I would generate a C ++ project through a C # script.


First I dug up the Solution (.sln) file format, then the C ++ project file format (.vcxproj) - in principle, there was nothing special about them, just the data. Microsoft probably never officially published the data file formats anywhere, it was necessary to partially search for information, partly the reverse engineer itself.


It was necessary to sketch out some kind of class model .vcxproj projects - and the model itself is currently very close to .vcxproj, not the most optimal model, but it is easier to load Solution and Projects - everything is loaded semi-manually, and partially through C # reflection.



But let's start with the simplest script:


test.cs: //css_ref syncproj.exe using System; partial class Builder : SolutionProjectBuilder { static void Main(String[] args) { solution("out_test"); platforms("Win32", "x64", "ARM", "ARM64"); project("out_test_windows"); platforms("Win32", "x64"); files("test.c"); filter("Debug"); defines("_DEBUG"); filter("Release"); defines("NDEBUG"); } //Main }; //class Builder 

I thought why not stick with the syntax premake5, and do similar functions - so if in premake5 we have {{_DEBUG}}, then in syncProj this is the function call - ((_DEBUG));


I tried to stick to the absolute minimum, so syncProj does nothing extra.


In principle, I do not know whether syncProj will become popular, whether community support will be, and so on, so I didn’t want to make plans for the future and make the utility simple and minimal. Although along the way, I added features that I do not consider most necessary, but for example C # (.csproj) did not add support (although this is not difficult).


Almost immediately, the development spun around C # scripts, and then it became possible to debug the scripts themselves from Visual Studio.


Tools> Extensions and update, in the Online Gallery you can find "CS-Script Tools", which allow you to debug C # scripts, without having to create projects.


Such tags as // css_ref, // css_include are taken directly from the C # script, and I myself made their support via Regex.


Naturally, with command line, project generation occurs like this:


> syncproj.exe test.cs


test.cs:


3 files updated


If we compare the utilities with each other, then cmake also generates a custom build action, where cmake is launched on CMakeLists.txt. In premake5, this does not happen automatically, but you can write the same thing through the definition of custom build step. In syncProj, I made a special command for this — for example, projectScript (”test.cs); configures this custom build step.


image

The most interesting thing that should happen if one .cs script, for example, is divided into two files - test.cs and helpers.cs, where test.cs points to helpers.cs via css_include - in theory, if you change at least one, you need to generate projects again. At the moment - this is done through additional dependencies, but nothing prevents the user from writing two times the projectScript for both scripts. It is very convenient, for example, to generate projects by Ctrl + F7, immediately when a project is changed.


Testing.


As I understand it all, programmers nowadays do not particularly like making software without testing, because if the code is complex, you need to somehow track so that nothing is broken. On the one hand, I understand them, on the other hand, I don’t really want to hover over each test kais. In general, I thought and thought and made unpretentious support for unit testing.


At first, the project was just testing, but I also wanted to measure the code coverage, in the end I slightly updated the testing so that testing could be run via [TestMethod] (one method) in order to measure the code coverage. At the moment I have a plan with each buffer and improvement to increase code coverage. In the last committe, it was 81.13%, and this can be tracked by commit history, I mark it in comments (cc: 81.13%).


Still, you're probably wondering how you can write one method for testing and test a bunch of functions?


The basic idea is that if you usually write some test function in a test application, then I pulled out the test function for the syncProj utility itself, saved it with a separate file (for example, NoProjectSelected.cs), and also added a mechanism for recording the output of the console application.


Let's say we run NoProjectSelected.cs, as is the case with the command line:


> syncProj.exe NoProjectSelected.cs


And syncProj prints us this:


NoProjectSelected.cs:


NoProjectSelected.cs (10,13): error: Project not specified (Use project ("specify" to specify new project)


All that is printed is the result of testing. The test result is saved in a separate file. At the time of development, the programmer knows that the program must print - and he either approves or not. And another option is if this is a new test.


As a result, if NoProjectSelected.cs would be a new test, syncProj testing would issue:


image

If the test result is already available, but it is different, then the message is about the same:


image
')

If Yes is selected, the file NoProjectSelected.cs.accepted_log.txt is created which contains what the utility has printed on the screen.


If No is selected, then the program is started to compare regular text files. (WinMerge for example)


Well, of course, if heavy refactoring occurs, then the programmer simply needs to “approve” the new test results.


With minimal testing costs, maximum results are achieved.


Well, in principle, everything - I think that the C # script allows a fairly flexible approach to creating projects - i.e. when projects become complex, respectively, the C # script itself becomes more difficult - functions appear, helperes appear, and so on.


As an example, I can show this . Where plugin projects are already being created with features.


Yes, I know, cmake and premake also allow you to write functions, but there is no way to debug it.


syncProj really works only for Windows so far and only recognizes Visual Studio projects, but so far I haven’t had to port elsewhere. I tried to bring the code to the ideal - it is fully commented, so if there are enthusiasts to continue my business, I will be pleased to introduce you to the situation.


Yes, syncProj is friends with Visual Studio, so in case of errors, you can double-click on the line where the error occurred, and get where you need to correct the code. Well, yes, and if this is not enough, then C # script tools, and debug.


Code


Documentation


If it is necessary that the proxy, report errors, proxy - well, yes, you can join the development of the syncProj itself.


Project author: Tarmo Pikaro, tapika- (at) -yahoo-dot-com

Source: https://habr.com/ru/post/337138/


All Articles