Wednesday, January 16, 2013

building twitcurl in visual studio 2010

UPDATE 20130122.1330: Verified this build chain does let you query twitter from Cinder, that being the goal.  Yeah, yeah, i should've tested that too;P  I don't have a really fun tutorial yet, just printing to the app::console(), but yeah, it works, so go forth and...uhh...twinderifiy?

    If you're wondering where the next round of C4CNC is, fear not, the manuscript is actually done and waiting to get some design and formatting love.  I wasn't kidding when I said this is probably a bad time to embark on a project that required some time and attention, but I'm committed to delivering on that.  Just got back from a great weekend of openFrameworkshops with Reza Ali and Josh Nimoy at GAFFTA, so i'm...not charged, but definitely refreshed and ready to keep cranking on creative coding related work, and especially C++ work.  I've really been dragging my feet on C++, but this year we're doing it live.  Seriously, my brain is so full of things i want to explore, prototype, visualize, maaaan...


    To that end, it's time to get cracking on an installation for GDC, my favorite time of year. Hopefully since I'm getting started sooner on this than I did for my ill-fated CES installation attempts, this one will go all the way. We've decided to do a twitter visualizer, and since I've decided that this year I'd like to do much more work in C++, I'm going with Cinder (of course).

    The first bump-in-the-road I came across is the lack of any official C++ support for twitter, but there are a few different twitter c++ libraries that have been written by various external parties. I've settled on twitcurl because it seems like the lightest, most straightforward version. The current download doesn't support Visual Studio 2010 though, which means the whole dependency chain needs to be rebuilt. It's not a terribly hard process, but there aren't a ton of good directions on the website, and in fact I got more out of the directions for building and using libcurl. I'm going to try and present a condensed version here, mainly for my own reference if I have to do this again, but also for anyone else trying to get up and running with C++/twitter in short order.


    I'm going to assume you've got some experience setting up Visual Studio projects, so I'm not going to go too deep into the specifics of that. First up, we need to grab the source distros:

openssl - Download (1.0.1c is latest as of this writing)
libssh2 - Download (1.4.3 is latest as of this writing)
libcURL - Download (7.28.1 is latest as of this writing)
twitcurl - Checkout SVN

    Now before we get down to business, I'm going to recommend a little bit of housekeeping.  These projects are all rather noisy, i.e. there are a lot of folders, a lot of files, solutions, workspaces, and support files for different IDEs, and...well you get the idea.  This may be 101 for some folks, but it's worth jotting down.  I've set my folder structure up so, feel free to adopt this or something similar (or ignore completely):

CPP/
  libs/
    src/
      curl-7.28.1/
      libssh2-1.4.3/
      libtwitcurl/
      openssl-1.0.1c/
    build/
      libcurl/
        include/
        lib/
          Debug/
          Release/
      libssh2/
        include/
        lib/
          Debug/
          Release/
      libtwitcurl/
        include/
            curl/
        lib/
          Debug/
          Release/
      openssl/

    Again, this is really just a suggestion based on how i store all my libraries on my machine, it's just for convenience.  That all in place, let's get to building some dependencies.

    All the directions are taken from the following document, which I HIGHLY recommend reading.  There are some really important points here that make all the difference between odd linker errors and not.

openssl


1) Install Perl.  I used ActivePerl, but any distribution should be sufficient, really you just need it to run some build configuration scripts.  The doc also recommends using NASM, but I haven't seen any disadvantage of not using it.  That said, I can't really comment, because I haven't seen the advantages of using it either.

2) Open a Visual Studio command line and switch over to your openssl source root directory. You may need to add perl to your path, which you can do by issuing the command:

path=%PATH%;<your perl executable folder>

3) Now we can configure and kick off our build. Issue the following commands (there'll be a pause in between as the scripts run):

perl Configure VC-WIN32 --prefix=<your openssl build path's root>
ms\do_ms
nmake -f ms\nt.mak
nmake -f ms\nt.mak test
nmake -f ms\nt.mak install

<your openssl build path's root> should be just that, the root folder of your desired openssl build with forward slashes.  In fact, if you jump back up and look at how I've laid out my folder, you'll see I have no folders under my openssl folder by design.  This is because the openssl build process creates include, lib, and a few other folders for you.  Also, pay close attention to the output of the test step, you shouldn't see any errors, but if you do, retrace your steps and try the build again.

From here on out, it's all in Visual Studio, so let's get the rest of our libraries built. So long, command line environment!

libssh2


1) Open the Visual Studio project, located at <your libssh2 source root>\win32\libssh2.dsp and take the project through the Visual Studio 2010 conversion process.

2) Now we need to configure the LIB Debug build configuration.  We need to add openssl as a dependency, so first, add the path to the openssl include folder to the C/C++ > General > Additional Include Directories.

