After some consideration, I realised I required further information. The default error information provided by waf seems to be about waf itself, rather than the wscripts or the project.
To rectify this, loggers need to be added. I added loggers to the configure and build functions.
configure logger:
cfg.logger = Logs.make_logger("configure_%s.log" % datetime.date.today().strftime("%Y_%m_%d"), "configure")
build logger:
bld.logger = Logs.make_logger("build_%s.log" % datetime.date.today().strftime("%Y_%m_%d"), "build")
Doing this lead me to that nature of the problems:
['C:\\MinGW64\\bin\\g++.exe', '-Wl,--enable-auto-import', '-Wl,--enable-auto-import', 'test.cpp.1.o', '-o', 'C:\\Users\\Administrator\\Downloads\\libpst-0.6.60\\clean\\build\\temp\\conf_check_5fe204eaa3b3bcb7a9f85e15cebb726e\\testbuild\\testprog.exe', '-Wl,-Bstatic', '-Wl,-Bdynamic', '-LC:\\Users\\Administrator\\Downloads\\libpst-0.6.60\\clean\\libs', '-llibiconv2']
err: c:/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/4.7.2/../../../../x86_64-w64-mingw32/bin/ld.exe: skipping incompatible C:\Users\Administrator\Downloads\libpst-0.6.60\clean\libs/libiconv2.dll when searching for -llibiconv2
The library path has been passed correctly to gcc, but the dll is 32bit whereas the gcc installation is 64bit and so it is incompatible.
top-level wscript:
#! /usr/bin/env python
VERSION = "0.1"
APPNAME = "readpst"
top = "." # The topmost directory of the waf project
out = "build/temp" # The build directory of the waf project
import os
import datetime
from waflib import Build
from waflib import ConfigSet
from waflib import Logs
# Variant memory variables
var_path = out + "/variant.txt" # The variant memory file path
default_variant = "debug" # The default if no variant is stored
stored_variant = ""
def options(opt):
'''
A script hook function that defines addtional switch options for the build.
'''
opt.load("compiler_c compiler_cxx")
def configure(cfg):
'''
A script hook function that configures the build environment.
'''
cfg.logger = Logs.make_logger("configure_%s.log" % datetime.date.today().strftime("%Y_%m_%d"), "configure")
cfg.load("compiler_c compiler_cxx")
cfg.find_program("strip")
cfg.env.DEFINES = \
[
"WAF=1",
"HAVE_CONFIG_H=1"
]
cfg.env.FEATURES = [] # Additional features
cfg.env.append_value("LIBPATH", os.path.join(os.getcwd(), "libs"))
cfg.env.append_value("INCLUDES", os.path.join(os.getcwd(), "inc"))
cfg.env.append_value("INCLUDES", os.path.join(os.getcwd(), "inc", "glib-2.0"))
cfg.env.append_value("INCLUDES", os.path.join(os.getcwd(), "inc", "glib-2.0", "glib"))
cfg.env.append_value("INCLUDES", os.path.join(os.getcwd(), "libs", "regex", "2.7", "regex-2.7-src", "src"))
cfg.env.append_value("INCLUDES", os.path.join(os.getcwd(), "libs", "libiconv", "1.9.2", "libiconv-1.9.2-src", "include"))
cfg.define("VERSION", VERSION)
base_env = cfg.env
# Compiler checks
cfg.check_large_file(mandatory = False)
cfg.check_inline()
cfg.multicheck\
(
{"header_name" : "fcntl.h"},
{"header_name" : "iostream"},
{"header_name" : "list"},
{"header_name" : "set"},
{"header_name" : "string"},
{"header_name" : "vector"},
msg = "Checking for standard headers",
mandatory = True
)
cfg.check(header_name = "glib.h", mandatory = False)
cfg.multicheck\
(
{"header_name" : "gsf\\gsf-infile-stdio.h"},
{"header_name" : "gsf\\gsf-infile.h"},
{"header_name" : "gsf\\gsf-input-stdio.h"},
{"header_name" : "gsf\\gsf-outfile-msole.h"},
{"header_name" : "gsf\\gsf-outfile.h"},
{"header_name" : "gsf\\gsf-output-stdio.h"},
{"header_name" : "gsf\\gsf-utils.h"},
msg = "Checking for gsf headers",
mandatory = False
)
# Checking for headers expected in config.h
cfg.check(header_name = "ctype.h", define_name = "HAVE_CTYPE_H" , mandatory = False)
cfg.check(header_name = "dirent.h", define_name = "HAVE_DIRENT_H" , mandatory = False)
cfg.check(header_name = "errno.h", define_name = "HAVE_ERRNO_H" , mandatory = False)
cfg.check(header_name = "gd.h", define_name = "HAVE_GD_H" , mandatory = False)
cfg.check(header_name = "iconv.h", define_name = "HAVE_ICON" , mandatory = False)
cfg.check(header_name = "limits.h", define_name = "HAVE_LIMITS_H" , mandatory = False)
cfg.check(header_name = "regex.h", define_name = "HAVE_REGEX_H" , mandatory = False)
#cfg.check(header_name = "semaphore.h", define_name = "HAVE_SEMAPHORE_H", mandatory = False)
cfg.check(header_name = "signal.h", define_name = "HAVE_SIGNAL_H" , mandatory = False)
cfg.check(header_name = "string.h", define_name = "HAVE_STRING_H" , mandatory = False)
cfg.check(header_name = "sys/shm.h", define_name = "HAVE_SYS_SHM_H" , mandatory = False)
cfg.check(header_name = "sys/stat.h", define_name = "HAVE_SYS_STAT_H" , mandatory = False)
cfg.check(header_name = "sys/types.h", define_name = "HAVE_SYS_TYPES_H", mandatory = False)
cfg.check(header_name = "sys/wait.h", define_name = "HAVE_SYS_WAIT_H" , mandatory = False)
cfg.check(header_name = "wchar.h", define_name = "HAVE_WCHAR_H" , mandatory = False)
cfg.check(header_name = "define.h", mandatory = False)
cfg.check(header_name = "lzfu.h", mandatory = False)
cfg.check(header_name = "msg.h", mandatory = False)
# Check for the existance and function of specific headers
cfg.check_cxx(lib = "libiconv2", uselib_store = "LIBICONV2", mandatory = False)
# Define the debug build environment
cfg.setenv("debug", env = base_env.derive())
cfg.env.append_value("CFLAGS", "-g")
cfg.define("DEBUG", 1)
cfg.write_config_header("/debug/inc/config.h")
# Define the release build environment
cfg.setenv("release", env = base_env.derive())
cfg.env.append_value("CFLAGS", "-02")
cfg.env.FEATURES = ["strip"]
cfg.define("RELEASE", 1)
cfg.write_config_header("/release/inc/config.h")
def pre(ctx):
'''
A callback for before build task start.
'''
print "Starting %sbuild" % (("%s " % ctx.variant) if(ctx.variant) else "")
if ctx.cmd == "install":
print "Installing"
def post(ctx):
'''
A callback for after build task finish.
'''
global var_path
print "Finished %sbuild" % (("%s " % ctx.variant) if(ctx.variant) else "")
env = ConfigSet.ConfigSet()
env.stored_variant = ctx.variant
env.store(var_path)
def build(bld):
'''
A script hook function that specifies the build behaviour.
'''
if bld.cmd != "clean":
bld.logger = Logs.make_logger("build_%s.log" % datetime.date.today().strftime("%Y_%m_%d"), "build")
bld.add_pre_fun(pre)
bld.add_post_fun(post)
bld.recurse\
(
[
"src"
]
)
def dist(ctx):
'''
A script hook function that specifies the packaging behaviour.
'''
ctx.base_name = "_".join([APPNAME, VERSION])
ctx.algo = "zip"
file_ex_patterns = \
[
out + "/**",
"**/.waf-1*",
"**/*~",
"**/*.pyc",
"**/*.swp",
"**/.lock-w*"
]
file_in_patterns = \
[
"**/wscript*",
"**/*.h",
"**/*.c",
"**/*.cpp",
"**/*.txt",
]
ctx.files = ctx.path.ant_glob(incl = file_in_patterns, excl = file_ex_patterns)
def set_variant():
'''
A function that facilitates dynamic changing of the Context classes variant member.
It retrieves the stored variant, if existant, otherwise the default.
'''
global default_variant
global stored_variant
global var_path
env = ConfigSet.ConfigSet()
try:
env.load(var_path)
except:
stored_variant = default_variant
else:
if(env.stored_variant):
stored_variant = env.stored_variant
print "Resuming %s variant" % stored_variant
else:
stored_variant = default_variant
def get_variant():
'''
A function that facilitates dynamic changing of the Context classes variant member.
It sets the variant, if undefined, and returns.
'''
global stored_variant
if(not stored_variant):
set_variant()
return stored_variant
class release(Build.BuildContext):
'''
A class that provides the release build.
'''
cmd = "release"
variant = "release"
class debug(Build.BuildContext):
'''
A class that provides the debug build.
'''
cmd = "debug"
variant = "debug"
class default_build(Build.BuildContext):
'''
A class that provides the default variant build.
This is set to debug.
'''
variant = "debug"
class default_clean(Build.CleanContext):
'''
A class that provides the stored variant build clean.
'''
@property
def variant(self):
return get_variant()
class default_install(Build.InstallContext):
'''
A class that provides the stored variant build install.
'''
@property
def variant(self):
return get_variant()
class default_uninstall(Build.UninstallContext):
'''
A class that provides the stored variant build uninstall.
'''
@property
def variant(self):
return get_variant()
# Addtional features
from waflib import Task, TaskGen
class strip(Task.Task):
run_str = "${STRIP} ${SRC}"
color = "BLUE"
@TaskGen.feature("strip")
@TaskGen.after("apply_link")
def add_strip_task(self):
try:
link_task = self.link_task
except:
return
tsk = self.create_task("strip", self.link_task.outputs[0])