def check_dependency(conf, dependency): print "\nChecking {0} dependencies..".format(dependency.name) for header in Split(dependency.check_headers): if not conf.CheckCXXHeader(header): print('!! Cannot locate header {0} ...'.format(header)) Exit(0) # check libs for lib in Split(dependency.libs): if not conf.CheckLib(lib): print('!! Cannot locate library {0}'.format(lib)) Exit(0)
def BuildFirmware(env): # fix ASM handling under non-casitive OS if not case_sensitive_suffixes(".s", ".S"): env.Replace(AS="$CC", ASCOM="$ASPPCOM") env.ProcessFlags() env.BuildFramework() firmenv = env.Clone() vdirs = firmenv.VariantDirRecursive(join("$BUILD_DIR", "src"), "$PROJECTSRC_DIR", duplicate=False) # build dependent libs deplibs = firmenv.BuildDependentLibraries("$PROJECTSRC_DIR") # append specified LD_SCRIPT if "LDSCRIPT_PATH" in firmenv: firmenv.Append(LINKFLAGS=["-T", "$LDSCRIPT_PATH"]) # enable "cyclic reference" for linker firmenv.Prepend(_LIBFLAGS="-Wl,--start-group ") firmenv.Append(_LIBFLAGS=" -Wl,--end-group") # Handle SRCBUILD_FLAGS if getenv("PLATFORMIO_SRCBUILD_FLAGS", None): firmenv.MergeFlags(getenv("PLATFORMIO_SRCBUILD_FLAGS")) if "SRCBUILD_FLAGS" in env: firmenv.MergeFlags(env['SRCBUILD_FLAGS']) firmenv.Append(CPPDEFINES=[ "PLATFORMIO={0:02d}{1:02d}{2:02d}".format(*pioversion_to_intstr()) ]) if "envdump" in COMMAND_LINE_TARGETS: print env.Dump() Exit() if "idedata" in COMMAND_LINE_TARGETS: print json.dumps(env.DumpIDEData()) Exit() return firmenv.Program(join("$BUILD_DIR", "firmware"), [firmenv.GlobCXXFiles(vdir) for vdir in vdirs], LIBS=env.get("LIBS", []) + deplibs, LIBPATH=env.get("LIBPATH", []) + ["$BUILD_DIR"], PROGSUFFIX=".elf")
def AutodetectUploadPort(env): if "UPLOAD_PORT" in env: return if env.subst("$FRAMEWORK") == "mbed": msdlabels = ("mbed", "nucleo", "frdm") for item in get_logicaldisks(): if (not item['name'] or not any([l in item['name'].lower() for l in msdlabels])): continue env.Replace(UPLOAD_PORT=item['disk']) break else: board_build_opts = env.get("BOARD_OPTIONS", {}).get("build", {}) board_hwid = ("%s:%s" % (board_build_opts.get("vid"), board_build_opts.get("pid"))).replace( "0x", "") for item in get_serialports(): if "VID:PID" not in item['hwid']: continue env.Replace(UPLOAD_PORT=item['port']) if board_hwid in item['hwid']: break if "UPLOAD_PORT" in env: print "Auto-detected UPLOAD_PORT/DISK: %s" % env['UPLOAD_PORT'] else: Exit("Error: Please specify `upload_port` for environment or use " "global `--upload-port` option.\n" "For some development platforms this can be a USB flash drive " "(i.e. /media/<user>/<device name>)\n")
def AutodetectUploadPort(env): if "UPLOAD_PORT" in env: return if env.subst("$FRAMEWORK") == "mbed": msdlabels = ("mbed", "nucleo", "frdm") for item in get_logicaldisks(): if (not item['name'] or not any([l in item['name'].lower() for l in msdlabels])): continue print "Auto-detected UPLOAD_PORT/DISK: %s" % item['disk'] env.Replace(UPLOAD_PORT=item['disk']) break else: for item in get_serialports(): if "VID:PID" not in item['hwid']: continue print "Auto-detected UPLOAD_PORT: %s" % item['port'] env.Replace(UPLOAD_PORT=item['port']) break if "UPLOAD_PORT" not in env: Exit("Error: Please specify `upload_port` for environment or use " "global `--upload-port` option.\n" "For the some development platforms it can be USB flash drive\n")
def add_mbedlib(libname, libar): if libar in env.get("LIBS"): return lib_dir = join(env.subst("$PLATFORMFW_DIR"), "libs", libname) if not isfile( join(lib_dir, "TARGET_%s" % variant, "TOOLCHAIN_GCC_ARM", "lib%s.a" % libar)): Exit("Error: %s board doesn't support %s library!" % (env.get("BOARD"), libname)) env.Append(LIBPATH=[ join(env.subst("$PLATFORMFW_DIR"), "libs", libname, "TARGET_%s" % variant, "TOOLCHAIN_GCC_ARM") ], LIBS=[libar]) sysincdirs = ("eth", "include", "ipv4", "lwip-eth", "lwip-sys") for root, _, files in walk(lib_dir): if (not any(f.endswith(".h") for f in files) and basename(root) not in sysincdirs): continue var_dir = join("$BUILD_DIR", "FrameworkMbed%sInc%d" % (libname.upper(), crc32(root))) if var_dir in env.get("CPPPATH"): continue env.VariantDir(var_dir, root) env.Append(CPPPATH=[var_dir])
def __init__(self, env, basedir, arg=""): """Class for reading and printing stack usage statistics""" self.dir_exclusions = [] self.dir_inclusions = [] self.file_inclusions = [] self.base_dir = basedir self.cutoff = 0 self.parse_args(arg) if '-fstack-usage' not in env["CCFLAGS"]: print("Stack analysis not supported with this compiler") Exit(1)
def __instantiate_exec(target, source, env): varlist = env['varlist'] missing = [key for key in varlist if not env.has_key(key)] if missing: print >> stderr, 'error: missing variables for template instantiation:', ', '.join( missing) Exit(1) keywords = dict((key, env.subst('$' + key)) for key in varlist) instantiate(str(source[0]), str(target[0]), **keywords)
def autobuild_docproject(): """Autobuild a project that only contains documentation""" try: #Build only release information family = utilities.get_family('module_settings.json') autobuild_release(family) autobuild_documentation(family.tile) except unit_test.IOTileException as e: print(e.format()) Exit(1)
def parms(target, source, env): """Assemble various AutoConfig parameters.""" workdir = dirname(str(source[0])) params = env.get('AutoConfigParams', []) if not isinstance(params, list): print 'AutoConfigParams must be a sequence' Exit(1) targetfile = env.get('AutoConfigTarget', 'config.h') sourcefile = env.get('AutoConfigSource', 'Makefile.in') out = env.get('AutoConfigStdOut') return (workdir, params, targetfile, sourcefile, out)
def autobuild_onlycopy(): """Autobuild a project that does not require building firmware, pcb or documentation """ try: # Build only release information family = utilities.get_family('module_settings.json') autobuild_release(family) Alias('release', os.path.join('build', 'output')) Default(['release']) except unit_test.IOTileException as e: print(e.format()) Exit(1)
def BuildFrameworks(env, frameworks): if not frameworks or "uploadlazy" in COMMAND_LINE_TARGETS: return board_frameworks = env.get("BOARD_OPTIONS", {}).get("frameworks") if frameworks == ["platformio"]: if board_frameworks: frameworks.insert(0, board_frameworks[0]) else: Exit("Error: Please specify board type") for f in frameworks: if f in ("arduino", "energia"): env.ConvertInoToCpp() if f in board_frameworks: SConscript( env.subst( join("$PIOBUILDER_DIR", "scripts", "frameworks", "%s.py" % f))) else: Exit("Error: This board doesn't support %s framework!" % f)
def emitter(target, source, env): """ Add all dependencies to this library. Called by SCons.Builder internally. @todo: Check for 'TARGET' and 'CMD' in all commands. @todo: Add "Value('CREATE_FOLDER')" check for extract """ # Check if this library definition exists if not env['LIB_BUILDER'].has_key(source[0].get_contents()): print 'Error:', source[0].get_contents(), 'is not defined.' Exit(1) lib = env['LIB_BUILDER'][source[0].get_contents()] # Add all lib properties as source value dependency source.append(Value(lib)) _substituteVars(lib) if lib.has_key('URL'): download = env.Download(target=lib['ARCHIVE'], source=lib['URL']) else: download = lib['ARCHIVE'] extract = env.Extract(target=lib['FOLDER'], source=download) # Add dependencies for all CMDS for cmd in lib['CMDS']: # Get command working directory if cmd.has_key('CWD'): folder = os.path.join(Dir('.').path, cmd['CWD']) else: folder = os.path.join(Dir('.').path, lib['FOLDER']) if isinstance(cmd['TARGET'], list): cmdTarget = map(File, cmd['TARGET']) else: # TODO: Find why SCons add wierd dependencies when 'File' is use # instead of 'Value' cmdTarget = Value(cmd['TARGET']) source.append( env.Command(action=cmd['CMD'], target=cmdTarget, source=extract, chdir=folder)) return target, source
def rebuild_cog(env, *args, **kwargs): ''' forces a rebuild of all .cog files. ''' # Glob for all .cog files filelist = recursive_glob(GetLaunchDir(), "*.cog") # remove .cog targets targets = [] for f in filelist: target, _ = os.path.splitext(f) # Remove target if os.path.isfile(target): os.remove(target) targets.append(target) # Rebuild targets prefix = GetLaunchDir() os.chdir(prefix) cmd = sys.argv PYTHON = sys.executable cmd.insert(0, PYTHON) cmd.remove('--cog') cmd.append('-Q') cmd.append('--no-cache') for t in targets: cmd.append(t) ecode = os.system(" ".join(cmd)) if ecode != 0: raise RuntimeError("Failed to execute: %s" % " ".join(cmd)) Exit(0)
def BuildFramework(env): if "FRAMEWORK" not in env or "uploadlazy" in COMMAND_LINE_TARGETS: return if env['FRAMEWORK'].lower() in ("arduino", "energia"): env.ConvertInoToCpp() for f in env['FRAMEWORK'].split(","): framework = f.strip().lower() if framework in env.get("BOARD_OPTIONS", {}).get("frameworks"): SConscript( env.subst( join("$PIOBUILDER_DIR", "scripts", "frameworks", "%s.py" % framework))) else: Exit("Error: This board doesn't support %s framework!" % framework)
def parse_args(self, arg_str): """Parse the arguments""" parser = argparse.ArgumentParser(description='Stack size analyzer') parser.add_argument( '-x', '--exclude-dir', dest='xdirs', nargs='*', default=[], help="string to match indicating directories to exclude") parser.add_argument( '-I', '--include-dir', dest='dirs', nargs='*', default=[], help="string to match indicating directories to include") parser.add_argument( '-i', '--include-file', dest='files', nargs='*', default=[], help="string to match indicating a directory to include") parser.add_argument('-c', '--cutoff', dest='cutoff', default=100, type=int, help="Lower bound cutoff for entries to print") parser.add_argument( '-e', '--exit', dest='exit', default=False, action="store_true", help="Do not wait for build. Run the analysis immediately and exit." ) args = parser.parse_args(arg_str.split()) self.dir_exclusions = args.xdirs self.dir_inclusions = args.dirs self.file_inclusions = args.files self.cutoff = args.cutoff if args.exit: self.analyze() Exit(0)
def parse_user_config(filename, dependencies): ''' Read user_config and update the relevant fields ''' cparse = ConfigParser() cparse.read(filename) for dep_name in cparse.sections(): if not dep_name in dependencies.keys(): print('!! user_config specifies unknown dependency "{0}"'.format(dep_name)) Exit(0) # loop over options for that dependencies for opt in cparse.options(dep_name): if opt in VALID_FIELDS: dependencies[dep_name].__setattr__(opt, cparse.get(dep_name, opt)) else: print "Unknown build option: {0} for dependency {1}".format(opt, dep_name)
def parms(target, source, env): """Assemble various Make parameters.""" if 'MakePath' not in env: print "Make builder requires MakePath variable" Exit(1) make_path = env.subst(str(env['MakePath'])) make_cmd = 'make' if 'MakeCmd' in env: make_cmd = env.subst(env['MakeCmd']) elif 'MAKE' in env: make_cmd = env.subst(env['MAKE']) make_env = None if env.get('CROSS_BUILD'): make_env = env['CROSS_ENV'] if 'MakeEnv' in env: if make_env == None: make_env = {} else: # We're appending to an existing dictionary, so create a copy # instead of appending to the original env['CROSS_ENV'] make_env = env['CROSS_ENV'][:] for (k, v) in env['MakeEnv'].items(): make_env[k] = v make_opts = None if 'MakeOpts' in env: make_opts = env.subst(env['MakeOpts']) make_jobs = GetOption('num_jobs') if 'MakeOneThread' in env and env['MakeOneThread']: make_jobs = 1 make_targets = None if 'MakeTargets' in env: make_targets = env.subst(env['MakeTargets']) out = env.get('MakeStdOut') return (make_path, make_env, make_targets, make_cmd, make_jobs, make_opts, out)
def WaitForNewSerialPort(_, before): new_port = None elapsed = 0 while elapsed < 10: now = [i['port'] for i in get_serialports()] diff = list(set(now) - set(before)) if diff: new_port = diff[0] break before = now sleep(0.25) elapsed += 0.25 if not new_port: Exit("Error: Couldn't find a board on the selected port. " "Check that you have the correct port selected. " "If it is correct, try pressing the board's reset " "button after initiating the upload.") return new_port
def autobuild_arm_library(libname): try: # Build for all targets family = utilities.get_family('module_settings.json') family.for_all_targets( family.tile.short_name, lambda x: arm.build_library(family.tile, libname, x)) # Build all unit tests unit_test.build_units(os.path.join('firmware', 'test'), family.targets(family.tile.short_name)) Alias('release', os.path.join('build', 'output')) Alias('test', os.path.join('build', 'test', 'output')) Default(['release', 'test']) autobuild_release(family) if os.path.exists('doc'): autobuild_documentation(family.tile) except unit_test.IOTileException as e: print(e.format()) Exit(1)
DefaultEnvironment(tools=["default", "platformio"], toolpath=[join("$PIOBUILDER_DIR", "tools")], variables=commonvars, PIOBUILDER_DIR=join(get_source_dir(), "builder"), PROJECT_DIR=get_project_dir(), PIOENVS_DIR=get_pioenvs_dir(), PLATFORMIOHOME_DIR=get_home_dir(), PLATFORM_DIR=join("$PLATFORMIOHOME_DIR", "$PLATFORM"), PLATFORMFW_DIR=join("$PLATFORM_DIR", "frameworks", "$FRAMEWORK"), PLATFORMTOOLS_DIR=join("$PLATFORM_DIR", "tools"), BUILD_DIR=join("$PIOENVS_DIR", "$PIOENV"), LIBSOURCE_DIRS=[ join("$PROJECT_DIR", "lib"), get_lib_dir(), join("$PLATFORMFW_DIR", "libraries"), ]) env = DefaultEnvironment() if not isdir(env['PLATFORMIOHOME_DIR']): Exit("You haven't installed any platforms yet. Please use " "`platformio install` command") elif not isdir(env.subst("$PLATFORM_DIR")): Exit("An '%s' platform hasn't been installed yet. Please use " "`platformio install %s` command" % (env['PLATFORM'], env['PLATFORM'])) SConscriptChdir(0) SConscript(env.subst(join("$PIOBUILDER_DIR", "scripts", "${PLATFORM}.py")))
if "UPLOAD_PROTOCOL" not in env: env.Replace( UPLOAD_PROTOCOL="${BOARD_OPTIONS['upload'].get('protocol', None)}") if "UPLOAD_SPEED" not in env: env.Replace( UPLOAD_SPEED="${BOARD_OPTIONS['upload'].get('speed', None)}") if "ldscript" in env.get("BOARD_OPTIONS", {}).get("build", {}): env.Replace( LDSCRIPT_PATH=(env['BOARD_OPTIONS']['build']['ldscript'] if isfile( env['BOARD_OPTIONS']['build']['ldscript'] ) else join("$PIOHOME_DIR", "packages", "ldscripts", "${BOARD_OPTIONS['build']['ldscript']}"))) if env['PLATFORM'] != env.get("BOARD_OPTIONS", {}).get("platform"): Exit("Error: '%s' platform doesn't support this board. " "Use '%s' platform instead." % (env['PLATFORM'], env.get("BOARD_OPTIONS", {}).get("platform"))) for opt in ("LIB_IGNORE", "LIB_USE"): if opt not in env: continue env[opt] = [l.strip() for l in env[opt].split(",") if l.strip()] env.PrependENVPath( "PATH", env.subst(join("$PIOPACKAGES_DIR", "$PIOPACKAGE_TOOLCHAIN", "bin"))) SConscriptChdir(0) SConscript(env.subst("$BUILD_SCRIPT")) if getenv("PLATFORMIO_EXTRA_SCRIPT", env.get("EXTRA_SCRIPT", None)):
def base_setup(env, prereqs=None): """Setup the scons environment for the compiler Include all our preferred compile options for the chosen compiler and build type. """ if GetOption('help') or GetOption('clean'): return compiler = env['CC'] build_type = env['BUILD_TYPE'] print(f'Setting up compile environment for {compiler}') print(f"Build type is '{build_type}'") prev_compiler = env.get('BSETUP', False) if prev_compiler: if prev_compiler != compiler: print('Env is already setup for a different compiler') print('Env already setup') Exit(2) # Turn on -Wall first, then DESIRED_FLAGS may disable some of the options # that this brings in. env.Append(CCFLAGS=['-g', '-Wshadow', '-Wall', '-fpic']) env.AppendIfSupported(CCFLAGS=DESIRED_FLAGS) if build_type == 'debug': if compiler == 'gcc': env.AppendUnique(CCFLAGS=['-Og']) else: env.AppendUnique(CCFLAGS=['-O0']) else: if build_type == 'release': env.AppendUnique(CPPDEFINES='DAOS_BUILD_RELEASE') env.AppendUnique(CCFLAGS=['-O2']) env.AppendUnique(CPPDEFINES={'_FORTIFY_SOURCE': '2'}) if build_type != 'release': env.AppendUnique(CPPDEFINES={'FAULT_INJECTION': '1'}) env.AppendUnique(CPPDEFINES={'CMOCKA_FILTER_SUPPORTED': '0'}) env.AppendUnique(CPPDEFINES='_GNU_SOURCE') cenv = env.Clone() cenv.Append(CFLAGS='-Werror') config = Configure(cenv) if config.CheckHeader('stdatomic.h'): config.Finish() env.AppendUnique(CPPDEFINES={'HAVE_STDATOMIC': '1'}) elif prereqs: config.Finish() prereqs.require(env, 'openpa', headers_only=True) else: config.Finish() if compiler == 'icx' and not GetOption('no_rpath'): # Hack to add rpaths for path in env['ENV']['LD_LIBRARY_PATH'].split(':'): if 'oneapi' in path: env.AppendUnique(RPATH_FULL=[path]) if GetOption('preprocess'): # Could refine this but for now, just assume these warnings are ok env.AppendIfSupported(CCFLAGS=PP_ONLY_FLAGS) env['BSETUP'] = compiler
def sanity_checks(conf): if not conf.CheckCXX(): print('!! C++ compiler is not available...') Exit(0)
testbench = None SIMULNAME = '' TARGET_SIM = '' # clean if len(COMMAND_LINE_TARGETS) == 0: if testbench is not None: # -- Simulation name testbench_file = os.path.split(testbench)[-1] SIMULNAME, ext = os.path.splitext(testbench_file) # sim elif 'sim' in COMMAND_LINE_TARGETS: if testbench is None: print('---> ERROR: NO testbench found for simulation') Exit(1) # -- Simulation name testbench_file = os.path.split(testbench)[-1] SIMULNAME, ext = os.path.splitext(testbench_file) # -- Target sim name if SIMULNAME: TARGET_SIM = join(env.subst('$BUILD_DIR'), SIMULNAME).replace('\\', '\\\\') # --- Get the synthesis files. They are ALL the files except the testbench src_synth = [f for f in src_sim if f not in list_tb] # -- Get the PCF file src_dir = env.subst('$PROJECTSRC_DIR') PCFs = join(src_dir, '*.pcf')
if len(list_tb) > 1: print "---> WARNING: More than one testbenches used" # -- Error checking try: testbench = list_tb[0] # -- there is no testbench except IndexError: testbench = None if 'sim' in COMMAND_LINE_TARGETS: if testbench is None: print "---> ERROR: NO testbench found for simulation" Exit(1) # -- Simulation name testbench_file = os.path.split(testbench)[-1] SIMULNAME, ext = os.path.splitext(testbench_file) else: SIMULNAME = '' TARGET_SIM = join(env.subst('$BUILD_DIR'), SIMULNAME) # --- Get the synthesis files. They are ALL the files except the testbench src_synth = [f for f in src_sim if f not in list_tb] # -- For debugging print "Testbench: %s" % testbench
""" import platform from os.path import isfile, join from SCons.Script import (COMMAND_LINE_TARGETS, AlwaysBuild, Default, DefaultEnvironment, Exit, SConscript) env = DefaultEnvironment() SConscript(env.subst(join("$PIOBUILDER_DIR", "scripts", "basearm.py"))) if env['UPLOAD_PROTOCOL'] == "gdb": if not isfile(join(env.subst("$PROJECT_DIR"), "upload.gdb")): Exit("You are using GDB as firmware uploader. " "Please specify upload commands in upload.gdb " "file in project directory!") env.Replace(UPLOADER=join("$PIOPACKAGES_DIR", "toolchain-gccarmnoneeabi", "bin", "arm-none-eabi-gdb"), UPLOADERFLAGS=[ join("$BUILD_DIR", "firmware.elf"), "-batch", "-x", join("$PROJECT_DIR", "upload.gdb") ], UPLOADCMD="$UPLOADER $UPLOADERFLAGS") else: env.Replace( UPLOADER=join("$PIOPACKAGES_DIR", "tool-stlink", "st-flash"), UPLOADERFLAGS=[ "write", # write in flash "$SOURCES", # firmware path to flash "0x08000000" # flash start adress
uploadeep = env.Alias( "uploadeep", target_eep, [lambda target, source, env: before_upload(), "$UPLOADEEPCMD"]) AlwaysBuild(uploadeep) # # Check for $UPLOAD_PORT variable # is_uptarget = (set(["upload", "uploadlazy", "uploadeep"]) & set(COMMAND_LINE_TARGETS)) if is_uptarget: # try autodetect upload port if "UPLOAD_PORT" not in env: for item in get_serialports(): if "VID:PID" in item['hwid']: print "Auto-detected UPLOAD_PORT: %s" % item['port'] env.Replace(UPLOAD_PORT=item['port']) break if "UPLOAD_PORT" not in env: Exit("Please specify environment 'upload_port' or use global " "--upload-port option.") # # Setup default targets # Default(target_hex)
if len(list_tb) > 1: print "---> WARNING: More than one testbenches used" # -- Error checking try: testbench = list_tb[0] # -- there is no testbench except IndexError: testbench = None if 'sim' in COMMAND_LINE_TARGETS: if testbench is None: print "ERROR!!! NO testbench found for simulation" Exit(1) # -- Simulation name testbench_file = os.path.split(testbench)[-1] SIMULNAME, ext = os.path.splitext(testbench_file) else: SIMULNAME = '' TARGET_SIM = join(env.subst('$BUILD_DIR'), SIMULNAME) # -------- Get the synthesis files. They are ALL the files except the # -------- testbench src_synth = [f for f in src_sim if f not in list_tb] # -- For debugging print "Testbench: %s" % testbench