How to add a .h file to a flex definition in CMake - cmake

So I am trying to use flex in a project with Clion (because I'm on windows), which uses CMake but I cannot compile because my lexer.l file includes token.h
my CMakeLists.txt:
cmake_minimum_required(VERSION 3.10)
find_package(FLEX)
FLEX_TARGET(MyScanner lexer.l ${CMAKE_CURRENT_BINARY_DIR}/lex.yy.c)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
add_executable(lexer token.h ${FLEX_MyScanner_OUTPUTS}
printtoken.c lexan.h lexanl.c )
ERROR:
[ 16%] Building C object CMakeFiles/lexer.dir/lex.yy.c.o
lexan.l:36:10: fatal error: token.h: No such file or directory
compilation terminated.
CMakeFiles/lexer.dir/build.make:74: recipe for target 'CMakeFiles/lexer.dir/lex.yy.c.o' failed
How do I include the token.h?

Problem Solved:
I had to add ${CMAKE_SOURCE_DIR} to the include_directories() call for it to find the header file.

Related

How to build cpp file which name has a special character by CMakeLists.txt

I'm learning CMake.I found a problem, when i try to build a cpp file which name has a special character(such as "[155]test_file.cpp").The compiler can't find this file.How can i solve this problem by modifying CMakeLists,rather than rename the file?
I'm testing in a window10 PC,and compiler is mingw.
error info
g++.exe: error: E:\test[155]test_file.cpp: No such file or directory
g++.exe: fatal error: no input files
CMakeLists.txt
cmake_minimum_required(VERSION 3.17)
project(TEST_ LANGUAGES CXX)
add_executable(test_ "${CMAKE_SOURCE_DIR}/[155]test_file.cpp")

CMake not able to find Debug Library

I am a CMake noob trying to put together a package installer so i can move between my windows development machine and my cluster.
I have the following directory tree for my files (an example)
-Primary
--Library Source
--CMakeLists.txt
--src1.cpp
--src1.h
--Application Source
--CMakeLists.txt
--src1.cpp
--src1.h
--CMakeLists.txt
Each CMakeLists.txt is
Primary/CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(BloodVesselRadiationDamageSimulations CXX)
SET(FIND_LIBRARY_USE_LIB64_PATHS true)
SET(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}) #only for testing
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_ROOT}/ ${CMAKE_SOURCE_DIR}/cmake/Modules/")
FIND_PACKAGE(OpenMP)
FIND_PACKAGE(MPI)
FIND_PACKAGE(HDF5)
FIND_PACKAGE(GTest)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
SET(CMAKE_DEBUG_POSTFIX _d)
ADD_SUBDIRECTORY(Source)
ADD_SUBDIRECTORY(SourceUnitTest)
Library Source/CMakeLists.txt
ADD_LIBRARY(VesselProjectBaseLibrary STATIC Src1.cpp
Src1.h)
INSTALL(TARGETS VesselProjectBaseLibrary DESTINATION x64/Debug CONFIGURATIONS Debug)
INSTALL(TARGETS VesselProjectBaseLibrary DESTINATION x64/Release CONFIGURATIONS Release|RelWithDebInfo)
Application Source/CMakeLists.txt
INCLUDE_DIRECTORIES("${GTEST_INCLUDE_DIRS}")
ADD_EXECUTABLE (SourceUnitTests Src1.cpp
Src1.h)
TARGET_LINK_LIBRARIES(SourceUnitTests ${GTEST_LIBRARY})
TARGET_LINK_LIBRARIES(SourceUnitTests debug VesselProjectBaseLibrary_d optimized VesselProjectBaseLibrary)
I am able to generate the projects correctly; I see all the correct files in the projects. However, when i go to compile the debug build I get the following error:
1>ipo: : error #11018: Cannot open VesselProjectBaseLibrary_d.lib
1>LINK : fatal error LNK1104: cannot open file 'VesselProjectBaseLibrary_d.lib'
If i compile my release build everything works perfectly and compilation is successful. The library compiles successfully under both builds.
When you link against a library created within the project, you need to specify library target name, not a library file. CMake will care about proper filename, path and other things:
TARGET_LINK_LIBRARIES(SourceUnitTests VesselProjectBaseLibrary)
Variable CMAKE_DEBUG_POSTFIX affects on library's filename. While file VesselProjectBaseLibrary_d.lib is actually created in debug build, it cannot be found automatically by the linker. Again, use target name and let CMake do all other work.

