# What's the best way to add thirdparty lib with existing makefile?

**URL:** https://discourse.cmake.org/t/whats-the-best-way-to-add-thirdparty-lib-with-existing-makefile/3397
**Category:** Code
**Tags:** os:linux
**Created:** [May 25, 2021, 12:23am UTC](https://discourse.cmake.org/t/whats-the-best-way-to-add-thirdparty-lib-with-existing-makefile/3397 "2021-05-25T00:23:37Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![Lin](https://discourse.cmake.org/user_avatar/discourse.cmake.org/lin/32/1472_2.png) [@Lin](https://discourse.cmake.org/u/Lin)
#### Post date: [May 25, 2021, 12:23am UTC](https://discourse.cmake.org/t/whats-the-best-way-to-add-thirdparty-lib-with-existing-makefile/3397/1 "2021-05-25T00:23:37Z")

</div>

Hi there,

I’m new to CMake, and I’m currently trying to add a third-party library into my CMake project. My problem is that this third-party library only builds on Linux and comes with its own makefile. I figure this is probably a common situation and many have run into, and wonder if there is a idiomatic way to do this?

What I’m currently doing is use `add_custom_target` where I call the `make` command to generate the `lib.a` file. However, my understanding is that `add_custom_target` only generate `utility` target which can’t be linked to. So I have my main target link to the `lib.a` file explicitly, like this: `target_link_libraries(MY_TARGET PRIVATE lib.a)`.

Is this the right way to do it?

---

<div class="post-metadata">

### Author: ![Angew](https://discourse.cmake.org/user_avatar/discourse.cmake.org/angew/32/229_2.png) [@Angew](https://discourse.cmake.org/u/Angew)
#### Post date: [May 25, 2021, 7:40am UTC](https://discourse.cmake.org/t/whats-the-best-way-to-add-thirdparty-lib-with-existing-makefile/3397/2 "2021-05-25T07:40:21Z")

</div>

Hi.

Regarding the “link to the target” bit: you can create an IMPORTED target for that 3rd-party library. I would personally do that in your situation. This will allow you to add usage requirements (e.g. defines, include directories) to the target and have them propagate automatically via linking, and generally allow you to treat the library as a target in your CMake code. It could look like this:

```auto
add_custom_target(BuildTheLib ALL
  COMMAND make ...
  # (as you have now)
)

add_library(TheLib STATIC IMPORTED)
set_target_properties(TheLib
  IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/path/to/lib.a # Make sure to use absolute path here
  INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/lib_include
  INTERFACE_COMPILE_DEFINITIONS "USING_THELIB;THELIB_STATIC"
)
add_dependencies(TheLib BuildTheLib) # So that anyone linking against TheLib causes BuildTheLib to build first

target_link_libraries(MY_TARGET PRIVATE TheLib)

```

(The values of the properties written above are just examples, naturally, and should be modified or removed based on your actual situation).

Feel free to look into the documentation of imported targets and `IMPORTED_*` properties to learn more about what you can do with them.

---

<div class="post-metadata">

### Author: ![McMartin](https://discourse.cmake.org/user_avatar/discourse.cmake.org/mcmartin/32/150_2.png) [@McMartin](https://discourse.cmake.org/u/McMartin)
#### Post date: [May 26, 2021, 7:06am UTC](https://discourse.cmake.org/t/whats-the-best-way-to-add-thirdparty-lib-with-existing-makefile/3397/3 "2021-05-26T07:06:12Z")

</div>

You should have a look at the [`ExternalProject` module](https://cmake.org/cmake/help/latest/module/ExternalProject.html).

---

<div class="post-metadata">

### Author: ![ImaginaryExponent](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/i/b19c9b/32.png) [@ImaginaryExponent](https://discourse.cmake.org/u/ImaginaryExponent)
#### Post date: [June 13, 2021, 12:27pm UTC](https://discourse.cmake.org/t/whats-the-best-way-to-add-thirdparty-lib-with-existing-makefile/3397/4 "2021-06-13T12:27:34Z")

</div>

Hi.

I was recently presented with the same exact problem, where Oracle “odpi” library I required in a CMake-based project is supplied with a Makefile.win32 for Windows compilations and CMakeLists.txt for the rest of the world. Having read the advice you provided I would like to clarify a few points for myself and, hopefully, for the others facing the same problem.

- Makefile script supplied with a third-party library de-facto defines the build process for the third-party library. And CMake is one level above in logical abstractions since it can produce various build-scripts, including Makefiles, but also Ninja-scripts, vcxproj projects and so on as user demands. As such, the third party actions should be handled separately. ExternalProject or FetchContent are designed for that and are the appropriate way to go.
- Makefile can be produced by CMake but CMake does not parse existing Makefiles (nor vcxproj, nor Ninja build-scripts) and so it cannot use or invoke targets mentioned in these files. I have to manually specify that I want to “make -f MyMakefile.win32” for the building purposes “make -f MyMakefile.win32 --install” for the installation purposes and so on. I am still uncertain on the “clean” step, but I suppose I have to call “make -f MyMakefile.win32 --clean” manually as well.
- If I am to link against a library built with MyMakefile.win32, I have to read through the makefile myself, find out what the library name is, in which sub-directory it will be placed and use that in a call to the target\_link\_libraries in my main project.
- To get a Makefile-based third-party library into my project that is distributed as source code I cannot rely on find\_package, find\_module or anything similar to find things like build targets for me. They are for the CMake-based projects only.

I will be grateful if you confirm or correct my understanding.

---

<div class="post-metadata">

### Author: ![barcharcraz](https://discourse.cmake.org/user_avatar/discourse.cmake.org/barcharcraz/32/1558_2.png) [@barcharcraz](https://discourse.cmake.org/u/barcharcraz)
#### Post date: [June 14, 2021, 5:28am UTC](https://discourse.cmake.org/t/whats-the-best-way-to-add-thirdparty-lib-with-existing-makefile/3397/5 "2021-06-14T05:28:04Z")

</div>

Both FetchContent and ExternalProject have trouble with stuff you want to build and link when you build your project. The problem is none of the things you need to find in the library will exist at configure time since you’ve not built the library yet.

I think the “cleanest” way may be to rewrite the build system of the project in cmake, and use that to build it.

You can use find\_package with third party projects that don’t use cmake, someone just has to supply the module find\_package calls (either Find.cmake or Config.cmake (with a few acceptable variations). The Find version is for when the “find module” is written, maintained, and provided by someone other than the upstream maintainers of the project, the config version is for when the maintainers of the upstream project provide the cmake configuration.

There are a few projects that don’t use cmake but provide cmake config files, Qt comes to mind (well, they use cmake to build as of Qt6, but they started providing config files in Qt5).

Another approach is to use pkg-config, cmake has a built in module called FindPkgConfig.cmake (you can call it with `find_package(PkgConfig)` and it will run pkg-config with the right flags, parse the output, and create a target for you.

Neither of these approaches help if the library (and the pkg-config or cmake configuration files) don’t actually exist when you are configuring, as is the case when you’d like to build the library as part of your project’s

As a workaround you can do things like spawning a new cmake process as a custom command or with `execute_process` (this is, in fact, how FetchContent works internally) but all such methods are pretty messy.

Also: most makefile based build systems don’t support all the stuff cmake does, and projects that ship Makefile.win32 files in many cases don’t actually do much CI on windows, and their windows makefiles are very frequently just broken.

tl;dr it’s probably easier to just rewrite the makefile in cmake (stuff like file(GLOB) that’s usually not recommended can be quite handy here). As a bonus it’ll build like 10x faster since nmake on windows can’t do multiple rules at once.
