Build Systems. Scons? WAF? Or what?

Hey everyone,

i am currently evaluating build systems once again and am looking for opinions. First of all, what i am looking for:

[ul]
[li]Primarily looking to build c++ code. Other kinds of builds (py2exe, java stuff, python, potentially deployment etc) is wanted if possible
[/li][li]Mostly building application plugins (Max, Nuke, Maya) few standalone tools
[/li][li]I want to make building plugins easy and quick to set up. So i would like to easy building against different host versions and (due to SDK requirements) different VC Versions (i think?)
[/li][li]To allow for that i would like to have a general setup, say “max plugin” that wraps all the switches and paths and libs for the deployed versions of max and make that easy to reuse (and possibly centrally managed) in plugin projects
[/li][li]I am aiming to move this away from the IDE. We’re using VS 2008 and 2010. I want this to run on buildslaves for nightlies, CI and deployment. So the SDK should be sufficient. I don’t want to buy loads of Licenses and deal with vsprops, slns, vcproj files that are different from project to project etc.
[/li][li]I do want the repos to be seperate per plugin. I am not sure yet how to best tackle that
[/li][/ul]

Now so far i have dealt with the standard IDE building, Scons and recently WAF. Whily i like Scons it seems to be not the best performance wise and i found some of the setup not ideal, especially in a windows world. I just recently learned about waf (in a presentation of Avalanche Studios) and gave it a quick try. It worked really well out of the box and supported windows SDK compilation really nicely out of the box including autodiscovery of compilers and creating x64 binaries. Also it seems it is not declatative as Scons is (which i found really confusing at times).

I have seen quite a lot of cmake usage. I have not ever used it in one of our projects. But everytime i tried to use it with projects that use it it felt like a complete non-working nightmare. I am pretty sure it is not that bad. But my milage varied :wink:

Also i really like SConstruct and wscript files being python.

So i am looking for opinions on build systems (feel free to add to the mix!) and also hints on setting this up, especially in regards to having seperate repos and still use a central setup to support versions etc. and only add libs and other project specific stuff in the repos themselves.

Cheers and thanks a lot for any input :slight_smile:
Thorsten

Hi,

i’m definetly not an expert on build systems, but i have very similar requirements to my development environment (Building DCC PlugIns andd small tools with C++ and Python), so i will give my 2 cents.

I have seen quite a lot of cmake usage. I have not ever used it in one of our projects. But everytime i tried to use it with projects that use it it felt like a complete non-working nightmare. I am pretty sure it is not that bad. But my milage varied :wink:

I totaly understand that :smiley: I actually thought that CMake is pretty much a disease, until i lately forced myself into using it. It has a steep learning curve, and i’m still at the beginning, but slowly i really start to like it.
I has reliefed me from dealing with the compilersettings in VS studio (which has traditionally been even worse) and creating custom build rules for automocing and .ui -> .dll conversion for the typical QT tool setup is two lines, and works like a charm. A boilerplate setup for a Maya Plugin for example is even more simple and quickly done, once you got the CMake syntax.

I want to make building plugins easy and quick to set up. So i would like to easy building against different host versions and (due to SDK requirements) different VC Versions (i think?)

I would think that the CMake GUI comes in handy here. You can quickly expose parameters that somebody can set in a GUI before building, for example for the Maya version or platform.

…especially in regards to having seperate repos and still use a central setup to support versions etc. and only add libs and other project specific stuff in the repos themselves.
…To allow for that i would like to have a general setup, say “max plugin” that wraps all the switches and paths and libs for the deployed versions of max and make that easy to reuse (and possibly centrally managed) in plugin projects

I’m pretty sure that is possible with a central CMakeList file somewhere for the basics of a Maya Plugin for example, which is included by a local CMakeList file in a plugin repo. I think it is also pretty common to have
a CMakeList file with solution wide settings upper level, and many lower level files for a the specific projects in a solution.

I frankly know no other build generator than CMake, i’ll have to look at some other like scons and waf to get a bigger picture. And yes, i would really like CMake to work somehow with Python and its syntax, but i now have arranged with it and the improvements in the workflow slowly, but massively come through.

Thanks a lot for sharing your thoughts Timm! As said i played with waf recently and here is a sample script. This contains both configuration phase and build phase, builds pretty quick using only the WinSDK and sets up all the paths etc. This feels really conventient right now. This includes building the .res from .rc and creates a 3dsmax plugin. After installing the SDK this autodiscovered all the tools and just worked. So currently i am tempted to go the waf route actually.


def options(opt):
    opt.load('compiler_c')

def configure(conf):
    conf.env['MSVC_VERSIONS'] = ['wsdk 7.1']
    conf.env['MSVC_TARGETS'] = ['x64']
    conf.load('compiler_c')


