Removed execute permissions from non-executable files.
[platform/upstream/iotivity.git] / build_common / arduino / SConscript
index d33cc55..4c3a01f 100644 (file)
 import os
 import platform
 
-Import('env', 'RELEASE_BUILD', 'TARGET_CPU_ARCH', 'ARDUINO_HOME')
+Import('env')
 
-if not ARDUINO_HOME:
+def __parse_config(f):
+       dict = {}
+
+       if not os.path.isfile(f):
+               return dict
+
+       file = open(f, 'r')
+       strs = file.readlines()
+       for str in strs:
+               str = str.strip()
+               if len(str) > 0 and str[0] == '#':
+                       continue
+
+               idx = str.find('=')
+               if idx > 0:
+                       dict.setdefault(str[0:idx], str[idx + 1:])
+
+       return dict
+
+def __get_boards(dict):
+       boards = []
+       keys = dict.keys()
+       for key in keys:
+               idx = key.find('.name')
+               if idx > 0:
+                       if key.endswith('.name'):
+                               boards.append(key[0:idx])
+       return boards
+
+def __get_cpu(dict, board):
+       cpus = []
+       keys = dict.keys()
+       for key in keys:
+               idx = key.find(board + '.menu.cpu.')
+               start = len(board + '.menu.cpu.')
+               if idx >= 0:
+                       end = key.find('.', start)
+                       if end > 0:
+                               cpu = key[start:end]
+                               exist = False
+                               for c in cpus:
+                                       if c == cpu:
+                                               exist = True
+                                               break
+
+                               if not exist:
+                                       cpus.append(cpu)
+       return cpus
+
+def __get_board_info(board, key):
+       if cpu:
+               v = boards_info.get(board + '.menu.cpu.' + cpu + key)
+               if not v:
+                       v = boards_info.get(board + key)
+       else:
+               v = boards_info.get(board + key)
+       return v
+
+def __search_files(path, pattern, ondisk=True, source=True, strings=False, recursive=True):
+       if not recursive:
+               return Glob(pattern, ondisk, source, strings)
+
+       matches = []
+       for root, dirnames, filenames in os.walk(path):
+               matches.extend(Glob(root + '/' + pattern, ondisk, source, strings))
+
+       return matches
+
+# To make sure the src is built in 'BUILD_DIR' (by default it will be built at
+# the same directory as the .c .cpp .S)
+def __src_to_obj(env, srcs):
+       objs = []
+       prefix = env.get('BOARD') + '_'
+       if env.get('CPU'):
+               prefix += env.get('CPU') + '_'
+
+       build_dir = env.get('BUILD_DIR') + '/arduino/'
+       for src in srcs:
+               obj = src.path.replace(arduino_home, build_dir)
+               i = obj.rfind('.')
+               obj = obj[0:i]
+               if env.get('OBJSUFFIX'):
+                       obj += env.get('OBJSUFFIX')
+               objs.extend(env.Object(obj, src, OBJPREFIX=prefix))
+       return objs
+
+def __import_lib(env, lib):
+       lib_path = arduino_home + '/libraries/' + lib
+       if not os.path.exists(lib_path):
+               if target_arch == 'avr':
+                       lib_path = arduino_home + '/hardware/arduino/avr/libraries/' + lib
+               else:
+                       lib_path = arduino_home + '/hardware/arduino/sam/libraries/' + lib
+
+       if os.path.exists(lib_path + '/src'):
+               lib_path = lib_path + '/src'
+
+       env.AppendUnique(CPPPATH = [lib_path])
+
+       if os.path.exists(lib_path + '/utility'):
+               env.AppendUnique(CPPPATH = [lib_path + '/utility'])
+
+       lib_src = []
+       lib_src.extend(__search_files(lib_path, '*.S'))
+       lib_src.extend(__search_files(lib_path, '*.c'))
+       lib_src.extend(__search_files(lib_path, '*.cpp'))
+
+       build_dir = env.get('BUILD_DIR')
+       if build_dir:
+               lib_a = env.StaticLibrary(build_dir + lib, __src_to_obj(env, lib_src))
+       else:
+               lib_a = env.StaticLibrary(lib, __src_to_obj(env, lib_src))
+       env.AppendUnique(LIBS = [File(lib_a[0])])
+
+def __build_core(env):
+       core_src = __search_files(core_folder, '*.S')
+       core_src.extend(__search_files(core_folder, '*.c'))
+       core_src.extend(__search_files(core_folder, '*.cpp'))
+
+       core_src.extend(__search_files(variant_folder, '*.S'))
+       core_src.extend(__search_files(variant_folder, '*.c'))
+       core_src.extend(__search_files(variant_folder, '*.cpp'))
+
+       core_obj = __src_to_obj(env, core_src)
+       build_dir = env.get('BUILD_DIR')
+       if build_dir:
+               s_core = env.StaticLibrary(build_dir + 'core', core_obj)
+       else:
+               s_core = env.StaticLibrary('core', core_obj)
+       env.AppendUnique(LIBS = [File(s_core[0])])
+
+       # To avoid compiler issue. Otherewise there may be warnings:
+       #       undefined reference to '_exit' '_close', '_getpid' ...
+       # Above functions are used in libc.a and implemented in syscalls_sam3.c
+       if env.get('TARGET_ARCH') == 'arm':
+               for obj in core_obj:
+                       if obj.name.endswith('syscalls_sam3.o'):
+                               env.AppendUnique(LIBS = [File(obj)])
+
+def __create_bin(env, source):
+       name = source
+       if env.get('TARGET_ARCH') == 'avr':
+               eep = env.Command(name + '.eep', source, 'avr-objcopy -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 $SOURCE $TARGET')
+               hex = env.Command(name + '.hex', source, 'avr-objcopy -O ihex -R .eeprom $SOURCE $TARGET')
+       else:
+               hex = env.Command(name + '.hex', source, 'arm-none-eabi-objcopy -O binary $SOURCE $TARGET')
+
+# Print the command line that to upload binary to the board
+def __upload_help(env):
+       if target_arch == 'avr':
+               protocol = __get_board_info(board, '.upload.protocol')
+               speed = __get_board_info(board, '.upload.speed')
+
+               upload_cmd = arduino_home + '/hardware/tools/avr/bin/avrdude -C' + arduino_home +'/hardware/tools/avr/etc/avrdude.conf -v -v -v -v -p' \
+       + mcu + ' -c' + protocol + ' -P<serial_port>' + ' -b' + speed + ' -D -Uflash:w:<hex_file>:i'
+       else:
+               uu = __get_board_info(board, '.upload.native_usb')
+               upload_cmd = arduino_home + '/hardware/tools/bossac -i -d --port=<serial_port> -U ' + uu + ' -e -w -v -b <bin file> -R'
+
+       Help('''
+===============================================================================
+You can upload the bin file with following command line:
+''')
+       Help('\n   $ ' + upload_cmd)
+       Help('''
+\nPlease replace <xxx> according to the actual situation.
+===============================================================================
+''')
+
+# ARDUINO_HOME build option
+help_vars = Variables()
+help_vars.Add(PathVariable('ARDUINO_HOME', 'ARDUINO root directory', os.environ.get('ARDUINO_HOME')))
+help_vars.Update(env)
+Help(help_vars.GenerateHelpText(env))
+
+target_arch = env.get('TARGET_ARCH')
+arduino_home = env.get('ARDUINO_HOME')
+if not arduino_home:
        print '''
 ************************************* Error ***********************************
-*   Arduino root directory (ARDUINO_HOME) isn't set, you can set enviornment  *
-* variable ARDUINO_HOME or add it in command line as:                         *
+*   Arduino root directory isn't set, you can set enviornment variable        *
+* ARDUINO_HOME or add it in command line as:                                  *
 *      # scons ARDUINO_HOME=<path to arduino root directory> ...              *
 *******************************************************************************
 '''
