Home | History | Annotate | Download | only in analyzer
      1 #!/usr/bin/env python
      2 
      3 """
      4 Static Analyzer qualification infrastructure: adding a new project to
      5 the Repository Directory.
      6 
      7  Add a new project for testing: build it and add to the Project Map file.
      8    Assumes it's being run from the Repository Directory.
      9    The project directory should be added inside the Repository Directory and
     10    have the same name as the project ID
     11 
     12  The project should use the following files for set up:
     13       - cleanup_run_static_analyzer.sh - prepare the build environment.
     14                                      Ex: make clean can be a part of it.
     15       - run_static_analyzer.cmd - a list of commands to run through scan-build.
     16                                      Each command should be on a separate line.
     17                                      Choose from: configure, make, xcodebuild
     18       - download_project.sh - download the project into the CachedSource/
     19                                      directory. For example, download a zip of
     20                                      the project source from GitHub, unzip it,
     21                                      and rename the unzipped directory to
     22                                      'CachedSource'. This script is not called
     23                                      when 'CachedSource' is already present,
     24                                      so an alternative is to check the
     25                                      'CachedSource' directory into the
     26                                      repository directly.
     27       - CachedSource/ - An optional directory containing the source of the
     28                                      project being analyzed. If present,
     29                                      download_project.sh will not be called.
     30       - changes_for_analyzer.patch - An optional patch file for any local changes
     31                                      (e.g., to adapt to newer version of clang)
     32                                      that should be applied to CachedSource
     33                                      before analysis. To construct this patch,
     34                                      run the the download script to download
     35                                      the project to CachedSource, copy the
     36                                      CachedSource to another directory (for
     37                                      example, PatchedSource) and make any needed
     38                                      modifications to the the copied source.
     39                                      Then run:
     40                                           diff -ur CachedSource PatchedSource \
     41                                               > changes_for_analyzer.patch
     42 """
     43 import SATestBuild
     44 
     45 import os
     46 import csv
     47 import sys
     48 
     49 def isExistingProject(PMapFile, projectID) :
     50     PMapReader = csv.reader(PMapFile)
     51     for I in PMapReader:
     52         if projectID == I[0]:
     53             return True
     54     return False
     55 
     56 # Add a new project for testing: build it and add to the Project Map file.
     57 # Params:
     58 #   Dir is the directory where the sources are.
     59 #   ID is a short string used to identify a project.
     60 def addNewProject(ID, BuildMode) :
     61     CurDir = os.path.abspath(os.curdir)
     62     Dir = SATestBuild.getProjectDir(ID)
     63     if not os.path.exists(Dir):
     64         print "Error: Project directory is missing: %s" % Dir
     65         sys.exit(-1)
     66 
     67     # Build the project.
     68     SATestBuild.testProject(ID, BuildMode, IsReferenceBuild=True, Dir=Dir)
     69 
     70     # Add the project ID to the project map.
     71     ProjectMapPath = os.path.join(CurDir, SATestBuild.ProjectMapFile)
     72     if os.path.exists(ProjectMapPath):
     73         PMapFile = open(ProjectMapPath, "r+b")
     74     else:
     75         print "Warning: Creating the Project Map file!!"
     76         PMapFile = open(ProjectMapPath, "w+b")
     77     try:
     78         if (isExistingProject(PMapFile, ID)) :
     79             print >> sys.stdout, 'Warning: Project with ID \'', ID, \
     80                                  '\' already exists.'
     81             print >> sys.stdout, "Reference output has been regenerated."
     82         else:
     83             PMapWriter = csv.writer(PMapFile)
     84             PMapWriter.writerow( (ID, int(BuildMode)) );
     85             print "The project map is updated: ", ProjectMapPath
     86     finally:
     87         PMapFile.close()
     88 
     89 
     90 # TODO: Add an option not to build.
     91 # TODO: Set the path to the Repository directory.
     92 if __name__ == '__main__':
     93     if len(sys.argv) < 2:
     94         print >> sys.stderr, 'Usage: ', sys.argv[0],\
     95                              'project_ID <mode>' \
     96                              'mode - 0 for single file project; ' \
     97                              '1 for scan_build; ' \
     98                              '2 for single file c++11 project'
     99         sys.exit(-1)
    100 
    101     BuildMode = 1
    102     if (len(sys.argv) >= 3):
    103         BuildMode = int(sys.argv[2])
    104     assert((BuildMode == 0) | (BuildMode == 1) | (BuildMode == 2))
    105 
    106     addNewProject(sys.argv[1], BuildMode)
    107