Thursday, December 19, 2013

Setting up Topcoder Greed plugin with your fav. IDE (Code::blocks)

I always talk about the Greed plugin, it is just so customizable. It is hard to measure the power it has. From its simple default setup to what I am going to introduce you to in this post. In this post, we are going to make Greed create a Code::blocks work environment and call code::blocks automatically whenever you open a problem. I hope this example can be adapted also for other IDEs.

This post is about Greed 2.0, which is currently in beta. And not just beta Greed 2.0, but possibly the latest in git, I hope greed can have a jar release soon, but for now you'll need to get it from github and compile it. Basically you just download the contents of the repository and use ./gradlew fatjar to compile it and make a jar for you which will be saved in the build/libs folder

Fiddling with the IDE

In a first step, let's learn all that is needed about the compiler and how to set it up. Open some problem in Greed. My favorite test subject is the problem TBlocks from the TCO13 championship round. After you open it in greed, assuming you are with default config, it will create 3 files in a specific folder in your Greed work folder.

  • TCO 2013 Finals/TBlocks.cpp
  • TCO 2013 Finals/TBlocks.sample
  • TCO 2013 Finals/TBlocks.html

In greed 2.0, the default behavior is to save example data in the .sample file. The .cpp file then has to read from this .sample file, and the .sample file has to be in the command's work folder when you run the compiled program. While the ability to save examples in a separate file is cool, I disagree with this as a default, I think it complicates things too much. It is possible to change this behavior, but for the matter of this tutorial it will be a good thing, because I am teaching you how to make it all work in your IDE.

Let's create a Code::blocks project that runs this stuff for us. Go to File/New project/ when asked for the kind of project, pick console application.

Tell it you want a C++ project. It will then ask you for a project title, folder, etc. For them use the name of the problem and the location in your Greed workspace. In following image, my Greed workspace is /home/vx/topcoder. We want the project file in the same folder as the source code and sample...

It will then ask you for what compiler to run. You should have already set up the correct compiler: (Hint: You'd like GCC 4.8.1 (Mingw in windows) to simulate TopCoder's server the best). If you ask me, you probably don't need a release configuration, as you only want to test code before sending to topcoder, leave it as debug.

Now we have some issues... First, it unilaterally decided that you want the main file to be called main.cpp. We would like it to be the same file as greed generated. Let's change it to TBlocks.cpp. Right click main.cpp and select remove file. Now right click the Project name and select Add files and add the TBlocks.cpp file generated by greed.

Another thing, you'd probably like c++11 support (and I hope you are using gcc 4.8.1) so go to Project/Build options... And tell it to use c++0x.

Actually, there is a plethora of options you'd like to set. To mimic topcoder the best, you'd like "Optimize even more (-O2)" and also I recommend to add "-Wreturn-type -Wcomment -Wunused-variable -Wunused-parameter -Wno-sign-compare" (without quotes) to the other options section.

After this, running the source code by pressing F9 will work just fine. Code::blocks will run the project in the directory we wanted.

Of course, doing this for every single problem is too much trouble, so we'll now use Greed's power to automatize it.

A code::blocks project template

All about greed works using templates. What we'd like Greed to do is to create a project file automatically for each problem. Code::blocks project files are saved with cbp extension and are actually XML files. Let's save all work we put in Code::blocks (Make sure to save the project!) and open TBlocks.cbp:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
 <FileVersion major="1" minor="6" />
 <Project>
  <Option title="TBlocks" />
  <Option pch_mode="2" />
  <Option compiler="gcc" />
  <Build>
   <Target title="Debug">
    <Option output="bin/Debug/TBlocks" prefix_auto="1" extension_auto="1" />
    <Option object_output="obj/Debug/" />
    <Option type="1" />
    <Option compiler="gcc" />
    <Compiler>
     <Add option="-O2" />
     <Add option="-std=c++0x" />
     <Add option="-g" />
     <Add option="-Wreturn-type -Wcomment -Wunused-variable -Wunused-parameter -Wno-sign-compare" />
    </Compiler>
   </Target>
  </Build>
  <Compiler>
   <Add option="-Wall" />
   <Add option="-fexceptions" />
  </Compiler>
  <Unit filename="TBlocks.cpp" />
  <Extensions>
   <code_completion />
   <debugger />
  </Extensions>
 </Project>
</CodeBlocks_project_file>

The rest is to create a Greed template to generate files like that. Let's first define the template in greed.conf. If you don't already have this file in your Greed workspace, create it.

greed {
    shared {
        templateDef {
            codeblocks {
                override = false
                outputFile = "${Problem.Name}.cbp"
                templateFile = "codeblocks.cbp.tmpl"
            }
        }
    }
}