@@ -32,53 +209,192 @@ elif platform.system().lower() == 'darwin':
        env['LIBSUFFIXES'] = ['.a', '.so']
        env['PROGSUFFIX'] = ''
 
-# Set toolchain
-def find_toolchain(dir, tc):
-       for root, dirs, files in os.walk(dir, True, None, False):
-               for f in files:
-                       lf = f.lower()
-                       if lf == tc:
-                               return root
-       return None
-
-if TARGET_CPU_ARCH == 'arm':
-       prefix = 'arm-none-eabi-'
+# Debug/release relative flags
+if env.get('RELEASE'):
+       env.AppendUnique(CCFLAGS = ['-Os'])
+       env.AppendUnique(CPPDEFINES = ['NDEBUG'])
 else:
-       prefix = 'avr-'
+       env.AppendUnique(CCFLAGS = ['-g'])
+
+# BOARD / CPU option
 
-tc_path = find_toolchain(ARDUINO_HOME + '/hardware/tools/', prefix + 'g++')
-if not tc_path:
+# Get IDE version
+if os.path.exists(arduino_home + '/lib/version.txt'):
+       vf = open(arduino_home + '/lib/version.txt', 'r')
+       version = vf.readline().replace('.', '')
+else:
        print '''
 ************************************* Error ***********************************
-*   Arduino toolchain isn't detected. Please specify the toolchain prefix and *
-* path, you can do it by setting enviornment variable TC_PREFIX and TC_PATH or*
-* add it in command line as:                                                  *
-*     # scons TC_PREFIX=<prefix> TC_PATH=<path to toolchain> ...              *
-* e.g. scons TC_PREFIX=avr- TC_PATH=/opt/arduino-1.5.7/hardware/tools/avr/bin *                                                                         *
-* Note: TC_PREFIX shouldn't include path                                      *
+* Can't find version file (lib/version.txt), please check if (%s)
+* is arduino root directory.                                                  *
 *******************************************************************************
-'''
+''' % arduino_home
        Exit(1)
 
-env.PrependENVPath('PATH', tc_path)
-env.Replace(CC = prefix + 'gcc')
-env.Replace(CXX = prefix + 'g++')
-env.Replace(AR = prefix + 'ar')
-env.Replace(AS = prefix + 'as')
-env.Replace(LINK = prefix + 'ld')
-env.Replace(RANLIB = prefix + 'ranlib')
+if version[0:2] == '10':
+       is_1_0_x = True
+       boards_info = __parse_config(arduino_home + '/hardware/arduino/boards.txt')
+       env.PrependENVPath('PATH', arduino_home + '/hardware/tools/avr/bin/')
+       env.Replace(CC = 'avr-gcc')
+       env.Replace(CXX = 'avr-g++')
+       env.Replace(AR = 'avr-ar')
+       env.Replace(AS = 'avr-as')
+       env.Replace(LINK = 'avr-gcc')
+       env.Replace(RANLIB = 'avr-ranlib')
+       if target_arch != 'avr':
+               print '''
+************************************* Error ***********************************
+* Arduino 1.0.x IDE only support 'avr', to support other arch at least 1.5.x  *
+* is required.
+*******************************************************************************
+'''
+               Exit(1)
+else:
+       is_1_0_x = False
+       if target_arch == 'avr':
+               boards_info = __parse_config(arduino_home + '/hardware/arduino/avr/boards.txt')
+               platform_info = __parse_config(arduino_home + '/hardware/arduino/avr/platform.txt')
+       elif target_arch == 'arm':
+               boards_info = __parse_config(arduino_home + '/hardware/arduino/sam/boards.txt')
+               platform_info = __parse_config(arduino_home + '/hardware/arduino/sam/platform.txt')
+       else:
+               print '''
+************************************* Error ***********************************
+* CPU arch %s isn't supported currently.
+*******************************************************************************
+''' % target_arch
 
-sys_root = os.path.abspath(os.path.join(tc_path, '..'))
-env.AppendUnique(CFLAGS = ['--sysroot=' + sys_root])
-env.AppendUnique(CXXFLAGS = ['--sysroot=' + sys_root])
-env.AppendUnique(LINKFLAGS = ['--sysroot=' + sys_root])
+#Board option, let user to select the board
+boards = __get_boards(boards_info)
+help_vars = Variables()
+help_vars.Add(EnumVariable('BOARD', 'arduino board', boards[0], boards))
+help_vars.Update(env)
+Help(help_vars.GenerateHelpText(env))
 
-# Debug/release relative flags
-if RELEASE_BUILD:
-       env.AppendUnique(CFLAGS = ['-Os'])
-       env.AppendUnique(CXXFLAGS = ['-Os'])
-       env.AppendUnique(CPPDEFINES = ['NDEBUG'])
-       env.AppendUnique(LINKFLAGS = ['-s'])
+#CPU option
+board = env.get('BOARD')
+cpus = __get_cpu(boards_info, board)
+if len(cpus) > 0:
+       help_vars = Variables()
+       help_vars.Add(EnumVariable('CPU', 'arduino board cpu', cpus[0], cpus))
+       help_vars.Update(env)
+       Help(help_vars.GenerateHelpText(env))
+
+# Arduino commom flags
+cpu = env.get('CPU')
+board = env.get('BOARD')
+mcu = __get_board_info(board, '.build.mcu')
+f_cpu = __get_board_info(board, '.build.f_cpu')
+usb_vid = __get_board_info(board, '.build.vid')
+usb_pid = __get_board_info(board, '.build.pid')
+variant = __get_board_info(board, '.build.variant')
+
+if not usb_vid:
+       usb_vid = __get_board_info(board, '.vid.0')
+if not usb_pid:
+       usb_pid = __get_board_info(board, '.pid.0')
+
+if is_1_0_x:
+       core_base = arduino_home + '/hardware/arduino/'
 else:
-       env.AppendUnique(CFLAGS = ['-g'])
-       env.AppendUnique(CXXFLAGS = ['-g'])
\ No newline at end of file
+       if target_arch == 'avr':
+               core_base = arduino_home + '/hardware/arduino/avr/'
+       else:
+               core_base = arduino_home + '/hardware/arduino/sam/'
+
+variant_folder = core_base + 'variants/' + variant
+env.AppendUnique(CPPPATH = [variant_folder])
+
+core = __get_board_info(board, '.build.core')
+core_folder = core_base + 'cores/' + core + '/'
+env.AppendUnique(CPPPATH = [core_folder])
+
+if is_1_0_x:
+       comm_flags = []
+       if mcu:
+               comm_flags.extend(['-mmcu=' + mcu])
+       if f_cpu:
+               comm_flags.extend(['-DF_CPU=' + f_cpu])
+       comm_flags.extend(['-DARDUINO=' + version])
+       if usb_vid:
+               comm_flags.extend(['-DUSB_VID=' + usb_vid])
+       if usb_pid:
+               comm_flags.extend(['-DUSB_PID=' + usb_pid])
+
+       env.AppendUnique(ASFLAGS = ['-x', 'assembler-with-cpp'])
+       env.AppendUnique(ASFLAGS = comm_flags)
+
+       env.AppendUnique(CFLAGS = ['-Os', '-ffunction-sections', '-fdata-sections', '-MMD'])
+       env.AppendUnique(CFLAGS = comm_flags)
+
+       env.AppendUnique(CXXFLAGS = ['-Os', '-fno-exceptions', '-ffunction-sections', '-fdata-sections','-MMD'])
+       env.AppendUnique(CXXFLAGS = comm_flags)
+
+       env.AppendUnique(LINKFLAGS = ['-Os'])
+       if mcu == 'atmega2560':
+               env.AppendUnique(LINKFLAGS = ['-Wl,--gc-sections,--relax'])
+       else:
+               env.AppendUnique(LINKFLAGS = ['-Wl,--gc-sections'])
+       env.AppendUnique(LINKFLAGS = ['-mmcu=' + mcu])
+else:
+       if target_arch == 'avr':
+               cpu_flag = '-mmcu=' + mcu
+       else:
+               cpu_flag = '-mcpu=' + mcu
+
+       comm_flag = [cpu_flag, '-DF_CPU=' + f_cpu, '-DARDUINO=' + version, '-DARDUINO_' + __get_board_info(board, '.build.board')]
+       if target_arch == 'arm':
+               comm_flag.extend(['-DARDUINO_ARCH_SAM'])
+       else:
+               comm_flag.extend(['-DARDUINO_ARCH_AVR'])
+
+       compiler_path = platform_info.get('compiler.path')
+       compiler_path = compiler_path.replace('{runtime.ide.path}', arduino_home)
+       env.PrependENVPath('PATH', compiler_path)
+       env.Replace(CC = platform_info.get('compiler.c.cmd'))
+       env.Replace(CXX = platform_info.get('compiler.cpp.cmd'))
+       env.Replace(AR = platform_info.get('compiler.ar.cmd'))
+       if target_arch == 'arm':
+               env.AppendUnique(CPPPATH = [arduino_home + '/hardware/arduino/sam/system/libsam',
+                                                       arduino_home + '/hardware/arduino/sam/system/CMSIS/CMSIS/Include/',
+                                                       arduino_home + '/hardware/arduino/sam/system//CMSIS/Device/ATMEL'])
+       env.AppendUnique(ASFLAGS = ['-x', 'assembler-with-cpp'])
+       env.AppendUnique(ASFLAGS = comm_flag)
+       env.AppendUnique(CFLAGS = Split(platform_info.get('compiler.c.flags')))
+       env.AppendUnique(CXXFLAGS = Split(platform_info.get('compiler.cpp.flags')))
+       env.AppendUnique(ARFLAGS = Split(platform_info.get('compiler.ar.flags')))
+       env.AppendUnique(CCFLAGS = comm_flag)
+
+       extra_flags = __get_board_info(board, '.build.extra_flags')
+       if extra_flags:
+               extra_flags = extra_flags.replace('{build.usb_flags}', '')
+               env.AppendUnique(CCFLAGS = Split(extra_flags))
+               usb_flags = ['-DUSB_VID=' + usb_vid, '-DUSB_PID=' + usb_pid, '-DUSBCON', '-DUSB_MANUFACTURER="Unknown"']
+               env.AppendUnique(CCFLAGS = usb_flags)
+
+       if target_arch == 'arm':
+               env.AppendUnique(LINKFLAGS = ['-Os', '-Wl,--gc-sections', cpu_flag,
+                                       '-T' + variant_folder + '/' + __get_board_info(board, '.build.ldscript'),
+                                       '-Wl,-Map,' + env.get('BUILD_DIR') + 'arduino_prj.map'])
+               env.AppendUnique(LINKFLAGS = Split('-lm -lgcc -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group'))
+
+               variant_system_lib = __get_board_info(board, '.build.variant_system_lib')
+               if variant_system_lib:
+                       if variant_folder.find(' ') >= 0:
+                               variant_folder = '"' + variant_folder + '"'
+                       env.Replace(LINKCOM = '$LINK -o $TARGET $_LIBDIRFLAGS $LINKFLAGS $SOURCES $_LIBFLAGS '
+                                       + variant_folder + '/' + variant_system_lib + ' -Wl,--end-group')
+               else:
+                       env.Replace(LINKCOM = '$LINK -o $TARGET $_LIBDIRFLAGS $LINKFLAGS $SOURCES $_LIBFLAGS -Wl,--end-group')
+       else:
+               env.AppendUnique(LINKFLAGS = Split(platform_info.get('compiler.c.elf.flags')))
+               env.AppendUnique(LINKFLAGS = [cpu_flag])
+               env.AppendUnique(LIBS = 'm')
+       env.Replace(ARCOM = '$AR ' + platform_info.get('compiler.ar.flags') + ' $TARGET $SOURCES')
+
+__build_core(env)
+
+env.AddMethod(__import_lib, "ImportLib") #import arduino library
+#env.AddMethod(__build_core, "BuildCore") #build arduino core
+env.AddMethod(__create_bin, "CreateBin") #create binary files(.eep and .hex)
+env.AddMethod(__upload_help, "UploadHelp") #print the command line that to upload binary to the boardf