# FindLibXml2 finds local library when cross compiling

**URL:** https://discourse.cmake.org/t/findlibxml2-finds-local-library-when-cross-compiling/7529
**Category:** Usage
**Created:** [February 23, 2023, 9:02am UTC](https://discourse.cmake.org/t/findlibxml2-finds-local-library-when-cross-compiling/7529 "2023-02-23T09:02:34Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![MarioKlebsch](https://discourse.cmake.org/user_avatar/discourse.cmake.org/marioklebsch/32/3196_2.png) [@MarioKlebsch](https://discourse.cmake.org/u/MarioKlebsch)
#### Post date: [February 23, 2023, 9:02am UTC](https://discourse.cmake.org/t/findlibxml2-finds-local-library-when-cross-compiling/7529/1 "2023-02-23T09:02:34Z")

</div>

I use FindLibXml2 in my CMakeLists.txt to detect wether libxml2 is available on the target system or wether it has to be built.

```auto
include(FindLibXml2)
add_library(LibXml2 INTERFACE )
if (NOT LIBXML2_FOUND)
   ... <build libxml2 from source>

```

It worked well for several targets, but now, I have got a new target system, where this check fails. I have got a toolchain file for the new target and I suspect, some setting might be missing or wrong in the toolchain file.

Unfortunately the documentation of FindLibXml2 ([https://cmake.org/cmake/help/v3.25/module/FindLibXml2.html](https://cmake.org/cmake/help/v3.25/module/FindLibXml2.html)) does not explain, how it works and which configuration settings can be used to tweak its behavoir.

I use cmake version 3.25.2

I am just an occasional cmake user and up to now, and I did not manage to debug a cmake program, yet. ☹

I hope, somebody has a hint for me.

P.S. I succeded to make cmake not finding the native libcurses by setting PKG\_CONFIG\_LIBDIR, but it had no visible effect on finding libxml2.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [February 23, 2023, 7:56pm UTC](https://discourse.cmake.org/t/findlibxml2-finds-local-library-when-cross-compiling/7529/2 "2023-02-23T19:56:15Z")

</div>

First of all, you should not use `include()` for `Find*` modules and instead use `find_package()` as CMake sets up variables that the code may be expecting to be around. Do things work better if you do that?

---

<div class="post-metadata">

### Author: ![MarioKlebsch](https://discourse.cmake.org/user_avatar/discourse.cmake.org/marioklebsch/32/3196_2.png) [@MarioKlebsch](https://discourse.cmake.org/u/MarioKlebsch)
#### Post date: [February 27, 2023, 11:13am UTC](https://discourse.cmake.org/t/findlibxml2-finds-local-library-when-cross-compiling/7529/3 "2023-02-27T11:13:01Z")

</div>

Using `find_package()` did not change the behavoir.

Instead of waisting my time with endless trying, I started to hack a primitive CMake debugger. I hope, I will be able to analyze my problem during this week. Unfortunately, I have to take care of other hi-prio topics, so no promise.

IN case anybody is ingterested, here is my debugger:

```auto
diff -c -r cmake-3.25.2/Source/cmake.cxx cmake-3.25.2-debugger/Source/cmake.cxx
*** cmake-3.25.2/Source/cmake.cxx	2023-01-19 15:32:19.000000000 +0100
--- cmake-3.25.2-debugger/Source/cmake.cxx	2023-02-27 11:25:12.948873298 +0100
***************
 ***869,874****
--- 869,879 ----
                       CommandArgument::RequiresSeparator::No, SourceArgLambda },
      CommandArgument{ "-O", CommandArgument::Values::Zero,
                       IgnoreAndTrueLambda },
+ CommandArgument{ "-d", CommandArgument::Values::Zero,
+ [](std::string const&, cmake* state) -> bool {
+ state->SetDebugger(true);
+ return true;
+ } },
      CommandArgument{ "-B", "No build directory specified for -B",
                       CommandArgument::Values::One,
                       CommandArgument::RequiresSeparator::No, BuildArgLambda },
diff -c -r cmake-3.25.2/Source/cmake.h cmake-3.25.2-debugger/Source/cmake.h
*** cmake-3.25.2/Source/cmake.h	2023-01-19 15:32:19.000000000 +0100
--- cmake-3.25.2-debugger/Source/cmake.h	2023-02-27 11:15:22.674405159 +0100
***************
 ***498,503****
--- 498,505 ----
    void SetDebugFindOutputPkgs(std::string const& args);
    void SetDebugFindOutputVars(std::string const& args);
  
+ bool GetDebugger() const { return this->Debugger; }
+ void SetDebugger(bool b) { this->Debugger = b; }
    //! Do we want trace output during the cmake run.
    bool GetTrace() const { return this->Trace; }
    void SetTrace(bool b) { this->Trace = b; }
***************
 ***684,689****
--- 686,692 ----
    WorkingMode CurrentWorkingMode = NORMAL_MODE;
    bool DebugOutput = false;
    bool DebugFindOutput = false;
+ bool Debugger = false;
    bool Trace = false;
    bool TraceExpand = false;
    TraceFormat TraceFormatVar = TRACE_HUMAN;
diff -c -r cmake-3.25.2/Source/cmMakefile.cxx cmake-3.25.2-debugger/Source/cmMakefile.cxx
*** cmake-3.25.2/Source/cmMakefile.cxx	2023-01-19 15:32:19.000000000 +0100
--- cmake-3.25.2-debugger/Source/cmMakefile.cxx	2023-02-27 12:00:41.762641447 +0100
***************
 ***12,17****
--- 12,18 ----
  #include <cstring>
  #include <sstream>
  #include <utility>
+ #include <list>
  
  #include <cm/iterator>
  #include <cm/memory>
***************
 ***406,411****
--- 407,545 ----
    this->ExecuteCommandCallback = std::move(callback);
  }
  
+ #include <iostream>
+ 
+ static void ShowSource(const cmListFileFunction func, const std::string &FileName)
+ {
+ std::ifstream file(FileName);
+ if (!file)
+ fprintf(stderr, "Failed to read %s\n", FileName.c_str());
+ else
+ {
+ int CurrentLine=0;
+ std::string SourceLine;
+ while (CurrentLine < func.Line() && std::getline(file, SourceLine))
+ CurrentLine++;
+ if (file)
+ {
+ printf("%s:%ld", FileName.c_str(),func.Line());
+ if (func.Line() < func.LineEnd())
+ printf("-%ld:\n",func.LineEnd());
+ else
+ printf(": ");
+ while (CurrentLine <= func.LineEnd() && file)
+ {
+ printf("%s\n", SourceLine.c_str());
+ std::getline(file, SourceLine);
+ CurrentLine++;
+ }
+ return;
+ }
+ }
+ printf("%s(", func.OriginalName().c_str());
+ for (const auto &arg: func.Arguments())
+ printf("%s ", arg.Value.c_str());
+ printf(")\n");
+ }
+ 
+ static std::list<std::string> splitLine(const std::string &line)
+ {
+ std::list<std::string> ret;
+ 
+ auto it = line.begin();
+ auto end = line.end();
+ while (it != end)
+ {
+ if (isspace(*it))
+ {
+ it++;
+ continue;
+ }
+ auto start = it;
+ while (it != end && !isspace(*it))
+ it++;
+ ret.emplace_back(start,it);
+ }
+ return ret;
+ }
+ 
+ void cmMakefile::Debugger(cmListFileFunction const& lff)
+ {
+ const auto FileName = this->StateSnapshot.GetExecutionListFile();
+ ShowSource(lff, FileName);
+ std::set<std::string> already_expanded;
+ for (const auto &arg:lff.Arguments())
+ {
+ auto temp = arg.Value;
+ if (already_expanded.find(temp) != already_expanded.end())
+ continue;
+ already_expanded.insert(temp);
+ auto expanded = this->ExpandVariablesInString(temp);
+ if (arg.Value != expanded)
+ printf("%s = \"%s\"\n", arg.Value.c_str(), expanded.c_str());
+ 
+ }
+ 
+ static unsigned LastStep=0;
+ 
+ for (;;)
+ {
+ printf("%u> ", (unsigned)this->RecursionDepth);
+ std::string line;
+ if (!std::getline(std::cin, line))
+ {
+ this->BreakLevel = 0;
+ return;
+ }
+ 
+ auto args=splitLine(line);
+ if (args.empty() && LastStep)
+ {
+ this->BreakLevel = LastStep;
+ return;
+ }
+ 
+ auto cmd = args.front();
+ args.pop_front();
+ 
+ if (cmd == "s")
+ {
+ this->BreakLevel = LastStep = std::numeric_limits<unsigned>::max();
+ return;
+ }
+ if (cmd == "n")
+ {
+ this->BreakLevel = LastStep = this->RecursionDepth;
+ return;
+ }
+ LastStep=0;
+ if (cmd == "f")
+ {
+ this->BreakLevel = this->RecursionDepth-1;
+ return;
+ }
+ if (cmd == "c")
+ {
+ this->BreakLevel = 0;
+ return;
+ }
+ if (cmd=="q")
+ exit(1);
+ if (cmd=="p")
+ {
+ for (const auto &arg:args)
+ {
+ auto var = this->GetDefinition(arg);
+ if (var)
+ printf("%s=\"%s\"\n", arg.c_str(), var->c_str());
+ else
+ printf("%s not found\n", arg.c_str());
+ }
+ }
+ }
+ }
+ 
+ 
  bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff,
                                  cmExecutionStatus& status,
                                  cm::optional<std::string> deferId)
***************
 ***444,449****
--- 578,586 ----
      return false;
    }
  
+ if (this->GetCMakeInstance()->GetDebugger() &&
+ this->RecursionDepth <= this->BreakLevel)
+ Debugger(lff);
    // Lookup the command prototype.
    if (cmState::Command command =
          this->GetState()->GetCommandByExactName(lff.LowerCaseName())) {
diff -c -r cmake-3.25.2/Source/cmMakefile.h cmake-3.25.2-debugger/Source/cmMakefile.h
*** cmake-3.25.2/Source/cmMakefile.h	2023-01-19 15:32:19.000000000 +0100
--- cmake-3.25.2-debugger/Source/cmMakefile.h	2023-02-27 11:59:16.035392037 +0100
***************
 ***713,718****
--- 713,720 ----
    bool ExecuteCommand(const cmListFileFunction& lff, cmExecutionStatus& status,
                        cm::optional<std::string> deferId = {});
  
+ void Debugger(cmListFileFunction const& lff);
+ 
    //! Enable support for named language, if nil then all languages are
    /// enabled.
    void EnableLanguage(std::vector<std::string> const& languages,
***************
 ***1189,1192****
--- 1191,1196 ----
    bool IsSourceFileTryCompile;
    mutable bool SuppressSideEffects;
    ImportedTargetScope CurrentImportedTargetScope = ImportedTargetScope::Local;
+ 
+ unsigned BreakLevel=std::numeric_limits<int>::max();
  };

```

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [February 27, 2023, 2:37pm UTC](https://discourse.cmake.org/t/findlibxml2-finds-local-library-when-cross-compiling/7529/4 "2023-02-27T14:37:41Z")

</div>

There is the `--trace-expand` flag which does most of what you want here (just doesn’t call out the actual argument values separately).

---

<div class="post-metadata">

### Author: ![MarioKlebsch](https://discourse.cmake.org/user_avatar/discourse.cmake.org/marioklebsch/32/3196_2.png) [@MarioKlebsch](https://discourse.cmake.org/u/MarioKlebsch)
#### Post date: [February 28, 2023, 1:56pm UTC](https://discourse.cmake.org/t/findlibxml2-finds-local-library-when-cross-compiling/7529/5 "2023-02-28T13:56:14Z")

</div>

I finally found, that FindLibXml2.cmake invokes PKG\_CHECK\_MODULES(PC\_LIBXML QUIET libxml-2.0), which does not seem to find libxml and than invokes find\_path(), passing the directories obtained from PKG\_CHECK\_MODULES():

```auto
find_path(LIBXML2_INCLUDE_DIR NAMES libxml/xpath.h
   HINTS
   ${PC_LIBXML_INCLUDEDIR}
   ${PC_LIBXML_INCLUDE_DIRS}
   PATH_SUFFIXES libxml2
   )
${PC_LIBXML_INCLUDEDIR} = ""
${PC_LIBXML_INCLUDE_DIRS} = ""

```

and find\_path() returns LIBXML2\_INCLUDE\_DIR=“/usr/include/libxml2”. The documentation of find\_path() lists a lots of CMake and environment variables, which are used. Setting CMAKE\_FIND\_USE\_SYSTEM\_ENVIRONMENT\_PATH to false looks promising, but cmake doesn’t even find make anymore, when I use this setting.

It then calls find\_library():

```auto
find_library(LIBXML2_LIBRARY NAMES xml2 libxml2 libxml2_a
   HINTS
   ${PC_LIBXML_LIBDIR}
   ${PC_LIBXML_LIBRARY_DIRS}
   )
${PC_LIBXML_LIBDIR} = ""
${PC_LIBXML_LIBRARY_DIRS} = ""

```

which returns LIBXML2\_LIBRARY=“/usr/lib/libxml2.so”.