Using constant folder with cmake

I have a constant MYPROJECT in my ~/.bashrc file:
export MYPROJECT = /home/loom/my_project
I can see the constant is defined in the terminal:
loom#loom$ ls -ld $MYPROJECT
drwxr-xr-x 25 loom loom 4096 Jul 21 22:12 /home/loom/my_project
I tried to use the constant in my CMakeLists.txt:
add_executable(booo src/main.cpp ${MYPROJECT}/foo/trunk/bar/File.h)
However, it produces an error:
CMake Error at CMakeLists.txt:17 (add_executable):
Cannot find source file:
/foo/trunk/bar/File.h
Tried extensions .c .C .c++ .cc .cpp .cxx .m .M .mm .h .hh .h++ .hm .hpp
.hxx .in .txx
CMake Error: CMake can not determine linker language for target: booo
CMake Error: Cannot determine link language for target "booo".
It is processed without errors if I have used explicit path without $MYPROJECT:
add_executable(booo src/main.cpp /home/loom/my_project/foo/trunk/bar/File.h)
How to use path defined in .bashrc in cmake?
Instead of
add_executable(booo src/main.cpp ${MYPROJECT}/foo/trunk/bar/File.h)
use
add_executable(booo src/main.cpp $ENV{MYPROJECT}/foo/trunk/bar/File.h)
The CMake documentation states:
Use the syntax $ENV{VAR} to read environment variable VAR. See also
the set() command to set ENV{VAR}.
https://cmake.org/cmake/help/v3.4/variable/ENV.html
Turning my comment into an answer
There are a lot of ways you could do this in CMake. Out of bad experiences with using environment variables directly inside CMake projects (they have to be valid not only during the first call to CMake configuration/generation but also later during all consecutive builds), I would recommend to transfer your constant into a cached CMake variable.
I'm using one of the following ways in my projects:
Injecting MYPROJECT CMake via its -D option, e.g.
cmake -DMYPROJECT:PATH=$MYPROJECT ..
Then CMake would cache this value in its own MYPROJECT internal variable.
When you get values from the "outside" you should think about what to do if no value is provided or it's not a valid directory. Throwing a fatal error and/or retry with a default value?
The following example shows only transformation steps and sanity checks (no default value retry):
if (NOT DEFINED MYPROJECT OR NOT IS_DIRECTORY MYPROJECT)
file(TO_CMAKE_PATH "$ENV{MYPROJECT}" _ENV_MYPROJECT_REL)
get_filename_component(_ENV_MYPROJECT "${_ENV_MYPROJECT_REL}" ABSOLUTE)
if (NOT _ENV_MYPROJECT)
message(FATAL_ERROR "Environment variable MYPROJECT not provided.")
else()
set(MYPROJECT "${_ENV_MYPROJECT}" CACHE INTERNAL "")
endif()
endif()
Using find_path(), which will also cache its result:
find_path(
MYPROJECT_INCLUDE_DIR
NAMES File.h
PATHS ENV MYPROJECT
/home/loom/my_project
PATH_SUFFIXES foo/trunk/bar
)
if (NOT MYPROJECT_INCLUDE_DIR)
...
Or - assuming your external project does not only consists of header files but also libraries like foo.a - following CMake's A Sample Find Module and extending the find_path() code from above by:
find_library(
MYPROJECT_LIBRARY
NAMES foo
PATHS ENV MYPROJECT
PATH_SUFFIXES foo/lib
)
if(MYPROJECT_INCLUDE_DIR AND MYPROJECT_LIBRARY AND NOT TARGET MyProject::MyProject)
add_library(MyProject::MyProject UNKNOWN IMPORTED)
set_target_properties(
MyProject::MyProject
PROPERTIES
IMPORTED_LOCATION "${MYPROJECT_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${MYPROJECT_INCLUDE_DIR}"
)
endif()
Now you can use it directly as any other CMake target with
add_executable(booo src/main.cpp)
target_link_libraries(booo MyProject::MyProject)
More References
What's the CMake syntax to set and use variables?
preferred cmake project structure

How to use libxml2 with CMake?