That is the basic stuff you need to add a new template to greed. The template will be called codeblocks. By default the file won't be overrided if it already exists. The template file will be codeblocks.cbp, located in your workspace folder. The file it generates will be called just like the problem name and be put in the code root folder (same folder as source and sample). What we'd like for this file is to be exactly like the one above, except to replace TBLocks with whatever problem name we need:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
 <FileVersion major="1" minor="6" />
 <Project>
  <Option title="${Problem.Name}" />
  <Option pch_mode="2" />
  <Option compiler="gcc" />
  <Build>
   <Target title="Debug">
    <Option output="bin/Debug/${Problem.Name}" prefix_auto="1" extension_auto="1" />
    <Option object_output="obj/Debug/" />
    <Option type="1" />
    <Option compiler="gcc" />
    <Compiler>
     <Add option="-O2" />
     <Add option="-std=c++0x" />
     <Add option="-g" />
     <Add option="-Wreturn-type -Wcomment -Wunused-variable -Wunused-parameter -Wno-sign-compare" />
    </Compiler>
   </Target>
  </Build>
  <Compiler>
   <Add option="-Wall" />
   <Add option="-fexceptions" />
  </Compiler>
  <Unit filename="${Problem.Name}.cpp" />
  <Extensions>
   <code_completion />
   <debugger />
  </Extensions>
 </Project>
</CodeBlocks_project_file>

We would just like the template to be created whenever we open the problem. Since it is specific to c++ we will modify the c++ templates line.

greed {
    language {
        cpp {
             templates = [ filetest, source, testcase, problem-desc, codeblocks ]
        }
    }
}

The templates line is usually [ filetest, source, testcase, problem-desc ], it is the list of templates to create automatically. By adding codeblocks, we tell greed to create the codeblocks template. In greed reload the configuration, if everything went right, open some other problem, like the 400 points problem in the same TCO finals match.

It should say: Generating template [codeblocks] -> TCO 2013 Finals/PackingSquares.cbp or something like that, depending on the folder.

Now open the newly-created PackingSquares.cbp in Code::blocks, it should have everything set up, including the new source file.

After generation hook

How about that, instead of just creating the project file and needing us to open it manually, Greed also ordered Code::blocks to open it when we open the problem? All is possible.

To the part where we added the codeblocks template, add this:

            codeblocks {
                override = false
                outputFile = "${Problem.Name}.cbp"
                templateFile = "codeblocks.cbp.tmpl"
          afterFileGen {
              execute = codeblocks
              arguments = ["${GeneratedFilePath}"]
          }
            }

Now whenever the project file is regenerated (You may need to tell greed to regenerate code for problems you already opened) code::blocks will be opened...

The arguments part tells codeblocks what file to open. GeneratedFilePath is a special variable that returns the whole path to the file generated by the template.

Ok , we have a problem, if code::blocks was closed before opening the problem/regenerating the code then code::blocks will close immediately after opening. This is because Greed will run the new process without creating a thread. I will ask for an option to fix this in greed, but for now, we have a couple of workarounds, the first is to have code::blocks open while running the arena. The other is to create a script to run code::blocks in another thread for us. In *n*x* operating systems, save the following as threadcodeblocks.sh in greed's workspace folder, remember to set it as executable in permissions:

#!/bin/bash
codeblocks '$1' &

Change the execute = codeblocks line to execute = /path/to/greed/workspace/folder/threadcodeblocks.sh.

And done!

Comments / etc?

I hope it was useful. I think that every decent IDE out there saves project files as XML, there might be variations, but it is usually a text file, I hope.

5 comments :

Jakub Tarnawski said...

But why do all of this? I use CodeBlocks for C++ in contests (all other than TopCoder, for which I use KawigiEdit). I don't have any projects or project files whatsoever, I just open C++ files in CodeBlocks (which I create from a template) and compile/run them with F9. Why bother with projects?

vexorian said...

You mean you don't even compile the files with --std=c++0x ? :/

Though I honestly don't use any IDE ever, I picked code::blocks because I could find it in ubuntu's repos. I didn't know running the cpp directly worked, but this is more about how to make a good project template. I know of people that have to keep their source files as main.cpp for some other IDEs .

Jakub Tarnawski said...

There are several compilation flags that I use, I just have them set as default in CodeBlocks global settings.

I see your point, I just think that CodeBlocks is maybe not the best example because there, it all happens to be unnecessary IMO :)

Joost said...

This tutorial is actually really useful, as CodeBlocks does not allow for debugging without the .cbp file (no single file debugging). I can not get the last part working though (auto launch of CodeBlocks). Could you be more specific about "To the part where we added the codeblocks template" (e.g. where in the brackets)? Thanks!

vexorian said...

Remember we created a "codeblocks" section in greed.conf?


I just meant that you had to change that section.


Something is off about the indenting there, for some reason.