Best way to have a library package install a main.cpp and run add_executable in context of user project when it calls my CMake function?

The ANTLR4 parser project provides a TestRig (Java) class which helps you debug your grammar, but running it from CMake via add_custom_command (or similar) only runs it at configure or build time. To run a command from the CLion IDE’s Debug/Run menu, it has to be an actual (C++) executable target. So, I wrote a main.cpp that just issues a system call to load Java.exe and run the TestRig class from the ANTLR4 jar with appropriate arguments. This works; I call it test-rig-runner.

Now, I would like to provide this functionality conveniently via a vcpkg port. When I include the test-rig-runner executable built in the context of the port, vcpkg complains there should not be anything in the /bin folder for a static build. Someone on the vcpkg Discussions page said it could go in /tools, instead. However I’m not sure it (in /bin or /tools) will show up this way as a runnable target in the CLion IDE. I think it has to be an add_executable in the context of the user project (not in the context of the port).

(When I say user project I mean the one importing the port and consuming the package.)

ANTLR4 itself provides a package, “antlr4-generator”, which provides a convenience function for generating the parser. It was through looking at that project’s code that I learned I need to put my CMake function into my cmake/*-config.cmake.in file to get it to show up in the user project as a callable function. I assume if I put add_executable in this function then when called from the user project that add_executable will be in the context of the user project.

I haven’t tried that yet because I got tripped up thinking about where to put my test-rig-runner-main.cpp file. Obviously I can’t (I think?) reference it as simply as an add_executable in the same source tree as its called. I would (I think?) have to use install(FILES …) on it, but then install to what subdirectory? To /include? To current binary directory? Maybe I could write the file from scratch (from a string) using file(WRITE).

  • Or -

Is this just a bad idea in general? That is, is my goal here not really the best way to do this in CMake and packages? For example, I could provide 90% of the functionality as a library, and then make the user project explicitly do their own add_executable & target_add_library. There’s actually still a question there what to do about the main.cpp, though because there’s three options:

  1. User has their own int main and calls my library explicitly.

  2. My library defines an int main for the user executable

  3. My library provides a main.cpp file the user project add_executable could reference.

Option 1 is the least astonishment. It’s also the most work for the user.

Option 2 is kinda what SDL2 does (defining it’s own main), and I hate SDL2 for doing that. Also, did I read somewhere add_executable need at least one source file provided?

Option 3 begs the question, again, where to install a .cpp file for the user to use.

I had a similar case just recently, so I can comment a bit on some of your points (not the major one though).

Someone on the vcpkg Discussions page said it could go in /tools

Yes, that’s the recommendation/policy, as far as a know. So it would be something like this:

vcpkg_copy_tools(TOOL_NAMES sometool AUTO_CLEAN)

I would (I think?) have to use install(FILES …) on it, but then install to what subdirectory?
where to install a .cpp file for the user to use

In my case I needed to distribute an additional source file of SQLite, and for now I decided to just put it into ./share/sqlite3/etc/:

file(
    INSTALL "/path/to/memvfs.c"
    DESTINATION "${CURRENT_PACKAGES_DIR}/share/sqlite3/etc"
)

And then in consuming projects I can use it like this (assuming that dependencies are resolved with vcpkg):

add_library(something) # add_executable(something)
target_sources(something
    PRIVATE
       "${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/share/sqlite3/etc/memvfs.c"
        # some other sources
)

From what I know, there is no policy for source files installation paths, so I reckon any path would be good, just need to make sure that consuming projects know where it is.

1 Like

Oh, hey, I recognize that user icon. You wrote the blog post which I keep revisiting as I learn vcpkg (Managing dependencies in a C++ project with vcpkg | Declaration of VAR). Thanks!

1 Like