#! /usr/bin/env python3 # Copyright 2023 Bradley D. Nelson # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import subprocess VERSION = '7.0.7.16' STABLE_VERSION = '7.0.6.19' OLD_STABLE_VERSION = '7.0.5.4' SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) ROOT_DIR = os.path.dirname(SCRIPT_DIR) REVISION = 'TODO' #REVISION=$(shell git rev-parse HEAD | head -c 20) #REVSHORT=$(shell echo $(REVISION) | head -c 7) CFLAGS_COMMON = [ '-O2', '-I', '$src/', '-I', './', ] CFLAGS_MINIMIZE = [ '-s', '-DUEFORTH_MINIMAL', '-fno-exceptions', '-ffreestanding', '-fno-stack-protector', '-fomit-frame-pointer', '-fno-ident', '-ffunction-sections', '-fdata-sections', '-fmerge-all-constants', ] if sys.platform == 'linux': CFLAGS_MINIMIZE.append('-Wl,--build-id=none') CFLAGS = CFLAGS_COMMON + CFLAGS_MINIMIZE + [ '-std=c++11', '-Wall', '-Werror', '-no-pie', '-Wl,--gc-sections', ] if sys.platform == 'darwin': CFLAGS += [ '-Wl,-dead_strip', '-D_GNU_SOURCE', ] elif sys.platform == 'linux': CFLAGS += [ '-s', '-Wl,--gc-sections', '-no-pie', '-Wl,--build-id=none', ] STRIP_ARGS = ['-S'] if sys.platform == 'darwin': STRIP_ARGS += ['-x'] elif sys.platform == 'linux': STRIP_ARGS += [ '--strip-unneeded', '--remove-section=.note.gnu.gold-version', '--remove-section=.comment', '--remove-section=.note', '--remove-section=.note.gnu.build-id', '--remove-section=.note.ABI-tag', ] LIBS = ['-ldl'] WIN_CFLAGS = CFLAGS_COMMON + [ '-I', '"c:/Program Files (x86)/Microsoft SDKs/Windows/v7.1A/Include"', '-I', '"c:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.28.29333/include"', '-I', '"c:/Program Files (x86)/Windows Kits/10/Include/10.0.19041.0/ucrt"', ] WIN_LIBS = [ 'user32.lib', ] WIN_LFLAGS32 = [ '/LIBPATH:"c:/Program Files (x86)/Microsoft SDKs/Windows/v7.1A/Lib"', '/LIBPATH:"c:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.28.29333/lib/x86"', '/LIBPATH:"c:/Program Files (x86)/Windows Kits/10/Lib/10.0.19041.0/ucrt/x86"', ] + WIN_LIBS WIN_LFLAGS64 = [ '/LIBPATH:"c:/Program Files (x86)/Microsoft SDKs/Windows/v7.1A/Lib/x64"', '/LIBPATH:"c:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.28.29333/lib/x64"', '/LIBPATH:"c:/Program Files (x86)/Windows Kits/10/Lib/10.0.19041.0/ucrt/x64"', ] + WIN_LIBS def Escape(path): return path.replace(' ', '\\ ').replace('(', '\\(').replace(')', '\\)') def LSQ(path): return '"' + str(subprocess.check_output('ls ' + Escape(path), shell=True), 'ascii').splitlines()[0] + '"' PROGFILES = '/mnt/c/Program Files (x86)' MSVS = PROGFILES + '/Microsoft Visual Studio' MSKITS = PROGFILES + '/Windows Kits' WIN_CL32 = LSQ(MSVS + '/*/*/VC/Tools/MSVC/*/bin/Hostx86/x86/cl.exe') WIN_CL64 = LSQ(MSVS + '/*/*/VC/Tools/MSVC/*/bin/Hostx86/x64/cl.exe') WIN_LINK32 = LSQ(MSVS + '/*/*/VC/Tools/MSVC/*/bin/Hostx86/x86/link.exe') WIN_LINK64 = LSQ(MSVS + '/*/*/VC/Tools/MSVC/*/bin/Hostx86/x64/link.exe') WIN_RC32 = LSQ(MSKITS + '/*/bin/*/x86/rc.exe') WIN_RC64 = LSQ(MSKITS + '/*/bin/*/x64/rc.exe') D8 = LSQ('${HOME}/src/v8/v8/out/x64.release/d8') NODEJS = LSQ('/usr/bin/nodejs') output = f""" ninja_required_version = 1.1 src = .. VERSION = {VERSION} REVISION = {REVISION} CFLAGS = {' '.join(CFLAGS)} STRIP_ARGS = {' '.join(STRIP_ARGS)} LIBS = {' '.join(LIBS)} CXX = g++ WIN_CL32 = {WIN_CL32} WIN_CL64 = {WIN_CL64} WIN_LINK32 = {WIN_LINK32} WIN_LINK64 = {WIN_LINK64} WIN_RC32 = {WIN_RC32} WIN_RC64 = {WIN_RC64} D8 = {D8} NODEJS = {NODEJS} WIN_CFLAGS = {' '.join(WIN_CFLAGS)} WIN_LFLAGS32 = {' '.join(WIN_LFLAGS32)} WIN_LFLAGS64 = {' '.join(WIN_LFLAGS64)} rule importation description = importation depfile = $out.d deps = gcc command = $src/tools/importation.py -i $in -o $out -I . -I $src $options --depsout $depfile -DVERSION=$VERSION -DREVISION=$REVERSION rule compile description = CXX depfile = $out.d deps = gcc command = $CXX $CFLAGS $in -o $out $LIBS -MD -MF $depfile && strip $STRIP_ARGS $out rule compile_win32 description = WIN_CL32 deps = msvc command = $WIN_CL32 /showIncludes /nologo /c /Fo$out $WIN_CFLAGS $in && touch $out rule compile_win64 description = WIN_CL64 deps = msvc command = $WIN_CL64 /showIncludes /nologo /c /Fo$out $WIN_CFLAGS $in && touch $out rule link_win32 description = WIN_LINK32 command = $WIN_LINK32 /nologo /OUT:$out $WIN_LFLAGS32 $in && touch $out && chmod a+x $out rule link_win64 description = WIN_LINK64 command = $WIN_LINK64 /nologo /OUT:$out $WIN_LFLAGS64 $in && touch $out && chmod a+x $out rule rc_win32 description = WIN_RC32 command = $WIN_RC32 /nologo /i $src /fo $out $in && touch $out rule rc_win64 description = WIN_RC64 command = $WIN_RC64 /nologo /i $src /fo $out $in && touch $out rule run description = RUN command = $in >$out rule resize description = RESIZE command = convert -resize $size $in $out rule convert_image description = IMAGE_CONVERT command = convert $in $out rule zip description = ZIP command = rm -f $out && cd $base && zip $relout $relin >/dev/null rule copy description = COPY command = cp $in $out """ def Importation(target, source, header_mode='cpp', name=None, keep=False, deps=None, implicit=[]): global output options = '' if keep: options += '--keep-first-comment' if name: options += ' --name ' + name + ' --header ' + header_mode implicit = ' '.join(implicit) output += f'build {target}: importation {source} | {implicit}\n' if options: output += f' options = {options}\n' if deps: output += f' depfile = {deps}\n' return target def Esp32Optional(main_name, main_source, parts): parts = [] for name, source in parts: parts.append(Importation('gen/esp32_' + name + '.h', source, name=name.replace('-', '_') + '_source')) return Importation('esp32/ESP32forth/optional/' + main_name + '.h', main_source, keep=True, deps='gen/esp32_optional_' + main_name + '.h.d', implicit=parts) def Simple(op, target, source, implicit=[]): global output implicit = ' '.join(implicit) output += f'build {target}: {op} {source} | {implicit}\n' return target def Compile(target, source, implicit=[]): return Simple('compile', target, source, implicit) def CompileW32(target, source, implicit=[]): return Simple('compile_win32', target, source, implicit) def CompileW64(target, source, implicit=[]): return Simple('compile_win64', target, source, implicit) def LinkW32(target, source, implicit=[]): return Simple('link_win32', target, source, implicit) def LinkW64(target, source, implicit=[]): return Simple('link_win64', target, source, implicit) def ResizeImage(target, source, size, implicit=[]): global output Simple('resize', target, source, implicit) output += f' size={size}\n' return target def ConvertImage(target, source, implicit=[]): return Simple('convert_image', target, source, implicit) def CompileResource32(target, source, implicit=[]): return Simple('rc_win32', target, source, implicit) def CompileResource64(target, source, implicit=[]): return Simple('rc_win64', target, source, implicit) def Run(target, source, implicit=[]): return Simple('run', target, source, implicit) def Zip(target, sources, base): global output ret = Simple('zip', target, ' '.join(sources)) relin = ' '.join([os.path.relpath(i, base) for i in sources]) relout = os.path.relpath(target, base) output += f' base = {base}\n' output += f' relout = {relout}\n' output += f' relin = {relin}\n' return ret def Alias(target, source): global output output += f'build {target}: phony {source}\n' return target def Copy(target, source): global output output += f'build {target}: copy {source}\n' return target def Default(target): global output output += f'default {target}\n' return target def Include(path): path = os.path.join(ROOT_DIR, path, 'BUILD') data = open(path).read() exec(data) Include('.') print(output)