Skip to content

Commit

Permalink
Merge branch 'upstream-codal' into nrf52833-mbedos
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesadevine committed Nov 18, 2019
2 parents 2dc2160 + 983084c commit e6ad2ba
Show file tree
Hide file tree
Showing 19 changed files with 2,518 additions and 209 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ Makefile
*.bin
pxtapp
buildcache.json
*.pyc
81 changes: 28 additions & 53 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ include(utils/cmake/JSONParser.cmake)
include(utils/cmake/util.cmake)
include(utils/cmake/colours.cmake)

if (NOT "${BUILD_TOOL}" STRGREATER "")
set(BUILD_TOOL "CODAL")
endif()

#
# Supress unecessary (and often inaccurate) validity check of the toolchain
#
Expand Down Expand Up @@ -173,8 +177,11 @@ endif()

# create a header file from the definitions specified in JSON
if("${CODAL_DEFINITIONS}" STRGREATER "")
set(EXTRA_INCLUDES_NEW_PATH "${PROJECT_SOURCE_DIR}/build/codal_extra_definitions_new.h")
set(EXTRA_INCLUDES_PATH "${PROJECT_SOURCE_DIR}/build/codal_extra_definitions.h")
file(WRITE "${EXTRA_INCLUDES_PATH}" ${CODAL_DEFINITIONS})
file(WRITE "${EXTRA_INCLUDES_NEW_PATH}" ${CODAL_DEFINITIONS})
configure_file(${EXTRA_INCLUDES_NEW_PATH} ${EXTRA_INCLUDES_PATH} COPYONLY)

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -include ${EXTRA_INCLUDES_PATH}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -include ${EXTRA_INCLUDES_PATH}")
endif()
Expand Down Expand Up @@ -204,11 +211,16 @@ if("${device.libraries}" STRGREATER "")

foreach(i ${DEVICE_LIBS})
SET(BRANCH "NONE")
SET(URL "${device.libraries_${i}.url}")
if("${device.libraries_${i}.branch}" STRGREATER "")
SET(BRANCH "${device.libraries_${i}.branch}")
endif()
if("${codal.target.branches.${URL}}" STRGREATER "")
SET(BRANCH "${codal.target.branches.${URL}}")
MESSAGE (STATUS "Override branch: ${BRANCH}")
endif()

INSTALL_DEPENDENCY(${LIB_DEST} ${device.libraries_${i}.name} ${device.libraries_${i}.url} ${BRANCH} ${device.libraries_${i}.type})
INSTALL_DEPENDENCY(${LIB_DEST} ${device.libraries_${i}.name} ${URL} ${BRANCH} ${device.libraries_${i}.type})
list(APPEND CODAL_DEPS "${device.libraries_${i}.name}")
endforeach()

Expand All @@ -220,65 +232,28 @@ endif()

#finally, find sources and includes of the application, and create a target.
RECURSIVE_FIND_DIR(INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/${CODAL_APP_SOURCE_DIR}" "*.h")
RECURSIVE_FIND_FILE(SOURCE_FILES "${PROJECT_SOURCE_DIR}/${CODAL_APP_SOURCE_DIR}" "*.c??")
# *.c?? only catches .cpp, not .c, so let's be precise
RECURSIVE_FIND_FILE(SOURCE_FILES "${PROJECT_SOURCE_DIR}/${CODAL_APP_SOURCE_DIR}" "*.cpp")

RECURSIVE_FIND_FILE(S_FILES "${PROJECT_SOURCE_DIR}/${CODAL_APP_SOURCE_DIR}" "*.s")
RECURSIVE_FIND_FILE(C_FILES "${PROJECT_SOURCE_DIR}/${CODAL_APP_SOURCE_DIR}" "*.c")
list(APPEND SOURCE_FILES ${S_FILES})
list(APPEND SOURCE_FILES ${C_FILES})

if("${SOURCE_FILES}" STREQUAL "")
message(FATAL_ERROR "${BoldRed}No user application to build, please add a main.cpp at: ${PROJECT_SOURCE_DIR}/${CODAL_APP_SOURCE_DIR}${ColourReset}")
endif()

add_executable(
${device.device}
${SOURCE_FILES}
)

if("${INCLUDE_DIRS}" STRGREATER "")
target_include_directories(${device.device} PUBLIC "${INCLUDE_DIRS}")
endif()

set_target_properties(${device.device} PROPERTIES SUFFIX "" ENABLE_EXPORTS ON)
if ("${BUILD_TOOL}" STRGREATER "")
string(COMPARE EQUAL "${BUILD_TOOL}" "YOTTA" YOTTA_BUILD)
if (${YOTTA_BUILD})
include("${PROJECT_SOURCE_DIR}/utils/cmake/buildtools/yotta.cmake")
endif ()

# link the executable with supporting libraries.
target_link_libraries(
${device.device}
${CODAL_DEPS}
)

# import toolchain bin generation command
if(${device.generate_bin})
include(${TOOLCHAIN_FOLDER}/bin-generator.cmake)
endif()

# import toolchain hex generation command
if(${device.generate_hex})
include(${TOOLCHAIN_FOLDER}/hex-generator.cmake)
endif()

# post process command hook, depends on the hex file generated by the build system.
if("${device.post_process}" STRGREATER "")

# replace specific strings in the command, this gives users flexibility, they don't have to manually specify the location of files
string(REPLACE "<OUTPUT_HEX_LOCATION>" ${PROJECT_SOURCE_DIR}/${CODAL_APP_OUTPUT_DIR}/${device.device}.hex CODAL_POSTPROCESS_COMMAND ${device.post_process})
string(REPLACE "<OUTPUT_HEX_DESTINATION>" ${PROJECT_SOURCE_DIR}/${CODAL_APP_OUTPUT_DIR} CODAL_POSTPROCESS_COMMAND ${CODAL_POSTPROCESS_COMMAND})
string(REPLACE "<OUTPUT_HEX_NAME>" ${device.device} CODAL_POSTPROCESS_COMMAND ${CODAL_POSTPROCESS_COMMAND})

string(REPLACE "<OUTPUT_BIN_LOCATION>" ${PROJECT_SOURCE_DIR}/${CODAL_APP_OUTPUT_DIR}/${device.device}.bin CODAL_POSTPROCESS_COMMAND ${CODAL_POSTPROCESS_COMMAND})
string(REPLACE "<OUTPUT_BIN_DESTINATION>" ${PROJECT_SOURCE_DIR}/${CODAL_APP_OUTPUT_DIR} CODAL_POSTPROCESS_COMMAND ${CODAL_POSTPROCESS_COMMAND})
string(REPLACE "<OUTPUT_BIN_NAME>" ${device.device}.bin CODAL_POSTPROCESS_COMMAND ${CODAL_POSTPROCESS_COMMAND})

#convert to a command
separate_arguments(FINAL_COMMAND UNIX_COMMAND ${CODAL_POSTPROCESS_COMMAND})

# execute
add_custom_command(
TARGET ${device.device}_bin
COMMAND ${FINAL_COMMAND}
DEPENDS ${device.device}_bin
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
COMMENT "Executing post process command"
)
string(COMPARE EQUAL "${BUILD_TOOL}" "CODAL" CODAL_BUILD)
if (${CODAL_BUILD})
include("${PROJECT_SOURCE_DIR}/utils/cmake/buildtools/codal.cmake")
endif()
endif()

#
Expand All @@ -287,4 +262,4 @@ endif()
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
set(CMAKE_EXE_EXPORTS_C_FLAG "")
set(CMAKE_EXE_EXPORTS_CXX_FLAG "")
set(CMAKE_EXE_EXPORTS_CXX_FLAG "")
190 changes: 40 additions & 150 deletions build.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,152 +29,28 @@
import json
import shutil
import re
from utils.python.codal_utils import system, build, read_json, checkgit, read_config, update, printstatus, status, get_next_version, lock, delete_build_folder, generate_docs


def system(cmd):
if os.system(cmd) != 0:
sys.exit(1)

def build(clean):
if platform.system() == "Windows":
# configure
system("cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -G \"Ninja\"")

# build
system("ninja")
else:
# configure
system("cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -G \"Unix Makefiles\"")

if clean:
system("make clean")

# build
system("make -j 10")

def read_json(fn):
json_file = ""
with open(fn) as f:
json_file = f.read()
return json.loads(json_file)

def checkgit():
stat = os.popen('git status --porcelain').read().strip()
if stat != "":
print "Missing checkin in", os.getcwd(), "\n" + stat
exit(1)

def read_config():
codal = read_json("codal.json")
targetdir = codal['target']['name']
target = read_json("libraries/" + targetdir + "/target.json")
return (codal, targetdir, target)

def update():
(codal, targetdir, target) = read_config()
dirname = os.getcwd()
for ln in target['libraries']:
os.chdir(dirname + "/libraries/" + ln['name'])
system("git checkout " + ln['branch'])
system("git pull")
os.chdir(dirname + "/libraries/" + targetdir)
system("git pull")
os.chdir(dirname)

def printstatus():
print "\n***%s" % os.getcwd()
system("git status -s")
system("git rev-parse HEAD")
system("git branch")

def status():
(codal, targetdir, target) = read_config()
dirname = os.getcwd()
for ln in target['libraries']:
os.chdir(dirname + "/libraries/" + ln['name'])
printstatus()
os.chdir(dirname + "/libraries/" + targetdir)
printstatus()
os.chdir(dirname)
printstatus()

def get_next_version():
log = os.popen('git log -n 100').read().strip()
m = re.search('Snapshot v(\d+)\.(\d+)\.(\d+)', log)
if m is None:
print "Cannot determine next version from git log"
exit(1)
v0 = int(m.group(1))
v1 = int(m.group(2))
v2 = int(m.group(3))
if options.update_major:
v0 += 1
v1 = 0
v2 = 0
elif options.update_minor:
v1 += 1
v2 = 0
else:
v2 += 1
return "v%d.%d.%d" % (v0, v1, v2)

def lock():
(codal, targetdir, target) = read_config()
dirname = os.getcwd()
for ln in target['libraries']:
os.chdir(dirname + "/libraries/" + ln['name'])
checkgit()
stat = os.popen('git status --porcelain -b').read().strip()
if "ahead" in stat:
print "Missing push in", os.getcwd()
exit(1)
sha = os.popen('git rev-parse HEAD').read().strip()
ln['branch'] = sha
print ln['name'], sha
os.chdir(dirname + "/libraries/" + targetdir)
ver = get_next_version()
print "Creating snaphot", ver
system("git checkout target-locked.json")
checkgit()
target["snapshot_version"] = ver
with open("target-locked.json", "w") as f:
f.write(json.dumps(target, indent=4, sort_keys=True))
system("git commit -am \"Snapshot %s\"" % ver) # must match get_next_version() regex
sha = os.popen('git rev-parse HEAD').read().strip()
system("git tag %s" % ver)
system("git pull")
system("git push")
system("git push --tags")
os.chdir(dirname)
print "\nNew snapshot: %s [%s]" % (ver, sha)

def delete_build_folder(in_folder = True):
if in_folder:
os.chdir("..")

shutil.rmtree('./build')
os.mkdir("./build")

if in_folder:
os.chdir("./build")

parser = optparse.OptionParser(usage="usage: %prog target-name [options]", description="This script manages the build system for a codal device. Passing a target-name generates a codal.json for that devices, to list all devices available specify the target-name as 'ls'.")
parser = optparse.OptionParser(usage="usage: %prog target-name-or-url [options]", description="This script manages the build system for a codal device. Passing a target-name generates a codal.json for that devices, to list all devices available specify the target-name as 'ls'.")
parser.add_option('-c', '--clean', dest='clean', action="store_true", help='Whether to clean before building. Applicable only to unix based builds.', default=False)
parser.add_option('-t', '--test-platforms', dest='test_platform', action="store_true", help='Whether to clean before building. Applicable only to unix based builds.', default=False)
parser.add_option('-l', '--lock', dest='lock_target', action="store_true", help='Create target-lock.json, updating patch version', default=False)
parser.add_option('-b', '--branch', dest='branch', action="store_true", help='With -l, use vX.X.X-BRANCH.Y', default=False)
parser.add_option('-m', '--minor', dest='update_minor', action="store_true", help='With -l, update minor version', default=False)
parser.add_option('-M', '--major', dest='update_major', action="store_true", help='With -l, update major version', default=False)
parser.add_option('-V', '--version', dest='version', metavar="VERSION", help='With -l, set the version; use "-V v0.0.1" to bootstrap', default=False)
parser.add_option('-u', '--update', dest='update', action="store_true", help='git pull target and libraries', default=False)
parser.add_option('-s', '--status', dest='status', action="store_true", help='git status target and libraries', default=False)
parser.add_option('-d', '--dev', dest='dev', action="store_true", help='enable developer mode (does not use target-locked.json)', default=False)
parser.add_option('-g', '--generate-docs', dest='generate_docs', action="store_true", help='generate documentation for the current target', default=False)

(options, args) = parser.parse_args()

if not os.path.exists("build"):
os.mkdir("build")

if options.lock_target:
lock()
lock(options)
exit(0)

if options.update:
Expand All @@ -194,15 +70,15 @@ def delete_build_folder(in_folder = True):
if len(args) == 1:

target_name = args[0]
target_found = False
target_config = None

# list all targets
if target_name == "ls":
for json_obj in test_json:
print "%s: %s" % (json_obj["name"], json_obj["info"]),
s = "%s: %s" % (json_obj["name"], json_obj["info"])
if "device_url" in json_obj.keys():
print "(%s)" % json_obj["device_url"],
print ""
s += "(%s)" % json_obj["device_url"]
print(s)
exit(0)

# cycle through out targets and check for a match
Expand All @@ -213,44 +89,58 @@ def delete_build_folder(in_folder = True):
del json_obj["device_url"]
del json_obj["info"]

# developer mode is for users who wish to contribute, it will clone and checkout commitable branches.
if options.dev:
json_obj["dev"] = True
target_config = json_obj
break

config = {
"target":json_obj,
if target_config == None and target_name.startswith("http"):
target_config = {
"name": re.sub("^.*/", "", target_name),
"url": target_name,
"branch": "master",
"type": "git"
}

with open("../codal.json", 'w') as codal_json:
json.dump(config, codal_json, indent=4)
if target_config == None:
print("'" + target_name + "'" + " is not a valid target.")
exit(1)

# developer mode is for users who wish to contribute, it will clone and checkout commitable branches.
if options.dev:
target_config["dev"] = True

target_found = True
config = {
"target":target_config
}

# remove the build folder, a user could be swapping targets.
delete_build_folder()
break
with open("../codal.json", 'w') as codal_json:
json.dump(config, codal_json, indent=4)

# remove the build folder, a user could be swapping targets.
delete_build_folder()

if not target_found:
print("'" + target_name + "'" + " is not a valid target.")
exit(1)

elif len(args) > 1:
print("Too many arguments supplied, only one target can be specified.")
exit(1)

if not options.test_platform:

if not os.path.exists("../codal.json"):
print("No target specified in codal.json, does codal.json exist?")
exit(1)

if options.generate_docs:
generate_docs()
exit(0)

build(options.clean)
exit(0)

for json_obj in test_json:

# some platforms aren't supported by travis, ignore them when testing.
if "test_ignore" in json_obj:
print "ignoring: " + json_obj["name"]
print("ignoring: " + json_obj["name"])
continue

# ensure we have a clean build tree.
Expand All @@ -270,4 +160,4 @@ def delete_build_folder(in_folder = True):
with open("../codal.json", 'w') as codal_json:
json.dump(config, codal_json, indent=4)

build(True)
build(True, True)
Empty file added utils/__init__.py
Empty file.
Loading

0 comments on commit e6ad2ba

Please sign in to comment.