3) We also need to set the C/C++ > Code Generation > Runtime Library option to Multi-threaded Debug (MTd).  This is easily the most important step in the whole process, every other project will need to have this set, or you'll get some weird linker errors.

4) Next, we need to add the openssl libraries to our linker dependencies.  Add libeay32.lib and ssleay32.lib to the Librarian > General > Additional Dependencies field; Be sure to also add <your openssl build root>\lib to the Librarian > General > Additional Library Directories field.

5) The last bit of configuration is to set the Librarian > General > Output File field to wherever you'd like the final lib file to end up.  In my case, the value is lib\build\libssh2\lib\Debug\libssh2.lib.  Be sure to configure the LIB Release configuration as well. The steps are all the same, save the output file settings.

6) Build the project and ignore the LNK4221 warnings, they won't affect anything here.

Whew!  Halfway done, now comes the main event, libcurl.  Twitcurl and any projects you build with twitcurl depend on this, so let's plow through and get tweeting from C++ (and Cinder (or ofx, or whatever your C++ framework of choice be)).


bro::comeAt(&me);

libcurl


1) For libcurl, we need to setup libssh2 as a dependency, so open the Visual Studio project <your curl source root>\lib\libcurl.vcproj and add the include path, the library, and the library path for your libssh2 build to the appropriate fields.

2) Remember to also set the C/C++ > Code Generation > Runtime Library to Multi-Threaded Debug (MTd) and stay odd linker error free!

3) libcurl requires a few preprocessor definitions.  To set these up, open the C/C++ > Preprocessor > Preprocessor Definitions window and copy-paste the following block below the existing definitions:

CURL_STATICLIB
USE_LIBSSH2
CURL_DISABLE_LDAP
HAVE_LIBSSH2
HAVE_LIBSSH2_H
LIBSSH2_WIN32
LIBSSH2_LIBRARY

4) If you've setup a custom folder structure, remember also to set your output file settings to wherever you'd like libcurl to sit after it gets built.

5) Hit build and you should be good to go.  All that's left now is to build twitcurl and you'll (we'll, i'll) be tweeting in style, because C++ never goes out of style.  Weird style fads and convoluted paradigms might, but that's a whole other conversation.

twitcurl


The twitcurl project page and wiki are a little odd and convoluted, so I would say those may not the best places to go for information on the project.  Probably a good idea to just checkout the source and make like Kenobi talking to storm troopers talking to Kenobi...(yo, dawg)


1) We'll need to do a little more housekeeping, this time with the twitcurl source.  In the <your twitcurl source root>\libtwitcurl folder, you'll see two subfolders, curl and lib. These folders contain the libcurl dependencies for twitcurl, but as we mentioned earlier, these are out of date.  At this point, we can take a few different approaches.  The end goal is to replace the existing libcurl dependencies with the ones we built previously, so we can replace the contents of the curl and lib folders with the contents from our libcurl build, or we can ignore these and change the project configurations. I chose to change the project configurations so I wouldn't have duplicates floating around.  Ultimately, we're going to need to change some configuration settings anyway, so I'm not sure there's much value in keeping the old dependencies around.

2) Once we've got a plan of action (keep,delete,etc), let's pop open libtwitcurl/twitcurl.sln in Visual Studio and replace all the references to curl with the paths to our previously built libcurl.  We need to update a few fields with the relevant info:

C/C++ > General > Additional Include Directories
Librarian > General > Additional Dependencies
Librarian > General > Additional Library Directories
Librarian > General > Output File (optional)
Librarian > General > Additional Dependencies (also add ws2_32.lib to this field)

3) Next, let's not forget to set the C/C++ > Code Generation > Runtime Library to...Yep, Multi-threaded Debug (MTd).

4) Lastly, let's add CURL_STATICLIB to C/C++ > Preprocessor > Preprocessor Definitions and build the project. If everything's setup correctly and all your previous builds of the dependency chain succeeded, congrats!  You now have everything you need to send tweets in C++.  Take a moment and be awesome (or keep being awesome if you already are)!


    So now it's pretty much just using twitcurl in a project.  Building the included twitterClient is pretty simple, we just need to:

1) Add our builds of libtwitcurl and libcurl as dependencies
2) Add ws2_32.lib as a dependency
3) Add the CURL_STATICLIB Preprocessor Definition
4) Set the C/C++ > Code Generation > Runtime Library option to...whaaaat?
5) Build that muthah (out).  We'll need to change some of the URLs in the project, but otherwise it should be a straight ahead process.

    Step one down, and trust me when I say this is monumental.  If I learned anything from this process it's RTFM!!!  TWICE!!!!  I had the hardest time getting things to build because I glossed over a step here and there and didn't read all the little details about what settings needed to be which specifically.  But that's all behind us now, so next we need to get tweeting from Cinder.  For the next segment, I'll probably recreate Jer Thorp's twitter and processing tutorial in Cinder just to get up and running.  Stay Tuned!