Here is my project structure:
.
├── include
├── src
│ ├── abc
│ │ ├── include
│ │ └── src
│ ├── def
│ │ ├── include
│ │ └── src
│ └── ghi
│ ├── include
│ └── src
└── vendor
├── bar
│ ├── include
│ └── src
└── foo
16 directories
I would like to port my build to Meson. However, I'm not sure how to link targets defined in sibling folders.
My dependency graph looks like this:
src/abc/meson.build defines a static library abc
src/def/meson.build defines a static library def that depends on abc and foo
src/ghi/meson.build defines a static library ghi that depends on bar
vendor/bar/meson.build defines a static library bar
vendor/foo/meson.build defines a static library foo
The top-level meson.build defines an executable app that depends on abc, def and ghi
In the documentation, there seem to be two mechanisms:
subdir
subproject
It is not clear to me which is best here. I do not have any dependencies outside of my source-code.
What should I write in my meson.build files to link these targets together?
You can use subdir from the top-level meson.build file down. All variables you declare in the subdir meson.build files are available to later meson.build files. As long as you get the order of subdir calls correct, it will work.
Besides #sdgfsdh's (correct) answer, another approach I like is to define libraries and executables only in the top-level meson file, and use subdir calls to define a sets of source files and "local" include paths. Done this way, the subdir files don't implicitly depend on each other; the entire dependency tree lives in the top-level meson file.
The advantages of this approach are:
subdirs don't need to know their own path (files() and include_directories() will track this for you)
The top-level file only needs to know subdir paths to call the subdir meson files. After that, you can define everything in terms of variables created in the subdirs
subdir files don't directly depend on any other meson files
Disadvantages:
The top-level file is more cluttered
Variable names in subdir files need to be globally unique, since everything is ultimately defined in the top-level scope
An example for your case:
# Top-level meson.build
subdir('src/abc')
subdir('src/def')
subdir('src/ghi')
subdir('vendor/foo')
subdir('vendor/bar')
libabc = static_library('abc', abc_files, include_directories: abc_includes)
libabc_dep = declare_dependency(include_directories: abc_includes, link_with : libabc)
libfoo = static_library('foo', foo_files, include_directories: foo_includes)
libfoo_dep = declare_dependency(include_directories: foo_includes, link_with : libfoo)
libdef = library('def', def_files, include_directories: def_includes, dependencies : [ libabc_dep, libfoo_dep])
# src/abc/meson.build (others would be similar)
abc_files = files(['1.c','2.c',...])
abc_includes = include_directories('include')
Related
I am developing a module, which depends on another library(wasmtime). I put files into:
modules/mod_wasm/src/include - header files, and
modules/mod_mine/src/lib/libwasmtime.a - the compiled library.
The problem which I faced is that when I compile the acore server with
./acore.sh compiler all
it gives me the error:
[100%] Linking CXX executable worldserver
/usr/bin/ld: ../../../modules/libmodules.a(ModWasm.cpp.o): in function `readWasmFile(char const*)':
ModWasm.cpp:(.text+0x63): undefined reference to `wasm_byte_vec_new_uninitialized'
/usr/bin/ld: ModWasm.cpp:(.text+0xce): undefined reference to `wasm_byte_vec_delete'
The question is it required somehow add to a config that library? If yes, then how to do that?
I was testing my code in simple main.cpp file and it was working with options like "-L${workspaceFolder}/lib" and "-lwasmtime".
Maybe, these options are also required for my module?
Here is a link to azerothcore project which I use.
my module locates in modules/mod-wasm folder
azerothcore-wotlk/modules ‹master*› » tree -L 3 mod-wasm
mod-wasm
├── CMakeLists.txt
├── LICENSE
├── Makefile
├── README.md
├── conf
│ ├── conf.sh.dist
│ └── wasm.conf.dist
├── include.sh
├── mod-wasm.cmake
├── setup_git_commit_template.sh
├── src
│ ├── ModWasm.cpp
│ ├── include
│ │ ├── doc-wasm.h
│ │ ├── wasi.h
│ │ ├── wasm.h
│ │ ├── wasmtime
│ │ ├── wasmtime.h
│ │ └── wasmtime.hh
│ ├── lib
│ │ ├── libwasmtime.a
│ │ └── libwasmtime.so
│ └── wasm_loader.cpp
└── wasm_modules
└── rust_wasm_app.wasm
As I understood from the logs what I see and because CMakeList.txt exists in modules folder, the project considers the folder as module. Which in its turn scans subdirs for *.cmake files and configures the project.
The question now is how to properly configure my module to show that it contains the compiled library wasmtime inside src/lib folder?
As I understood, I could use target_link_libraries, but it requires a target name, and I have no idea what it should be and where I can take it.
At the end, I was able to find an answer with try and catch.
Azerothcore modules supports modname.cmake file to be run when configure libmodules.a which contains all extra modules(if I understood it correctly.
this is part of modules/CMakeFiles.txt
# Enables Devs to Include a cmake file in their module that will get run inline with the config.
foreach(SOURCE_MODULE ${MODULES_MODULE_LIST})
message("SOURCE_MODULE: ${SOURCE_MODULE}")
include("${CMAKE_SOURCE_DIR}/modules/${SOURCE_MODULE}/${SOURCE_MODULE}.cmake" OPTIONAL)
endforeach()
here I have my dirty cmake file which allow me to compile the server
set(WASM_MODULE_DIR ${CMAKE_SOURCE_DIR}/modules/${SOURCE_MODULE})
set(WASM_MODULE_SRC_DIR ${WASM_MODULE_DIR}/src)
message("--------------------->>>>> APPLICATION_NAME : ${APPLICATION_NAME}")
message("--------------------->>>>> APP_PROJECT_NAME : ${APP_PROJECT_NAME}")
message("--------------------->>>>> SOURCE_MODULE : ${SOURCE_MODULE}")
message("--------------------->>>>> WASM_MODULE_DIR : ${WASM_MODULE_DIR}")
message("--------------------->>>>> WASM_MODULE_SRC_DIR : ${WASM_MODULE_SRC_DIR}")
# include wasmtime
target_include_directories(modules PUBLIC ${WASM_MODULE_SRC_DIR}/include)
target_link_directories(modules PUBLIC ${WASM_MODULE_SRC_DIR}/lib)
find_library(LIBWASMTIME_TO_INCLUDE NAMES wasmtime PATHS ${WASM_MODULE_SRC_DIR}/lib REQUIRED)
message("--------------------->>>>>>>>> LIBWASMTIME_TO_INCLUDE: ${LIBWASMTIME_TO_INCLUDE}")
target_link_libraries(modules PUBLIC wasmtime)
So, it compiles now.
But I have next problem, which I am trying to resolve. but this is another story.
Thank you all for the help
I have a given project structure
.
├── CMakeLists.txt
├── lib
│ ├── lodepng
│ │ ├── CMakeLists.txt
│ │ └── src
│ │ ├── lodepng.cpp
│ │ └── lodepng.h
│ └── pixel_reader
│ ├── CMakeLists.txt
│ └── src
│ ├── hello.cpp
│ └── hello.h
├── main.cpp
With the following CMakeLists
./CMakeLists.txt
cmake_minimum_required(VERSION 3.17)
project(pov_system VERSION 1.0)
add_subdirectory(lib/lodepng)
add_subdirectory(lib/pixel_reader)
add_executable(pov_system main.cpp)
target_link_libraries(pixel_reader PRIVATE lodepng)
target_link_libraries(pov_system PRIVATE pixel_reader)
./lodepng/CMakeLists.txt
add_library(
lodepng
src/lodepng.cpp
src/lodepng.h
)
target_include_directories(lodepng PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src")
./pixel_reader/CMakeLists.txt
add_library(
pixel_reader SHARED
src/hello.cpp
src/hello.h
)
target_include_directories(pixel_reader PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src")
As one can see, I try to link the 'lodepng' library to the 'pixel_reader' library and include the 'lodepng.h' to the 'hello.h' file.
But at the moment I get the following error while trying to build the project.
[build] <path-to-project>/pov_system/lib/pixel_reader/src/hello.h:2:10: fatal error: lodepng.h: No such file or directory
[build] 2 | #include "lodepng.h"
[build] | ^~~~~~~~~~~
[build] compilation terminated.
Question
Why is my code not finding the 'lodepng.h' file or (and even more important) is it a good practice to link from one library to another?
Maybe two really simple questions, but just started to dive into the world of CMake, Compiling, etc... and I really appreciate your help.
Why is my code not finding the 'lodepng.h' file or (and even more important)
Because you probably didn't give it correct path. One way to fix that would be to give the exact path in hello.h
#include "../../lodepng/src/lodepng.h
Second way is to use target_include_directories:
target_include_directories(pixel_reader PUBLIC "../../lodepng/src/")
is it a good practice to link from one library to another?
It depends on your project. If library A requires library B, then yes, it is okay in my opinion.
More importantly, you are creating the target in the wrong place i.e., in the root CMakeLists file. It must be done in the directory in which target is created.
./pixel_reader/CMakeLists.txt
# create target
add_library(
pixel_reader SHARED
src/hello.cpp
src/hello.h
)
target_link_libraries(pixel_reader PRIVATE lodepng) #link library where target is created
target_include_directories(pixel_reader PUBLIC "../../lodepng/src/")
target_include_directories(pixel_reader PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src")
Your pixel_reader library target possibly needs lodepng.h header to compile, because it depends on it.
something like
target_include_directories(pixel_reader PUBLIC "PATH_TO_LODE_PNG_HEADER_DIRECTORY")
could solve this problem.
I have a project which uses cmake to build. The project has a number of submodules which build as libraries. The structure looks like this:
src
├── CMakeLists.txt
├── libA
│ ├── CMakeLists.txt
│ ├── include
│ │ └── A
│ │ └── A.h
│ └── src
│ └── A.cpp
│
├── libB
│ ├── CMakeLists.txt
│ ├── include
│ │ └── B
│ │ └── B.h
│ └── src
│ └── B.cpp
│
├── include
│ └── project.h
├── main
│ ├── CMakeLists.txt
│ └── main.cpp
└── other_main
├── CMakeLists.txt
└── main.cpp
Now it turns out that I need to convert module B to be template based rather than a linkable lib; i.e. I want to export just headers from module B.
Currently module B's CMakeLists.txt contains the following:
add_library(B STATIC ${SOURCES})
target_include_directories(B
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
... other include dirs ...
PRIVATE
src)
# B depends on A
target_link_libraries(B A)
export(
TARGETS B
FILE BLibraryConfig.cmake)
What are the minimum changes I need to make to my CMakeLists files (at either module or project scope) to be able to support B as a template library given that B still depends on A and both my main projects make use of A and B?
As another answer says, you could declare B as an interface library. This approach has some limitations, though. For instance, you cannot set custom properties on interface libraries. Also B's headers might not be properly displayed by an IDE, e.g. QtCreator 4.6.1 does not show them in the project tree.
If this is critical for you, there is an alternative. You could have a static library which contains only headers, but you need to manually specify it's linker language.
add_library(B STATIC ${SOURCES})
target_include_directories(B
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
... other include dirs ...
)
# As B does not have any source files, you have to explicitly
# specify the linker language
set_target_properties(B PROPERTIES LINKER_LANGUAGE CXX)
# B depends on A
target_link_libraries(B A)
export(
TARGETS B
FILE BLibraryConfig.cmake)
You can declare B as an interface library to define it as header-only. It will just require slight modifications of target_include_directories and target_link_libraries (define INTERFACE properties instead of public/private)
add_library(B INTERFACE) # no sources
target_include_directories(B INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
# other include dirs ...
)
# B depends on A
target_link_libraries(B INTERFACE A)
export(
TARGETS B
FILE BLibraryConfig.cmake
)
I have for some time had some problems incorporating modern cmake into a project I've been working fr some while and seem to be stuck on how i should define the the individual CMakeLists, and the top-level CMakeList.
My project structure is pretty simple.
├── build
└── src
├── include
│ ├── database
│ │ ├── database.cpp
│ │ └── database.h
│ ├── match
│ │ ├── match.h
│ │ └── mathc.cpp
│ ├── record
│ │ ├── lib
│ │ ├── record.cpp
│ │ └── record.h
│ └── spectogram
│ ├── spectogram.cpp
│ └── spectrogram.h
└── main.cpp
main.cpp are linked to all the includes, and some of the includes should know the presence of other includes, meaning, I should be able to include match.h in
database.h. Some third-party libs are also going to be used, in this case I am using portaudio, download and installed using externalproject_add, which should only be visible for the include which holds the library, in this case record, should only see this.
But how I should define the individual CMakeList, is currently unknown.
I've scouted the net for a proper way of setting this up, but cannot seem to find one that I understand.
How do i define the CMakeLists for this project, and how do i make sure that the includes, are visible for the Main.cpp and the includes files that need them, and how do I make third-party-libraries visible only for the includes that it is being used for.
CMakeLists example structure tried:
CMakeLists.txt
cmake_minimum_required(VERSION 3.2)
project(soundcloud)
#add_subdirectory(src/database)
#add_subdirectory(src/match)
#add_subdirectory(src/record)
add_subdirectory(src/include/spectogram)
add_executable(cmakeDemo src/main.cpp)
SET_TARGET_PROPERTIES(cmakeDemo PROPERTIES LINKER_LANGUAGE Cxx)
target_link_libraries(cmakeDemo spectogram)
#target_link_libraries(cmakeDemo database match record spectogram)
src/include/database/CMakeLists.txt
add_library(spectogram STATIC .)
target_include_directories(spectogram PUBLIC .)
getting error message:
CMake Error: Error required internal CMake variable not set, cmake may not be built correctly.
Missing variable is:
CMAKE_Cxx_LINK_EXECUTABLE
CMake Error: Cannot determine link language for target "spectogram".
CMake Error: CMake can not determine linker language for target: spectogram
You can use the PRIVATE property of target_include_directories. When PRIVATE, it means that the include directories will be available to the sources of the target. When PUBLIC, it will also be available to whomever links to the target.
If I were writing this in a single CMakeLists.txt, I'd do this:
cmake_minimum_required(VERSION 3.0)
add_library(database STATIC src/include/database.cpp)
target_include_directories(database PUBLIC src/include/database)
################
add_library(match STATIC src/include/mathc.cpp)
target_include_directories(match PUBLIC src/include/match)
################
include(ExternalProject)
ExternalProject_Add(portAudio ${SomeCommands})
add_library(record STATIC src/include/record.cpp)
target_include_directories(record PUBLIC src/include/record) # When cmakeDemo links to this, it'll get these includes
target_include_directories(record PRIVATE src/include/record/lib) # When cmakeDemo links to this, it won't get these includes
target_link_libraries(record portAudio)
#################
add_library(spectogram STATIC src/include/spectogram.cpp)
target_include_directories(spectogram PUBLIC src/include/spectogram)
##################
add_executable(cmakeDemo src/main.cpp)
target_link_libraries(cmakeDemo database match record spectogram)
If I were to do this with distributed CMakeLists.txt, I'd split the files where the ###### lines are, fix the paths, and use add_subdirectory() to include the sub-directories from higher-level cmake files.
First, you don't link to includes, you just "include" them during compilation.
Some people put one CMakeList.txt into every directory that contains a fairly independent compilation unit.
Some people just use one big one at the the top.
Having just one CMakeList.txt file makes it easier to start, but if the project gets huge, things get messy.
For every compilation unit, you can specify the include directories with target_include_directories
There is a project layout:
.
├── bin # <= executables go here
├── build # <= object files created here
├── lib # <= libraries go here
├── Makefile
├── src
│ ├── bin1 # <= if there is no "lib" prefix
│ ├── bin2 # <= it must be considered as executable
│ │ ├── a.c
│ │ ├── b.c
│ │ └── foo.h
│ ├── include # <= shared .h files, nothing to build here
│ ├── libt1 # <= if there is "lib" prefix - it must be
│ │ ├── blah.c # a library
│ │ └── blah.h
│ └── libt2
└── test
So i want gnu make to go through every directory in src with "lib" prefix and build a static and shared library with the same name as a directory, i.e. libt1.so and libt1.a and put them all in lib directory. Let's assume the libraries aren't linked with each other so the don't depend on each other either.
After building libs, it must go through every directory except include, and bin an executable with the same name as the directory has, and put it into bin dir. build directory is used for temporary object files.
What is the best way to do this with gnu make? I want rely on implicit rules as much as it's possible.
So now i just collect all directories into variables:
LIBS_TO_BUILD=$(wildcard $(SOURCES_DIR)/lib*)
BINS_TO_BUILD=$(filter-out $(INCLUDE_DIR) $(LIBS_TO_BUILD),\
$(wildcard $(SOURCES_DIR)/*))
But i can't figure out how to do all other steps, how should i iterate by all dirs? Assuming, that if i'll do it "by hands" it will look like:
lib/libt1.a:
$(CC) -o build/libt1.o $(CFLAGS) -c $(wildcard $(SOURCES_DIR)/libt1/*.c)
ar rcs lib/libt1.a build/libt1.o