Skip to content

NOB_GO_REBUILD_URSELF_PLUS is not suitable for depending on files which Nob itself will generate. #208

@echoephile

Description

@echoephile

I've been more frequently wanting to let Nob act as its own configuration generator tool, creating a config.h header for the rest of the project to use. Since it's a header, I also end up wanting Nob to be able to include it so it can use the same configuration when determining what to build and how as the project itself will use during compilation.

For example, I can let the user specify that LLVM should be included in the build of a compiler by doing something like:

$ ./nob config --enable-llvm

which might generate the following define in config.h:

// ... other config
#define PROJ_ENABLE_LLVM  (1)
// ... other config

defining it to 0 if --enable-llvm was not present during configuration. Nob itself would then want to query the configuration during build to know if LLVM needs to be linked with. The project itself will most likely also want to check if LLVM is enabled in-source.

Using NOB_GO_REBUILD_URSELF_PLUS(argc, argv, "config.h"); does not work for a clean project, as config.h does not yet exist. Nob will exit with the error "could not stat config.h: No such file or directory" (or the equivalent on other targets). I have solved this in the past by modifying nob__go_rebuild_urself to check the existence of a dependency before querying nob_needs_rebuild on its constructed dynamic array of source paths, marking it as requiring a rebuild automatically.

I wanted to make this an issue first as a place to discuss what a desirable solution would be for Nob beyond just my personal hacks. Should this be the default behavior? Should there be a compile-time define like the other Nob configuration macros? Should this be an alternate NOB_GO_REBUILD_URSELF* macro which implicitly passes a new flag to the implementation detail? Should this be, somehow, added in a backwards-compatible way to the existing macros similarly? Is this even worth adding to Nob in your opinion?

I ask if it's even worth including, because this is most useful with a compiler which has the __has_include preprocessor function, else your Nob will fail to build before it generates a file it needs to include. I solve this by doing basically the following:

#if !defined(__has_include)
#  error "Your error here about a lacking compiler."
#  define __has_include(...) 0 /* Define __has_include to prevent further cascading errors */
#endif

// .....

#if __has_include("config.h")
#  include "config.h"
#else
/* Inline some default config if the build script depends on names being defined. */
#  define PROJ_ENABLE_LLVM (0)
#endif

It's not enough to create an empty/default config.h and commit it to your source control, as then it will most likely show up every single time you want to commit other changes and you don't want to commit your specific configuration into the repository. For Git, it is better to have config.h in your .gitignore file so it can be transient and solely generated by the build script.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions