[CMake] Force target to always run last?
David Cole
DLRdave at aol.com
Thu May 18 16:11:26 EDT 2017
Hopefully, somebody else doing something similar to what you're doing
will chime in here.
Seems overly complicated from an outsider's perspective.
If what you say is true ...:
"If 'copy_dlls' happens while 'B' is building, then it's possible the
post-build event run by B that deletes the 'libs' directory also
deletes some files copied by 'copy_dlls'"
...then copy_dlls depends on B, because if it runs before or while B
is running, you have problems. So it has to run after.
Seems like you have some untangling to do.
On Thu, May 18, 2017 at 3:42 PM, Robert Dailey <rcdailey.lists at gmail.com> wrote:
> To be clear, I do have a "package" target per real native target.
> However, if I set up the dependencies like so:
>
> Target 'A' depends on 'copy_dlls'
> Target 'A' depends on target 'B'
> Target 'A_package' depends on 'A'
> Target 'A_package' depends on 'copy_dlls'
>
> Furthermore, the add_custom_command() to delete 'libs' and copy the
> *.so is added to 'A' and 'B' (each for their own 'libs' directory and
> their own *.so output)
>
> Then when I do:
>
> $ ninja A_package
>
> The following items are built in any order (due to parallel builds):
>
> * B
> * A (after B)
> * copy_dlls
>
> If 'copy_dlls' happens while 'B' is building, then it's possible the
> post-build event run by B that deletes the 'libs' directory also
> deletes some files copied by 'copy_dlls', which means those files will
> not get packaged when 'A_package' invokes `ant release` for the APK
> packaging.
>
> I hope that makes the issue a little clearer... sorry for the confusion.
>
> On Thu, May 18, 2017 at 1:22 PM, David Cole <DLRdave at aol.com> wrote:
>> Seems to me the simplest thing to do would be to have copy_dlls depend
>> on nothing, and have package depend on copy_dlls and all the native
>> targets, and then tell your developers to run:
>>
>> make individualTarget && make package
>>
>> Either that, or introduce a packageIndividualTarget target for each
>> individualTarget.
>>
>> Maybe I just don't understand fully, but why would you ever "make
>> individualTarget" and then expect package to work properly? What if
>> stuff that depends on that individualTarget also needs to rebuild
>> before packaging? Shouldn't you have to do a build all to guarantee
>> that packaging the results works properly?
>>
>>
>>
>>
>>
>>
>> On Thu, May 18, 2017 at 12:16 PM, Robert Dailey
>> <rcdailey.lists at gmail.com> wrote:
>>> So let me go over the problem I'm trying to solve, because it's
>>> possible at this point I'm over-engineering it, but it's hard to fix.
>>>
>>> So my build process is for native shared library targets that
>>> eventually get included in an APK for Android. I'm using the NDK
>>> toolchain to build my native targets. The general flow from nothing to
>>> complete APK is as follows:
>>>
>>> 1. Build all native library targets
>>> 2. Copy native *.so outputs from the CMake build to `libs/armeabi-v7a`
>>> in the android project directory (where the src, res, and other
>>> android directories are located)
>>> 3. Run custom commands that basically invoke 'ant release', and since
>>> I positioned the *.so files under 'libs' they get packaged with the
>>> APK itself.
>>>
>>> This is how I provide support for using CMake to build native, run
>>> java build, and perform APK packaging.
>>>
>>> There's a lot of setup that happens in CMake in order to make sure the
>>> 'ant release' command behaves as expected. I have to handle a few
>>> corner cases:
>>>
>>> * Each new build of the custom target that runs the 'ant release'
>>> command has to only contain the *.so files that were built during that
>>> run
>>> * Various third-party libraries (pre-compiled *.so files) have to also
>>> be copied to libs/armeabi-v7a for only certain android projects,
>>> because we do not want duplicated *.so files across multiple android
>>> libraries (ant release will fail if there are duplicate *.so files
>>> across android project dependencies)
>>>
>>> So given this, my complete pipeline is as follows:
>>>
>>> 1. A `android_clean_libs` custom target is run which iterates all
>>> known native targets with mapped java projects and completely deletes
>>> its 'libs' directory (this is a forced clean prior to building)
>>> 2. A `copy_dlls` target runs next, which copies third party
>>> (precompiled) *.so files to a single common java project, in its
>>> 'libs/armeabi-v7a' directory.
>>> 3. Each native target now builds in parallel, as a post-build event it
>>> copies its output *.so file to its respective libs/armeabi-v7a
>>> directory for packaging.
>>> 4. A final 'package' custom target runs which runs 'ant release' on
>>> the bottom-most android project (that is not a library target by
>>> itself).
>>>
>>> The part I don't like here is step #1. I don't like the clean to
>>> require keeping track of a global property of a list of directories to
>>> remove. Ideally, #1 should run as a post-build event during step 3.
>>> Basically each native target should delete its 'libs' directory prior
>>> to copying its own *.so target to that directory. However, I can't do
>>> this because of step #2. Step 2 must happen first, because it's the
>>> only way I can guarantee that it will execute regardless of which
>>> target I build (all, or specific target). I make `copy_dlls` a
>>> dependency of every other target, so it always runs. If I could force
>>> it to run *last*, then I could simplify step 1.
>>>
>>> Sorry if this is too much information or if I've not explained things
>>> clearly, but I wanted to hash out the details because maybe there is a
>>> better approach. I'm willing to start from scratch on this if it
>>> improves the design of the targets.
>>>
>>> Thanks again!!
>>>
>>>
>>> On Thu, May 18, 2017 at 10:51 AM, David Cole <DLRdave at aol.com> wrote:
>>>> I'm sorry, I misunderstood that you wanted it to run last regardless
>>>> of what target you are building. I was assuming you wanted it to
>>>> happen when you build the "all" target. I didn't think you wanted to
>>>> run it after any other *individual* target which you might specify.
>>>>
>>>> I don't know of an easy way to do that. You could add a custom command
>>>> as a post-build command on every single target, but that seems like it
>>>> wouldn't work for you either, as it would run the command potentially
>>>> multiple times, with no way to tell whether you're being called last
>>>> or not.
>>>>
>>>> Sorry.
>>>>
>>>> Why does this need to run after the build of any individual target?
>>>> Why not just say there are two ways to get it to run: build "all" or
>>>> explicitly build it after you build the other individual thing you
>>>> want?
>>>>
>>>>
>>>>
>>>>
>>>> On Thu, May 18, 2017 at 10:24 AM, Robert Dailey
>>>> <rcdailey.lists at gmail.com> wrote:
>>>>> David,
>>>>>
>>>>> Thanks for your help. So if I do it as you suggest, this will also
>>>>> require I specify `ALL` to add_custom_target(), correct? If I do it
>>>>> this way, will it still run even if it isn't a dependency of the
>>>>> target I'm building?
>>>>>
>>>>> Let me set up a simple scenario for my own understanding. Suppose I
>>>>> have the following targets:
>>>>>
>>>>> * A (add_library target)
>>>>> * B (add_library target)
>>>>> * C (add_custom_target target)
>>>>>
>>>>> Dependencies:
>>>>>
>>>>> B depends on A
>>>>> C depends on B and A
>>>>>
>>>>> Normally if I build B, only A and B will build. However, if C was set
>>>>> up using `ALL`, will it build C when I build B? So the expected build
>>>>> order in this case would be:
>>>>>
>>>>> 1. A
>>>>> 2. B
>>>>> 3. C
>>>>>
>>>>> Thanks in advance.
>>>>>
>>>>> On Wed, May 17, 2017 at 4:26 PM, David Cole <DLRdave at aol.com> wrote:
>>>>>> The way I know how to do this is to add it last at the bottom of the
>>>>>> top-level CMakeLists.txt file, and then use add_dependencies to make
>>>>>> it depend on all other targets. (Or at least all other "leaf" targets,
>>>>>> which further depend on others, ... the sum of which is "all other
>>>>>> targets" besides the new "last" target.)
>>>>>>
>>>>>> So it's not pretty, but it's possible.
>>>>>>
>>>>>>
>>>>>> HTH,
>>>>>> David C.
>>>>>>
>>>>>>
>>>>>>
>>>>>> On Wed, May 17, 2017 at 11:36 AM, Robert Dailey
>>>>>> <rcdailey.lists at gmail.com> wrote:
>>>>>>> I have a custom target that must meet the following requirements:
>>>>>>>
>>>>>>> * It must always run, regardless of what subset of other targets are being built
>>>>>>> * It must always be the very last thing run. In parallelized builds,
>>>>>>> it must wait until all other targets are done building before
>>>>>>> starting, so that it is the very last target run, and should not run
>>>>>>> in parallel with others.
>>>>>>>
>>>>>>> Is this possible? I'm willing to use hackery if needed...
>>>>>>>
>>>>>>> Running CMake 3.8.0. Thanks!
>>>>>>> --
>>>>>>>
>>>>>>> Powered by www.kitware.com
>>>>>>>
>>>>>>> Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ
>>>>>>>
>>>>>>> Kitware offers various services to support the CMake community. For more information on each offering, please visit:
>>>>>>>
>>>>>>> CMake Support: http://cmake.org/cmake/help/support.html
>>>>>>> CMake Consulting: http://cmake.org/cmake/help/consulting.html
>>>>>>> CMake Training Courses: http://cmake.org/cmake/help/training.html
>>>>>>>
>>>>>>> Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html
>>>>>>>
>>>>>>> Follow this link to subscribe/unsubscribe:
>>>>>>> http://public.kitware.com/mailman/listinfo/cmake
More information about the CMake
mailing list