-1

我正在尝试编写一个 ocamlbuild 插件。目标是构建 Qt 应用程序(暂时没有OCaml 代码)。为了处理最后的链接阶段,我在 .qtobjs 文件(如 .itarget)中编写了 obj、mocs、uis 和 rcs 的列表,在 .qtpackages 文件中编写了 Qt 库的列表。适用于这些文件的规则会解析这些列表并在链接所有内容之前动态构建对象、mocs 等。

问题是我不想动态构建没有改变的目标。请参阅以下规则:

rule "Link a c++ executable that uses Qt."
  ~deps:["%.qtobjs"; "%.qtpackages"]
  ~prod:"%.cxxnative"
  (fun env build ->
     let dir = Pathname.dirname (env "%.qtobjs") in
     let output = env "%.cxxnative" in
     let objlist = pwd / (env "%.qtobjs") in
     let liblist = pwd / (env "%.qtpackages") in
     let packages = read_lines liblist in
     let lflags = List.map (fun p -> "-l"^p) packages
                  @ find_all "lflags" in
     let objs = List.map (fun o -> dir / o) (read_lines objlist) in



     (* Here, I would like to forget the targets that have not changed *)
     let objs_to_build = List.filter 
         (fun target -> 
            (* something to tell if "target" has to be rebuilt *))
         objs in



     (* This is where I build the dependencies : *)
     let success_builds = build 
         (List.map (fun o -> [o]) 
         objs_to_build) in


     let objects = filter_map
         (function
           | Outcome.Good x when get_extension x = "opp" ->
             Some (pwd / "_build" / (update_extension "o" x))
           | Outcome.Good _ -> None 
             (* Because I don't want to link the ui.h file generated by uic *)
           | Outcome.Bad exn -> raise exn)
         success_builds in
     let tags_objs = tags_of_pathname (env "%.qtobjs") ++ "link" in
     let tags_packs = tags_of_pathname (env "%.qtpackages") in
     Cmd (S [A (find_one "cxx"); T tags_objs; T tags_packs; Command.atomize lflags;
             A "-o"; P output; Command.atomize objects]));

我不想在没有必要的时候调用“build”。

注意:一个函数

newer_than: Pathname.t -> Pathname.t -> bool

可以解决我的问题。

4

1 回答 1

0

问题解决了。

对于那些感兴趣的人,问题出在编译规则:因为“.o”规则已经被 ocamlbuild 使用,我将它注册为正式生成“.opp”文件,但该命令实际上写入了 .o 文件。所以在重新编译时,ocamlbuild 不知道目标文件已经存在。

三个选项:

  • 替换默认的“.o”规则(我什至不知道是否可能?),
  • 生成“.opp”文件(但不那么标准),
  • 或者如果 .o 文件存在,则更改编译规则以执行 Nop:

    if Pathname.exists (env "%.o") then Nop
    else Cmd (S [A ("c++");
                 A "-c";
                 A "-o"; P (env "%.o"); P (env "%.cpp")]));
    
于 2015-09-07T17:58:09.880 回答