Click here to Skip to main content
16,021,041 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
In a CMake project:

I have a directory "A" for an external project. Its CMakeLists.txt file first attempts find_package (A-PKG ...).

If A-PKG_FOUND, it extracts some paths, and defines some variables according to what it found.

Else, it sets up and calls ExternalProject_Add (A-PRJ ...) to (try to) download, build, and install that project, and defines some variables according to what it built.

I now want directory "B" to configure variously, depending on the outcome of either finding or building "A" -- specifically, to set target_compile_definitions and target_include_directories in "B" depending on whether and what the build step produced in "A".

CMake dependencies seem to affect only the build sequence, not the configure sequence. Everything is configured before anything is built. So "B" is configured for the non-existence of "A"'s output. In the build step, "A" does produce something that "B" would use, but it's too late: "B" has already been configured to not rely on "A".

Of course, I could change the configuration of "B" to be optimistic and assume that "A" will successfully find or build something, but I'm trying to make this smarter. If "A" fails, or if we choose to not include "A", I would prefer to not have to manually change the configuration of "B" ("C", "D", ...)

I can force the result I want by touching "B"'s CMakeLists.txt file after the first configure & build cycle, to force B to reconfigure, and then "build" again. I have not found a way to force "A" to build before "B" configures.

What I have tried:

In the "A" CMakeLists.txt, in ExternalProject_Add (A-PRJ ...), I've set the BUILD_BYPRODUCTS, and STEP_TARGETS build install; I have an add_custom_target (A-TARG ALL DEPENDS A-PRJ-build ...); I've looked for and tried various ways to set dependencies. As far as I can tell, everything is configured before anything is built, and dependencies affect only the build order. I haven't found a way to make a configuration of one directory depend on the build of another.

I've tried setting an A_FOUND cache variable, but it gets set during "A"'s configuration before the thing in question actually exists. "B" then tries to include a header that doesn't exist yet, and the whole build dies. I guess there might be some clue lurking in there, because if the build of "B" properly depended on the build of "A", the header would have been there to include. But again, this would require the configuration "B" to be optimistic about the build of "A" producing that thing. I'm trying to avoid that optimism :-O And I want "B" to build whether or not "A" does, but to build differently, so a hard dependence of "B" on "A" (as implemented in the explicit CMake dependencies) doesn't quite seem to accomplish what I'm after.
Posted
Comments
Peter_in_2780 31-Mar-23 0:08am    
I haven't messed with *make for years, but way back, what we used to do was use file existence as a linkage. You probably need two, one to say that A has built (which is a dependency in B, and is deleted when B succeeds) and one to tell B which path A went down.
twhall 3-Apr-23 22:19pm    
[I hope that a "Comment" preserves formatting. We shall see. Apologies if it does not.]

Thanks Peter_in_2780. Yes, I'm trying something like that. If "A" builds A.dll, it sets cache variables for A_RUNTIME and A_INCLUDE_DIR with the full pathnames for A.dll and A/include. When "B" configures, it tests for the existence of ${A_RUNTIME}. If it exists, it adds a compile_definition and an include_directory, with the intention that "B" will dynamically load and use A:


if (EXISTS "${A_RUNTIME}")
target_compile_definitions(B PRIVATE A_RUNTIME="${A_RUNTIME}")
target_include_directories(B PRIVATE "${A_INCLUDE_DIR}")
endif()


B.cpp then uses #ifdef A_RUNTIME to conditionally include A's headers and dynamically load A_RUNTIME

If ${A_RUNTIME} doesn't exist, B should fall back to some alternative implementation or graceful failure, without a hard dependence on "A".

Still trying to get CMake to try to build A and determine the existence of A.dll before configuring "B" to use it or not.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900