Search code examples
mysqlautotools

Execute SQL statements with Autotools


I'm writing a library of MySQL UDF. The build system is based on GNU Autotools. The compilation and installation of the shared library itself works well. However to use the UDF, we need to execute some SQL statements as explained here:

CREATE FUNCTION metaphon RETURNS STRING SONAME 'udf_example.so';

The current Makefile.am contains an explicit rule:

installdb: 
    $(MYSQL) <./installdb.sql

where ./installdb.sql contains the CREATE FUNCTION statements. However, it doesn't work when building outside of source tree and the user must call make installdb explicitly (while I would like it to be part of make install).

Any idea on how to do that ?


Solution

  • The current Makefile.am contains an explicit rule:

    installdb: 
        $(MYSQL) <./installdb.sql
    

    where ./installdb.sql contains the CREATE FUNCTION statements. However, it doesn't work when building outside of source tree

    Supposing that installdb.sql is a file included in the package distribution, not a built one, no, that wouldn't work in an out-of-source build, because "./installdb.sql" would not then refer to an existing file. If you want a build recipe to refer to a file that is neither a rule prerequisite nor a target built by some other rule, then you cannot expect magic -- you need to specify the wanted file via a usable path. The same applies even to prerequisites if you refer to them explicitly in your build rules. VPATH builds operate via make's automatic variables, such as $< and $^.

    And GNU make has a solution to that. The path to the source-tree directory corresponding to the current make's working directory is always available via the $(srcdir) variable. Using that, your recipe would look more like this:

    installdb: 
        $(MYSQL) < $(srcdir)/installdb.sql
    

    For an in-source build, $(srcdir) will evaluate to ., so in that case the above is equivalent to what you started with. For an out-of-source build, $(srcdir) will contain the appropriate path.

    Occasionally, it is also useful to reference the root of the source tree. For instance, you might want to refer to files in a direct subdirectory of the source root, without introducing other dependencies on source-tree structure. For that, you can use $(top_srcdir) to refer to the source tree root.

    These details are not clearly covered in the current Automake docs, but you can find them in other GNU documentation.

    and the user must call make installdb explicitly (while I would like it to be part of make install).

    Well, yes, Automake does not assume that every target for which you provide a rule has to be exercised by a make install. Not even all the targets it generates itself are exercised that way. But Automake does have mechanisms for indicating which user-provided rules should be included, and at what point. The current manual covers this in section 23.1.

    In your case, I would use an installation hook, either by renaming your target to install-data-hook or by declaring a new target of that name, and making your installdb target a prerequisite. The latter would look like this:

    install-data-hook: installdb
    

    The former has stronger promises about timing, however, so if it were critical that the database initialization be performed near the end of the installation, then it would be better to do the target name change in the hook's own recipe:

    install-data-hook: 
        $(MYSQL) < $(srcdir)/installdb.sql
    

    Either way, do also consider what, if any, corresponding uninstallation rules may be needed. Also, if you retain your separate installdb target, then it would be good form to mark it as phony:

    PHONY = installdb
    

    That avoids breakage in the event that an actual file of that name happens to be in the build directory for some reason.