I am using CLion editor (with CMake) for my C project,
I've never used an external library though,
my question is how do I link an external lib (for ex. libxml2) to my project?
I've seen some questions similar to this but none worked for me.
My project is compiled on Windows, and I have libxml .dll, include, and .lib files(binaries for Windows).
Edit: My CMakeLists.txt file after the answer suggested:
cmake_minimum_required(VERSION 3.2)
project(time_table)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES
course.c
course.h
day.h
defines.h
find_tables.c
find_tables.h
item.h
parse_info.c
parse_info.h
table.c
table.h
time_table.c grades.c grades.h)
link_libraries(C:/Users/Gal/Desktop/time_table/libxml2-2.7.8.win32/lib)
add_executable(time_table ${SOURCE_FILES})
target_link_libraries(time_table libxml2)
and this is what I get:
"C:\Program Files (x86)\JetBrains\CLion 1.1.1\bin\cmake\bin\cmake.exe" --build C:\Users\Gal\.clion11\system\cmake\generated\2eda76ff\2eda76ff\Debug --target time_table -- -j 8
[ 14%] Linking C executable time_table.exe
c:/mingw/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: cannot find -llibxml2
collect2.exe: error: ld returned 1 exit status
mingw32-make.exe[3]: *** [time_table.exe] Error 1
CMakeFiles\time_table.dir\build.make:225: recipe for target 'time_table.exe' failed
CMakeFiles\Makefile2:66: recipe for target 'CMakeFiles/time_table.dir/all' failed
mingw32-make.exe[2]: *** [CMakeFiles/time_table.dir/all] Error 2
CMakeFiles\Makefile2:78: recipe for target 'CMakeFiles/time_table.dir/rule' failed
mingw32-make.exe[1]: *** [CMakeFiles/time_table.dir/rule] Error 2
What is wrong?
There is a key work for libraries installed on your machine. <lib_name>_INCLUDE_DIR and <lib_name>_LIBRARIES once you have done find_package. This works for me.
find_package(LibXml2 REQUIRED)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/<my_stuff> ${LIBXML2_INCLUDE_DIR})
add_executable(<my_exe> <my_source_files>)
target_link_libraries(<my_exe> ${LIBXML2_LIBRARIES})
---- Just a note for your curiosity ----
If you ever needed to build (1) a (static) library of your calculations, maybe reusable, and (2) an executable that uses that library and LIBXML2, do this.
find_package(LibXml2 REQUIRED)
# add a calculation library: file "lib<mycalc>.a"
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/<your header files folder> ${LIBXML2_INCLUDE_DIR})
add_library(<mycalc> STATIC ${CMAKE_CURRENT_SOURCE_DIR}/<your src files folder>)
target_link_libraries(<mycalc> ${LIBXML2_LIBRARIES})
# add the executable: file <my_exe>
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/<your header files folder> ${LIBXML2_INCLUDE_DIR})
add_executable(<my_exe> <your exe src files>)
target_link_libraries(<my_exe> <mycalc> ${LIBXML2_LIBRARIES})
Assume that full path to the library(.lib) can be expressed as
<library_dir>/<library_name>.lib
For compile executable, which uses this library, you need:
CMakeLists.txt:
link_libraries(<library_dir>)
add_excutable(<my_exe> ..)
target_link_libraries(<my_exe> <library_name>)
For use(run) compiled executable, you need to have <library_name>.dll either under one of the directory, listed in the PATH environment variable, or within same directory with executable.
there are 32bit and 64bit version of libxml2, to be found here.
you can put them below the PATH - or the C:\Windows directory.
With moderns CMake (version 3.2 or newer), it got much easier:
Search for the library. CMake has an according find module, thus it boils down to
find_package(LibXml2 REQUIRED)
Then you can link the library it to your target foo
target_link_libraries(foo PUBLIC LibXml2::LibXml2)
That's it folks! No fiddling around with headers and libraries, all done automatically.
If you have not installed the library, you might want to set LibXml2_DIR to the location where LibXml2 is located, i.e., by passing -DLibXml2_DIR=C:\software\libxml2 to your CMake call. That will help CMake finding LibXml2.

Unknown Cmake command "add_llvm_tool"

I am trying to build llvm from source using Cmake.
I have an error coming when Cmake is trying to build it : Unknown CMake command "add_llvm_tool".
I don't know why there is this error, here is my CMakeLists.txt file
cmake_minimum_required(VERSION 3.2)
set(LLVM_LINK_COMPONENTS
${LLVM_TARGETS_TO_BUILD}
Core
Object
Support
)
add_llvm_tool(llvm-nm
llvm-nm.cpp
)
You need to include(AddLLVM.cmake) to have this macro defined.