#line 485 "/home/travis/build/felix-lang/felix/src/packages/toolchain.fdoc"
  include "std/felix/toolchain_clang_config";
  include "std/felix/flx_pkg"; // only for "fix2word_flags"
  include "std/felix/flx_cp";
  include "std/felix/flx/flx_depchk";
  
  class FlxLibBuild
  {
    private fun / (x:string,y:string) => Filename::join(x,y);
  
    noinline gen make_lib
    (
      db: FlxPkgConfig::FlxPkgConfigQuery_t,
      toolchain-maker: clang_config_t -> toolchain_t,
      src_dir:string,
      target_dir:string,
      share_rtl:string,
      pkg:string,
      tmpdir:string,
      static_only:bool,
      debug: bool
    ) () : bool =
    {
      proc dbug (x:string) => if debug call println$ '[make_lib: '+pkg+']' x;
  
      println$ "------------";
      println$ "Make lib " + pkg;
      println$ "------------";
      var srcdir = db.getpkgfielddflt (pkg,"srcdir");
      var srcpath = src_dir / srcdir;
  println$ "[make_lib] source directory " + srcpath;
  
      var build_includes= db.getpkgfield (pkg,"build_includes");
      var result3,ddeps= db.query$ list$ pkg, "--keepleftmost", "--field=requires_dlibs";
      ddeps = FlxPkg::fix2word_flags ddeps;
      var deps = db.getpkgfield(pkg,"Requires");
      var result,depdlibs =  db.query("--field=provides_dlib"+deps); // packaged dlibs
      var macros = db.getpkgfield(pkg,"macros");
      var result2,ccflags = db.query$ list$ pkg, "--keepleftmost", "--field=cflags";
      var config =
        (
          header_search_dirs= list[string] (target_dir, srcpath, share_rtl)+build_includes,
          macros= macros,
          ccflags = ccflags,
          library_search_dirs= list[string] ("-L"+target_dir), // HACK!!!
          dynamic_libraries= ddeps+depdlibs,
          static_libraries= Empty[string],
          debugln = dbug
        )
      ;
      var toolchain = toolchain-maker config;
      println$ #(toolchain.whatami);
      var headers = db.getpkgfielddflt(pkg,"headers");
      if headers == "" do headers = r".*\.h(pp)?"; println$ "copying all header files"; done
      var hsrc, hdst = "","";
      match split (headers, ">") with
      | #Empty => ;
      | Cons (h,#Empty) => hsrc = h;
      | Cons (h,Cons (d,#Empty)) => hsrc = h; hdst = d;
      | _ => println$ "Header file too many > characters " + headers;
      endmatch;
  
      if hdst == "" do hdst = "${0}"; done
      println$ "Copying headers " + hsrc + " > " + hdst;
      CopyFiles::copyfiles (srcpath, hsrc,target_dir/hdst,true, true);
  
      var pats = db.getpkgfield(pkg,"src");
      var pat = catmap '|' (fun (x:string)=>"("+x+")") pats;
    //println$ "Finding Sources in "+srcpath;
    //println$ "Matching pattern "+pat;
      var files = FileSystem::regfilesin (srcpath,pat);
    //println$ "Sources = " + str files;
      if not static_only
      do
        begin
          fun objname (file:string) => let
              dstobj = file.Filename::strip_extension + #(toolchain.dynamic_object_extension) in
              tmpdir/ dstobj
          ;
  
          for file in files do
            var srcfile = srcpath/ file;
            var dst = objname file;
            Directory::mkdirs (Filename::dirname dst);
            match Filename::get_extension srcfile with
            | x when x == ".cc" or x == ".cpp" =>
              var fresh = cxx_depcheck (toolchain, srcfile, dst);
              if fresh do
                println$ "C++: Up to date [dynamic] " + file " -> " + objname file;
                result = 0;
              else
                println$ "C++: Compiling  [dynamic] " + file " -> " + objname file;
                result = toolchain.cxx_dynamic_object_compiler (src=srcfile, dst=dst);
              done
            | ".c" =>
              fresh = c_depcheck (toolchain, srcfile, dst);
              if fresh do
                println$ "C:   Up to date [dynamic] " + file " -> " + objname file;
                result = 0;
              else
                println$ "C:   Compiling  [dynamic] " + file " -> " + objname file;
                result = toolchain.c_dynamic_object_compiler (src=srcfile, dst=dst) ;
              done
  
            | x =>
              println$ "Unknown extension " + x;
              goto bad;
            endmatch
            ;
            if result != 0 do
              println$ "Compiler result " + str result;
              goto bad;
            done
          done
  
          var objs = map objname files;
          var libname =
            let dlib_root = db.getpkgfield1(pkg,"provides_dlib") in
            if prefix (dlib_root,"-l") then "lib"+dlib_root.[2 to]
            elif prefix (dlib_root,"/DEFAULTLIB:") then dlib_root.[12 to]
            else dlib_root
            endif
            +#(toolchain.dynamic_library_extension)
          ;
          var dstlib = target_dir/libname;
          println$ "Dynamic Linking library " + dstlib;
          result = toolchain.dynamic_library_linker(srcs=objs, dst=dstlib);
          if result != 0 do
            println$ "Linker result " + str result;
            goto bad;
          done
        end
      done
  
      begin
        fun objname (file:string) => let
            dstobj = file.Filename::strip_extension + #(toolchain.static_object_extension) in
            tmpdir/ dstobj
        ;
  
        for file in files do
          var srcfile = srcpath/ file;
          var dst = objname file;
          Directory::mkdirs (Filename::dirname dst);
          match Filename::get_extension srcfile with
          | x when x == ".cc" or x == ".cpp" =>
            var fresh = cxx_depcheck (toolchain, srcfile, dst);
            if fresh do
              println$ "C++: Up to date [static] " + file " -> " + objname file;
              result = 0;
            else
              println$ "C++: Compiling [static] " + file " -> " + objname file;
              result = toolchain.cxx_static_library_object_compiler (src=srcfile, dst=dst);
            done
          | ".c" =>
            fresh = c_depcheck (toolchain, srcfile, dst);
            if fresh do
              println$ "C:   Up to date [static] " + file " -> " + objname file;
              result = 0;
            else
              println$ "C:   Compiling [static] " + file " -> " + objname file;
              result = toolchain.c_static_object_compiler (src=srcfile, dst=dst);
            done
          | x => println$
            "Unknown extension " + x;
            println$ "Compiler result " + str result;
            goto bad;
          endmatch
          ;
          if result != 0 do
            println$ "Compiler result " + str result;
            goto bad;
          done
        done
  
        var objs = map objname files;
        var libname =
          let dlib_root = db.getpkgfield1(pkg,"provides_slib") in
          if prefix (dlib_root,"-l") then  "lib"+dlib_root.[2 to]
          elif prefix (dlib_root,"/DEFAULTLIB:") then dlib_root.[12 to]
          else dlib_root
          endif
          +#(toolchain.static_library_extension);
        ;
        var dstlib = target_dir/libname;
        println$ "Static Linking Library " + dstlib;
        result = toolchain.static_library_linker(srcs=objs, dst=dstlib);
        if result != 0 do
          println$ "Linker result " + str result;
          goto bad;
        done
      end
      return true;
  bad:>
      return false;
    }
  }