def build(bld):
    bld.shlib(  source=[
                        'src/vraymultimtl.cpp',
                        'src/mtlshade.cpp',
                        'src/plugin.cpp',
                        'src/vraymultimtl.rc',
                        ],
                target='mvFlipNormal',
                includes = [
                            r'C:\_DEV\LIB\max2011sdk\include',
                            r'C:	emp\vray_adv_23001_max2011_x64\Chaos Group\V-Ray\3dsmax 2011 for x64\include',
                            r'C:\cygwin64\lib\gcc\x86_64-pc-cygwin\4.8.2\include',
                            r'.\src',
                            r'C:\Program Files\Microsoft SDKs\Windows\v7.1\Include',
                            r'C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include',
                            r'C:\Program Files\Microsoft SDKs\Windows\v7.1\Samples\winui	sf	sfapp',
                            
                            ],
                stlibpath = [
                            r'C:\_DEV\LIB\max2011sdk\x64\lib',
                            r'C:	emp\vray_adv_23001_max2011_x64\Chaos Group\V-Ray\3dsmax 2011 for x64\lib\x64',
                            r'C:	emp\vray_adv_23001_max2011_x64\Chaos Group\V-Ray\3dsmax 2011 for x64\lib\x64\vc91',
                            r'C:\Program Files\Microsoft SDKs\Windows\v7.1\Lib\x64', 
                            r'C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\lib\amd64',
                            ],
                stlib = ['odbccp32', 'comctl32', 'bmm', 'core', 'geom', 'gfx', 'mesh', 'maxutil', 'maxscrpt', 'manipsys', 'paramblk2', 'Poly', 'MNMath','user32'
                        ],
                defs = 'src/plugin.def'
                )

Here is a CMake file which i am currently using for a little Qt tool.
I use it mostly with the CMake Gui to create a VS2013 project, which nevertheless compiles with msvc11.
Its really handy, i do it with all my projects no matter what msvc version they need…VS2013 is a great advancement compared to VS2010 for example.

If you want it to run “headless” overnight, you would probably have to create a batch script that first invokes CMake with the given script
and then generates an nmakefile (msvc) or makefile.
Then within the same batch you run the msvc with the just created makefile. (I’ve read that people basically use the same workflow with Sublime Build scripts when developing
C++ with Sublime)
A nice bonus might be, that with the variables specified in the script (like CMAKE_GENERATOR_TOOLSET for example), people could always quickly
open the gui and build a visual studio project that compiles with a different msvc, without messing with the script.

I also feel like it works really well together with Qt:

set(CMAKE_AUTOMOC ON) <-- Auto Meta object compilation build rules
qt5_wrap_ui(FORM_HEADERS ${FORMS}) <-- Compile .ui files to .h files
cmake_minimum_required(VERSION 2.8.8)

#solution
project(ocio_view)





#CMake settings
#---------------------------------------

#Build Type 
IF (NOT CMAKE_BUILD_TYPE)
	SET(CMAKE_BUILD_TYPE Release)
ENDIF (NOT CMAKE_BUILD_TYPE)

#Generator toolset (which visual studio version is used for compilation. Standard is: IDE Editing: VS2013 Compiling: VS2012)
if(MSVC OR MSVC_IDE)
	set(CMAKE_GENERATOR_TOOLSET "v110" CACHE STRING "Platform Toolset" FORCE)
endif()

set(CMAKE_INCLUDE_CURRENT_DIR ON) #<-- Include current directory

#QT
#---------------------------------------
set(CUSTOM_QT_DIR "C:/symlinks/libraries/Qt/x64/msvc11/Qt/Qt5.2.0/5.2.0/msvc2012_64_opengl")
set(CMAKE_AUTOMOC ON) #<-- Auto meta object compilation for Q_Object macro
set(OPENGL_INCLUDE_PATH "C:/symlinks/microsoft_sdks/Windows/v7.0A/Lib")
set(CMAKE_PREFIX_PATH ${CUSTOM_QT_DIR}; ${OPENGL_INCLUDE_PATH})
FIND_PACKAGE(Qt5Core REQUIRED)
FIND_PACKAGE(Qt5Widgets REQUIRED)
FIND_PACKAGE(Qt5Gui REQUIRED)

#Boost
#---------------------------------------
SET(BOOST_ROOT "C:/symlinks/boost/boost_1_54_0")
SET(BOOST_INCLUDEDIR "C:/symlinks/boost/boost_1_54_0/boost")
SET(BOOST_LIBRARYDIR "C:/symlinks/boost/boost_1_54_0/stage/x64/msvc11/python26/lib")
find_package(Boost REQUIRED)




#Headers
#---------------------------------------
file (GLOB HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
	source/*.h)

#Source files
#---------------------------------------
file (GLOB SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
	source/*.cpp)

#Forms (.ui files)
#---------------------------------------
file (GLOB FORMS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
	media/*.ui)








#Qt uic (compile .ui files to .h files)
#---------------------------------------
qt5_wrap_ui(FORM_HEADERS ${FORMS})


#Filters
#---------------------------------------
source_group(headers FILES ${HEADERS})
source_group(sources FILES ${SOURCES})
source_group(media FILES ${FORMS} ${FORM_HEADERS})



#project
add_executable(ocio_view ${SOURCES} ${HEADERS} ${FORM_HEADERS})

#include directories
include_directories(
	"C:/symlinks/libraries/OpenColorIO/build_harness/OpenColorIO/export"
	"C:/symlinks/libraries/OpenColorIO/build_harness/OpenColorIO_build/msvc11/x64/export"
	${Boost_INCLUDE_DIR}
	)

#target link libraries
target_link_libraries(ocio_view debug "C:/symlinks/libraries/OpenColorIO/x64/msvc11/static/debug/OpenColorIO.lib")
target_link_libraries(ocio_view optimized "C:/symlinks/libraries/OpenColorIO/x64/msvc11/static/release/OpenColorIO.lib")



#Use modules
#---------------------------------------
qt5_use_modules(ocio_view Core Widgets)