2

我正在尝试将 makefile 从另一个构建系统转换为 waf。

我正在尝试将 waf 定向到包含必要 dll 的目录。

但是,在运行 waf 配置时:

Checking for library libiconv2           : not found

它找不到所需的库。

目录结构:

project/
| build/
| inc/
| | XGetopt.h
| | common.h
| | define.h
| | libpst.h
| | libstrfunc.h
| | lzfu.h
| | msg.h
| | timeconv.h
| | vbuf.h
| libs/
| | libiconv2.dll
| | regex2.dll
| src/
| | XGetopt.c
| | debug.c
| | dumpblocks.c
| | getidblock.c
| | libpst.c
| | libstrfunc.c
| | lspst.c
| | lzfu.c
| | readpst.c
| | timeconv.c
| | vbuf.c
| | deltasearch.cpp
| | msg.cpp
| | nick2ldif.cpp
| | pst2dii.cpp
| | pst2ldif.cpp
| | wscript_build
| waf-1.7.10
| 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
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_cxx")

def configure(cfg):
    '''
    A script hook function that configures the build environment.
    '''
    cfg.load("compiler_cxx")
    cfg.find_program("strip")
    cfg.env.PREFIX = "."
    cfg.env.DEFINES = ["WAF=1"]
    cfg.env.FEATURES = [] # Additional features
    cfg.env.LIBPATH = [os.path.join(os.getcwd(), "libs")]
    print cfg.env.LIBPATH
    cfg.define("VERSION", VERSION)
    base_env = cfg.env

    # Compiler checks
    cfg.check_large_file(mandatory = False)
    cfg.check_inline()

    # Check for the existance and function of specific headers
    cfg.check(header_name = "stdint.h")
    cfg.check(header_name = "stdio.h")
    cfg.check(compiler="cxx", uselib_store="LIBICONV2", mandatory=True, lib="libiconv2")

    # Define the debug build environment
    cfg.setenv("debug", env = base_env.derive())
    cfg.env.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.CFLAGS = ["-O2"]
    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.
    '''
    bld.add_pre_fun(pre)
    bld.add_post_fun(post)

    bld.recurse\
    (
        [
            "src"
        ]
    )
    if bld.cmd != "clean":
        bld.logger = Logs.make_logger("test.log", "build") # just to get a clean output

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])
4

2 回答 2

1

您只是缺少use变量设置,但这必须在您的子脚本中修复,即

bld.program (...,
    libpath = ['/usr/lib', 'subpath'], #this has to be relative to the wscript it appears in! (or the root wscript, can not recall)
    ...,
    use = ['iconv2', 'regex2'] )

请参阅waf 书的第 9.1.2 节


或者:(可能是更清洁的版本)

cfg.check_cc(lib='iconv2', uselib_store="LIBICONV2", mandatory=True)

然后uselib

bld.program (...,
    libpath = ['/usr/lib', 'subpath'], #this has to be relative to the wscript it appears in! (or the root wscript, can not recall)
    ...,
    uselib = ['LIBICONV2', ...] )
于 2013-07-30T07:00:55.750 回答
1

经过一番考虑,我意识到我需要更多信息。waf 提供的默认错误信息似乎是关于 waf 本身,而不是 wscripts 或项目。

为了纠正这个问题,需要添加记录器。我在配置和构建功能中添加了记录器。

配置记录器:

cfg.logger = Logs.make_logger("configure_%s.log" % datetime.date.today().strftime("%Y_%m_%d"), "configure")

构建记录器:

bld.logger = Logs.make_logger("build_%s.log" % datetime.date.today().strftime("%Y_%m_%d"), "build")

这样做让我想到了问题的本质:

['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

库路径已正确传递给 gcc,但 dll 是32 位,而 gcc 安装是64 位,因此不兼容

顶级脚本:

#! /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])
于 2013-08-01T07:46:18.417 回答