Решил в своём проекте заменить Make на что-то более современное, желательно, основанное на Python. Вариантов было немного: Scons и Waf. Первый при поверхностном рассмотрении показался несколько сумбурным, к тому же не очень «питоновским». Больше понравился Waf, показался более продуманным, на нём и решил пока остановиться.
Что я пытаюсь сделать:
1. скомпилировать boot32.cc (32-битный код, которому передаёт управление grub2)
2. перевести boot32.o из elf32 в elf64 для будущей линковки с остальным 64-битным кодом
3. скомпилировать все остальные 64-битные исходники (*.cc) в папке
4. прогнать шаблон линковочного скрипта через C-препроцессор
4. слинковать полученные объектные файлы в бинарник ядра
Имею следующий wscript:
APPNAME = 'Toy OS'
VERSION = '0.4'
SUPPORTED_ARCHS = ['x86_64']
DEFAULT_ARCH = 'x86_64'
SUPPORTED_CXXS = ['clang++', 'g++']
DEFAULT_CXX = 'clang++'
SUPPORTED_OPTS = ['0', '1', '3']
DEFAULT_OPT = '3'
def options(opt):
opt.load('compiler_cxx')
grp = opt.get_option_group('configure options')
grp.add_option('', '--arch', dest='arch', default=DEFAULT_ARCH,
help="target architecture [default: '%s']" % DEFAULT_ARCH)
grp.add_option('', '--cxx', dest='CXX', default=DEFAULT_CXX,
help="C++ compiler command [default: '%s']" % DEFAULT_CXX)
grp.add_option('', '--opt', dest='opt', default=DEFAULT_OPT,
help="code optimization level [default: '%s']" %DEFAULT_OPT)
grp.add_option('-d', '--debug', dest='debug', default=False,
action='store_true', help='produce debug builds')
def configure(conf):
conf.load('compiler_cxx')
conf.find_program('cpp')
conf.find_program('objcopy')
options = vars(conf.options)
cases = [('arch', 'target architecture', SUPPORTED_ARCHS),
('CXX', 'C++ compiler', SUPPORTED_CXXS),
('opt', 'code optimization level', SUPPORTED_OPTS)]
for name, desc, supported, in cases:
if options[name] not in supported:
conf.fatal('Unsupported %s: %s' % (desc, options[name]))
conf.env[name] = options[name]
conf.env.debug = conf.options.debug
flags = ['-std=c++0x', '-Wall', '-Wextra', '-O%s' % conf.env.opt,
'-DARCH=%s' % conf.env.arch ]
if conf.env.debug:
flags += ['-DDEBUG']
if conf.env.arch == 'x86_64':
flags += ['-fno-stack-protector']
conf.env.cxxflags_boot32 = flags + ['-m32']
flags += ['-m64']
conf.env.CXXFLAGS = flags
conf.env.SHLIB_MARKER, conf.env.STLIB_MARKER = '', ''
conf.env.LINKFLAGS = ['-nostdlib', '-Wl,--build-id=none',
'-Tsrc/%s/linker_script.lds' % conf.env.arch]
def build(bld):
source, use = [], []
if bld.env.arch == 'x86_64':
boot32 = 'src/x86_64/boot32.cc'
env, env.CXXFLAGS = bld.env.derive(), bld.env.cxxflags_boot32
bld.objects(source=boot32, target=boot32+'.1.o', env=env)
bld(rule='objcopy -O elf64-x86-64 ${SRC} ${TGT}',
source=boot32+'.1.o', target=boot32+'.2.o')
source += [boot32+'.2.o']
bld.objects(source=bld.path.ant_glob('src/x86_64/*.cc', excl=boot32),
target='objs_x86_64')
use += ['objs_x86_64']
lds = 'src/%s/linker_script' % bld.env.arch
bld(source=lds, target=lds+'.lds', rule='cpp -E -P ${SRC} > ${TGT}')
bld.program(source=source, use=use, target='toy.bin')
На выходе всё собирается без ошибок (вроде), но в verbose-режиме waf пишет:
* Node /home/ababo/Dropbox/toy/build/src/x86_64/boot32.cc.2.o is created more than once (full message on 'waf -v -v'). The task generators are:
1. 'src/x86_64/boot32.cc.2.o' in /home/ababo/Dropbox/toy
2. 'toy.bin' in /home/ababo/Dropbox/toy
Почему Waf считает, что линковка пересоздаёт boot32.cc.2.o? У меня есть подозрение, что я делаю что-то неправильно (с точки зрения идеологии Waf). В этом случае, буду рад, если поясните. Спасибо.