JetBrains/teamcity-cpp

Header-only library

Opened this issue · 15 comments

Consider making the library header-only. It would simplify linking it to the test projects.

Considered it and found that "BOOST_GLOBAL_FIXTURE(TeamcityFormatterRegistrar)" (https://github.com/JetBrains/teamcity-cpp/blob/master/boost/teamcity_boost.cpp) prevents it from being header-only

I worked around that by wrapping it in:

    #if defined(BOOST_TEST_MODULE)
        BOOST_GLOBAL_FIXTURE(TeamcityFormatterRegistrar);
    #endif

Then, it only gets included and compiled when you are actually building the boost test module (the main entry module for all boost unit tests).

@toonetown @zaufi What do you think about migration to header only?
With BOOST_TEST_MODULE it's possible.

I can work up a pull request if you like. I don't have the changes in my actual fork...it was just a one-off thing I did a year or so back - but I'm willing to work on getting it added as a PR so it can be integrated, if it would be something that is desired.

My only issue is that I only use teamcity_messages.h, teamcity_messages.cpp and teamcity_boost.cpp in my current projects...so some details about how to build and run unit tests might be good before I started messing around with something that may break things for other people.

Good point. I plan to fix travis (Unix) & appveyor (Windows) CI first.

On local machine you just need to run "make test" or "ctest"

@toonetown As for header only - my question is actually - is it desired?

My personal preference (at least form working on a Boost::Test project), is "yes" - because it's more "boost-like". There are some libraries that are required...(Boost::System, Boost::Filesystem, and even Boost::Test itself) - but the fewer third-party libraries that I need to compile for my projects the better.

I do, however, see the simplicity of not worrying about it and leaving it as a compiled library.

Personally, I use teamcity-cpp in conjunction with Boost::Build on 3-4 projects across multiple platforms - but my company is a bit wary of including third-party source directly in our code...so any third-party libraries we want to use need to be packaged up and installed on the build machine. A header-only library is easiest (given our current build systems) because it is cross-platform...otherwise, we need to compile the library for each supported platform.

Yes - there are other ways we could deal with this (i.e. including the cpp files in our distribution, etc)...which is why I am fine if the suggestion to go header-only is ultimately not desired. For example, something like this might work:

    #if defined(BOOST_TEST_MODULE)
        #include "teamcity-cpp/boost/teamcity_boost.cpp"
        #include "teamcity-cpp/common/teamcity_messages.cpp"
    #endif

And then we (in my company) could just distribute the entire source code distribution as if it were all headers. You could also achieve the same without the conditional by only "#include"-ing the implementation files in one compilation unit of our project.

However, that is not a very "boost-like" way of doing things...I think that most people coming from boost would expect header-only libraries. However, I understand that this project is more than just boost...so can see both sides of it.

Just let me know if you'd like me to work up a PR...I'm willing to - but if it isn't the direction the project wants to go, then I'll deal with my own workarounds in my own projects.

As for header only - my question is actually - is it desired?

I, as a topic starter, obviously wish the library to be header only. Such libraries are easier to use in your projects. And people tend to like header only approach. There are many popular header only libraries, for example, another good unit testing library Catch (https://github.com/philsquared/Catch) or a modern Json lib (https://github.com/nlohmann/json) to name a few.

On the other hand, it's not a must. Including a couple of .cpp into the project is not a big deal.

zaufi commented

As for me I see no reason to make this libs header-only. Moreover, in my case it'll be even worse. As for me, I use it w/ CMake build system which helps me to not care about #include something or not forget to add some sources to my test executable. My further efforts will be towards making that integration more tightly (add finder/config module and maybe some exported targets), so it'll be easy as pie to use that library w/ CMake.

Also, I use packages (RPM or DEB) installed to build machine, so having this project as another one dependency packages sounds more naturally to me (especially w/ support to be found by CMake via ordinal find_package()).

I think @toonetown provides a good example of how to make it "header-only", so no reason to do anything else for that -- whoever wants it "header-only" can do that easily...

Thank you for feedback. I think I'll at least postpone it then in favor of good CI and tests.
And header-only library does not automatically exclude CMake...

zaufi commented

And header-only library does not automatically exclude CMake...

sure, it doesn't, but then you need to provide a path to headers installed in your system and add #include to some of your sources. The strange part that you need to do that in particular translation unit, where the BOOST_TEST_MODULE (or BOOST_AUTO_TEST_MAIN) has defined and yes, #include should be at very specific place in a file -- below mentioned macros definition. The other strange thing is that you actually need nothing from that #included header -- I mean usually header files get included for some reason, like to call some function of be able to make an instance of some class... in case of teamcity_boost.hpp you need nothing to call or use from it! :-)

So, I prefer to let CMake to take care about it and have my sources clean from useless crap...

Moreover, in my case it'll be even worse.

@zaufi, I'm just wondering how header-only library can make your CMake and packages on the build server workflow harder or worse? Is there really a difference?
I have no hands-on experience with CMake. But I do have with c++ libraries as NuGet packages. As a package author you have to take an extra compilation step if the library is not header-only. And as a package user you don't notice any differences. Is it CMake specific?

BTW, at JetBrains we also use NuGet packages and it'll be much easier with header-only library.

@zaufi That works only for boost part. cppunit and gtest require explicit test result listener registration and will definitely benefit from being header-only.

I would also argue that if the library were header only, it doesn't matter what build system is used (cmake or otherwise)....because you just include the headers into your current build system...no need to maintain or support a build system at all.