SlideShare a Scribd company logo
1 of 9
Download to read offline
SCons: an introduction


              Dean Giberson <dean@deangiberson.com>


                                   Dec 17, 2008




    If you've tried putting a build system together for a modern game you know
that you are facing a monumental, never ending task. Once you do get a basic
pipeline working, modern games require source assets that are in the range of
100 Gb of raw data. Tracking this amount of data takes time and resources.
    SCons (http://www.scons.org) is a Python based make replacement; with
it you can tame your dependencies and data sizes. What follows is quick art
centric introduction.

1 The Canonical Example
The SCons documentation1 would give an example like this:

     env = Environment()

     env.Program( 'HelloWorld', ['HelloWorld.cpp'])


   follow this and provide a compilable HelloWorld.cpp and you would have a
program ready to go. But how would you extend this to use your own pipeline
tools?

2 Adding Compressed Textures
Lets assume that you want to compress textures for use in a game. NVidia
Textures2 Tools can be used on your TGA/PNG/JPG/DDS images. For exam-
ple you want to convert this image3 into a DXT5 compressed image for use on
target:

     nvcompress -color -bc3 gunmap.png gunmap.dds

  1 http://www.scons.org/doc/0.97/HTML/scons-user/book1.html
  2 http://developer.nvidia.com/object/texture_tools.html
  3 Images provide by G3D Engine Data Collection http://g3d-cpp.sourceforge.net/.



                                           1
Once we understand how to do this from the command line adding it to
SCons is quite easy.


     import SCons

     env = Environment(ENV = os.environ)

     env['NVCOMPRESS'] = 'nvcompress'
     env['NVCOMPRESSTYPE'] = SCons.Util.CLVar('-color')
     env['NVCOMPRESSFLAGS'] = SCons.Util.CLVar('-bc3')
     env['NVCOMPRESSCOM'] = '$NVCOMPRESS $NVCOMPRESSFLAGS $SOURCE $TARGET'

     NvCompressAction = Action( '$NVCOMPRESSCOM')
     NvCompressBuilder = Builder( action=NvCompressAction,
                                  suffix='.dds')

     env['BUILDERS']['NvCompress'] = NvCompressBuilder


     env.NvCompress( 'image', 'image.png')




                                  2
3 A Quick walk-through to understand what is
  happening
     import SCons


    We import the SCons python module into our script. Normally you don't
have to do this, but I'm using the 'SCons.Util.CLVar' class provided by SCons
so I import the module to gain access to it.


     env = Environment(ENV = os.environ)


   Construct a SCons Environment object. SCons does not copy the system
environment by default, this is by design as a build environment should be as
explicit as possible. For now I'll just copy the system environment, but please
note that this is bad practice.


     env['NVCOMPRESS'] = 'nvcompress'
     env['NVCOMPRESSTYPE'] = SCons.Util.CLVar('-color')
     env['NVCOMPRESSFLAGS'] = SCons.Util.CLVar('-bc3')
     env['NVCOMPRESSCOM'] = '$NVCOMPRESS $NVCOMPRESSFLAGS $SOURCE $TARGET'


    Now begin populating the Environment with data. Environment objects
are class instances that behave like dictionaries. We can add to them through
assignment, and query the contents using normal Python dictionary functions.
    In our case I'm lling four slots with:
   • the name of the executable ('NVCOMPRESS'),
   • the default type ag ('NVCOMPRESSTYPE'),
   • the default compression ag('NVCOMPRESSFLAGS'),

   • a template command line ('NVCOMPRESSCOM').
     SCons uses late binding of variables found within environment strings,
     any sub-string that starts with a '$' character is interpreted at the calling
     site for the current value within the current environment. This acts like a
     controlled dynamic scoping system.
     I'll come back to what this means in practical terms in a moment, but
     for now accept that our default command line evaluates to:    'nvcompress
     -color -bc3 $SOURCE $TARGET'             .


                                       3
NvCompressAction = Action( '$NVCOMPRESSCOM')
     NvCompressBuilder = Builder( action=NvCompressAction,
                                  suffix='.dds')


    These three lines are the core of our SCons extension; an Action object is
created, and the command line string is set. The evaluation of this command
follows the same rules as for environment variables set earlier.
    Then a Builder is constructed using the Action object just created. We also
set the default extension for all targets.


     env['BUILDERS']['NvCompress'] = NvCompressBuilder


    The Environment is then extended with this builder, and a name is given
for calls to it.


     env.NvCompress( 'image', 'image.png')


   The only thing left is to construct a Node in the dependency tree for the
target le.
   SCons is a three stage process:
  1. Create or gather a collection of tools and set the environment,
  2. Create a tree of dependencies with sources and targets,
  3. The dependencies are scanned, then for any out of date data, the action
     is called.
     Each of these steps is discrete, and must be occur in this order. Step
     1 happens during the setup phase of SCons (default tools are scanned
     for and basic environments are constructed) and to a lesser extent within
     the running SConstruct script itself (as I've just shown). Step 2 happens
     within the SConstruct script and continues until the end of the script.
     After control returns to the SCons system the Step 3 begins and the
     dependency tree is scanned and the actions are triggered. Always in this
     order.
     It's for this reason that I say that a dependency node is constructed from
     the last line of the SConstruct. It doesn't actually run 'nvcompress' at
     this point. Only an object, representing the potential to run 'nvcompress',
     is constructed and added to the system. Work is done later by an internal
     SCons class, 'Taskmaster.


                                      4
4 More les, more controls
One of the great things about SCons is that it's embedded with Python. A
consequence of this choice is that you, the tool writer, have access to all of
Pythons functions.
   I've shown you how to add one Builder and access that Builder for a single
target texture. Games are not made from one texture, you're going to want
access to many textures and that means several targets.     Glob
                                                              to the rescue.


      from glob import glob

      for tex in glob( r'./*/*.png'):
          target = tex.replace('.png','.dds')
          env.NvCompress( target, tex)


   This will nd all of the source textures in subdirectories, and add them to
the dependency graph. Any textures that are added are found automatically.
   The same strategy can be applied to other types of data as well. Python
has great libraries for XML, SQL, even direct in memory structure access or
peeking in compressed les. You will not have to drop out of Python for very
many reasons. Check the module documentation4 for details.

5 Other compression types
The previous method of adding dependencies will add each texture into the
pipeline with the same compression options. Normally you will want a range
of compression methods for textures. I want to focus on the clearest method,
changing the values in the Environment.
    I mentioned earlier that the evaluation of strings set for Builders and Actions
acts like dynamic scoping for variables. This feature allows us to change the
functionality of a call by changing values when the dependency node is built.


      env.NvCompress( 'image2', 'image.png', NVCOMPRESSFLAGS='-bc2')


   Which will result in this command:      'nvcompress -color -bc2 image.png
image2.dds'.
    Adding a method to match lename patterns in a database (or text le)
gives us a simple way to control the compression of individual textures.


      # Global texture compression options
  4 http://docs.python.org/modindex.html



                                           5
# format 'glob,opts'
     .envmaps*.png,-bc1 # Does not include cubemaps
     .nmaps*.png,-bc3n

   This simple text le has a line for each le pattern, a comma (',') and
the compression option for the command line. Comments start with a hash
character ('#') and continue to the end of the line. A parser for this format is
easy to write.

     from glob import glob
     from fnmatch import fnmatch

     gCompressionOptions = []

     f = open('texture_options.txt','rt')
     try:
          for line in f:
              line = line.split('#')[0]
              if line != '':
                  (pattern,options) = line.split(',')
                  gCompressionOptions.append( (pattern,options))
     finally:
          f.close()

     for tex in glob( r'.**.png'):
         hasCustomPattern = False
         target = tex.replace('.png','.dds')
         for pat,opt in gCompressionOptions:
             if fnmatch(tex,pat):
                 opt = opt.strip()
                 env.NvCompress( target, tex, NVCOMPRESSFLAGS=opt)
                 hasCustomPattern = True
         if not hasCustomPattern:
             env.NvCompress( target, tex)

   Once we have the patterns into an array it's simple to check if any les found
by the glob matches a given pattern. If there is a match, set the compression
options for that texture. If not the default is used.

6 Exploring dependencies
A core strength of SCons is it's dependency system. This system is not normally
based on time stamps but on a one way hash of the le contents (MD5). Using
hash values allows for stronger connections between assets.

                                       6
In order to follow what SCons is doing with dependency checking you can
use the 'debug=explain'       command line option. This option will print out
information about dependency checks and commands being run.
    The interesting thing about using hash values for dependency check is that
you can't use  touch   to force a recompile of an asset, you must change the
contents of the le or force SCons to rebuild an asset.
    On the ip side of this, you get control of the derived le from both the
contents of the source les and the contents of the command line used to build
the derived le. SCons combines all of these values into a string that represents
the derived target asset, if any sources have changed that targets action is
invoked.
    To get a view of the dependency tree use the  tree=derived      option.



     scons: Reading SConscript files ...
     special .envmapsgunmap.dds .envmapsgunmap.png -bc1
     special .nmapsgunmap.dds .nmapsgunmap.png -bc3n
     normal .texgunmap.dds .texgunmap.png
     scons: done reading SConscript files.
     scons: Building targets ...
     scons: `.' is up to date.
     +-.
       +-envmaps
       | +-envmapsgunmap.dds
       +-nmaps
       | +-nmapsgunmap.dds
       +-tex
         +-texgunmap.dds
     scons: done building targets.




7 Sharing the results
Strong dependency systems are great for personal development, you can be sure
that you only need to build the minimum following a change. This doesn't help
on a large team; if an artist makes a change then once submitted every person
on the team needs to build that same asset. In my case building a compressed
texture takes 9.5 seconds, if you have 20 other people on your team, you team
will spend 190 seconds for each texture change. The odd part of this result is
that every person is trying to get the same result from the same source.
    SCons took the strong hash key info and took it to the next logical level. If
everyone calculates the hash the same way, then it's possible to store copies of
the result in a shared location under that name. Then when you go to build, do


                                       7
a quick check rst. If the asset exists under that name in this cache then just
copy it; if not then build the asset and place it into the cache under it's hash
name.
    The result is a distributed build cache. And you can take advantage of it
out of the box. Create a location with a lot of available disk space, available for
everyone on your team, some server. Next place this line into you SConstruct
le.


      env.CacheDir(r'x:Locationofcachedir')


    Now your derived les are shared, and only one person, normally the origi-
nator of the source art, needs to build the nal result. In most cases, this saves
hours of cumulative time for a large team of people. You results will be better
if you have a continuous integration server for art.

8 The script we have
Taking all of these changes into account we get the following script.


      import SCons

      env = Environment(ENV = os.environ)

      env.CacheDir(r'x:Locationofcachedir')

      env['NVCOMPRESS'] = 'nvcompress'
      env['NVCOMPRESSTYPE'] = SCons.Util.CLVar('-color')
      env['NVCOMPRESSFLAGS'] = SCons.Util.CLVar('-bc3')
      env['NVCOMPRESSCOM'] = '$NVCOMPRESS $NVCOMPRESSFLAGS $SOURCE $TARGET'

      NvCompressAction = Action( '$NVCOMPRESSCOM')
      NvCompressBuilder = Builder( action=NvCompressAction,
                                   suffix='.dds')

      env['BUILDERS']['NvCompress'] = NvCompressBuilder

      from glob import glob
      from fnmatch import fnmatch

      gCompressionOptions = []

      f = open('texture_options.txt','rt')
      try:

                                        8
for line in f:
              line = line.split('#')[0]
              if line != '':
                  (pattern,options) = line.split(',')
                  gCompressionOptions.append( (pattern,options))
     finally:
         f.close()

     for tex in glob( r'.**.png'):
         hasCustomPattern = False
         target = tex.replace('.png','.dds')
         for pat,opt in gCompressionOptions:
             if fnmatch(tex,pat):
                 opt = opt.strip()
                 env.NvCompress( target, tex, NVCOMPRESSFLAGS=opt)
                 hasCustomPattern = True
         if not hasCustomPattern:
             env.NvCompress( target, tex)



    This will build all of your textures found in sub directories, using the com-
pression options found in the  texture_options.txt      le, and share the results
with colleagues using a shared drive.
    I hope you see how easy it is to build a strong build system for art given the
right tools.
    SCons is not just for code, but can be used for art builds as well. Coupled
with a continuous integration server, having a quick, robust pipeline is within
your grasp.




                                        9

More Related Content

What's hot

Course 102: Lecture 18: Process Life Cycle
Course 102: Lecture 18: Process Life CycleCourse 102: Lecture 18: Process Life Cycle
Course 102: Lecture 18: Process Life CycleAhmed El-Arabawy
 
Os structure
Os structureOs structure
Os structureMohd Arif
 
Optimising the Training Load during the Pre-taper Phase
Optimising the Training Load during the Pre-taper PhaseOptimising the Training Load during the Pre-taper Phase
Optimising the Training Load during the Pre-taper PhaseYann Le Meur
 
5. Mergulho Livre - Preparação Física (v5.12.25)
5. Mergulho Livre - Preparação Física (v5.12.25)5. Mergulho Livre - Preparação Física (v5.12.25)
5. Mergulho Livre - Preparação Física (v5.12.25)João Costa
 
Plan de Développement de l'Athlète - Basketball phénix
Plan de Développement de l'Athlète - Basketball phénixPlan de Développement de l'Athlète - Basketball phénix
Plan de Développement de l'Athlète - Basketball phénixBasketball Phénix
 
Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드
Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드 Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드
Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드 SangIn Choung
 
Flynn's classification
Flynn's classificationFlynn's classification
Flynn's classificationHamidul Islam
 
Java (spring) vs javascript (node.js)
Java (spring) vs javascript (node.js)Java (spring) vs javascript (node.js)
Java (spring) vs javascript (node.js)류 영수
 
Course 102: Lecture 1: Course Overview
Course 102: Lecture 1: Course Overview Course 102: Lecture 1: Course Overview
Course 102: Lecture 1: Course Overview Ahmed El-Arabawy
 
OS - Ch2
OS - Ch2OS - Ch2
OS - Ch2sphs
 
Linux administration
Linux administrationLinux administration
Linux administrationYogesh Ks
 
Twitter의 snowflake 소개 및 활용
Twitter의 snowflake 소개 및 활용Twitter의 snowflake 소개 및 활용
Twitter의 snowflake 소개 및 활용흥배 최
 
FIFA 11+ POSTER: Warm-Up to Prevent Injuries
FIFA 11+ POSTER: Warm-Up to Prevent InjuriesFIFA 11+ POSTER: Warm-Up to Prevent Injuries
FIFA 11+ POSTER: Warm-Up to Prevent InjuriesFundação Real Madrid
 

What's hot (14)

Course 102: Lecture 18: Process Life Cycle
Course 102: Lecture 18: Process Life CycleCourse 102: Lecture 18: Process Life Cycle
Course 102: Lecture 18: Process Life Cycle
 
Os structure
Os structureOs structure
Os structure
 
Optimising the Training Load during the Pre-taper Phase
Optimising the Training Load during the Pre-taper PhaseOptimising the Training Load during the Pre-taper Phase
Optimising the Training Load during the Pre-taper Phase
 
5. Mergulho Livre - Preparação Física (v5.12.25)
5. Mergulho Livre - Preparação Física (v5.12.25)5. Mergulho Livre - Preparação Física (v5.12.25)
5. Mergulho Livre - Preparação Física (v5.12.25)
 
Plan de Développement de l'Athlète - Basketball phénix
Plan de Développement de l'Athlète - Basketball phénixPlan de Développement de l'Athlète - Basketball phénix
Plan de Développement de l'Athlète - Basketball phénix
 
Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드
Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드 Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드
Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드
 
Process Management
Process ManagementProcess Management
Process Management
 
Flynn's classification
Flynn's classificationFlynn's classification
Flynn's classification
 
Java (spring) vs javascript (node.js)
Java (spring) vs javascript (node.js)Java (spring) vs javascript (node.js)
Java (spring) vs javascript (node.js)
 
Course 102: Lecture 1: Course Overview
Course 102: Lecture 1: Course Overview Course 102: Lecture 1: Course Overview
Course 102: Lecture 1: Course Overview
 
OS - Ch2
OS - Ch2OS - Ch2
OS - Ch2
 
Linux administration
Linux administrationLinux administration
Linux administration
 
Twitter의 snowflake 소개 및 활용
Twitter의 snowflake 소개 및 활용Twitter의 snowflake 소개 및 활용
Twitter의 snowflake 소개 및 활용
 
FIFA 11+ POSTER: Warm-Up to Prevent Injuries
FIFA 11+ POSTER: Warm-Up to Prevent InjuriesFIFA 11+ POSTER: Warm-Up to Prevent Injuries
FIFA 11+ POSTER: Warm-Up to Prevent Injuries
 

Viewers also liked

Confrontation Pipeline and SCons
Confrontation Pipeline and SConsConfrontation Pipeline and SCons
Confrontation Pipeline and SConsslantsixgames
 
Técnicas de Comunicación Oral
Técnicas de Comunicación OralTécnicas de Comunicación Oral
Técnicas de Comunicación Oralyesibrandao24
 
Federal Health Care Spending:Why Is It Growing? What Could Be Done About It?
Federal Health Care Spending:Why Is It Growing? What Could Be Done About It?Federal Health Care Spending:Why Is It Growing? What Could Be Done About It?
Federal Health Care Spending:Why Is It Growing? What Could Be Done About It?Congressional Budget Office
 
DIFICULTADES DEL APRENDIZAJE
DIFICULTADES DEL APRENDIZAJE DIFICULTADES DEL APRENDIZAJE
DIFICULTADES DEL APRENDIZAJE Belén Quinaluisa
 
"Корреляция между эффективными коммуникациями и прибыльностью бизнеса", Натал...
"Корреляция между эффективными коммуникациями и прибыльностью бизнеса", Натал..."Корреляция между эффективными коммуникациями и прибыльностью бизнеса", Натал...
"Корреляция между эффективными коммуникациями и прибыльностью бизнеса", Натал...rabota.ua
 
How Linkedin uses Gamification to improve its Business!
How Linkedin uses Gamification to improve its Business!How Linkedin uses Gamification to improve its Business!
How Linkedin uses Gamification to improve its Business!Alok Rodinhood Kejriwal
 
Introduction to dry needling
Introduction to dry needlingIntroduction to dry needling
Introduction to dry needlingSubhanjan Das
 
Continuous Integration, Build Pipelines and Continuous Deployment
Continuous Integration, Build Pipelines and Continuous DeploymentContinuous Integration, Build Pipelines and Continuous Deployment
Continuous Integration, Build Pipelines and Continuous DeploymentChristopher Read
 
60 Content Predictions for 2015 by Content Marketing Institute
60 Content Predictions for 2015 by Content Marketing Institute60 Content Predictions for 2015 by Content Marketing Institute
60 Content Predictions for 2015 by Content Marketing InstituteContent Marketing Institute
 
11 Inspirational Quotes from the Top CEOs of the Modern Business World
11 Inspirational Quotes from the Top CEOs of the Modern Business World11 Inspirational Quotes from the Top CEOs of the Modern Business World
11 Inspirational Quotes from the Top CEOs of the Modern Business WorldMatt Burke
 
Marco Común de Competencia Digital Docente - 2017
Marco Común de Competencia Digital Docente - 2017Marco Común de Competencia Digital Docente - 2017
Marco Común de Competencia Digital Docente - 2017INTEF
 
The French Revolution of 1789
The French Revolution of 1789The French Revolution of 1789
The French Revolution of 1789Tom Richey
 

Viewers also liked (17)

Confrontation Pipeline and SCons
Confrontation Pipeline and SConsConfrontation Pipeline and SCons
Confrontation Pipeline and SCons
 
Presentación1
Presentación1Presentación1
Presentación1
 
Técnicas de Comunicación Oral
Técnicas de Comunicación OralTécnicas de Comunicación Oral
Técnicas de Comunicación Oral
 
Digital divide
Digital divideDigital divide
Digital divide
 
Federal Health Care Spending:Why Is It Growing? What Could Be Done About It?
Federal Health Care Spending:Why Is It Growing? What Could Be Done About It?Federal Health Care Spending:Why Is It Growing? What Could Be Done About It?
Federal Health Care Spending:Why Is It Growing? What Could Be Done About It?
 
DIFICULTADES DEL APRENDIZAJE
DIFICULTADES DEL APRENDIZAJE DIFICULTADES DEL APRENDIZAJE
DIFICULTADES DEL APRENDIZAJE
 
Time-based Animation Games
Time-based Animation GamesTime-based Animation Games
Time-based Animation Games
 
"Корреляция между эффективными коммуникациями и прибыльностью бизнеса", Натал...
"Корреляция между эффективными коммуникациями и прибыльностью бизнеса", Натал..."Корреляция между эффективными коммуникациями и прибыльностью бизнеса", Натал...
"Корреляция между эффективными коммуникациями и прибыльностью бизнеса", Натал...
 
How Linkedin uses Gamification to improve its Business!
How Linkedin uses Gamification to improve its Business!How Linkedin uses Gamification to improve its Business!
How Linkedin uses Gamification to improve its Business!
 
Introduction to dry needling
Introduction to dry needlingIntroduction to dry needling
Introduction to dry needling
 
Continuous Integration, Build Pipelines and Continuous Deployment
Continuous Integration, Build Pipelines and Continuous DeploymentContinuous Integration, Build Pipelines and Continuous Deployment
Continuous Integration, Build Pipelines and Continuous Deployment
 
Living Brands
Living BrandsLiving Brands
Living Brands
 
60 Content Predictions for 2015 by Content Marketing Institute
60 Content Predictions for 2015 by Content Marketing Institute60 Content Predictions for 2015 by Content Marketing Institute
60 Content Predictions for 2015 by Content Marketing Institute
 
11 Inspirational Quotes from the Top CEOs of the Modern Business World
11 Inspirational Quotes from the Top CEOs of the Modern Business World11 Inspirational Quotes from the Top CEOs of the Modern Business World
11 Inspirational Quotes from the Top CEOs of the Modern Business World
 
The Executioner's Tale
The Executioner's TaleThe Executioner's Tale
The Executioner's Tale
 
Marco Común de Competencia Digital Docente - 2017
Marco Común de Competencia Digital Docente - 2017Marco Común de Competencia Digital Docente - 2017
Marco Común de Competencia Digital Docente - 2017
 
The French Revolution of 1789
The French Revolution of 1789The French Revolution of 1789
The French Revolution of 1789
 

Similar to SCons: an introduction to using the SCons build system for games

Armitage – The Ultimate Attack Platform for Metasploit
Armitage – The  Ultimate Attack  Platform for Metasploit Armitage – The  Ultimate Attack  Platform for Metasploit
Armitage – The Ultimate Attack Platform for Metasploit Ishan Girdhar
 
Viktor Tsykunov: Azure Machine Learning Service
Viktor Tsykunov: Azure Machine Learning ServiceViktor Tsykunov: Azure Machine Learning Service
Viktor Tsykunov: Azure Machine Learning ServiceLviv Startup Club
 
Alex Smola at AI Frontiers: Scalable Deep Learning Using MXNet
Alex Smola at AI Frontiers: Scalable Deep Learning Using MXNetAlex Smola at AI Frontiers: Scalable Deep Learning Using MXNet
Alex Smola at AI Frontiers: Scalable Deep Learning Using MXNetAI Frontiers
 
maxbox starter60 machine learning
maxbox starter60 machine learningmaxbox starter60 machine learning
maxbox starter60 machine learningMax Kleiner
 
Power ai tensorflowworkloadtutorial-20171117
Power ai tensorflowworkloadtutorial-20171117Power ai tensorflowworkloadtutorial-20171117
Power ai tensorflowworkloadtutorial-20171117Ganesan Narayanasamy
 
Introduction to NS2 - Cont..
Introduction to NS2 - Cont..Introduction to NS2 - Cont..
Introduction to NS2 - Cont..cscarcas
 
Tutorial: Image Generation and Image-to-Image Translation using GAN
Tutorial: Image Generation and Image-to-Image Translation using GANTutorial: Image Generation and Image-to-Image Translation using GAN
Tutorial: Image Generation and Image-to-Image Translation using GANWuhyun Rico Shin
 
Final training course
Final training courseFinal training course
Final training courseNoor Dhiya
 
An Experiment with Checking the glibc Library
An Experiment with Checking the glibc LibraryAn Experiment with Checking the glibc Library
An Experiment with Checking the glibc LibraryAndrey Karpov
 
Linux Kernel, tested by the Linux-version of PVS-Studio
Linux Kernel, tested by the Linux-version of PVS-StudioLinux Kernel, tested by the Linux-version of PVS-Studio
Linux Kernel, tested by the Linux-version of PVS-StudioPVS-Studio
 
NativeBoost
NativeBoostNativeBoost
NativeBoostESUG
 
nlp dl 1.pdf
nlp dl 1.pdfnlp dl 1.pdf
nlp dl 1.pdfnyomans1
 
Build a Complex, Realtime Data Management App with Postgres 14!
Build a Complex, Realtime Data Management App with Postgres 14!Build a Complex, Realtime Data Management App with Postgres 14!
Build a Complex, Realtime Data Management App with Postgres 14!Jonathan Katz
 
Network Simulator Tutorial
Network Simulator TutorialNetwork Simulator Tutorial
Network Simulator Tutorialcscarcas
 
maXbox Starter 42 Multiprocessing Programming
maXbox Starter 42 Multiprocessing Programming maXbox Starter 42 Multiprocessing Programming
maXbox Starter 42 Multiprocessing Programming Max Kleiner
 

Similar to SCons: an introduction to using the SCons build system for games (20)

Armitage – The Ultimate Attack Platform for Metasploit
Armitage – The  Ultimate Attack  Platform for Metasploit Armitage – The  Ultimate Attack  Platform for Metasploit
Armitage – The Ultimate Attack Platform for Metasploit
 
Viktor Tsykunov: Azure Machine Learning Service
Viktor Tsykunov: Azure Machine Learning ServiceViktor Tsykunov: Azure Machine Learning Service
Viktor Tsykunov: Azure Machine Learning Service
 
Alex Smola at AI Frontiers: Scalable Deep Learning Using MXNet
Alex Smola at AI Frontiers: Scalable Deep Learning Using MXNetAlex Smola at AI Frontiers: Scalable Deep Learning Using MXNet
Alex Smola at AI Frontiers: Scalable Deep Learning Using MXNet
 
Deep Learning for Computer Vision: Software Frameworks (UPC 2016)
Deep Learning for Computer Vision: Software Frameworks (UPC 2016)Deep Learning for Computer Vision: Software Frameworks (UPC 2016)
Deep Learning for Computer Vision: Software Frameworks (UPC 2016)
 
DB Conan 1.0
DB Conan 1.0DB Conan 1.0
DB Conan 1.0
 
maxbox starter60 machine learning
maxbox starter60 machine learningmaxbox starter60 machine learning
maxbox starter60 machine learning
 
Power ai tensorflowworkloadtutorial-20171117
Power ai tensorflowworkloadtutorial-20171117Power ai tensorflowworkloadtutorial-20171117
Power ai tensorflowworkloadtutorial-20171117
 
Introduction to NS2 - Cont..
Introduction to NS2 - Cont..Introduction to NS2 - Cont..
Introduction to NS2 - Cont..
 
Tensor flow
Tensor flowTensor flow
Tensor flow
 
Tutorial: Image Generation and Image-to-Image Translation using GAN
Tutorial: Image Generation and Image-to-Image Translation using GANTutorial: Image Generation and Image-to-Image Translation using GAN
Tutorial: Image Generation and Image-to-Image Translation using GAN
 
Final training course
Final training courseFinal training course
Final training course
 
An Experiment with Checking the glibc Library
An Experiment with Checking the glibc LibraryAn Experiment with Checking the glibc Library
An Experiment with Checking the glibc Library
 
Linux Kernel, tested by the Linux-version of PVS-Studio
Linux Kernel, tested by the Linux-version of PVS-StudioLinux Kernel, tested by the Linux-version of PVS-Studio
Linux Kernel, tested by the Linux-version of PVS-Studio
 
NativeBoost
NativeBoostNativeBoost
NativeBoost
 
Cppcheck
CppcheckCppcheck
Cppcheck
 
nlp dl 1.pdf
nlp dl 1.pdfnlp dl 1.pdf
nlp dl 1.pdf
 
Build a Complex, Realtime Data Management App with Postgres 14!
Build a Complex, Realtime Data Management App with Postgres 14!Build a Complex, Realtime Data Management App with Postgres 14!
Build a Complex, Realtime Data Management App with Postgres 14!
 
Network Simulator Tutorial
Network Simulator TutorialNetwork Simulator Tutorial
Network Simulator Tutorial
 
maXbox Starter 42 Multiprocessing Programming
maXbox Starter 42 Multiprocessing Programming maXbox Starter 42 Multiprocessing Programming
maXbox Starter 42 Multiprocessing Programming
 
Keras and TensorFlow
Keras and TensorFlowKeras and TensorFlow
Keras and TensorFlow
 

More from slantsixgames

Supersize your production pipe enjmin 2013 v1.1 hd
Supersize your production pipe    enjmin 2013 v1.1 hdSupersize your production pipe    enjmin 2013 v1.1 hd
Supersize your production pipe enjmin 2013 v1.1 hdslantsixgames
 
Ask the Producers Feb 8th
Ask the Producers Feb 8thAsk the Producers Feb 8th
Ask the Producers Feb 8thslantsixgames
 
Maximize Your Production Effort (English)
Maximize Your Production Effort (English)Maximize Your Production Effort (English)
Maximize Your Production Effort (English)slantsixgames
 
Maximize Your Production Effort (Chinese)
Maximize Your Production Effort (Chinese)Maximize Your Production Effort (Chinese)
Maximize Your Production Effort (Chinese)slantsixgames
 
Confrontation Audio GDC 2009
Confrontation Audio GDC 2009Confrontation Audio GDC 2009
Confrontation Audio GDC 2009slantsixgames
 
Audio SPU Presentation
Audio SPU PresentationAudio SPU Presentation
Audio SPU Presentationslantsixgames
 
Collision Detection an Overview
Collision Detection an OverviewCollision Detection an Overview
Collision Detection an Overviewslantsixgames
 
Modern Graphics Pipeline Overview
Modern Graphics Pipeline OverviewModern Graphics Pipeline Overview
Modern Graphics Pipeline Overviewslantsixgames
 
PPU Optimisation Lesson
PPU Optimisation LessonPPU Optimisation Lesson
PPU Optimisation Lessonslantsixgames
 
Event System Presentation
Event System PresentationEvent System Presentation
Event System Presentationslantsixgames
 
Supersize Your Production Pipe
Supersize Your Production PipeSupersize Your Production Pipe
Supersize Your Production Pipeslantsixgames
 

More from slantsixgames (11)

Supersize your production pipe enjmin 2013 v1.1 hd
Supersize your production pipe    enjmin 2013 v1.1 hdSupersize your production pipe    enjmin 2013 v1.1 hd
Supersize your production pipe enjmin 2013 v1.1 hd
 
Ask the Producers Feb 8th
Ask the Producers Feb 8thAsk the Producers Feb 8th
Ask the Producers Feb 8th
 
Maximize Your Production Effort (English)
Maximize Your Production Effort (English)Maximize Your Production Effort (English)
Maximize Your Production Effort (English)
 
Maximize Your Production Effort (Chinese)
Maximize Your Production Effort (Chinese)Maximize Your Production Effort (Chinese)
Maximize Your Production Effort (Chinese)
 
Confrontation Audio GDC 2009
Confrontation Audio GDC 2009Confrontation Audio GDC 2009
Confrontation Audio GDC 2009
 
Audio SPU Presentation
Audio SPU PresentationAudio SPU Presentation
Audio SPU Presentation
 
Collision Detection an Overview
Collision Detection an OverviewCollision Detection an Overview
Collision Detection an Overview
 
Modern Graphics Pipeline Overview
Modern Graphics Pipeline OverviewModern Graphics Pipeline Overview
Modern Graphics Pipeline Overview
 
PPU Optimisation Lesson
PPU Optimisation LessonPPU Optimisation Lesson
PPU Optimisation Lesson
 
Event System Presentation
Event System PresentationEvent System Presentation
Event System Presentation
 
Supersize Your Production Pipe
Supersize Your Production PipeSupersize Your Production Pipe
Supersize Your Production Pipe
 

Recently uploaded

Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesZilliz
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Wonjun Hwang
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfRankYa
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embeddingZilliz
 

Recently uploaded (20)

Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector Databases
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdf
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embedding
 

SCons: an introduction to using the SCons build system for games

  • 1. SCons: an introduction Dean Giberson <dean@deangiberson.com> Dec 17, 2008 If you've tried putting a build system together for a modern game you know that you are facing a monumental, never ending task. Once you do get a basic pipeline working, modern games require source assets that are in the range of 100 Gb of raw data. Tracking this amount of data takes time and resources. SCons (http://www.scons.org) is a Python based make replacement; with it you can tame your dependencies and data sizes. What follows is quick art centric introduction. 1 The Canonical Example The SCons documentation1 would give an example like this: env = Environment() env.Program( 'HelloWorld', ['HelloWorld.cpp']) follow this and provide a compilable HelloWorld.cpp and you would have a program ready to go. But how would you extend this to use your own pipeline tools? 2 Adding Compressed Textures Lets assume that you want to compress textures for use in a game. NVidia Textures2 Tools can be used on your TGA/PNG/JPG/DDS images. For exam- ple you want to convert this image3 into a DXT5 compressed image for use on target: nvcompress -color -bc3 gunmap.png gunmap.dds 1 http://www.scons.org/doc/0.97/HTML/scons-user/book1.html 2 http://developer.nvidia.com/object/texture_tools.html 3 Images provide by G3D Engine Data Collection http://g3d-cpp.sourceforge.net/. 1
  • 2. Once we understand how to do this from the command line adding it to SCons is quite easy. import SCons env = Environment(ENV = os.environ) env['NVCOMPRESS'] = 'nvcompress' env['NVCOMPRESSTYPE'] = SCons.Util.CLVar('-color') env['NVCOMPRESSFLAGS'] = SCons.Util.CLVar('-bc3') env['NVCOMPRESSCOM'] = '$NVCOMPRESS $NVCOMPRESSFLAGS $SOURCE $TARGET' NvCompressAction = Action( '$NVCOMPRESSCOM') NvCompressBuilder = Builder( action=NvCompressAction, suffix='.dds') env['BUILDERS']['NvCompress'] = NvCompressBuilder env.NvCompress( 'image', 'image.png') 2
  • 3. 3 A Quick walk-through to understand what is happening import SCons We import the SCons python module into our script. Normally you don't have to do this, but I'm using the 'SCons.Util.CLVar' class provided by SCons so I import the module to gain access to it. env = Environment(ENV = os.environ) Construct a SCons Environment object. SCons does not copy the system environment by default, this is by design as a build environment should be as explicit as possible. For now I'll just copy the system environment, but please note that this is bad practice. env['NVCOMPRESS'] = 'nvcompress' env['NVCOMPRESSTYPE'] = SCons.Util.CLVar('-color') env['NVCOMPRESSFLAGS'] = SCons.Util.CLVar('-bc3') env['NVCOMPRESSCOM'] = '$NVCOMPRESS $NVCOMPRESSFLAGS $SOURCE $TARGET' Now begin populating the Environment with data. Environment objects are class instances that behave like dictionaries. We can add to them through assignment, and query the contents using normal Python dictionary functions. In our case I'm lling four slots with: • the name of the executable ('NVCOMPRESS'), • the default type ag ('NVCOMPRESSTYPE'), • the default compression ag('NVCOMPRESSFLAGS'), • a template command line ('NVCOMPRESSCOM'). SCons uses late binding of variables found within environment strings, any sub-string that starts with a '$' character is interpreted at the calling site for the current value within the current environment. This acts like a controlled dynamic scoping system. I'll come back to what this means in practical terms in a moment, but for now accept that our default command line evaluates to: 'nvcompress -color -bc3 $SOURCE $TARGET' . 3
  • 4. NvCompressAction = Action( '$NVCOMPRESSCOM') NvCompressBuilder = Builder( action=NvCompressAction, suffix='.dds') These three lines are the core of our SCons extension; an Action object is created, and the command line string is set. The evaluation of this command follows the same rules as for environment variables set earlier. Then a Builder is constructed using the Action object just created. We also set the default extension for all targets. env['BUILDERS']['NvCompress'] = NvCompressBuilder The Environment is then extended with this builder, and a name is given for calls to it. env.NvCompress( 'image', 'image.png') The only thing left is to construct a Node in the dependency tree for the target le. SCons is a three stage process: 1. Create or gather a collection of tools and set the environment, 2. Create a tree of dependencies with sources and targets, 3. The dependencies are scanned, then for any out of date data, the action is called. Each of these steps is discrete, and must be occur in this order. Step 1 happens during the setup phase of SCons (default tools are scanned for and basic environments are constructed) and to a lesser extent within the running SConstruct script itself (as I've just shown). Step 2 happens within the SConstruct script and continues until the end of the script. After control returns to the SCons system the Step 3 begins and the dependency tree is scanned and the actions are triggered. Always in this order. It's for this reason that I say that a dependency node is constructed from the last line of the SConstruct. It doesn't actually run 'nvcompress' at this point. Only an object, representing the potential to run 'nvcompress', is constructed and added to the system. Work is done later by an internal SCons class, 'Taskmaster. 4
  • 5. 4 More les, more controls One of the great things about SCons is that it's embedded with Python. A consequence of this choice is that you, the tool writer, have access to all of Pythons functions. I've shown you how to add one Builder and access that Builder for a single target texture. Games are not made from one texture, you're going to want access to many textures and that means several targets. Glob to the rescue. from glob import glob for tex in glob( r'./*/*.png'): target = tex.replace('.png','.dds') env.NvCompress( target, tex) This will nd all of the source textures in subdirectories, and add them to the dependency graph. Any textures that are added are found automatically. The same strategy can be applied to other types of data as well. Python has great libraries for XML, SQL, even direct in memory structure access or peeking in compressed les. You will not have to drop out of Python for very many reasons. Check the module documentation4 for details. 5 Other compression types The previous method of adding dependencies will add each texture into the pipeline with the same compression options. Normally you will want a range of compression methods for textures. I want to focus on the clearest method, changing the values in the Environment. I mentioned earlier that the evaluation of strings set for Builders and Actions acts like dynamic scoping for variables. This feature allows us to change the functionality of a call by changing values when the dependency node is built. env.NvCompress( 'image2', 'image.png', NVCOMPRESSFLAGS='-bc2') Which will result in this command: 'nvcompress -color -bc2 image.png image2.dds'. Adding a method to match lename patterns in a database (or text le) gives us a simple way to control the compression of individual textures. # Global texture compression options 4 http://docs.python.org/modindex.html 5
  • 6. # format 'glob,opts' .envmaps*.png,-bc1 # Does not include cubemaps .nmaps*.png,-bc3n This simple text le has a line for each le pattern, a comma (',') and the compression option for the command line. Comments start with a hash character ('#') and continue to the end of the line. A parser for this format is easy to write. from glob import glob from fnmatch import fnmatch gCompressionOptions = [] f = open('texture_options.txt','rt') try: for line in f: line = line.split('#')[0] if line != '': (pattern,options) = line.split(',') gCompressionOptions.append( (pattern,options)) finally: f.close() for tex in glob( r'.**.png'): hasCustomPattern = False target = tex.replace('.png','.dds') for pat,opt in gCompressionOptions: if fnmatch(tex,pat): opt = opt.strip() env.NvCompress( target, tex, NVCOMPRESSFLAGS=opt) hasCustomPattern = True if not hasCustomPattern: env.NvCompress( target, tex) Once we have the patterns into an array it's simple to check if any les found by the glob matches a given pattern. If there is a match, set the compression options for that texture. If not the default is used. 6 Exploring dependencies A core strength of SCons is it's dependency system. This system is not normally based on time stamps but on a one way hash of the le contents (MD5). Using hash values allows for stronger connections between assets. 6
  • 7. In order to follow what SCons is doing with dependency checking you can use the 'debug=explain' command line option. This option will print out information about dependency checks and commands being run. The interesting thing about using hash values for dependency check is that you can't use touch to force a recompile of an asset, you must change the contents of the le or force SCons to rebuild an asset. On the ip side of this, you get control of the derived le from both the contents of the source les and the contents of the command line used to build the derived le. SCons combines all of these values into a string that represents the derived target asset, if any sources have changed that targets action is invoked. To get a view of the dependency tree use the tree=derived option. scons: Reading SConscript files ... special .envmapsgunmap.dds .envmapsgunmap.png -bc1 special .nmapsgunmap.dds .nmapsgunmap.png -bc3n normal .texgunmap.dds .texgunmap.png scons: done reading SConscript files. scons: Building targets ... scons: `.' is up to date. +-. +-envmaps | +-envmapsgunmap.dds +-nmaps | +-nmapsgunmap.dds +-tex +-texgunmap.dds scons: done building targets. 7 Sharing the results Strong dependency systems are great for personal development, you can be sure that you only need to build the minimum following a change. This doesn't help on a large team; if an artist makes a change then once submitted every person on the team needs to build that same asset. In my case building a compressed texture takes 9.5 seconds, if you have 20 other people on your team, you team will spend 190 seconds for each texture change. The odd part of this result is that every person is trying to get the same result from the same source. SCons took the strong hash key info and took it to the next logical level. If everyone calculates the hash the same way, then it's possible to store copies of the result in a shared location under that name. Then when you go to build, do 7
  • 8. a quick check rst. If the asset exists under that name in this cache then just copy it; if not then build the asset and place it into the cache under it's hash name. The result is a distributed build cache. And you can take advantage of it out of the box. Create a location with a lot of available disk space, available for everyone on your team, some server. Next place this line into you SConstruct le. env.CacheDir(r'x:Locationofcachedir') Now your derived les are shared, and only one person, normally the origi- nator of the source art, needs to build the nal result. In most cases, this saves hours of cumulative time for a large team of people. You results will be better if you have a continuous integration server for art. 8 The script we have Taking all of these changes into account we get the following script. import SCons env = Environment(ENV = os.environ) env.CacheDir(r'x:Locationofcachedir') env['NVCOMPRESS'] = 'nvcompress' env['NVCOMPRESSTYPE'] = SCons.Util.CLVar('-color') env['NVCOMPRESSFLAGS'] = SCons.Util.CLVar('-bc3') env['NVCOMPRESSCOM'] = '$NVCOMPRESS $NVCOMPRESSFLAGS $SOURCE $TARGET' NvCompressAction = Action( '$NVCOMPRESSCOM') NvCompressBuilder = Builder( action=NvCompressAction, suffix='.dds') env['BUILDERS']['NvCompress'] = NvCompressBuilder from glob import glob from fnmatch import fnmatch gCompressionOptions = [] f = open('texture_options.txt','rt') try: 8
  • 9. for line in f: line = line.split('#')[0] if line != '': (pattern,options) = line.split(',') gCompressionOptions.append( (pattern,options)) finally: f.close() for tex in glob( r'.**.png'): hasCustomPattern = False target = tex.replace('.png','.dds') for pat,opt in gCompressionOptions: if fnmatch(tex,pat): opt = opt.strip() env.NvCompress( target, tex, NVCOMPRESSFLAGS=opt) hasCustomPattern = True if not hasCustomPattern: env.NvCompress( target, tex) This will build all of your textures found in sub directories, using the com- pression options found in the texture_options.txt le, and share the results with colleagues using a shared drive. I hope you see how easy it is to build a strong build system for art given the right tools. SCons is not just for code, but can be used for art builds as well. Coupled with a continuous integration server, having a quick, robust pipeline is within your grasp. 9