1

tl;dr;

When using ADD_LIBRARY in CMake it will check during cmake .. that all the source files exist. I have some that are generated during compile time. Is there a way to force CMake to ignore the missing files since they will exist when they are needed?

Full version:

I am trying to build Sqlite3 with CMake, and I can get it to compile, however, I need to comment out a few lines in CMake and run it, then uncomment them and run it again. I would like to do everything in one pass.

The main issue I'm having is that Sqlite3 using a code generator called "lemon". So to properly build everything, I need to compile lemon. Then I need to run lemon. Once lemon is done running there is a new file called "parse.c". "parse.c" needs to be included with the source to build sqlite3.

I will strip down the code to show the applicable bits.

set(SourceFiles
    #Lots of Files are here
    build/parse.c
    )

add_executable(lemon sqlite/tool/lemon.c)
add_custom_target(CreateParse ALL COMMAND 
    cp ../sqlite/tool/lempar.c . 
    && ./lemon -s ../sqlite/src/parse.y 
    && mv ../sqlite/src/parse.h . 
    && mv ../sqlite/src/parse.c . 
    && mv ../sqlite/src/parse.out .)
add_library(sqlite ${SourceFiles})

add_dependencies(CreateParse lemon)
add_dependencies(sqlite CreateParse)

So there are 3 steps that happen here:

  1. The executable lemon is created.
  2. lemon is used to create parse.c (among other things)
  3. parse.c is compiled with a ton of other files to create the sqlite3 library.

With the add_dependencies this should work. But it doesn't. The reason it doesn't work is that build/parse.c doesn't exist on the first pass. I've been able to work around it by commenting out parse.c. After it is done half building. Then I can uncomment it and it will compile successfully.

I've looked into using ADD_CUSTOM_COMMAND, which I believe will run lemon when cmake .. is run rather than ninja is run. However, when cmake .. is run, "lemon" doesn't exist yet so the custom command is unable to run.

Edit 1

So I came up with a hack...

execute_process(COMMAND touch ${CMAKE_SOURCE_DIR}/build/parse.c)

So when cmake .. is run it will create an empty file in the correct spot. However, there has to a be a better way. Help is appreciated.

Questionable
  • 768
  • 5
  • 26
  • 1
    Use `add_custom_command(OUTPUT ...)` to produce your file and then just list it in `add_library`. It will work out of the box. – arrowd Feb 18 '21 at 05:42
  • @arrowd How do I make sure that the custom command is run after add_executable(lemon sqlite/tool/lemon.c) since it will fail until that file exists. – Questionable Feb 18 '21 at 05:51
  • 1
    CMake will figure it automatically. Just use `${CMAKE_CURRENT_BINARY_DIR}/generated_file.c` in the `add_executable`. – arrowd Feb 18 '21 at 06:19
  • You may be able to adjust the approach presented in the last code snippet in my answer here: https://stackoverflow.com/a/64736151/2991525 `add_custom_command` allows you to specify multiple commands and use the names of targets built in the current project btw; also I'd use `COMMAND ${CMAKE_COMMAND} -E rename ...` instead of `mv` to avoid the OS dependency. – fabian Feb 18 '21 at 22:59
  • @arrowd this not work if i want to glob generated files with regular expression – shan Jul 26 '23 at 02:59

0 Answers0