[CMake] Force target to always run last?
David Cole
DLRdave at aol.com
Thu May 18 14:22:55 EDT 2017
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