I decided some time ago to "factor" the build tools so they compile a lot faster. On my old Macbook pro, it takes ages to compile the build tools themselves. Chucking some stuff out of the auto included parts of the std library helped but more radical action is needed.
So here's an experiment that worked to stage 1. Most of the build tools use flx_pkgconfig. In the old days this was a stand alone program called using popen(). Argument passing by shells isn't reliable though, and it's tricky to ensure the executable can be found on the path. Compiling the sources into the code with include directives is more certain .. but much slower! This technique refactors the old program into two parts: a library class in an include file in the library, which contains all the logic, and a stub executable in tools directory which just calls it passing #System::args as arguments. Now we have, more or less transparently, obtains a library function as well as an executable. *Most* of the tools are built this way, so for example the functionality of the executable flx_cp can be called under program control with proper type checking, but will have the same effect. Because the executable was original and the library function new, the build system will remain unchanged building the executable, however calls to popen to invoke it in programs must be modified to use the programatic interface. This situation is more complicated with the tool I'm looking at first: flx_pkgconfig. Here, flx and the build tools are converted to the programatic interface, however the executable is special because it is used by the Python build to build flx. This means the standard build of flx_pkgconfig must be simple (since I don't really know how to change the fbuild system to do complex things emulating flx and I can't actually use flx because it isn't built yet). So as an experiment what I did was copy src/lib/std/felix/flx_pkgconfig.flx -> fpclib.flx Then I commented out the code doing queries using object FlxPkgConfigQuery to simplify the situation. Then I took at the function in class FlxPkgConfig: gen flx_pkgconfig_impl (args:list[string]) : int * list[string] = which I would like to export. Only I cannot do that, because it returns a tuple, and tuples cannot cross compilation boundaries easily. So I did this instead: class FlxPkgConfig { open Lexer; export struct flx_pkgconfig_return { int return_code; list[string] result; }; export gen flx_pkgconfig_exported (args:list[string]) : flx_pkgconfig_return = { var r = flx_pkgconfig args; return flx_pkgconfig_return (r.0, r.1); } gen flx_pkgconfig (args:list[string]) : int * list[string] = ..... That is, I added a struct to replace the tuple, and exported it. Then I made an export version of the original function. Now we compile with: flx -c --force --staticlib --od . fpclib This adds three files to the current directory: ~/felix>ls fpclib* fpclib.a fpclib.flx fpclib.hpp fpclib_interface.flx To use this I wrote this client, fpcc.flx: /////////// include "./fpclib_interface"; var r = fpclib_interface::flx_pkgconfig_exported(#System::args); var return_code, result = r.return_code, r.result; print$ strip$ cat ' ' result; endl; System::exit return_code; //////////////// which I compile and link with flx --static -c -od . fpclib.a fpcc and now I can test with: ~/felix>./fpcc --path=build/release/host/config --list ld faio dl faio dl Yea! It works! You can also build the library with and link with: --staticlib --> fpclib.a --nolink --> fpclib.os --static --nolink --> fpclib.o [no option] --> fpclib.dylib (on OSX). I don't actually know what the last thing does but it is unlikely to work on Linux with fpclib.so unless you put it in the LD_LIBRARY_PATH: OSX uses absolute filenames for dylibs so it also won't work if you move the library, unless you put it in the DYLD_LIBRARY_PATH. <rant> Note the confusion here (and everywhere with crappy x86_64 ABI) between static link code and -fPIC code. --staticlib implies --static but it probably shouldn't. Archives can contain both PIC and non PIC code. Static linkage (on OSX at least) works fine against both PIC and non PIC code. Dynamic libraries, however, require PIC code. non-PIC is supposedly faster. Apple is removing non-PIC code in newer OSX versions, because of the confusion created by the demands of archaic OS technology. </rant> With some trivial wrapping in a header file, we can do this: any program doing this: include "std/felix/flx_pkgconfig"; ... var return_code, result = FlxPkgConfig::flx_pkgconfig (... ) can be modified to use the new wrapper, by simply replacing the include and the call. in fact, with some risk, the call can be wrapped so it works without modification, and only the include needs changing. Note that at present Felix syntax doesn't allow you to export an object. I will have to fix that! Also note, objects return records, which cannot be exported. What a pain! We'll have to use a cast. So there is a bit of fiddling to refactor our build tools to *link* a shared flx_pkgconfig instead of compiling the source every time, but it will significantly reduce compile times. Trickily this will work for "flx" too because the Python build does NOT build flx, it builds instead "bootflx" which is copied to flx. Bootflx does everything by source inclusion. Takes ages to build, but only have to be done once when bootstrapping. There is one further lesson here. There are two problems to note: 1. I originally tested the various kinds of output (object, dylib, archive) for linkage by removing all the products from the library compilation in the current directory and got a shock when I realised --staticlib didn't produce fpclib_interface.flx. Dang, a bug! Only it isn't. flx is too smart. It uses the C++ from the previous compile and doesn't generate the interface because flxg does that as a side effect. If you don't call flxg, the interface isn't generated. The --force flag fixed that. It's a bug in the dependency checking I probably won't fix until there are more complaints :) 2. The linkage requires including the library binary file name on the command line: fpclib.a, fpclib.o, fpclib.os, fpclib.dylib. All these are platform dependent names, so build scripts will have to be customised for the OS. That's no good! The -ox and -od switches were introduced precisely to avoid platform dependent extensions. I will note also our output library would normally be libfpclib.a .. etc to use with -lfpclib on Unix. This DOES matter in general because with linkers like Unix ld placing an archive on the command line does not search the library, it links the whole library in (AFAIK). So I need to figure a way to fix that .. :) -- john skaller skal...@users.sourceforge.net http://felix-lang.org ------------------------------------------------------------------------------ CenturyLink Cloud: The Leader in Enterprise Cloud Services. Learn Why More Businesses Are Choosing CenturyLink Cloud For Critical Workloads, Development Environments & Everything In Between. Get a Quote or Start a Free Trial Today. http://pubads.g.doubleclick.net/gampad/clk?id=119420431&iu=/4140/ostg.clktrk _______________________________________________ Felix-language mailing list Felix-language@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/felix-language