I'm trying to get a file produced by an add_custom_command in one directory to be a dependency of an add_custom_command in another directory.
In the first directory (lib/core) I have a build command that looks like this:
add_custom_command(
OUTPUT libcore.bc
COMMAND tartln -filetype=bc -link-as-library -o libcore.bc ${STDLIB_BC_FILES}
DEPENDS ${STDLIB_BC_FILES} tartln
COMMENT "Linking libcore.bc")
In the second directory, I have a command that uses the output of that command:
add_custom_command(OUTPUT ${OBJ_FILE}
COMMAND tartln -disable-fp-elim -filetype=obj -o ${OBJ_FILE} ${BC_FILE}
"${PROJECT_BINARY_DIR}/lib/core/libcore.bc"
MAIN_DEPENDENCY "${BC_FILE}"
DEPENDS "${PROJECT_BINARY_DIR}/lib/core/libcore.bc"
COMMENT "Linking Tart bitcode file ${BC_FILE}")
However, when I try to build, I get the following error:
make[3]: *** No rule to make target `lib/core/libcore.bc', needed by `test/stdlib/ReflectionTest.o'. Stop.
One weird thing that I see is that the path in the error message is a relative, not an absolute path, despite the fact that I know that ${PROJECT_BINARY_DIR} is a full, correct path. I don't know if this is a problem or just a strangeness of make.
I've also tried making a top-level target for the libcore library, in the lib/core directory:
add_custom_target(libcore DEPENDS libcore.bc libcore.deps)
And then using that in the DEPENDS clause. The strange thing about that is it works the first time you do a clean build, but gives an error on any subsequent build. In any case, my understanding is DEPENDS is only supposed to work for file dependencies, so this doesn't seem like the correct solution. (How do you have a custom command that depends on a top-level target then?)
I've also tried putting absolute paths everywhere, no effect.
The cmake documentation says the following about the DEPENDS parameter:
Therefore I think you will have to define a target using add_custom_target and depend on this.
The documentation for add_custom_target says:
So you will have to use add_custom_command and add_custom_target as follows:
In the first directory generating the bc file you do
add_custom_command(OUTPUT libcore.bc ... ) # just as in your question
add_custom_target (LibCoreBC DEPENDS libcore.bc)
In the second directory you do
add_custom_command (OUT ${OBJ_FILE} DEPENDS LibCoreBC ....)
try to add following command into second directory: set_source_files_properties(${PROJECT_BINARY_DIR}/lib/core/libcore.bc PROPERTIES GENERATED TRUE)
I solved my problem with this command. a relating link: https://cmake.org/cmake/help/latest/prop_sf/GENERATED.html
I don't think
add_custom_target
will work for what I want. According to the cmake documents, a custom target created by add_custom_target is always considered out of date and is always built.The problem is that I am trying to take the output from one
add_custom_command
, and feed it into the input of anotheradd_custom_command
in a different directory. I only want this to happen if the original source file is out of date - if I usedadd_custom_target
, then the output would always be rebuilt even if the source file had not changed. Given that there are hundreds of these source files, this would make the build very slow.Here's what I am trying to do: I have a program which generates a .bc file (LLVM bitcode) given a source file. There are a lot of these source files, which create a lot of .bc files.
A second program transforms all of the the .bc files into a single .obj (ELF object) file. So the transformation steps look like this:
The original source code files are in different directories because they are libraries of classes - I don't want to have to put all the code for every class library in the same directory.
This is a non-answer but a clarification to one of your answers above.
IMO, the cmake documents should say instead:
That means that if all of your targets are marked as
EXCLUDE_FROM_ALL
, and you haveadd_custom_target
commands that create new targets, and you typemake
from the command line with no targets specified, the targets added withadd_custom_target
are not built. But if you spell them out on themake
command line explicitly, then they are built. Also, there is theALL
keyword that you can specify to theadd_custom_target
to force those to be built as a part of the all rule, which I believe means whenmake
is executed without arguments.